pax_global_header00006660000000000000000000000064152041463740014520gustar00rootroot0000000000000052 comment=43ce9f792d10e0f328b6cc1c08aa218d052db9f9 bazaar-org-bazaar-43ce9f7/000077500000000000000000000000001520414637400154315ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/.clang-format000066400000000000000000000007531520414637400200110ustar00rootroot00000000000000BasedOnStyle: 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 bazaar-org-bazaar-43ce9f7/.devcontainer/000077500000000000000000000000001520414637400201705ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/.devcontainer/Dockerfile000066400000000000000000000010321520414637400221560ustar00rootroot00000000000000FROM 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 \ libproxy-devel \ gtksourceview5-devel \ glib-networking \ clangd bazaar-org-bazaar-43ce9f7/.devcontainer/devcontainer.json000066400000000000000000000017551520414637400235540ustar00rootroot00000000000000{ "name": "Bazaar devcontainer", "build": { "dockerfile": "Dockerfile" }, "runArgs": [ "--device=/dev/dri", "--network=host" ], "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}", "DBUS_SYSTEM_BUS_ADDRESS": "unix:path=/var/run/dbus/system_bus_socket" }, "mounts": [ "source=${localEnv:XDG_RUNTIME_DIR},target=${localEnv:XDG_RUNTIME_DIR},type=bind,consistency=cached", "source=/var/run/dbus/system_bus_socket,target=/var/run/dbus/system_bus_socket,type=bind,consistency=cached" ] }bazaar-org-bazaar-43ce9f7/.foundry/000077500000000000000000000000001520414637400171755ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/.foundry/.gitignore000066400000000000000000000000221520414637400211570ustar00rootroot00000000000000tmp/ user/ cache/ bazaar-org-bazaar-43ce9f7/.github/000077500000000000000000000000001520414637400167715ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/.github/CODEOWNERS000066400000000000000000000001761520414637400203700ustar00rootroot00000000000000# All files * @kolunmi @AlexanderVanhee .github/workflows/ @renner0e @tulilirockz build-aux/flatpak/ @renner0e @tulilirockz bazaar-org-bazaar-43ce9f7/.github/FUNDING.yml000066400000000000000000000001201520414637400205770ustar00rootroot00000000000000github: [kolunmi] ko_fi: kolunmi custom: - https://ko-fi.com/alexandervanhee bazaar-org-bazaar-43ce9f7/.github/ISSUE_TEMPLATE/000077500000000000000000000000001520414637400211545ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/.github/ISSUE_TEMPLATE/bug_form.yml000066400000000000000000000040001520414637400234710ustar00rootroot00000000000000name: 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 please take a look at https://github.com/bazaar-org/bazaar/blob/debug-symbols/docs/debugging.md#debugging-crashes 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 or secureblue 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. bazaar-org-bazaar-43ce9f7/.github/workflows/000077500000000000000000000000001520414637400210265ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/.github/workflows/build-flatpak.yml000066400000000000000000000020421520414637400242660ustar00rootroot00000000000000on: 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-50 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: submodules: recursive - uses: flatpak/flatpak-github-actions/flatpak-builder@92ae9851ad316786193b1fd3f40c4b51eb5cb101 # v6.6 with: bundle: Bazaar.flatpak manifest-path: build-aux/flatpak/io.github.kolunmi.Bazaar.json cache-key: flatpak-builder-046f9ec arch: ${{ matrix.variant.arch }} verbose: true bazaar-org-bazaar-43ce9f7/.github/workflows/flatpak-external-data-checker.yml000066400000000000000000000020521520414637400273230ustar00rootroot00000000000000name: Check for Flatpak dependency updates on: schedule: - cron: "0 0 * * *" # every day workflow_dispatch: jobs: flatpak-external-data-checker: runs-on: ubuntu-latest strategy: matrix: branch: [ main ] steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ matrix.branch }} - uses: docker://ghcr.io/flathub/flatpak-external-data-checker:latest env: GIT_AUTHOR_NAME: Flatpak External Data Checker GIT_COMMITTER_NAME: Flatpak External Data Checker # email sets "github-actions[bot]" as commit author, see https://github.community/t/github-actions-bot-email-address/17204/6 GIT_AUTHOR_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com GIT_COMMITTER_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: args: --update --never-fork --require-important-update build-aux/flatpak/io.github.kolunmi.Bazaar.json bazaar-org-bazaar-43ce9f7/.gitignore000066400000000000000000000000151520414637400174150ustar00rootroot00000000000000build .cache bazaar-org-bazaar-43ce9f7/.gitmodules000066400000000000000000000002141520414637400176030ustar00rootroot00000000000000[submodule "flatpak-builder-tools"] path = build-aux/flatpak/flatpak-builder-tools url = https://github.com/flatpak/flatpak-builder-tools bazaar-org-bazaar-43ce9f7/.well-known/000077500000000000000000000000001520414637400176045ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/.well-known/funding-manifest-urls000066400000000000000000000000601520414637400237440ustar00rootroot00000000000000https://www.kolunmi.net/ https://usebazaar.org/ bazaar-org-bazaar-43ce9f7/CODESTYLE.md000066400000000000000000000042161520414637400173110ustar00rootroot00000000000000# 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 bazaar-org-bazaar-43ce9f7/CONTRIBUTING.md000066400000000000000000000067731520414637400176770ustar00rootroot00000000000000# 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/bazaar-org/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/bazaar-org/bazaar/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22help%20wanted%22) - [Good first issues](https://github.com/bazaar-org/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/bazaar-org/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/bazaar-org/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) bazaar-org-bazaar-43ce9f7/COPYING000066400000000000000000001045201520414637400164660ustar00rootroot00000000000000 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 . bazaar-org-bazaar-43ce9f7/Justfile000066400000000000000000000051151520414637400171430ustar00rootroot00000000000000# 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-updates") 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: build-flatpak #!/usr/bin/env bash set -euo pipefail FLATPAK_BUILDER_DIR="$(realpath ".flatpak-builder")" 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; } bazaar-org-bazaar-43ce9f7/README.md000066400000000000000000000161621520414637400167160ustar00rootroot00000000000000


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/bazaar-org/bazaar/actions/workflows/build-flatpak.yml/badge.svg)](https://github.com/bazaar-org/bazaar/actions/workflows/build-flatpak.yml) There also exist packages for [Debian](https://tracker.debian.org/pkg/bazaar) and [Arch](https://archlinux.org/packages/extra/x86_64/bazaar/). These are not directly supported but should work fine. If you encounter a bug on any package of Bazaar other than the flatpak, ensure the bug also exists on the flatpak before reporting it here. ### 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 --libdir=/usr/lib64 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` | `4.22.1` | 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` | Interpret 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` | Decode image URIs | | [glycin-gtk4](https://gitlab.gnome.org/GNOME/glycin) | `glycin-gtk4-2` | `2.0` | Convert glycin frames to texture representations | | [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 some HTTP replies | | [md4c](https://github.com/mity/md4c) | `md4c` | `0.5.1` | Parse markdown (.md) | | [gtksourceview](https://gitlab.gnome.org/GNOME/gtksourceview) | `gtksourceview-5` | `5.17` | Render markdown code blocks | | [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 | | [libproxy](https://github.com/libproxy/libproxy) | `libproxy-1.0` | `0.5` | Parse proxies for networking operations | | [malcontent](https://gitlab.freedesktop.org/pwithnall/malcontent) | `malcontent-0` | `0.12.0` | Adhere to system parental controls settings | #### 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/) bazaar-org-bazaar-43ce9f7/TRANSLATORS-FR.md000066400000000000000000000122561520414637400201020ustar00rootroot00000000000000# 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. bazaar-org-bazaar-43ce9f7/TRANSLATORS-PL.md000066400000000000000000000103671520414637400201070ustar00rootroot00000000000000# 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 ``` bazaar-org-bazaar-43ce9f7/TRANSLATORS-ZH-CN.md000066400000000000000000000101051520414637400204010ustar00rootroot00000000000000# 翻译者指南 感谢你对翻译 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 中。 bazaar-org-bazaar-43ce9f7/TRANSLATORS.md000066400000000000000000000101671520414637400175740ustar00rootroot00000000000000# 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. bazaar-org-bazaar-43ce9f7/bazaar.doap000066400000000000000000000025171520414637400175430ustar00rootroot00000000000000 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 bazaar-org-bazaar-43ce9f7/bge/000077500000000000000000000000001520414637400161665ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/bge/README.md000066400000000000000000000000301520414637400174360ustar00rootroot00000000000000# Bazaar GTK Extensions bazaar-org-bazaar-43ce9f7/bge/bge-animation-private.h000066400000000000000000000032341520414637400225230ustar00rootroot00000000000000/* bge-animation-private.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 /* Copied with modifications from libadwaita */ double spring_oscillate (double damping, double mass, double stiffness, double from, double to, double time, double *velocity); /* Copied with modifications from libadwaita */ double spring_get_first_zero (double damping, double mass, double stiffness, double from, double to); /* Copied with modifications from libadwaita */ double spring_calculate_duration (double damping, double mass, double stiffness, double from, double to, gboolean clamp); gboolean bge_should_animate (GtkWidget *widget); bazaar-org-bazaar-43ce9f7/bge/bge-animation.c000066400000000000000000000542651520414637400210600ustar00rootroot00000000000000/* bge-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 */ /** * BgeAnimation: * * 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 "BGE::ANIMATION" #define DELTA 0.001 #define EPSILON 0.00001 #include "bge.h" #include "bge-animation-private.h" enum { PROP_0, PROP_WIDGET, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; struct _BgeAnimation { GObject parent_instance; GtkWidget *widget; GWeakRef wr; guint tag; GHashTable *data; GPtrArray *anonymous; }; G_DEFINE_FINAL_TYPE (BgeAnimation, bge_animation, G_TYPE_OBJECT) typedef struct { double from; double to; double damping_ratio; double mass; double stiffness; double damping; gboolean clamp; BgeAnimationCallback cb; gpointer user_data; GDestroyNotify destroy_data; double est_duration; GTimer *timer; double velocity; GCancellable *cancellable; } SpringData; static gboolean tick_cb (GtkWidget *widget, GdkFrameClock *frame_clock, GWeakRef *wr); static void ensure_tick (BgeAnimation *self, GtkWidget *widget); static void destroy_spring_data (gpointer ptr); static void destroy_wr (gpointer ptr); static void dispose (GObject *object) { BgeAnimation *self = BGE_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_clear_pointer (&self->anonymous, g_ptr_array_unref); G_OBJECT_CLASS (bge_animation_parent_class)->dispose (object); } static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BgeAnimation *self = BGE_ANIMATION (object); switch (prop_id) { case PROP_WIDGET: g_value_take_object (value, bge_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) { BgeAnimation *self = BGE_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) { BgeAnimation *self = BGE_ANIMATION (object); g_weak_ref_init (&self->wr, self->widget); g_clear_object (&self->widget); } static void bge_animation_class_init (BgeAnimationClass *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; /** * BgeAnimation: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 bge_animation_init (BgeAnimation *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); self->anonymous = g_ptr_array_new_with_free_func ( destroy_spring_data); } /** * bge_animation_new: * @widget: The widget onto which to attach the tick callback * * Creates a new `BgeAnimation` object. * * Returns: The newly created `BgeAnimation` object. */ BgeAnimation * bge_animation_new (GtkWidget *widget) { g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); return g_object_new ( BGE_TYPE_ANIMATION, "widget", widget, NULL); } /** * bge_animation_dup_widget: * @self: a `BgeAnimation` * * Gets the widget on which @self is attached. * * Returns: (nullable) (transfer full): the widget for @self */ GtkWidget * bge_animation_dup_widget (BgeAnimation *self) { g_return_val_if_fail (BGE_IS_ANIMATION (self), NULL); return g_weak_ref_get (&self->wr); } /** * bge_animation_add_spring: * @self: a `BgeAnimation` * @key: (nullable): a string ID to replace, or NULL for anonymous * @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: (nullable): the user data pointer to be passed to @cb * @destroy_data: (nullable): the destruction function for @user_data * @cancellable: (nullable): a cancellable to cancel the operation * * 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 bge_animation_add_spring (BgeAnimation *self, const char *key, double from, double to, double damping_ratio, double mass, double stiffness, BgeAnimationCallback cb, gpointer user_data, GDestroyNotify destroy_data, GCancellable *cancellable) { g_autoptr (GtkWidget) widget = NULL; g_return_if_fail (BGE_IS_ANIMATION (self)); g_return_if_fail (cb != NULL); widget = g_weak_ref_get (&self->wr); if (widget != NULL) { if (bge_should_animate (widget)) { SpringData *data = NULL; if (key != 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); g_clear_object (&data->cancellable); /* old velocity is retained */ } else { data = g_new0 (typeof (*data), 1); if (key != NULL) g_hash_table_replace (self->data, g_strdup (key), data); else g_ptr_array_add (self->anonymous, 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; data->damping = damping_ratio * (/* critical damping */ 2 * sqrt (mass * stiffness)); /* We'll fill this in on the first iteration */ data->timer = NULL; if (cancellable != NULL) data->cancellable = g_object_ref (cancellable); data->est_duration = spring_calculate_duration ( data->damping, data->mass, data->stiffness, data->from, data->to, data->clamp); cb (widget, key, from, user_data); ensure_tick (self, widget); } 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); } } /** * bge_animation_has_key: * @self: a `BgeAnimation` * @key: a string ID * * Determines whether @key exists and represents an active animation on @self. * * Returns: a boolean representing whether the string ID exists */ gboolean bge_animation_has_key (BgeAnimation *self, const char *key) { g_return_val_if_fail (BGE_IS_ANIMATION (self), FALSE); g_return_val_if_fail (key != NULL, FALSE); return g_hash_table_contains (self->data, key); } /** * bge_animation_cancel: * @self: a `BgeAnimation` * @key: a string ID to remove * * If @key exists on @self, cancel the associated animation. */ void bge_animation_cancel (BgeAnimation *self, const char *key) { SpringData *data = NULL; g_autoptr (GtkWidget) widget = NULL; g_return_if_fail (BGE_IS_ANIMATION (self)); g_return_if_fail (key != NULL); data = g_hash_table_lookup (self->data, key); if (data == NULL) return; widget = g_weak_ref_get (&self->wr); if (widget != NULL) data->cb (widget, key, data->to, data->user_data); g_hash_table_remove (self->data, key); } /** * bge_animation_cancel_all: * @self: a `BgeAnimation` * * Cancel all animations on @self. */ void bge_animation_cancel_all (BgeAnimation *self) { GHashTableIter iter = { 0 }; g_autoptr (GtkWidget) widget = NULL; g_return_if_fail (BGE_IS_ANIMATION (self)); g_hash_table_iter_init (&iter, self->data); widget = g_weak_ref_get (&self->wr); for (;;) { char *key = NULL; SpringData *data = NULL; if (!g_hash_table_iter_next ( &iter, (gpointer *) &key, (gpointer *) &data)) break; if (widget != NULL) data->cb (widget, key, data->to, data->user_data); g_hash_table_iter_remove (&iter); } } static gboolean tick_cb (GtkWidget *widget, GdkFrameClock *frame_clock, GWeakRef *wr) { g_autoptr (BgeAnimation) self = NULL; gboolean cancel = FALSE; GHashTableIter iter = { 0 }; self = g_weak_ref_get (wr); if (self == NULL) return G_SOURCE_REMOVE; cancel = !bge_should_animate (widget); #define UPDATE(_data, _out_value, _out_finished, _out_cancelled) \ G_STMT_START \ { \ if (cancel || \ ((_data)->cancellable != NULL && \ g_cancellable_is_cancelled ((_data)->cancellable))) \ (_out_finished) = (_out_cancelled) = TRUE; \ else \ { \ double elapsed = 0.0; \ \ if ((_data)->timer == NULL) \ { \ (_data)->timer = g_timer_new (); \ (_out_value) = (_data)->from; \ } \ else \ { \ elapsed = g_timer_elapsed ((_data)->timer, NULL); \ (_out_value) = spring_oscillate ( \ data->damping, \ data->mass, \ data->stiffness, \ data->from, \ data->to, \ elapsed, \ &(_data)->velocity); \ } \ \ (_out_finished) = elapsed >= (_data)->est_duration; \ } \ if ((_out_finished)) \ (_out_value) = (_data)->to; \ } \ G_STMT_END /* Named anims */ g_hash_table_iter_init (&iter, self->data); for (;;) { char *key = NULL; SpringData *data = NULL; double value = 0.0; gboolean finished = FALSE; gboolean cancelled = FALSE; if (!g_hash_table_iter_next ( &iter, (gpointer *) &key, (gpointer *) &data)) break; UPDATE (data, value, finished, cancelled); if (!cancelled) data->cb (widget, key, value, data->user_data); if (finished) g_hash_table_iter_remove (&iter); } /* Anonymous anims */ for (guint i = 0; i < self->anonymous->len;) { SpringData *data = NULL; double value = 0.0; gboolean finished = FALSE; gboolean cancelled = FALSE; data = g_ptr_array_index (self->anonymous, i); UPDATE (data, value, finished, cancelled); if (!cancelled) data->cb (widget, NULL, value, data->user_data); if (finished) g_ptr_array_remove_index (self->anonymous, i); else i++; } #undef UPDATE if (g_hash_table_size (self->data) == 0 && self->anonymous->len == 0) { gtk_widget_remove_tick_callback (widget, self->tag); self->tag = 0; return G_SOURCE_REMOVE; } 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 */ double spring_oscillate (double damping, double mass, double stiffness, double from, double to, double time, double *velocity) { double b = damping; double m = mass; double k = 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 = from - to; envelope = exp (-beta * time); /* * 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 * time * v0 - beta * beta * time * x0 + v0); return to + envelope * (x0 + (beta * x0 + v0) * time); } /* Underdamped */ if (beta < omega0) { double omega1 = 0.0; omega1 = sqrt ((omega0 * omega0) - (beta * beta)); if (velocity != NULL) *velocity = envelope * (v0 * cos (omega1 * time) - (x0 * omega1 + (beta * beta * x0 + beta * v0) / (omega1)) * sin (omega1 * time)); return to + envelope * (x0 * cos (omega1 * time) + ((beta * x0 + v0) / omega1) * sin (omega1 * time)); } /* Overdamped */ if (beta > omega0) { double omega2 = 0.0; omega2 = sqrt ((beta * beta) - (omega0 * omega0)); if (velocity != NULL) *velocity = envelope * (v0 * coshl (omega2 * time) + (omega2 * x0 - (beta * beta * x0 + beta * v0) / omega2) * sinhl (omega2 * time)); return to + envelope * (x0 * coshl (omega2 * time) + ((beta * x0 + v0) / omega2) * sinhl (omega2 * time)); } g_assert_not_reached (); } double spring_get_first_zero (double damping, double mass, double stiffness, double from, double to) { /* The first frame is not that important and we avoid finding the trivial 0 * for in-place animations. */ for (int i = 0; i < 20000; i++) { double y = 0.0; y = spring_oscillate ( damping, mass, stiffness, from, to, (double) i / 1000.0, NULL); if (!((to - from > DBL_EPSILON && to - y > EPSILON) || (from - to > DBL_EPSILON && y - to > EPSILON))) return y; } return 0.0; } double spring_calculate_duration (double damping, double mass, double stiffness, double from, double to, gboolean clamp) { 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; beta = damping / (2 * mass); if (G_APPROX_VALUE (beta, 0, DBL_EPSILON) || beta < 0) return G_MAXDOUBLE; if (clamp) { if (G_APPROX_VALUE (to, from, DBL_EPSILON)) return 0; return spring_get_first_zero (damping, mass, stiffness, from, to); } omega0 = sqrt (stiffness / 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 = spring_oscillate (damping, mass, stiffness, from, to, x0, NULL); m = (spring_oscillate ( damping, mass, stiffness, from, to, (x0 + DELTA), NULL) - y0) / DELTA; x1 = (to - y0 + m * x0) / m; y1 = spring_oscillate ( damping, mass, stiffness, from, to, x1, NULL); for (int i = 0; ABS (to - y1) > EPSILON && i < 1000; i++) { x0 = x1; y0 = y1; m = (spring_oscillate ( damping, mass, stiffness, from, to, x0 + DELTA, NULL) - y0) / DELTA; x1 = (to - y0 + m * x0) / m; y1 = spring_oscillate ( damping, mass, stiffness, from, to, x1, NULL); } if (ABS (to - y1) <= EPSILON) return x1; else return 0.0; } /* ///COPIED FROM LIBADWAITA */ static void ensure_tick (BgeAnimation *self, GtkWidget *widget) { GWeakRef *wr = NULL; if (self->tag > 0) return; wr = g_new0 (typeof (*wr), 1); g_weak_ref_init (wr, self); self->tag = gtk_widget_add_tick_callback ( widget, (GtkTickCallback) tick_cb, wr, destroy_wr); } 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_clear_object (&data->cancellable); g_free (ptr); } static void destroy_wr (gpointer ptr) { GWeakRef *wr = ptr; g_weak_ref_clear (wr); g_free (ptr); } gboolean bge_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; } bazaar-org-bazaar-43ce9f7/bge/bge-animation.h000066400000000000000000000044311520414637400210530ustar00rootroot00000000000000/* bge-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 #ifndef BGE_INSIDE #error "Only can be included directly." #endif G_BEGIN_DECLS #define BGE_TYPE_ANIMATION (bge_animation_get_type ()) G_DECLARE_FINAL_TYPE (BgeAnimation, bge_animation, BGE, ANIMATION, GObject) typedef void (*BgeAnimationCallback) (GtkWidget *widget, const char *key, double value, gpointer user_data); BGE_AVAILABLE_IN_ALL BgeAnimation * bge_animation_new (GtkWidget *widget); BGE_AVAILABLE_IN_ALL GtkWidget * bge_animation_dup_widget (BgeAnimation *self); BGE_AVAILABLE_IN_ALL void bge_animation_add_spring (BgeAnimation *self, const char *key, double from, double to, double damping_ratio, double mass, double stiffness, BgeAnimationCallback cb, gpointer user_data, GDestroyNotify destroy_data, GCancellable *cancellable); BGE_AVAILABLE_IN_ALL gboolean bge_animation_has_key (BgeAnimation *self, const char *key); BGE_AVAILABLE_IN_ALL void bge_animation_cancel (BgeAnimation *self, const char *key); BGE_AVAILABLE_IN_ALL void bge_animation_cancel_all (BgeAnimation *self); G_END_DECLS bazaar-org-bazaar-43ce9f7/bge/bge-carousel.c000066400000000000000000001126061520414637400207100ustar00rootroot00000000000000/* bge-carousel.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 */ /** * BgeCarousel: * * Arranges widgets into a horizontal carousel */ #define G_LOG_DOMAIN "BGE::CAROUSEL" #include "bge.h" #include "bge-marshalers.h" #include "util.h" #define RAISE_FACTOR 0.025 /* `ratio < 1.0` means it overshoots */ #define ANIMATION_DAMPING_RATIO 1.15 struct _BgeCarousel { GtkWidget parent_instance; GtkEventController *motion; double motion_x; double motion_y; GtkEventController *scroll; gboolean scrolling; int hscroll_start; int hscroll_current; GtkGesture *drag; gboolean dragging; double drag_x; double drag_y; BgeAnimation *animation; gboolean allow_mouse_drag; gboolean allow_overshoot; gboolean allow_scroll_wheel; gboolean allow_raise; GtkSingleSelection *model; GPtrArray *mirror; GPtrArray *widgets; }; G_DEFINE_FINAL_TYPE (BgeCarousel, bge_carousel, GTK_TYPE_WIDGET); enum { PROP_0, PROP_ALLOW_MOUSE_DRAG, PROP_ALLOW_OVERSHOOT, PROP_ALLOW_SCROLL_WHEEL, PROP_ALLOW_RAISE, PROP_MODEL, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_CREATE_WIDGET, SIGNAL_REMOVE_WIDGET, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; BGE_DEFINE_DATA ( carousel_widget, CarouselWidget, { GtkWidget *widget; int width; graphene_rect_t rect; graphene_rect_t target; gboolean raised; GCancellable *cancellable; }, BGE_RELEASE_DATA (widget, gtk_widget_unparent); BGE_RELEASE_DATA (cancellable, g_object_unref)) static void items_changed (BgeCarousel *self, guint position, guint removed, guint added, GListModel *model); static void model_selected_changed (BgeCarousel *self, GParamSpec *pspec, GtkSingleSelection *selection); static void move_to_idx (BgeCarousel *self, guint idx, /* damping_ratio <= 0.0 means no animation */ double damping_ratio); static void animate (BgeCarousel *self, const char *key, double value, CarouselWidgetData *data); static void ensure_viewport (BgeCarousel *self, GtkSingleSelection *model, gboolean animate); static void motion_enter (BgeCarousel *self, gdouble x, gdouble y, GtkEventControllerMotion *controller); static void motion_event (BgeCarousel *self, gdouble x, gdouble y, GtkEventControllerMotion *controller); static void motion_leave (BgeCarousel *self, GtkEventControllerMotion *controller); static void update_motion (BgeCarousel *self, gdouble x, gdouble y); static void scroll_begin (BgeCarousel *self, GtkEventControllerScroll *controller); static void scroll_end (BgeCarousel *self, GtkEventControllerScroll *controller); static gboolean scroll (BgeCarousel *self, gdouble dx, gdouble dy, GtkEventControllerScroll *controller); static void drag_begin (BgeCarousel *self, gdouble start_x, gdouble start_y, GtkGestureDrag *gesture); static void drag_end (BgeCarousel *self, gdouble offset_x, gdouble offset_y, GtkGestureDrag *gesture); static void drag_update (BgeCarousel *self, gdouble offset_x, gdouble offset_y, GtkGestureDrag *gesture); static void finish_horizontal_gesture (BgeCarousel *self, int offset_x, int offset_y); static void bge_carousel_dispose (GObject *object) { BgeCarousel *self = BGE_CAROUSEL (object); if (self->model != NULL) { g_signal_handlers_disconnect_by_func (self->model, items_changed, self); g_signal_handlers_disconnect_by_func (self->model, model_selected_changed, self); } g_clear_pointer (&self->animation, g_object_unref); g_clear_pointer (&self->model, g_object_unref); g_clear_pointer (&self->mirror, g_ptr_array_unref); g_clear_pointer (&self->widgets, g_ptr_array_unref); G_OBJECT_CLASS (bge_carousel_parent_class)->dispose (object); } static void bge_carousel_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BgeCarousel *self = BGE_CAROUSEL (object); switch (prop_id) { case PROP_ALLOW_MOUSE_DRAG: g_value_set_boolean (value, bge_carousel_get_allow_mouse_drag (self)); break; case PROP_ALLOW_OVERSHOOT: g_value_set_boolean (value, bge_carousel_get_allow_overshoot (self)); break; case PROP_ALLOW_SCROLL_WHEEL: g_value_set_boolean (value, bge_carousel_get_allow_scroll_wheel (self)); break; case PROP_ALLOW_RAISE: g_value_set_boolean (value, bge_carousel_get_allow_raise (self)); break; case PROP_MODEL: g_value_set_object (value, bge_carousel_get_model (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bge_carousel_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BgeCarousel *self = BGE_CAROUSEL (object); switch (prop_id) { case PROP_ALLOW_MOUSE_DRAG: bge_carousel_set_allow_mouse_drag (self, g_value_get_boolean (value)); break; case PROP_ALLOW_OVERSHOOT: bge_carousel_set_allow_overshoot (self, g_value_get_boolean (value)); break; case PROP_ALLOW_SCROLL_WHEEL: bge_carousel_set_allow_scroll_wheel (self, g_value_get_boolean (value)); break; case PROP_ALLOW_RAISE: bge_carousel_set_allow_raise (self, g_value_get_boolean (value)); break; case PROP_MODEL: bge_carousel_set_model (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bge_carousel_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BgeCarousel *self = BGE_CAROUSEL (widget); for (guint i = 0; i < self->widgets->len; i++) { CarouselWidgetData *child = NULL; int tmp_minimum = 0; int tmp_natural = 0; int tmp_minimum_baseline = 0; int tmp_natural_baseline = 0; child = g_ptr_array_index (self->widgets, i); gtk_widget_measure ( child->widget, orientation, for_size, &tmp_minimum, &tmp_natural, &tmp_minimum_baseline, &tmp_natural_baseline); if (tmp_minimum > 0 && tmp_minimum > *minimum) *minimum = tmp_minimum; if (tmp_natural > 0 && tmp_natural > *natural) *natural = tmp_natural; if (tmp_minimum_baseline > 0 && tmp_minimum_baseline > *minimum_baseline) *minimum_baseline = tmp_minimum_baseline; if (tmp_natural_baseline > 0 && tmp_natural_baseline > *natural_baseline) *natural_baseline = tmp_natural_baseline; } } static void bge_carousel_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BgeCarousel *self = BGE_CAROUSEL (widget); ensure_viewport (self, self->model, FALSE); for (guint i = 0; i < self->widgets->len; i++) { CarouselWidgetData *child = NULL; g_autoptr (GskTransform) transform = NULL; child = g_ptr_array_index (self->widgets, i); transform = gsk_transform_translate ( gsk_transform_new (), &child->rect.origin); gtk_widget_allocate ( child->widget, child->rect.size.width, child->rect.size.height, baseline, g_steal_pointer (&transform)); } } static void bge_carousel_class_init (BgeCarouselClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bge_carousel_set_property; object_class->get_property = bge_carousel_get_property; object_class->dispose = bge_carousel_dispose; /** * BgeCarousel:allow-mouse-drag: * * Whether to allow dragging with the mouse. */ props[PROP_ALLOW_MOUSE_DRAG] = g_param_spec_boolean ( "allow-mouse-drag", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * BgeCarousel:allow-overshoot: * * Whether to allow overshooting the ends of the carousel with drag/touchpad * input. Once the event completes, the carousel offset value will go back to * that of the start/end widget. Setting this value to FALSE will prevent this * widget from capturing input events which would result in an overshoot. */ props[PROP_ALLOW_OVERSHOOT] = g_param_spec_boolean ( "allow-overshoot", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * BgeCarousel:allow-scroll-wheel: * * Whether to allow moving the carousel contents with the horizontal scroll * wheel. */ props[PROP_ALLOW_SCROLL_WHEEL] = g_param_spec_boolean ( "allow-scroll-wheel", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * BgeCarousel:allow-raise: * * Whether to allow raise animations when motion input events hover over them * carousel widgets. */ props[PROP_ALLOW_RAISE] = g_param_spec_boolean ( "allow-raise", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * BgeCarousel:model: * * The selection model for the carousel contents. */ props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, GTK_TYPE_SINGLE_SELECTION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); /** * BgeCarousel::create-widget: * @carousel: the object that received the signal * @object: a list item object from [property@Bge.Carousel:model] * * Emitted when an object is being bound to the carousel * * Return: a newly allocated widget to add to the carousel */ signals[SIGNAL_CREATE_WIDGET] = g_signal_new ( "create-widget", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, bge_marshal_OBJECT__OBJECT, GTK_TYPE_WIDGET, 1, G_TYPE_OBJECT); g_signal_set_va_marshaller ( signals[SIGNAL_CREATE_WIDGET], G_TYPE_FROM_CLASS (klass), bge_marshal_OBJECT__OBJECTv); /** * BgeCarousel::remove-widget: * @carousel: the object that received the signal * @widget: the widget which was created by [signal@Bge.Carousel::create-widget] * @object: a list item object from [property@Bge.Carousel:model] * * Emitted when an object is being unbound from the carousel */ signals[SIGNAL_REMOVE_WIDGET] = g_signal_new ( "remove-widget", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, bge_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, GTK_TYPE_WIDGET, G_TYPE_OBJECT); g_signal_set_va_marshaller ( signals[SIGNAL_REMOVE_WIDGET], G_TYPE_FROM_CLASS (klass), bge_marshal_VOID__OBJECT_OBJECTv); widget_class->measure = bge_carousel_measure; widget_class->size_allocate = bge_carousel_size_allocate; } static void bge_carousel_init (BgeCarousel *self) { self->animation = bge_animation_new (GTK_WIDGET (self)); self->mirror = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_object_unref); self->widgets = g_ptr_array_new_with_free_func ( carousel_widget_data_unref); gtk_widget_set_overflow (GTK_WIDGET (self), GTK_OVERFLOW_HIDDEN); 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->scroll = gtk_event_controller_scroll_new ( GTK_EVENT_CONTROLLER_SCROLL_HORIZONTAL | GTK_EVENT_CONTROLLER_SCROLL_KINETIC); g_signal_connect_swapped (self->scroll, "scroll-begin", G_CALLBACK (scroll_begin), self); g_signal_connect_swapped (self->scroll, "scroll-end", G_CALLBACK (scroll_end), self); g_signal_connect_swapped (self->scroll, "scroll", G_CALLBACK (scroll), self); gtk_widget_add_controller (GTK_WIDGET (self), self->scroll); self->drag = gtk_gesture_drag_new (); gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (self->drag), GTK_PHASE_CAPTURE); g_signal_connect_swapped (self->drag, "drag-begin", G_CALLBACK (drag_begin), self); g_signal_connect_swapped (self->drag, "drag-end", G_CALLBACK (drag_end), self); g_signal_connect_swapped (self->drag, "drag-update", G_CALLBACK (drag_update), self); gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (self->drag)); } /** * bge_carousel_new: * * Creates a new `BgeCarousel` object. * * Returns: The newly created `BgeCarousel` object. */ GtkWidget * bge_carousel_new (void) { return g_object_new (BGE_TYPE_CAROUSEL, NULL); } /** * bge_carousel_get_allow_mouse_drag: * @self: a `BgeCarousel` * * Gets [property@Bge.Carousel:allow-mouse-drag]. * * Returns: the value of the property */ gboolean bge_carousel_get_allow_mouse_drag (BgeCarousel *self) { g_return_val_if_fail (BGE_IS_CAROUSEL (self), FALSE); return self->allow_mouse_drag; } /** * bge_carousel_get_allow_overshoot: * @self: a `BgeCarousel` * * Gets [property@Bge.Carousel:allow-overshoot]. * * Returns: the value of the property */ gboolean bge_carousel_get_allow_overshoot (BgeCarousel *self) { g_return_val_if_fail (BGE_IS_CAROUSEL (self), FALSE); return self->allow_overshoot; } /** * bge_carousel_get_allow_scroll_wheel: * @self: a `BgeCarousel` * * Gets [property@Bge.Carousel:allow-scroll-wheel]. * * Returns: the value of the property */ gboolean bge_carousel_get_allow_scroll_wheel (BgeCarousel *self) { g_return_val_if_fail (BGE_IS_CAROUSEL (self), FALSE); return self->allow_scroll_wheel; } /** * bge_carousel_get_allow_raise: * @self: a `BgeCarousel` * * Gets [property@Bge.Carousel:allow-raise]. * * Returns: the value of the property */ gboolean bge_carousel_get_allow_raise (BgeCarousel *self) { g_return_val_if_fail (BGE_IS_CAROUSEL (self), FALSE); return self->allow_raise; } /** * bge_carousel_get_model: * @self: a `BgeCarousel` * * Gets [property@Bge.Carousel:model]. * * Returns: (nullable): the value of the property */ GtkSingleSelection * bge_carousel_get_model (BgeCarousel *self) { g_return_val_if_fail (BGE_IS_CAROUSEL (self), NULL); return self->model; } /** * bge_carousel_get_nth_page: * @self: a `BgeCarousel` * @index: Index of the page. * * Returns: (nullable) (transfer none): the page at @index, or NULL if out of bounds */ GtkWidget * bge_carousel_get_nth_page (BgeCarousel *self, guint index) { CarouselWidgetData *data = NULL; g_return_val_if_fail (BGE_IS_CAROUSEL (self), NULL); if (index >= self->widgets->len) return NULL; data = g_ptr_array_index (self->widgets, index); return data->widget; } /** * bge_carousel_set_allow_mouse_drag: * @self: a `BgeCarousel` * @allow_mouse_drag: a boolean * * Sets [property@Bge.Carousel:allow-mouse-drag]. */ void bge_carousel_set_allow_mouse_drag (BgeCarousel *self, gboolean allow_mouse_drag) { g_return_if_fail (BGE_IS_CAROUSEL (self)); if (!!allow_mouse_drag == !!self->allow_mouse_drag) return; self->allow_mouse_drag = allow_mouse_drag; if (!allow_mouse_drag && self->dragging) { self->dragging = FALSE; finish_horizontal_gesture (self, self->drag_x, self->drag_y); self->drag_x = 0.0; self->drag_y = 0.0; } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALLOW_MOUSE_DRAG]); } /** * bge_carousel_set_allow_overshoot: * @self: a `BgeCarousel` * @allow_overshoot: a boolean * * Sets [property@Bge.Carousel:allow-overshoot]. */ void bge_carousel_set_allow_overshoot (BgeCarousel *self, gboolean allow_overshoot) { g_return_if_fail (BGE_IS_CAROUSEL (self)); if (!!allow_overshoot == !!self->allow_overshoot) return; self->allow_overshoot = allow_overshoot; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALLOW_OVERSHOOT]); } /** * bge_carousel_set_allow_scroll_wheel: * @self: a `BgeCarousel` * @allow_scroll_wheel: a boolean * * Sets [property@Bge.Carousel:allow-scroll-wheel]. */ void bge_carousel_set_allow_scroll_wheel (BgeCarousel *self, gboolean allow_scroll_wheel) { g_return_if_fail (BGE_IS_CAROUSEL (self)); if (!!allow_scroll_wheel == !!self->allow_scroll_wheel) return; self->allow_scroll_wheel = allow_scroll_wheel; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALLOW_SCROLL_WHEEL]); } /** * bge_carousel_set_allow_raise: * @self: a `BgeCarousel` * @allow_raise: a boolean * * Sets [property@Bge.Carousel:allow-raise]. */ void bge_carousel_set_allow_raise (BgeCarousel *self, gboolean allow_raise) { g_return_if_fail (BGE_IS_CAROUSEL (self)); if (!!allow_raise == !!self->allow_raise) return; self->allow_raise = allow_raise; if (self->model != NULL) ensure_viewport (self, self->model, TRUE); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALLOW_RAISE]); } /** * bge_carousel_set_model: * @self: a `BgeCarousel` * @model: a `GtkSingleSelection` object * * Sets [property@Bge.Carousel:model]. */ void bge_carousel_set_model (BgeCarousel *self, GtkSingleSelection *model) { g_return_if_fail (BGE_IS_CAROUSEL (self)); g_return_if_fail (model == NULL || GTK_IS_SINGLE_SELECTION (model)); if (model == self->model) return; if (self->model != NULL) { g_signal_handlers_disconnect_by_func (self->model, items_changed, self); g_signal_handlers_disconnect_by_func (self->model, model_selected_changed, self); items_changed ( self, 0, g_list_model_get_n_items (G_LIST_MODEL (self->model)), 0, G_LIST_MODEL (self->model)); } g_clear_pointer (&self->model, g_object_unref); if (model != NULL) { self->model = g_object_ref (model); items_changed ( self, 0, 0, g_list_model_get_n_items (G_LIST_MODEL (model)), G_LIST_MODEL (model)); g_signal_connect_swapped ( model, "items-changed", G_CALLBACK (items_changed), self); g_signal_connect_swapped ( model, "notify::selected", G_CALLBACK (model_selected_changed), self); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); } static void items_changed (BgeCarousel *self, guint position, guint removed, guint added, GListModel *model) { for (guint i = 0; i < removed; i++) { GObject *object = NULL; CarouselWidgetData *child = NULL; object = g_ptr_array_index (self->mirror, position + i); child = g_ptr_array_index (self->widgets, position + i); if (child->cancellable != NULL) g_cancellable_cancel (child->cancellable); g_signal_emit (self, signals[SIGNAL_REMOVE_WIDGET], 0, child->widget, object); } if (removed > 0) { g_ptr_array_remove_range (self->mirror, position, removed); g_ptr_array_remove_range (self->widgets, position, removed); } for (guint i = 0; i < added; i++) { g_autoptr (GObject) object = NULL; GtkWidget *child = NULL; CarouselWidgetData *data = NULL; object = g_list_model_get_item (model, position + i); g_signal_emit (self, signals[SIGNAL_CREATE_WIDGET], 0, object, &child); if (child == NULL) { g_critical ("Failed to populate child for carousel widget"); child = gtk_fixed_new (); } if (position + i == 0) gtk_widget_set_parent (child, GTK_WIDGET (self)); else { CarouselWidgetData *prev = NULL; prev = g_ptr_array_index (self->widgets, position + i - 1); gtk_widget_insert_after (child, GTK_WIDGET (self), prev->widget); } data = carousel_widget_data_new (); data->widget = child; g_ptr_array_insert (self->mirror, position + i, g_object_ref (object)); g_ptr_array_insert (self->widgets, position + i, data); } ensure_viewport (self, GTK_SINGLE_SELECTION (model), FALSE); } static void model_selected_changed (BgeCarousel *self, GParamSpec *pspec, GtkSingleSelection *selection) { guint idx = 0; idx = gtk_single_selection_get_selected (selection); if (idx != G_MAXUINT) move_to_idx (self, idx, ANIMATION_DAMPING_RATIO); gtk_widget_queue_allocate (GTK_WIDGET (self)); } static void move_to_idx (BgeCarousel *self, guint idx, /* damping_ratio <= 0.0 means no animation */ double damping_ratio) { int width = 0; int height = 0; int offset = 0; width = gtk_widget_get_width (GTK_WIDGET (self)); height = gtk_widget_get_height (GTK_WIDGET (self)); if (width == 0 || height == 0) { gtk_widget_queue_allocate (GTK_WIDGET (self)); return; } offset = width / 2; if (self->scrolling) offset += self->hscroll_start - self->hscroll_current; if (self->dragging) offset += self->drag_x; for (guint i = 0; i <= idx; i++) { CarouselWidgetData *child = NULL; int hminimum = 0; int hnatural = 0; int unused = 0; int child_width = 0; child = g_ptr_array_index (self->widgets, i); gtk_widget_measure ( child->widget, GTK_ORIENTATION_HORIZONTAL, height, &hminimum, &hnatural, &unused, &unused); if (gtk_widget_get_hexpand (child->widget)) child_width = MAX (hminimum, width); else child_width = CLAMP (hnatural, hminimum, width); if (i == idx) offset -= child_width / 2; else offset -= child_width; } for (guint i = 0; i < self->widgets->len; i++) { CarouselWidgetData *child = NULL; int hminimum = 0; int hnatural = 0; int unused = 0; int rect_width = 0; int child_width = 0; int child_height = 0; int child_x = 0; int child_y = 0; graphene_rect_t target = { 0 }; gboolean avoid_animation = FALSE; child = g_ptr_array_index (self->widgets, i); gtk_widget_measure ( child->widget, GTK_ORIENTATION_HORIZONTAL, height, &hminimum, &hnatural, &unused, &unused); if (gtk_widget_get_hexpand (child->widget)) rect_width = MAX (hminimum, width); else rect_width = CLAMP (hnatural, hminimum, width); if (child->raised || !self->allow_raise) { child_width = rect_width; child_height = height; child_x = offset; child_y = 0; } else { child_height = round ((double) height * (1.0 - RAISE_FACTOR)); gtk_widget_measure ( child->widget, GTK_ORIENTATION_HORIZONTAL, child_height, &hminimum, &hnatural, &unused, &unused); child_width = CLAMP (hnatural, hminimum, width); child_x = offset + round ((double) (rect_width - child_width) * 0.5); child_y = round ((double) height * (0.5 * RAISE_FACTOR)); } target = GRAPHENE_RECT_INIT (child_x, child_y, child_width, child_height); avoid_animation = graphene_rect_equal (&target, &child->target); if (child->width != rect_width || (damping_ratio < 0.0 && !avoid_animation)) { if (child->cancellable != NULL) g_cancellable_cancel (child->cancellable); child->width = rect_width; child->rect = target; child->target = target; } else if (avoid_animation) child->target = target; else { char buf[64] = { 0 }; g_clear_object (&child->cancellable); child->cancellable = g_cancellable_new (); #define MASS 1.0 #define STIFFNESS 800.0 /* pointer is to ensure a unique identifier so as not to overwrite any other child's key */ g_snprintf (buf, sizeof (buf), "x%p", child); bge_animation_add_spring ( self->animation, buf, child->rect.origin.x, target.origin.x, damping_ratio, MASS, STIFFNESS, (BgeAnimationCallback) animate, carousel_widget_data_ref (child), carousel_widget_data_unref, child->cancellable); g_snprintf (buf, sizeof (buf), "y%p", child); bge_animation_add_spring ( self->animation, buf, child->rect.origin.y, target.origin.y, damping_ratio, MASS, STIFFNESS, (BgeAnimationCallback) animate, carousel_widget_data_ref (child), carousel_widget_data_unref, child->cancellable); g_snprintf (buf, sizeof (buf), "w%p", child); bge_animation_add_spring ( self->animation, buf, child->rect.size.width, target.size.width, damping_ratio, MASS, STIFFNESS, (BgeAnimationCallback) animate, carousel_widget_data_ref (child), carousel_widget_data_unref, child->cancellable); g_snprintf (buf, sizeof (buf), "h%p", child); bge_animation_add_spring ( self->animation, buf, child->rect.size.height, target.size.height, damping_ratio, MASS, STIFFNESS, (BgeAnimationCallback) animate, carousel_widget_data_ref (child), carousel_widget_data_unref, child->cancellable); #undef STIFFNESS #undef MASS child->target = target; } offset += rect_width; } gtk_widget_queue_allocate (GTK_WIDGET (self)); } static void animate (BgeCarousel *self, const char *key, double value, CarouselWidgetData *data) { switch (*key) { case 'x': data->rect.origin.x = value; break; case 'y': data->rect.origin.y = value; break; case 'w': data->rect.size.width = value; break; case 'h': data->rect.size.height = value; break; default: g_assert_not_reached (); } gtk_widget_queue_allocate (GTK_WIDGET (self)); } static void ensure_viewport (BgeCarousel *self, GtkSingleSelection *model, gboolean animate) { guint n_items = 0; n_items = g_list_model_get_n_items (G_LIST_MODEL (model)); if (n_items > 0) { guint selected = 0; selected = gtk_single_selection_get_selected (model); if (selected == G_MAXUINT) { gtk_single_selection_set_selected (model, 0); move_to_idx (self, 0, animate ? ANIMATION_DAMPING_RATIO : -1.0); } else move_to_idx (self, selected, animate ? ANIMATION_DAMPING_RATIO : -1.0); } gtk_widget_queue_allocate (GTK_WIDGET (self)); } static void motion_enter (BgeCarousel *self, gdouble x, gdouble y, GtkEventControllerMotion *controller) { self->motion_x = x; self->motion_y = y; update_motion (self, x, y); } static void motion_event (BgeCarousel *self, gdouble x, gdouble y, GtkEventControllerMotion *controller) { self->motion_x = x; self->motion_y = y; update_motion (self, x, y); } static void motion_leave (BgeCarousel *self, GtkEventControllerMotion *controller) { if (self->dragging) return; self->motion_x = -1.0; self->motion_y = -1.0; update_motion (self, -1.0, -1.0); } static void update_motion (BgeCarousel *self, gdouble x, gdouble y) { graphene_point_t point = { 0 }; gboolean ensure = FALSE; point = GRAPHENE_POINT_INIT (x, y); if (self->scrolling) return; for (guint i = 0; i < self->widgets->len; i++) { CarouselWidgetData *child = NULL; gboolean contained = FALSE; child = g_ptr_array_index (self->widgets, i); contained = graphene_rect_contains_point (&child->target, &point); if (!!contained != !!child->raised) { child->raised = contained; ensure = TRUE; } } if (self->dragging) return; if (ensure) ensure_viewport (self, self->model, TRUE); } static void scroll_begin (BgeCarousel *self, GtkEventControllerScroll *controller) { self->scrolling = TRUE; self->hscroll_start = self->motion_x; self->hscroll_current = self->motion_x; } static void scroll_end (BgeCarousel *self, GtkEventControllerScroll *controller) { self->scrolling = FALSE; finish_horizontal_gesture ( self, self->hscroll_start - self->hscroll_current, 0); self->hscroll_start = -1; self->hscroll_current = -1; update_motion (self, self->motion_x, self->motion_y); } static gboolean scroll (BgeCarousel *self, gdouble dx, gdouble dy, GtkEventControllerScroll *controller) { guint n_items = 0; GdkDevice *device = NULL; GdkInputSource source = 0; if (self->model == NULL) { self->scrolling = FALSE; return FALSE; } n_items = g_list_model_get_n_items (G_LIST_MODEL (self->model)); if (n_items == 0) { self->scrolling = FALSE; return FALSE; } device = gtk_event_controller_get_current_event_device ( GTK_EVENT_CONTROLLER (controller)); source = gdk_device_get_source (device); switch (source) { case GDK_SOURCE_TOUCHPAD: case GDK_SOURCE_TRACKPOINT: { if (self->widgets->len > 0 && !self->allow_overshoot) { guint selection = 0; selection = gtk_single_selection_get_selected (self->model); if ((selection == 0 && self->hscroll_current + dx < 0) || (selection == self->widgets->len - 1 && self->hscroll_current + dx > 0)) { self->scrolling = FALSE; return FALSE; } } self->hscroll_current += dx; ensure_viewport (self, self->model, FALSE); } break; case GDK_SOURCE_MOUSE: case GDK_SOURCE_PEN: case GDK_SOURCE_KEYBOARD: case GDK_SOURCE_TOUCHSCREEN: case GDK_SOURCE_TABLET_PAD: default: { guint selected = 0; guint new_selected = 0; if (!self->allow_scroll_wheel) break; selected = gtk_single_selection_get_selected (self->model); if (dx > 0) new_selected = MIN (selected + 1, n_items - 1); else { if (selected == 0) new_selected = 0; else new_selected = selected - 1; } gtk_single_selection_set_selected (self->model, new_selected); } break; } return TRUE; } static void drag_begin (BgeCarousel *self, gdouble start_x, gdouble start_y, GtkGestureDrag *gesture) { if (!self->allow_mouse_drag) return; self->dragging = TRUE; if (self->model == NULL) return; ensure_viewport (self, self->model, TRUE); } static void drag_end (BgeCarousel *self, gdouble offset_x, gdouble offset_y, GtkGestureDrag *gesture) { if (!self->dragging) /* This situation will happen if the `allow-mouse-drag` prop is set to FALSE while a drag is taking place */ return; self->dragging = FALSE; finish_horizontal_gesture (self, self->drag_x, self->drag_y); self->drag_x = 0.0; self->drag_y = 0.0; if (offset_x < -3 || offset_x > 3 || offset_y < -3 || offset_y > 3) gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED); } static void drag_update (BgeCarousel *self, gdouble offset_x, gdouble offset_y, GtkGestureDrag *gesture) { if (!self->dragging) return; self->drag_x = offset_x; self->drag_y = offset_y; if (self->model == NULL) return; if (self->widgets->len > 0 && !self->allow_overshoot) { guint selected = 0; selected = gtk_single_selection_get_selected (self->model); if (selected == 0) self->drag_x = MIN (self->drag_x, 0.0); if (selected == self->widgets->len - 1) self->drag_x = MAX (self->drag_x, 0.0); } ensure_viewport (self, self->model, FALSE); } static void finish_horizontal_gesture (BgeCarousel *self, int offset_x, int offset_y) { guint selected = 0; double width = 0.0; guint new_selected = G_MAXUINT; int min_distance = G_MAXINT; if (self->model == NULL || self->widgets->len == 0) return; if (offset_x == 0) return; selected = gtk_single_selection_get_selected (self->model); width = gtk_widget_get_width (GTK_WIDGET (self)); for (guint i = 0; i < self->widgets->len; i++) { CarouselWidgetData *child = NULL; int left_distance = 0; int right_distance = 0; int distance_from_center = 0; child = g_ptr_array_index (self->widgets, i); if (child->rect.origin.x > width / 2.0) left_distance = child->rect.origin.x - width / 2.0; else left_distance = width / 2.0 - child->rect.origin.x; if ((child->rect.origin.x + child->rect.size.width) > width / 2.0) right_distance = (child->rect.origin.x + child->rect.size.width) - width / 2.0; else right_distance = width / 2.0 - (child->rect.origin.x + child->rect.size.width); distance_from_center = MIN (left_distance, right_distance); if (distance_from_center < min_distance) { new_selected = i; min_distance = distance_from_center; } } if (new_selected == selected) { /* Ensure dragging is not too stiff; meaning if we drag the content at least 15 pixels in either direction, it will automatically snap to the next widget */ if (offset_x > 15 && selected > 0) new_selected--; else if (offset_x < -15 && selected < self->widgets->len - 1) new_selected++; } if (new_selected == G_MAXUINT || new_selected == selected) ensure_viewport (self, self->model, TRUE); else gtk_single_selection_set_selected (self->model, new_selected); } /* End of bge-carousel.c */ bazaar-org-bazaar-43ce9f7/bge/bge-carousel.h000066400000000000000000000044511520414637400207130ustar00rootroot00000000000000/* bge-carousel.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 #ifndef BGE_INSIDE #error "Only can be included directly." #endif G_BEGIN_DECLS #define BGE_TYPE_CAROUSEL (bge_carousel_get_type ()) G_DECLARE_FINAL_TYPE (BgeCarousel, bge_carousel, BGE, CAROUSEL, GtkWidget) BGE_AVAILABLE_IN_ALL GtkWidget * bge_carousel_new (void); BGE_AVAILABLE_IN_ALL gboolean bge_carousel_get_allow_mouse_drag (BgeCarousel *self); BGE_AVAILABLE_IN_ALL gboolean bge_carousel_get_allow_overshoot (BgeCarousel *self); BGE_AVAILABLE_IN_ALL gboolean bge_carousel_get_allow_scroll_wheel (BgeCarousel *self); BGE_AVAILABLE_IN_ALL gboolean bge_carousel_get_allow_raise (BgeCarousel *self); BGE_AVAILABLE_IN_ALL GtkSingleSelection * bge_carousel_get_model (BgeCarousel *self); BGE_AVAILABLE_IN_ALL GtkWidget * bge_carousel_get_nth_page (BgeCarousel *self, guint index); BGE_AVAILABLE_IN_ALL void bge_carousel_set_allow_mouse_drag (BgeCarousel *self, gboolean allow_mouse_drag); BGE_AVAILABLE_IN_ALL void bge_carousel_set_allow_overshoot (BgeCarousel *self, gboolean allow_overshoot); BGE_AVAILABLE_IN_ALL void bge_carousel_set_allow_scroll_wheel (BgeCarousel *self, gboolean allow_scroll_wheel); BGE_AVAILABLE_IN_ALL void bge_carousel_set_allow_raise (BgeCarousel *self, gboolean allow_raise); BGE_AVAILABLE_IN_ALL void bge_carousel_set_model (BgeCarousel *self, GtkSingleSelection *model); G_END_DECLS /* End of bge-carousel.h */ bazaar-org-bazaar-43ce9f7/bge/bge-markdown-render.c000066400000000000000000000603341520414637400221720ustar00rootroot00000000000000/* bge-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 */ /** * BgeMarkdownRender: * * Renders markdown input using regular GTK widgets. * * For code blocks with a specified language, BgeMarkdownRender will attempt to * apply gtksourceview styling. */ #define G_LOG_DOMAIN "BGE::MARKDOWN-RENDER" #include #include #include "bge-marshalers.h" #include "bge.h" struct _BgeMarkdownRender { GtkWidget parent_instance; char *markdown; gboolean dark; GtkWidget *box; GPtrArray *box_children; GPtrArray *source_views; }; G_DEFINE_FINAL_TYPE (BgeMarkdownRender, bge_markdown_render, GTK_TYPE_WIDGET); enum { PROP_0, PROP_MARKDOWN, PROP_DARK, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_BIND_INLINE_URI, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void regenerate (BgeMarkdownRender *self); typedef struct { BgeMarkdownRender *self; GtkBox *box; GPtrArray *box_children; char *beginning; GString *markup; GArray *block_stack; int indent; int list_index; MD_CHAR list_prefix; GPtrArray *source_views; } 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 check_dark_mode (BgeMarkdownRender *self); static void bge_markdown_render_dispose (GObject *object) { BgeMarkdownRender *self = BGE_MARKDOWN_RENDER (object); g_clear_pointer (&self->markdown, g_free); g_clear_pointer (&self->box, gtk_widget_unparent); g_clear_pointer (&self->box_children, g_ptr_array_unref); g_clear_pointer (&self->source_views, g_ptr_array_unref); G_OBJECT_CLASS (bge_markdown_render_parent_class)->dispose (object); } static void bge_markdown_render_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BgeMarkdownRender *self = BGE_MARKDOWN_RENDER (object); switch (prop_id) { case PROP_MARKDOWN: g_value_set_string (value, bge_markdown_render_get_markdown (self)); break; case PROP_DARK: g_value_set_boolean (value, bge_markdown_render_get_dark (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bge_markdown_render_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BgeMarkdownRender *self = BGE_MARKDOWN_RENDER (object); switch (prop_id) { case PROP_MARKDOWN: bge_markdown_render_set_markdown (self, g_value_get_string (value)); break; case PROP_DARK: bge_markdown_render_set_dark (self, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static GtkSizeRequestMode bge_markdown_render_get_request_mode (GtkWidget *widget) { return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; } static void bge_markdown_render_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BgeMarkdownRender *self = BGE_MARKDOWN_RENDER (widget); gtk_widget_measure ( self->box, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline); } static void bge_markdown_render_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BgeMarkdownRender *self = BGE_MARKDOWN_RENDER (widget); if (gtk_widget_should_layout (self->box)) gtk_widget_allocate (self->box, width, height, baseline, NULL); } static void bge_markdown_render_class_init (BgeMarkdownRenderClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bge_markdown_render_set_property; object_class->get_property = bge_markdown_render_get_property; object_class->dispose = bge_markdown_render_dispose; /** * BgeMarkdownRender:markdown: * * Raw markdown text. */ props[PROP_MARKDOWN] = g_param_spec_string ( "markdown", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * BgeMarkdownRender:dark: * * Whether to apply dark styling to widgets where applicable. */ props[PROP_DARK] = g_param_spec_boolean ( "dark", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); /** * BgeMarkdownRender::bind-inline-uri: * @markdown: the object that received the signal * @title: a string title * @src: a string source uri * * Emitted when an inline image is encountered during parsing. The callback * should respond with a new widget to add to represent the uri. If no * callback is registered for this signal, or if the callback returns NULL, a * [class@Gtk.Picture] is automatically constructed and used. * * Return: a newly allocated widget to add to the markdown view */ signals[SIGNAL_BIND_INLINE_URI] = g_signal_new ( "bind-inline-uri", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, bge_marshal_OBJECT__STRING_STRING, GTK_TYPE_WIDGET, 2, G_TYPE_STRING, G_TYPE_STRING); g_signal_set_va_marshaller ( signals[SIGNAL_BIND_INLINE_URI], G_TYPE_FROM_CLASS (klass), bge_marshal_OBJECT__STRING_STRINGv); widget_class->get_request_mode = bge_markdown_render_get_request_mode; widget_class->measure = bge_markdown_render_measure; widget_class->size_allocate = bge_markdown_render_size_allocate; } static void bge_markdown_render_init (BgeMarkdownRender *self) { self->box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 7); gtk_widget_set_parent (self->box, GTK_WIDGET (self)); self->box_children = g_ptr_array_new (); self->source_views = g_ptr_array_new (); } /** * bge_markdown_render_new: * * Creates a new `BgeMarkdownRender` object. * * Returns: The newly created `BgeMarkdownRender` object. */ GtkWidget * bge_markdown_render_new (void) { return g_object_new (BGE_TYPE_MARKDOWN_RENDER, NULL); } /** * bge_markdown_render_get_markdown: * @self: a `BgeMarkdown` * * Gets [property@Bge.MarkdownRender:markdown]. * * Returns: (nullable) (transfer none): the value of the property */ const char * bge_markdown_render_get_markdown (BgeMarkdownRender *self) { g_return_val_if_fail (BGE_IS_MARKDOWN_RENDER (self), NULL); return self->markdown; } /** * bge_markdown_render_get_dark: * @self: a `BgeMarkdown` * * Gets [property@Bge.MarkdownRender:dark]. * * Returns: the value of the property */ gboolean bge_markdown_render_get_dark (BgeMarkdownRender *self) { g_return_val_if_fail (BGE_IS_MARKDOWN_RENDER (self), FALSE); return self->dark; } /** * bge_markdown_render_set_markdown: * @self: a `BgeMarkdownRender` * @markdown: a string * * Sets [property@Bge.MarkdownRender:markdown]. */ void bge_markdown_render_set_markdown (BgeMarkdownRender *self, const char *markdown) { g_return_if_fail (BGE_IS_MARKDOWN_RENDER (self)); g_clear_pointer (&self->markdown, g_free); if (markdown != NULL) self->markdown = g_strdup (markdown); regenerate (self); check_dark_mode (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MARKDOWN]); } /** * bge_markdown_render_set_dark: * @self: a `BgeMarkdownRender` * @dark: a boolean * * Sets [property@Bge.MarkdownRender:dark]. */ void bge_markdown_render_set_dark (BgeMarkdownRender *self, gboolean dark) { g_return_if_fail (BGE_IS_MARKDOWN_RENDER (self)); if (!!dark == !!self->dark) return; self->dark = dark; check_dark_mode (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DARK]); } static void regenerate (BgeMarkdownRender *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 (GTK_BOX (self->box), child); } g_ptr_array_set_size (self->box_children, 0); g_ptr_array_set_size (self->source_views, 0); if (self->markdown == NULL) return; ctx.self = self; ctx.box = GTK_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'; ctx.source_views = self->source_views; 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: 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: { MD_SPAN_IMG_DETAIL *img_detail = detail; g_autofree char *title = NULL; g_autofree char *src = NULL; GtkWidget *widget = NULL; if (img_detail->title.text != NULL) title = g_strndup (img_detail->title.text, img_detail->title.size); if (img_detail->src.text != NULL) src = g_strndup (img_detail->src.text, img_detail->src.size); g_signal_emit (ctx->self, signals[SIGNAL_BIND_INLINE_URI], 0, title, src, &widget); if (widget != NULL) { gtk_widget_set_margin_start (widget, 10 * ctx->indent); gtk_box_append (ctx->box, widget); g_ptr_array_add (ctx->box_children, widget); } } 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; int block = -1; g_assert (ctx->markup != NULL); if (ctx->block_stack->len > 0) block = g_array_index (ctx->block_stack, int, ctx->block_stack->len - 1); 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 if (block == MD_BLOCK_CODE) g_string_append_len (ctx->markup, buf, size); else { g_autofree char *escaped = NULL; 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); if (ctx->markup->len == 0) break; 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); if (ctx->markup->len == 0) break; 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, 5); 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); if (ctx->markup->len == 0) break; 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; g_assert (ctx->markup != NULL); if (ctx->markup->len == 0) break; 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: { MD_BLOCK_CODE_DETAIL *code_detail = detail; g_autofree char *lang_id = NULL; GtkSourceLanguage *language = NULL; g_autoptr (GtkSourceBuffer) buffer = NULL; GtkWidget *view = NULL; GtkWidget *window = NULL; g_assert (ctx->markup != NULL); if (ctx->markup->len == 0) break; if (code_detail->lang.text != NULL) { lang_id = g_strndup (code_detail->lang.text, code_detail->lang.size); language = gtk_source_language_manager_get_language ( gtk_source_language_manager_get_default (), lang_id); } if (language != NULL) buffer = gtk_source_buffer_new_with_language (language); else buffer = gtk_source_buffer_new (NULL); gtk_text_buffer_set_text ( GTK_TEXT_BUFFER (buffer), ctx->markup->str, ctx->markup->len); view = gtk_source_view_new_with_buffer (buffer); g_ptr_array_add (ctx->source_views, view); gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE); gtk_text_view_set_monospace (GTK_TEXT_VIEW (view), TRUE); gtk_widget_add_css_class (view, "monospace"); window = gtk_scrolled_window_new (); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (window), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (window), view); child = gtk_frame_new (lang_id); gtk_frame_set_child (GTK_FRAME (child), window); } break; case MD_BLOCK_P: { g_assert (ctx->markup != NULL); if (ctx->markup->len == 0) break; 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; } static void check_dark_mode (BgeMarkdownRender *self) { const char *id = NULL; GtkSourceStyleScheme *scheme = NULL; if (self->dark) id = "Adwaita-dark"; else id = "Adwaita"; scheme = gtk_source_style_scheme_manager_get_scheme ( gtk_source_style_scheme_manager_get_default (), id); for (guint i = 0; i < self->source_views->len; i++) { GtkSourceView *view = NULL; GtkTextBuffer *buffer = NULL; view = g_ptr_array_index (self->source_views, i); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); if (scheme != NULL) { gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (buffer), TRUE); gtk_source_buffer_set_style_scheme (GTK_SOURCE_BUFFER (buffer), scheme); } else gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (buffer), FALSE); } } /* End of bge-markdown-render.c */ bazaar-org-bazaar-43ce9f7/bge/bge-markdown-render.h000066400000000000000000000027351520414637400222000ustar00rootroot00000000000000/* bge-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 #ifndef BGE_INSIDE #error "Only can be included directly." #endif G_BEGIN_DECLS #define BGE_TYPE_MARKDOWN_RENDER (bge_markdown_render_get_type ()) G_DECLARE_FINAL_TYPE (BgeMarkdownRender, bge_markdown_render, BGE, MARKDOWN_RENDER, GtkWidget) GtkWidget * bge_markdown_render_new (void); const char * bge_markdown_render_get_markdown (BgeMarkdownRender *self); gboolean bge_markdown_render_get_dark (BgeMarkdownRender *self); void bge_markdown_render_set_markdown (BgeMarkdownRender *self, const char *markdown); void bge_markdown_render_set_dark (BgeMarkdownRender *self, gboolean dark); G_END_DECLS /* End of bge-markdown-render.h */ bazaar-org-bazaar-43ce9f7/bge/bge-marshalers.list000066400000000000000000000034211520414637400217570ustar00rootroot00000000000000# 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 OBJECT:VOID OBJECT:STRING,STRING OBJECT:OBJECT VOID:OBJECT,OBJECT # for wdgt stuff # graphene types DOUBLE:DOUBLE DOUBLE:DOUBLE,DOUBLE DOUBLE:DOUBLE,DOUBLE,DOUBLE DOUBLE:DOUBLE,DOUBLE,DOUBLE,DOUBLE DOUBLE:DOUBLE,DOUBLE,DOUBLE,DOUBLE,DOUBLE BOXED:DOUBLE,DOUBLE BOXED:DOUBLE,DOUBLE,DOUBLE BOXED:DOUBLE,DOUBLE,DOUBLE,DOUBLE BOXED:DOUBLE,ENUM,ENUM,DOUBLE INT:DOUBLE OBJECT:DOUBLE UINT:DOUBLE OBJECT:OBJECT,UINT,DOUBLE bazaar-org-bazaar-43ce9f7/bge/bge-version-macros.h000066400000000000000000000046201520414637400220430ustar00rootroot00000000000000/* bge-version-macros.h * * Copyright 2026 Eva M * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include #include "bge-version.h" #ifndef _BGE_EXTERN #define _BGE_EXTERN extern #endif #define BGE_VERSION_CUR_STABLE (G_ENCODE_VERSION (BGE_MAJOR_VERSION, 0)) #ifdef BGE_DISABLE_DEPRECATION_WARNINGS #define BGE_DEPRECATED _BGE_EXTERN #define BGE_DEPRECATED_FOR(f) _BGE_EXTERN #define BGE_UNAVAILABLE(maj, min) _BGE_EXTERN #else #define BGE_DEPRECATED G_DEPRECATED _BGE_EXTERN #define BGE_DEPRECATED_FOR(f) G_DEPRECATED_FOR (f) _BGE_EXTERN #define BGE_UNAVAILABLE(maj, min) G_UNAVAILABLE (maj, min) _BGE_EXTERN #endif #define BGE_VERSION_1_0 (G_ENCODE_VERSION (1, 0)) #if BGE_MAJOR_VERSION == BGE_VERSION_1_0 #define BGE_VERSION_PREV_STABLE (BGE_VERSION_1_0) #else #define BGE_VERSION_PREV_STABLE (G_ENCODE_VERSION (BGE_MAJOR_VERSION - 1, 0)) #endif #ifndef BGE_VERSION_MIN_REQUIRED #define BGE_VERSION_MIN_REQUIRED (BGE_VERSION_CUR_STABLE) #endif #ifndef BGE_VERSION_MAX_ALLOWED #if BGE_VERSION_MIN_REQUIRED > BGE_VERSION_PREV_STABLE #define BGE_VERSION_MAX_ALLOWED (BGE_VERSION_MIN_REQUIRED) #else #define BGE_VERSION_MAX_ALLOWED (BGE_VERSION_CUR_STABLE) #endif #endif #define BGE_AVAILABLE_IN_ALL _BGE_EXTERN #if BGE_VERSION_MIN_REQUIRED >= BGE_VERSION_1_0 #define BGE_DEPRECATED_IN_1_0 BGE_DEPRECATED #define BGE_DEPRECATED_IN_1_0_FOR(f) BGE_DEPRECATED_FOR (f) #else #define BGE_DEPRECATED_IN_1_0 _BGE_EXTERN #define BGE_DEPRECATED_IN_1_0_FOR(f) _BGE_EXTERN #endif #if BGE_VERSION_MAX_ALLOWED < BGE_VERSION_1_0 #define BGE_AVAILABLE_IN_1_0 BGE_UNAVAILABLE (1, 0) #else #define BGE_AVAILABLE_IN_1_0 _BGE_EXTERN #endif bazaar-org-bazaar-43ce9f7/bge/bge-version.h.in000066400000000000000000000047571520414637400212010ustar00rootroot00000000000000/* bge-version.h.in * * 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 #if !defined(BGE_INSIDE) && !defined(BGE_COMPILATION) # error "Only can be included directly." #endif /** * SECTION:bgeversion * @short_description: bge version checking * * bge provides macros to check the version of the library * at compile-time */ /** * BGE_MAJOR_VERSION: * * bge major version component (e.g. 1 if %BGE_VERSION is 1.2.3) */ #define BGE_MAJOR_VERSION (@MAJOR_VERSION@) /** * BGE_MINOR_VERSION: * * bge minor version component (e.g. 2 if %BGE_VERSION is 1.2.3) */ #define BGE_MINOR_VERSION (@MINOR_VERSION@) /** * BGE_MICRO_VERSION: * * bge micro version component (e.g. 3 if %BGE_VERSION is 1.2.3) */ #define BGE_MICRO_VERSION (@MICRO_VERSION@) /** * BGE_VERSION * * bge version. */ #define BGE_VERSION (@VERSION@) /** * BGE_VERSION_S: * * bge version, encoded as a string, useful for printing and * concatenation. */ #define BGE_VERSION_S "@VERSION@" #define BGE_ENCODE_VERSION(major,minor,micro) \ ((major) << 24 | (minor) << 16 | (micro) << 8) /** * BGE_VERSION_HEX: * * bge version, encoded as an hexadecimal number, useful for * integer comparisons. */ #define BGE_VERSION_HEX \ (BGE_ENCODE_VERSION (BGE_MAJOR_VERSION, BGE_MINOR_VERSION, BGE_MICRO_VERSION)) /** * BGE_CHECK_VERSION: * @major: required major version * @minor: required minor version * @micro: required micro version * * Compile-time version checking. Evaluates to %TRUE if the version * of bge is greater than the required one. */ #define BGE_CHECK_VERSION(major,minor,micro) \ (BGE_MAJOR_VERSION > (major) || \ (BGE_MAJOR_VERSION == (major) && BGE_MINOR_VERSION > (minor)) || \ (BGE_MAJOR_VERSION == (major) && BGE_MINOR_VERSION == (minor) && \ BGE_MICRO_VERSION >= (micro))) bazaar-org-bazaar-43ce9f7/bge/bge.h000066400000000000000000000021441520414637400170750ustar00rootroot00000000000000/* bge.h - Bazaar GTK Extensions * * 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 BGE_INSIDE #include "bge-version-macros.h" #include "bge-animation.h" #include "bge-carousel.h" #include "bge-markdown-render.h" #include "wdgt/bge-easing.h" #include "wdgt/bge-wdgt-renderer.h" #include "wdgt/bge-wdgt-spec.h" #undef BGE_INSIDE BGE_AVAILABLE_IN_ALL void bge_init (void); G_END_DECLS bazaar-org-bazaar-43ce9f7/bge/demo/000077500000000000000000000000001520414637400171125ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/bge/demo/demo.c000066400000000000000000000113041520414637400202010ustar00rootroot00000000000000/* demo.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 static BgeWdgtRenderer *wdgt = NULL; static GtkLabel *error_lbl = NULL; static void on_activate (GtkApplication *app); static void on_buffer_changed (GtkTextBuffer *buffer, gpointer user_data); int main (int argc, char **argv) { g_autoptr (GtkApplication) app = NULL; g_autoptr (GtkCssProvider) provider = NULL; bge_init (); app = gtk_application_new ( "io.github.kolunmi.BgeDemo", G_APPLICATION_NON_UNIQUE); g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL); provider = gtk_css_provider_new (); gtk_css_provider_load_from_resource (provider, "/io/github/kolunmi/BgeDemo/style.css"); gtk_style_context_add_provider_for_display ( gdk_display_get_default (), GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); return g_application_run (G_APPLICATION (app), argc, argv); } static void on_activate (GtkApplication *app) { GtkWidget *window = NULL; GtkWidget *root = NULL; GtkTextBuffer *buffer = NULL; BgeMarkdownRender *markdown = NULL; g_autoptr (GtkStringObject) reference = NULL; g_autoptr (GtkBuilder) builder = NULL; g_autoptr (GtkBuilderScope) scope = NULL; g_autoptr (GBytes) wdgt_bytes = NULL; gsize wdgt_buffer_size = 0; gconstpointer wdgt_buffer = NULL; g_autoptr (GBytes) markdown_bytes = NULL; gsize markdown_buffer_size = 0; gconstpointer markdown_buffer = NULL; window = gtk_application_window_new (app); gtk_window_set_default_size (GTK_WINDOW (window), 1000, 500); scope = gtk_builder_cscope_new (); builder = gtk_builder_new (); gtk_builder_set_scope (builder, scope); gtk_builder_add_from_resource (builder, "/io/github/kolunmi/BgeDemo/window.ui", NULL); root = GTK_WIDGET (gtk_builder_get_object (builder, "root")); buffer = GTK_TEXT_BUFFER (gtk_builder_get_object (builder, "buffer")); wdgt = BGE_WDGT_RENDERER (gtk_builder_get_object (builder, "wdgt")); error_lbl = GTK_LABEL (gtk_builder_get_object (builder, "error_lbl")); markdown = BGE_MARKDOWN_RENDER (gtk_builder_get_object (builder, "markdown")); reference = gtk_string_object_new ("Hello from demo.c!!"); bge_wdgt_renderer_set_reference (wdgt, G_OBJECT (reference)); g_signal_connect ( buffer, "changed", G_CALLBACK (on_buffer_changed), NULL); wdgt_bytes = g_resources_lookup_data ( "/io/github/kolunmi/BgeDemo/test.wdgt", G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); g_assert (wdgt_bytes != NULL); wdgt_buffer = g_bytes_get_data (wdgt_bytes, &wdgt_buffer_size); gtk_text_buffer_set_text (buffer, wdgt_buffer, wdgt_buffer_size); markdown_bytes = g_resources_lookup_data ( "/io/github/kolunmi/BgeDemo/example-markdown.md", G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); g_assert (markdown_bytes != NULL); markdown_buffer = g_bytes_get_data (markdown_bytes, &markdown_buffer_size); bge_markdown_render_set_markdown (markdown, markdown_buffer); gtk_window_set_child (GTK_WINDOW (window), g_object_ref_sink (root)); gtk_window_present (GTK_WINDOW (window)); } static void on_buffer_changed (GtkTextBuffer *buffer, gpointer user_data) { g_autoptr (GError) local_error = NULL; g_autofree char *text = NULL; GtkTextIter start_iter = { 0 }; GtkTextIter end_iter = { 0 }; g_autoptr (BgeWdgtSpec) spec = NULL; gtk_text_buffer_get_start_iter (buffer, &start_iter); gtk_text_buffer_get_end_iter (buffer, &end_iter); text = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE); spec = bge_wdgt_spec_new_for_string (text, &local_error); if (spec != NULL) gtk_widget_set_visible (GTK_WIDGET (error_lbl), FALSE); else { gtk_label_set_label (error_lbl, local_error->message); gtk_widget_set_visible (GTK_WIDGET (error_lbl), TRUE); } bge_wdgt_renderer_set_spec (wdgt, spec); } bazaar-org-bazaar-43ce9f7/bge/demo/demo.gresource.xml000066400000000000000000000004301520414637400225520ustar00rootroot00000000000000 window.ui style.css test.wdgt ../../docs/overview.md bazaar-org-bazaar-43ce9f7/bge/demo/meson.build000066400000000000000000000010431520414637400212520ustar00rootroot00000000000000demo_sources = files( 'demo.c', ) blueprints = custom_target( 'blueprints', input: files( 'window.blp', ), output: '.', command: [ find_program('blueprint-compiler', version: '>= 0.20.0'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@' ], ) demo_sources += gnome.compile_resources('demo-resources', 'demo.gresource.xml', c_name: 'demo', dependencies: blueprints ) demo_deps = [ bge_dep, ] demo = executable( 'bge-demo', demo_sources, dependencies: demo_deps, install: true, ) bazaar-org-bazaar-43ce9f7/bge/demo/style.css000066400000000000000000000003421520414637400207630ustar00rootroot00000000000000.source-edit { font-family: monospace; font-size: large; } .debug { background-color: alpha(pink, 0.25); } .gradient { background-image: linear-gradient(to bottom left, #1f2d8f, #159eff); color: white; } bazaar-org-bazaar-43ce9f7/bge/demo/test.wdgt000066400000000000000000000057001520414637400207620ustar00rootroot00000000000000defwidget "My Widget" { reference ref-string : "GtkStringObject"; var box : "GtkBox"; var cx : "gdouble"; var cy : "gdouble"; var w : "gdouble"; var h : "gdouble"; var corner : "gdouble"; var x : "gdouble"; var y : "gdouble"; var start : "gdouble"; var end : "gdouble"; var outline : "GskPath"; var measure : "GskPathMeasure"; init { set box = #child/(""("gradient") orientation = vertical; _=#child/GtkLabel(""() margin-start = 10; margin-end = 10; margin-top = 10; margin-bottom = 10; label = ref-string:string; wrap = true; ); ); measure 200, 300, 200, 300; set x = #eval(#(cx)-#(w)/2.0); set y = #eval(#(cy)-#(h)/2.0); allocate box w, h, #(translate(#GraphenePoint(x, y));); set outline = #GskPath( move-to(#eval(#(x)+#(corner)), y); rel-line-to(#eval(#(w)-#(corner)*2.0), 0.0); rel-arc-to(corner, 0.0, corner, corner); rel-line-to(0.0, #eval(#(h)-#(corner)*2.0)); rel-arc-to(0.0, corner, #eval(-#(corner)), corner); rel-line-to(#eval(-(#(w)-#(corner)*2.0)), 0.0); rel-arc-to(#eval(-#(corner)), 0.0, #eval(-#(corner)), #eval(-#(corner))); rel-line-to(0.0, #eval(-(#(h)-#(corner)*2.0))); rel-arc-to(0.0, #eval(-#(corner)), corner, #eval(-#(corner))); close(); ); set measure = #measure-path(outline); snapshot { with fill( outline, #GskFillRule(winding), ) { do-child box; } add stroke( #GskPath( add-segment( outline, #path-point(measure, start), #path-point(measure, end), ); ), #GskStroke(6.0, round, round, 0.0), #GdkRGBA("#101432"), ); } } state-default "1" { set w = 100.0; set h = 100.0; set corner = 10.0; set cx = #eval(30.0*sin(#(%tick%)) + #(%width%)/2.0); set cy = #eval(#(%height%)/2.0); set start = #eval(#(#path-length(measure))*(0.333*sin(#(%tick%))+0.333)); set end = #eval(#(#path-length(measure))*(0.333*sin(#(%tick%))+0.666)); transition-spring w 1.0, 0.5, 100.0; transition-spring h 1.0, 0.5, 100.0; transition-spring corner 1.0, 0.5, 100.0; transition-spring cx 1.0, 0.5, 100.0; transition-spring cy 1.0, 0.5, 100.0; transition-spring start 0.5, 0.5, 5.0; transition-spring end 0.5, 0.5, 5.0; } state "2" { set w = 200.0; set h = 200.0; set corner = 20.0; set cx = #eval(#(%width%)/2.0); set cy = #eval(#(%height%)/2.0); set start = 0.0; set end = #path-length(measure); transition-spring w 0.9, 0.5, 100.0; transition-spring h 0.9, 0.5, 100.0; transition-spring corner 0.9, 0.5, 100.0; transition-spring cx 0.9, 0.5, 100.0; transition-spring cy 0.9, 0.5, 100.0; transition-spring start 1.1, 0.2, 10.0; transition-spring end 1.1, 0.2, 10.0; } } bazaar-org-bazaar-43ce9f7/bge/demo/window.blp000066400000000000000000000017571520414637400211320ustar00rootroot00000000000000using Gtk 4.0; Box root { Paned { orientation: horizontal; position: 400; wide-handle: true; start-child: ScrolledWindow { child: $BgeMarkdownRender markdown { margin-start: 10; margin-end: 10; }; }; end-child: Paned { orientation: horizontal; position: 400; start-child: ScrolledWindow { child: TextView { styles ["source-edit"] monospace: true; buffer: TextBuffer buffer { }; }; }; end-child: Box { orientation: vertical; Label error_lbl { styles ["error"] visible: false; wrap: true; } $BgeWdgtRenderer wdgt { styles ["debug"] halign: center; valign: center; hexpand: true; vexpand: true; state: bind state_entry.text; } Entry state_entry { text: "1"; } }; shrink-end-child: false; }; } } bazaar-org-bazaar-43ce9f7/bge/libbge.c000066400000000000000000000021431520414637400175560ustar00rootroot00000000000000/* libbge.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 "BGE::CORE" #include "bge.h" /** * bge_init: * * Initializes BGE (And GTK). * * This function must be called before using any other BGE functions. */ void bge_init (void) { gtk_init (); g_type_ensure (BGE_TYPE_ANIMATION); g_type_ensure (BGE_TYPE_CAROUSEL); g_type_ensure (BGE_TYPE_MARKDOWN_RENDER); g_type_ensure (BGE_TYPE_WDGT_RENDERER); } bazaar-org-bazaar-43ce9f7/bge/meson.build000066400000000000000000000032541520414637400203340ustar00rootroot00000000000000api_version = bz_version bge_sources = [ 'libbge.c', 'bge-animation.c', 'bge-carousel.c', 'bge-markdown-render.c', ] bge_headers = [ 'bge.h', 'bge-animation.h', 'bge-carousel.h', ] subdir('wdgt') version_split = api_version.split('.') version_conf = configuration_data() version_conf.set('VERSION', api_version) version_conf.set('MAJOR_VERSION', version_split[0]) version_conf.set('MINOR_VERSION', version_split[1]) version_conf.set('MICRO_VERSION', version_split[2]) configure_file( input: 'bge-version.h.in', output: 'bge-version.h', configuration: version_conf, install: true, install_dir: get_option('includedir') / 'bge' ) bge_deps = [ cc.find_library('m', required: true), dependency('gtk4', version: '>= 4.22.1'), dependency('gtksourceview-5', version: '>= 5.17'), dependency('md4c', version: '>= 0.5.1'), ] bge_marshalers = gnome.genmarshal('bge-marshalers', sources: 'bge-marshalers.list', prefix: 'bge_marshal', valist_marshallers: true, ) bge_lib = shared_library( 'bge-' + api_version, bge_sources, bge_marshalers, dependencies: bge_deps, install: true, ) install_headers( bge_headers + files('bge-version-macros.h'), subdir: 'bge') pkg = import('pkgconfig') pkg.generate( description: 'Bazaar GTK Extensions', libraries: bge_lib, name: 'libbge', filebase: 'bge-' + api_version, version: api_version, subdirs: 'bge', requires: ['gtk4', 'md4c', 'gtksourceview-5'], install_dir: get_option('libdir') / 'pkgconfig' ) bge_dep = declare_dependency( link_with: bge_lib, dependencies: [bge_deps], include_directories : include_directories('..', '.'), ) subdir('demo') bazaar-org-bazaar-43ce9f7/bge/util.h000066400000000000000000000076521520414637400173260ustar00rootroot00000000000000/* util.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 #define BGE_RELEASE_DATA(name, unref) \ if ((unref) != NULL) \ { \ g_clear_pointer (&self->name, (unref)); \ } #define BGE_RELEASE_UTAG(name, remove) \ if ((remove) != NULL) \ { \ g_clear_handle_id (&self->name, (remove)); \ } /* va args = releases */ #define BGE_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_unref (gpointer ptr); \ 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); bazaar-org-bazaar-43ce9f7/bge/wdgt/000077500000000000000000000000001520414637400171335ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/bge/wdgt/bge-easing.c000066400000000000000000000400231520414637400212770ustar00rootroot00000000000000/* TAKEN FROM LIBADWAITA */ /* * Copyright (C) 2021 Manuel GenovĂŠs * Copyright (C) 2021 Purism SPC * * SPDX-License-Identifier: LGPL-2.1-or-later */ #define G_LOG_DOMAIN "BGE::EASING" #include "bge.h" G_DEFINE_ENUM_TYPE ( BgeEasing, bge_easing, G_DEFINE_ENUM_VALUE (BGE_LINEAR, "linear"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_QUAD, "in-quad"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT_QUAD, "out-quad"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT_QUAD, "in-out-quad"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_CUBIC, "in-cubic"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT_CUBIC, "out-cubic"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT_CUBIC, "in-out-cubic"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_QUART, "in-quart"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT_QUART, "out-quart"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT_QUART, "in-out-quart"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_QUINT, "in-quint"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT_QUINT, "out-quint"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT_QUINT, "in-out-quint"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_SINE, "in-sine"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT_SINE, "out-sine"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT_SINE, "in-out-sine"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_EXPO, "in-expo"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT_EXPO, "out-expo"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT_EXPO, "in-out-expo"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_CIRC, "in-circ"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT_CIRC, "out-circ"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT_CIRC, "in-out-circ"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_ELASTIC, "in-elastic"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT_ELASTIC, "out-elastic"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT_ELASTIC, "in-out-elastic"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_BACK, "in-back"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT_BACK, "out-back"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT_BACK, "in-out-back"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_BOUNCE, "in-bounce"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT_BOUNCE, "out-bounce"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT_BOUNCE, "in-out-bounce"), G_DEFINE_ENUM_VALUE (BGE_EASE, "ease"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN, "ease-in"), G_DEFINE_ENUM_VALUE (BGE_EASE_OUT, "ease-out"), G_DEFINE_ENUM_VALUE (BGE_EASE_IN_OUT, "ease-in-out")); #include /* * Copied from: * https://gitlab.gnome.org/GNOME/clutter/-/blob/a236494ea7f31848b4a459dad41330f225137832/clutter/clutter-easing.c * https://gitlab.gnome.org/GNOME/clutter/-/blob/a236494ea7f31848b4a459dad41330f225137832/clutter/clutter-enums.h * * Copyright (C) 2011 Intel Corporation */ /** * BgeEasing: * @BGE_LINEAR: Linear tweening. * @BGE_EASE_IN_QUAD: Quadratic tweening. * @BGE_EASE_OUT_QUAD: Quadratic tweening, inverse of * [enum@Bge.Easing.ease-in-quad]. * @BGE_EASE_IN_OUT_QUAD: Quadratic tweening, combining * [enum@Bge.Easing.ease-in-quad] and [enum@Bge.Easing.ease-out-quad]. * @BGE_EASE_IN_CUBIC: Cubic tweening. * @BGE_EASE_OUT_CUBIC: Cubic tweening, inverse of * [enum@Bge.Easing.ease-in-cubic]. * @BGE_EASE_IN_OUT_CUBIC: Cubic tweening, combining * [enum@Bge.Easing.ease-in-cubic] and [enum@Bge.Easing.ease-out-cubic]. * @BGE_EASE_IN_QUART: Quartic tweening. * @BGE_EASE_OUT_QUART: Quartic tweening, inverse of * [enum@Bge.Easing.ease-in-quart]. * @BGE_EASE_IN_OUT_QUART: Quartic tweening, combining * [enum@Bge.Easing.ease-in-quart] and [enum@Bge.Easing.ease-out-quart]. * @BGE_EASE_IN_QUINT: Quintic tweening. * @BGE_EASE_OUT_QUINT: Quintic tweening, inverse of * [enum@Bge.Easing.ease-in-quint]. * @BGE_EASE_IN_OUT_QUINT: Quintic tweening, combining * [enum@Bge.Easing.ease-in-quint] and [enum@Bge.Easing.ease-out-quint]. * @BGE_EASE_IN_SINE: Sine wave tweening. * @BGE_EASE_OUT_SINE: Sine wave tweening, inverse of * [enum@Bge.Easing.ease-in-sine]. * @BGE_EASE_IN_OUT_SINE: Sine wave tweening, combining * [enum@Bge.Easing.ease-in-sine] and [enum@Bge.Easing.ease-out-sine]. * @BGE_EASE_IN_EXPO: Exponential tweening. * @BGE_EASE_OUT_EXPO: Exponential tweening, inverse of * [enum@Bge.Easing.ease-in-expo]. * @BGE_EASE_IN_OUT_EXPO: Exponential tweening, combining * [enum@Bge.Easing.ease-in-expo] and [enum@Bge.Easing.ease-out-expo]. * @BGE_EASE_IN_CIRC: Circular tweening. * @BGE_EASE_OUT_CIRC: Circular tweening, inverse of * [enum@Bge.Easing.ease-in-circ]. * @BGE_EASE_IN_OUT_CIRC: Circular tweening, combining * [enum@Bge.Easing.ease-in-circ] and [enum@Bge.Easing.ease-out-circ]. * @BGE_EASE_IN_ELASTIC: Elastic tweening, with offshoot on start. * @BGE_EASE_OUT_ELASTIC: Elastic tweening, with offshoot on end, inverse of * [enum@Bge.Easing.ease-in-elastic]. * @BGE_EASE_IN_OUT_ELASTIC: Elastic tweening, with offshoot on both ends, * combining [enum@Bge.Easing.ease-in-elastic] and * [enum@Bge.Easing.ease-out-elastic]. * @BGE_EASE_IN_BACK: Overshooting cubic tweening, with backtracking on start. * @BGE_EASE_OUT_BACK: Overshooting cubic tweening, with backtracking on end, * inverse of [enum@Bge.Easing.ease-in-back]. * @BGE_EASE_IN_OUT_BACK: Overshooting cubic tweening, with backtracking on both * ends, combining [enum@Bge.Easing.ease-in-back] and * [enum@Bge.Easing.ease-out-back]. * @BGE_EASE_IN_BOUNCE: Exponentially decaying parabolic (bounce) tweening, * on start. * @BGE_EASE_OUT_BOUNCE: Exponentially decaying parabolic (bounce) tweening, * with bounce on end, inverse of [enum@Bge.Easing.ease-in-bounce]. * @BGE_EASE_IN_OUT_BOUNCE: Exponentially decaying parabolic (bounce) tweening, * with bounce on both ends, combining [enum@Bge.Easing.ease-in-bounce] and * [enum@Bge.Easing.ease-out-bounce]. * * Describes the available easing functions for use with * [class@TimedAnimation]. * * New values may be added to this enumeration over time. */ /** * BGE_EASE: * * Cubic bezier tweening, with control points in (0.25, 0.1) and (0.25, 1.0). * * Increases in velocity towards the middle of the animation, slowing back down * at the end. * * Since: 1.7 */ /** * BGE_EASE_IN: * * Cubic bezier tweening, with control points in (0.42, 0.0) and (1.0, 1.0). * * Starts off slowly, with the speed of the animation increasing until complete. * * Since: 1.7 */ /** * BGE_EASE_OUT: * * Cubic bezier tweening, with control points in (0.0, 0.0) and (0.58, 1.0). * * Starts quickly, slowing down the animation until complete. * * Since: 1.7 */ /** * BGE_EASE_IN_OUT: * * Cubic bezier tweening, with control points in (0.42, 0.0) and (0.58, 1.0). * * Starts off slowly, speeds up in the middle, and then slows down again. * * Since: 1.7 */ static inline double linear (double t, double d) { return t / d; } static inline double ease_in_quad (double t, double d) { double p = t / d; return p * p; } static inline double ease_out_quad (double t, double d) { double p = t / d; return -1.0 * p * (p - 2); } static inline double ease_in_out_quad (double t, double d) { double p = t / (d / 2); if (p < 1) return 0.5 * p * p; p -= 1; return -0.5 * (p * (p - 2) - 1); } static inline double ease_in_cubic (double t, double d) { double p = t / d; return p * p * p; } static inline double ease_out_cubic (double t, double d) { double p = t / d - 1; return p * p * p + 1; } static inline double ease_in_out_cubic (double t, double d) { double p = t / (d / 2); if (p < 1) return 0.5 * p * p * p; p -= 2; return 0.5 * (p * p * p + 2); } static inline double ease_in_quart (double t, double d) { double p = t / d; return p * p * p * p; } static inline double ease_out_quart (double t, double d) { double p = t / d - 1; return -1.0 * (p * p * p * p - 1); } static inline double ease_in_out_quart (double t, double d) { double p = t / (d / 2); if (p < 1) return 0.5 * p * p * p * p; p -= 2; return -0.5 * (p * p * p * p - 2); } static inline double ease_in_quint (double t, double d) { double p = t / d; return p * p * p * p * p; } static inline double ease_out_quint (double t, double d) { double p = t / d - 1; return p * p * p * p * p + 1; } static inline double ease_in_out_quint (double t, double d) { double p = t / (d / 2); if (p < 1) return 0.5 * p * p * p * p * p; p -= 2; return 0.5 * (p * p * p * p * p + 2); } static inline double ease_in_sine (double t, double d) { return -1.0 * cos (t / d * G_PI_2) + 1.0; } static inline double ease_out_sine (double t, double d) { return sin (t / d * G_PI_2); } static inline double ease_in_out_sine (double t, double d) { return -0.5 * (cos (G_PI * t / d) - 1); } static inline double ease_in_expo (double t, double d) { return G_APPROX_VALUE (t, 0, DBL_EPSILON) ? 0.0 : pow (2, 10 * (t / d - 1)); } static double ease_out_expo (double t, double d) { return G_APPROX_VALUE (t, d, DBL_EPSILON) ? 1.0 : -pow (2, -10 * t / d) + 1; } static inline double ease_in_out_expo (double t, double d) { double p; if (G_APPROX_VALUE (t, 0, DBL_EPSILON)) return 0.0; if (G_APPROX_VALUE (t, d, DBL_EPSILON)) return 1.0; p = t / (d / 2); if (p < 1) return 0.5 * pow (2, 10 * (p - 1)); p -= 1; return 0.5 * (-pow (2, -10 * p) + 2); } static inline double ease_in_circ (double t, double d) { double p = t / d; return -1.0 * (sqrt (1 - p * p) - 1); } static inline double ease_out_circ (double t, double d) { double p = t / d - 1; return sqrt (1 - p * p); } static inline double ease_in_out_circ (double t, double d) { double p = t / (d / 2); if (p < 1) return -0.5 * (sqrt (1 - p * p) - 1); p -= 2; return 0.5 * (sqrt (1 - p * p) + 1); } static inline double ease_in_elastic (double t, double d) { double p = d * .3; double s = p / 4; double q = t / d; if (G_APPROX_VALUE (q, 1, DBL_EPSILON)) return 1.0; q -= 1; return -(pow (2, 10 * q) * sin ((q * d - s) * (2 * G_PI) / p)); } static inline double ease_out_elastic (double t, double d) { double p = d * .3; double s = p / 4; double q = t / d; if (G_APPROX_VALUE (q, 1, DBL_EPSILON)) return 1.0; return pow (2, -10 * q) * sin ((q * d - s) * (2 * G_PI) / p) + 1.0; } static inline double ease_in_out_elastic (double t, double d) { double p = d * (.3 * 1.5); double s = p / 4; double q = t / (d / 2); if (G_APPROX_VALUE (q, 2, DBL_EPSILON)) return 1.0; if (q < 1) { q -= 1; return -.5 * (pow (2, 10 * q) * sin ((q * d - s) * (2 * G_PI) / p)); } else { q -= 1; return pow (2, -10 * q) * sin ((q * d - s) * (2 * G_PI) / p) * .5 + 1.0; } } static inline double ease_in_back (double t, double d) { double p = t / d; return p * p * ((1.70158 + 1) * p - 1.70158); } static inline double ease_out_back (double t, double d) { double p = t / d - 1; return p * p * ((1.70158 + 1) * p + 1.70158) + 1; } static inline double ease_in_out_back (double t, double d) { double p = t / (d / 2); double s = 1.70158 * 1.525; if (p < 1) return 0.5 * (p * p * ((s + 1) * p - s)); p -= 2; return 0.5 * (p * p * ((s + 1) * p + s) + 2); } static inline double ease_out_bounce (double t, double d) { double p = t / d; if (p < (1 / 2.75)) { return 7.5625 * p * p; } else if (p < (2 / 2.75)) { p -= (1.5 / 2.75); return 7.5625 * p * p + .75; } else if (p < (2.5 / 2.75)) { p -= (2.25 / 2.75); return 7.5625 * p * p + .9375; } else { p -= (2.625 / 2.75); return 7.5625 * p * p + .984375; } } static inline double ease_in_bounce (double t, double d) { return 1.0 - ease_out_bounce (d - t, d); } static inline double ease_in_out_bounce (double t, double d) { if (t < d / 2) return ease_in_bounce (t * 2, d) * 0.5; else return ease_out_bounce (t * 2 - d, d) * 0.5 + 1.0 * 0.5; } static inline double x_for_t (double t, double x_1, double x_2) { double omt = 1.0 - t; return 3.0 * omt * omt * t * x_1 + 3.0 * omt * t * t * x_2 + t * t * t; } static inline double y_for_t (double t, double y_1, double y_2) { double omt = 1.0 - t; return 3.0 * omt * omt * t * y_1 + 3.0 * omt * t * t * y_2 + t * t * t; } static inline double t_for_x (double x, double x_1, double x_2) { double min_t = 0, max_t = 1; int i; for (i = 0; i < 30; ++i) { double guess_t = (min_t + max_t) / 2.0; double guess_x = x_for_t (guess_t, x_1, x_2); if (x < guess_x) max_t = guess_t; else min_t = guess_t; } return (min_t + max_t) / 2.0; } static double ease_cubic_bezier (double t, double d, double x_1, double y_1, double x_2, double y_2) { double p = t / d; if (G_APPROX_VALUE (p, 0.0, DBL_EPSILON)) return 0.0; if (G_APPROX_VALUE (p, 1.0, DBL_EPSILON)) return 1.0; return y_for_t (t_for_x (p, x_1, x_2), y_1, y_2); } /** * bge_easing_ease: * @self: an easing value * @value: a value to ease * * Computes easing with @easing for @value. * * @value should generally be in the [0, 1] range. * * Returns: the easing for @value */ double bge_easing_ease (BgeEasing self, double value) { switch (self) { case BGE_LINEAR: return linear (value, 1); case BGE_EASE_IN_QUAD: return ease_in_quad (value, 1); case BGE_EASE_OUT_QUAD: return ease_out_quad (value, 1); case BGE_EASE_IN_OUT_QUAD: return ease_in_out_quad (value, 1); case BGE_EASE_IN_CUBIC: return ease_in_cubic (value, 1); case BGE_EASE_OUT_CUBIC: return ease_out_cubic (value, 1); case BGE_EASE_IN_OUT_CUBIC: return ease_in_out_cubic (value, 1); case BGE_EASE_IN_QUART: return ease_in_quart (value, 1); case BGE_EASE_OUT_QUART: return ease_out_quart (value, 1); case BGE_EASE_IN_OUT_QUART: return ease_in_out_quart (value, 1); case BGE_EASE_IN_QUINT: return ease_in_quint (value, 1); case BGE_EASE_OUT_QUINT: return ease_out_quint (value, 1); case BGE_EASE_IN_OUT_QUINT: return ease_in_out_quint (value, 1); case BGE_EASE_IN_SINE: return ease_in_sine (value, 1); case BGE_EASE_OUT_SINE: return ease_out_sine (value, 1); case BGE_EASE_IN_OUT_SINE: return ease_in_out_sine (value, 1); case BGE_EASE_IN_EXPO: return ease_in_expo (value, 1); case BGE_EASE_OUT_EXPO: return ease_out_expo (value, 1); case BGE_EASE_IN_OUT_EXPO: return ease_in_out_expo (value, 1); case BGE_EASE_IN_CIRC: return ease_in_circ (value, 1); case BGE_EASE_OUT_CIRC: return ease_out_circ (value, 1); case BGE_EASE_IN_OUT_CIRC: return ease_in_out_circ (value, 1); case BGE_EASE_IN_ELASTIC: return ease_in_elastic (value, 1); case BGE_EASE_OUT_ELASTIC: return ease_out_elastic (value, 1); case BGE_EASE_IN_OUT_ELASTIC: return ease_in_out_elastic (value, 1); case BGE_EASE_IN_BACK: return ease_in_back (value, 1); case BGE_EASE_OUT_BACK: return ease_out_back (value, 1); case BGE_EASE_IN_OUT_BACK: return ease_in_out_back (value, 1); case BGE_EASE_IN_BOUNCE: return ease_in_bounce (value, 1); case BGE_EASE_OUT_BOUNCE: return ease_out_bounce (value, 1); case BGE_EASE_IN_OUT_BOUNCE: return ease_in_out_bounce (value, 1); case BGE_EASE: return ease_cubic_bezier (value, 1, 0.25, 0.1, 0.25, 1.0); case BGE_EASE_IN: return ease_cubic_bezier (value, 1, 0.42, 0.0, 1.0, 1.0); case BGE_EASE_OUT: return ease_cubic_bezier (value, 1, 0.0, 0.0, 0.58, 1.0); case BGE_EASE_IN_OUT: return ease_cubic_bezier (value, 1, 0.42, 0.0, 0.58, 1.0); default: g_assert_not_reached (); } } bazaar-org-bazaar-43ce9f7/bge/wdgt/bge-easing.h000066400000000000000000000023611520414637400213070ustar00rootroot00000000000000/* TAKEN FROM LIBADWAITA */ /* * Copyright (C) 2021 Manuel GenovĂŠs * Copyright (C) 2021 Purism SPC * * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #ifndef BGE_INSIDE #error "Only can be included directly." #endif G_BEGIN_DECLS typedef enum { BGE_LINEAR, BGE_EASE_IN_QUAD, BGE_EASE_OUT_QUAD, BGE_EASE_IN_OUT_QUAD, BGE_EASE_IN_CUBIC, BGE_EASE_OUT_CUBIC, BGE_EASE_IN_OUT_CUBIC, BGE_EASE_IN_QUART, BGE_EASE_OUT_QUART, BGE_EASE_IN_OUT_QUART, BGE_EASE_IN_QUINT, BGE_EASE_OUT_QUINT, BGE_EASE_IN_OUT_QUINT, BGE_EASE_IN_SINE, BGE_EASE_OUT_SINE, BGE_EASE_IN_OUT_SINE, BGE_EASE_IN_EXPO, BGE_EASE_OUT_EXPO, BGE_EASE_IN_OUT_EXPO, BGE_EASE_IN_CIRC, BGE_EASE_OUT_CIRC, BGE_EASE_IN_OUT_CIRC, BGE_EASE_IN_ELASTIC, BGE_EASE_OUT_ELASTIC, BGE_EASE_IN_OUT_ELASTIC, BGE_EASE_IN_BACK, BGE_EASE_OUT_BACK, BGE_EASE_IN_OUT_BACK, BGE_EASE_IN_BOUNCE, BGE_EASE_OUT_BOUNCE, BGE_EASE_IN_OUT_BOUNCE, BGE_EASE, BGE_EASE_IN, BGE_EASE_OUT, BGE_EASE_IN_OUT } BgeEasing; GType bge_easing_get_type (void); #define BGE_TYPE_EASING (bge_easing_get_type ()) BGE_AVAILABLE_IN_ALL double bge_easing_ease (BgeEasing self, double value); G_END_DECLS bazaar-org-bazaar-43ce9f7/bge/wdgt/bge-wdgt-renderer.h000066400000000000000000000046411520414637400226150ustar00rootroot00000000000000/* bge-wdgt-renderer.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 #ifndef BGE_INSIDE #error "Only can be included directly." #endif #include "bge-wdgt-spec.h" G_BEGIN_DECLS #define BGE_TYPE_WDGT_RENDERER (bge_wdgt_renderer_get_type ()) G_DECLARE_FINAL_TYPE (BgeWdgtRenderer, bge_wdgt_renderer, BGE, WDGT_RENDERER, GtkWidget) BGE_AVAILABLE_IN_ALL BgeWdgtRenderer * bge_wdgt_renderer_new (void); BGE_AVAILABLE_IN_ALL BgeWdgtSpec * bge_wdgt_renderer_get_spec (BgeWdgtRenderer *self); BGE_AVAILABLE_IN_ALL const char * bge_wdgt_renderer_get_state (BgeWdgtRenderer *self); BGE_AVAILABLE_IN_ALL GObject * bge_wdgt_renderer_get_reference (BgeWdgtRenderer *self); BGE_AVAILABLE_IN_ALL GtkWidget * bge_wdgt_renderer_get_child (BgeWdgtRenderer *self); BGE_AVAILABLE_IN_ALL void bge_wdgt_renderer_set_spec (BgeWdgtRenderer *self, BgeWdgtSpec *spec); BGE_AVAILABLE_IN_ALL void bge_wdgt_renderer_set_state (BgeWdgtRenderer *self, const char *state); BGE_AVAILABLE_IN_ALL void bge_wdgt_renderer_set_reference (BgeWdgtRenderer *self, GObject *reference); BGE_AVAILABLE_IN_ALL void bge_wdgt_renderer_set_child (BgeWdgtRenderer *self, GtkWidget *child); BGE_AVAILABLE_IN_ALL void bge_wdgt_renderer_set_state_take (BgeWdgtRenderer *self, char *state); #define bge_wdgt_renderer_set_state_take_printf(self, ...) bge_wdgt_renderer_set_state_take (self, g_strdup_printf (__VA_ARGS__)) BGE_AVAILABLE_IN_ALL gpointer bge_wdgt_renderer_lookup_object (BgeWdgtRenderer *self, const char *name); G_END_DECLS /* End of bge-wdgt-renderer.h */ bazaar-org-bazaar-43ce9f7/bge/wdgt/bge-wdgt-spec-private.h000066400000000000000000000232541520414637400234120ustar00rootroot00000000000000/* bge-wdgt-spec-private.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 "bge.h" G_BEGIN_DECLS typedef enum { BGE_WDGT_SNAPSHOT_INSTR_APPEND = 0, BGE_WDGT_SNAPSHOT_INSTR_PUSH, BGE_WDGT_SNAPSHOT_INSTR_POP, BGE_WDGT_SNAPSHOT_INSTR_SAVE, BGE_WDGT_SNAPSHOT_INSTR_TRANSFORM, BGE_WDGT_SNAPSHOT_INSTR_RESTORE, BGE_WDGT_SNAPSHOT_INSTR_SNAPSHOT_CHILD, } BgeWdgtSnapshotInstrKind; typedef enum { BGE_WDGT_MEASURE_MINIMUM_WIDTH, BGE_WDGT_MEASURE_NATURAL_WIDTH, BGE_WDGT_MEASURE_MINIMUM_HEIGHT, BGE_WDGT_MEASURE_NATURAL_HEIGHT, } BgeWdgtMeasureKind; gboolean bge_wdgt_spec_add_constant_source_value (BgeWdgtSpec *self, const char *name, const GValue *constant, GError **error); gboolean bge_wdgt_spec_add_component_source_value (BgeWdgtSpec *self, const char *name, GType type, const char *const *components, guint n_components, GError **error); gboolean bge_wdgt_spec_add_transform_source_value (BgeWdgtSpec *self, const char *name, const char *next, const char *instruction, const char *const *args, guint n_args, GError **error); gboolean bge_wdgt_spec_add_path_source_value (BgeWdgtSpec *self, const char *name, const char *const *instructions, const char *const *const *argss, const guint *n_argss, guint n_args, GError **error); gboolean bge_wdgt_spec_add_instance_source_value (BgeWdgtSpec *self, const char *name, GType type, GError **error); gboolean bge_wdgt_spec_add_child_source_value (BgeWdgtSpec *self, const char *name, GType type, const char *parent_widget, const char *builder_type, const char *const *css_classes, guint n_css_classes, GError **error); gboolean bge_wdgt_spec_add_cclosure_source_value (BgeWdgtSpec *self, const char *name, GType type, GClosureMarshal marshal, GCallback func, const char *const *args, const GType *arg_types, guint n_args, gpointer user_data, GDestroyNotify destroy_user_data, GError **error); gboolean bge_wdgt_spec_add_measure_for_size_source_value (BgeWdgtSpec *self, const char *name, GError **error); gboolean bge_wdgt_spec_add_widget_width_source_value (BgeWdgtSpec *self, const char *name, GError **error); gboolean bge_wdgt_spec_add_widget_height_source_value (BgeWdgtSpec *self, const char *name, GError **error); gboolean bge_wdgt_spec_add_tick_time_source_value (BgeWdgtSpec *self, const char *name, GError **error); gboolean bge_wdgt_spec_add_track_transition_source_value (BgeWdgtSpec *self, const char *name, const char *src, const char *damping_ratio, const char *mass, const char *stiffness, GError **error); gboolean bge_wdgt_spec_add_variable_value (BgeWdgtSpec *self, GType type, const char *name, GError **error); gboolean bge_wdgt_spec_add_reference_object_value (BgeWdgtSpec *self, GType type, const char *name, GError **error); gboolean bge_wdgt_spec_add_property_value (BgeWdgtSpec *self, const char *name, const char *object, const char *property, GType *type_out, GError **error); gboolean bge_wdgt_spec_add_allocation_width_value (BgeWdgtSpec *self, const char *name, const char *child, GError **error); gboolean bge_wdgt_spec_add_allocation_height_value (BgeWdgtSpec *self, const char *name, const char *child, GError **error); gboolean bge_wdgt_spec_add_allocation_transform_value (BgeWdgtSpec *self, const char *name, const char *child, GError **error); gboolean bge_wdgt_spec_add_measure_value (BgeWdgtSpec *self, const char *name, BgeWdgtMeasureKind kind, GError **error); gboolean bge_wdgt_spec_add_state (BgeWdgtSpec *self, const char *name, gboolean default_state, GError **error); gboolean bge_wdgt_spec_set_value (BgeWdgtSpec *self, const char *state, const char *dest_value, const char *src_value, GError **error); gboolean bge_wdgt_spec_transition_value (BgeWdgtSpec *self, const char *state, const char *value, const char *seconds, const char *easing, GError **error); gboolean bge_wdgt_spec_transition_value_spring (BgeWdgtSpec *self, const char *state, const char *value, const char *damping_ratio, const char *mass, const char *stiffness, GError **error); gboolean bge_wdgt_spec_append_snapshot_instr (BgeWdgtSpec *self, const char *state, BgeWdgtSnapshotInstrKind kind, const char *instr, const char *const *args, guint n_args, guint *n_pops_out, GError **error); gboolean bge_wdgt_spec_push_foreach (BgeWdgtSpec *self, const char *model, const char *value_iterator, const char *index_iterator, GType iterator_type, GError **error); gboolean bge_wdgt_spec_pop_foreach (BgeWdgtSpec *self); G_END_DECLS /* End of bge-wdgt-spec-private.h */ bazaar-org-bazaar-43ce9f7/bge/wdgt/bge-wdgt-spec.c000066400000000000000000006334731520414637400217470ustar00rootroot00000000000000/* bge-wdgt-spec.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 "BGE::WDGT" #include "../bge-animation-private.h" #include "bge-marshalers.h" #include "bge-wdgt-spec-private.h" #include "bge.h" #include "fmt/parser.h" #include "graphene-gobject.h" #include "lookup/lookup.h" #include "util.h" static void _marshal_DIRECT__ARGS_DIRECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data); static void _marshal_BOXED__ARGS_DIRECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data); typedef enum { VALUE_ALLOCATION_HEIGHT = 0, VALUE_ALLOCATION_TRANSFORM, VALUE_ALLOCATION_WIDTH, VALUE_CHILD, VALUE_CLOSURE, VALUE_COERCION, VALUE_COMPONENT, VALUE_CONSTANT, VALUE_ITERATOR, VALUE_MEASURE_FOR_SIZE, VALUE_MEASURE_MINIMUM_HEIGHT, VALUE_MEASURE_MINIMUM_WIDTH, VALUE_MEASURE_NATURAL_HEIGHT, VALUE_MEASURE_NATURAL_WIDTH, VALUE_OBJECT, VALUE_PATH, VALUE_PROPERTY, VALUE_REFERENCE_OBJECT, VALUE_TICK_TIME, VALUE_TRACK_TRANSITION, VALUE_TRANSFORM, VALUE_VARIABLE, VALUE_WIDGET_HEIGHT, VALUE_WIDGET_WIDTH, } ValueKind; typedef enum { TRANSITION_EASE = 0, TRANSITION_SPRING, } TransitionKind; typedef struct _ForeachData ForeachData; static void deinit_value (gpointer ptr); BGE_DEFINE_DATA ( value, Value, { char *name; GType type; ValueKind kind; union { struct { GValue value; } constant; struct { GPtrArray *params; } component; struct { ForeachData *context; } iterator; struct { TransformCallFunc func; ValueData *next; GPtrArray *args; } transform; struct { GPtrArray *funcs; GPtrArray *argss; } path; struct { GPtrArray *args; GClosureMarshal marshal; GCallback func; gpointer user_data; GDestroyNotify destroy_user_data; } closure; struct { ValueData *src; struct { ValueData *damping_ratio; ValueData *mass; ValueData *stiffness; } spring; } track_transition; struct { ValueData *value; } coercion; struct { ValueData *object; char *prop_name; GParamFlags pspec_flags; } property; struct { ValueData *parent_widget; char *builder_type; GPtrArray *css_classes; } child; struct { ValueData *widget; } allocation; }; }, deinit_value (self);) BGE_DEFINE_DATA ( foreach, Foreach, { ValueData *model; GHashTable *values; ForeachData *parent; }, BGE_RELEASE_DATA (model, value_data_unref); BGE_RELEASE_DATA (values, g_hash_table_unref); BGE_RELEASE_DATA (parent, foreach_data_unref)) static void deinit_value (gpointer ptr) { ValueData *value = ptr; g_clear_pointer (&value->name, g_free); switch (value->kind) { case VALUE_CONSTANT: g_value_unset (&value->constant.value); break; case VALUE_ITERATOR: g_clear_pointer (&value->iterator.context, foreach_data_unref); break; case VALUE_COMPONENT: g_clear_pointer (&value->component.params, g_ptr_array_unref); break; case VALUE_TRANSFORM: g_clear_pointer (&value->transform.next, value_data_unref); g_clear_pointer (&value->transform.args, g_ptr_array_unref); break; case VALUE_PATH: g_clear_pointer (&value->path.funcs, g_ptr_array_unref); g_clear_pointer (&value->path.argss, g_ptr_array_unref); break; case VALUE_CLOSURE: g_clear_pointer (&value->closure.args, g_ptr_array_unref); if (value->closure.destroy_user_data != NULL) g_clear_pointer (&value->closure.user_data, value->closure.destroy_user_data); break; case VALUE_COERCION: g_clear_pointer (&value->coercion.value, value_data_unref); break; case VALUE_TRACK_TRANSITION: g_clear_pointer (&value->track_transition.src, value_data_unref); g_clear_pointer (&value->track_transition.spring.damping_ratio, value_data_unref); g_clear_pointer (&value->track_transition.spring.mass, value_data_unref); g_clear_pointer (&value->track_transition.spring.stiffness, value_data_unref); break; case VALUE_PROPERTY: g_clear_pointer (&value->property.object, value_data_unref); g_clear_pointer (&value->property.prop_name, g_free); break; case VALUE_CHILD: g_clear_pointer (&value->child.parent_widget, value_data_unref); g_clear_pointer (&value->child.builder_type, g_free); g_clear_pointer (&value->child.css_classes, g_ptr_array_unref); break; case VALUE_ALLOCATION_WIDTH: case VALUE_ALLOCATION_HEIGHT: case VALUE_ALLOCATION_TRANSFORM: g_clear_pointer (&value->allocation.widget, value_data_unref); break; case VALUE_MEASURE_FOR_SIZE: case VALUE_MEASURE_MINIMUM_HEIGHT: case VALUE_MEASURE_MINIMUM_WIDTH: case VALUE_MEASURE_NATURAL_HEIGHT: case VALUE_MEASURE_NATURAL_WIDTH: case VALUE_OBJECT: case VALUE_REFERENCE_OBJECT: case VALUE_TICK_TIME: case VALUE_VARIABLE: case VALUE_WIDGET_HEIGHT: case VALUE_WIDGET_WIDTH: break; default: g_assert_not_reached (); } } static void deinit_transition (gpointer ptr); BGE_DEFINE_DATA ( transition, Transition, { TransitionKind kind; union { struct { ValueData *seconds; ValueData *easing; } ease; struct { ValueData *damping_ratio; ValueData *mass; ValueData *stiffness; } spring; }; }, deinit_transition (self);) static void deinit_transition (gpointer ptr) { TransitionData *transition = ptr; switch (transition->kind) { case TRANSITION_EASE: g_clear_pointer (&transition->ease.seconds, value_data_unref); g_clear_pointer (&transition->ease.easing, value_data_unref); break; case TRANSITION_SPRING: g_clear_pointer (&transition->spring.damping_ratio, value_data_unref); g_clear_pointer (&transition->spring.mass, value_data_unref); g_clear_pointer (&transition->spring.stiffness, value_data_unref); break; default: g_assert_not_reached (); } } BGE_DEFINE_DATA ( snapshot_call, SnapshotCall, { BgeWdgtSnapshotInstrKind kind; SnapshotCallFunc func; GPtrArray *args; GPtrArray *rest; ValueData *child; ForeachData *foreach_context; }, BGE_RELEASE_DATA (args, g_ptr_array_unref); BGE_RELEASE_DATA (rest, g_ptr_array_unref); BGE_RELEASE_DATA (child, value_data_unref); BGE_RELEASE_DATA (foreach_context, foreach_data_unref)) BGE_DEFINE_DATA ( snapshot, Snapshot, { GPtrArray *calls; }, BGE_RELEASE_DATA (calls, g_ptr_array_unref)) BGE_DEFINE_DATA ( state, State, { char *name; GHashTable *setters; GHashTable *transitions; SnapshotData *snapshot; GHashTable *expressions; GPtrArray *snapshot_deps; GHashTable *values_need_tick; gboolean needs_tick; }, BGE_RELEASE_DATA (name, g_free); BGE_RELEASE_DATA (setters, g_hash_table_unref); BGE_RELEASE_DATA (transitions, g_hash_table_unref); BGE_RELEASE_DATA (snapshot, snapshot_data_unref); BGE_RELEASE_DATA (expressions, g_hash_table_unref); BGE_RELEASE_DATA (snapshot_deps, g_ptr_array_unref); BGE_RELEASE_DATA (values_need_tick, g_hash_table_unref);); /* --------------------------- */ /* Spec Builder Implementation */ /* --------------------------- */ struct _BgeWdgtSpec { GObject parent_instance; char *name; GHashTable *values; GPtrArray *values_stack; GPtrArray *foreaches; GPtrArray *foreach_stack; GPtrArray *anon_values; GPtrArray *track_transition_values; GHashTable *states; GPtrArray *children; GPtrArray *nonchildren; StateData *init_state; StateData *default_state; ValueData *reference; gboolean ready; }; G_DEFINE_FINAL_TYPE (BgeWdgtSpec, bge_wdgt_spec, G_TYPE_OBJECT); enum { PROP_0, PROP_NAME, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static gboolean check_can_coerce_type (GType dest, GType src); static void coerce_value (const GValue *in, GType dest_type, GValue *out); static ValueData * wrap_coerce_value (BgeWdgtSpec *self, ValueData *value, GType dest_type); static void ensure_state_snapshot (StateData *state); static void bge_wdgt_spec_dispose (GObject *object) { BgeWdgtSpec *self = BGE_WDGT_SPEC (object); g_clear_pointer (&self->name, g_free); g_clear_pointer (&self->values, g_hash_table_unref); g_clear_pointer (&self->values_stack, g_ptr_array_unref); g_clear_pointer (&self->foreaches, g_ptr_array_unref); g_clear_pointer (&self->foreach_stack, g_ptr_array_unref); g_clear_pointer (&self->anon_values, g_ptr_array_unref); g_clear_pointer (&self->track_transition_values, g_ptr_array_unref); g_clear_pointer (&self->states, g_hash_table_unref); g_clear_pointer (&self->children, g_ptr_array_unref); g_clear_pointer (&self->nonchildren, g_ptr_array_unref); g_clear_pointer (&self->init_state, state_data_unref); g_clear_pointer (&self->default_state, state_data_unref); g_clear_pointer (&self->reference, value_data_unref); G_OBJECT_CLASS (bge_wdgt_spec_parent_class)->dispose (object); } static void bge_wdgt_spec_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BgeWdgtSpec *self = BGE_WDGT_SPEC (object); switch (prop_id) { case PROP_NAME: g_value_set_string (value, bge_wdgt_spec_get_name (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bge_wdgt_spec_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BgeWdgtSpec *self = BGE_WDGT_SPEC (object); switch (prop_id) { case PROP_NAME: bge_wdgt_spec_set_name (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bge_wdgt_spec_class_init (BgeWdgtSpecClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bge_wdgt_spec_set_property; object_class->get_property = bge_wdgt_spec_get_property; object_class->dispose = bge_wdgt_spec_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); g_type_ensure (BGE_TYPE_EASING); /* Make sure these names are available for the parser */ g_type_ensure (GRAPHENE_TYPE_POINT); g_type_ensure (GRAPHENE_TYPE_POINT3D); g_type_ensure (GRAPHENE_TYPE_SIZE); g_type_ensure (GRAPHENE_TYPE_RECT); g_type_ensure (GRAPHENE_TYPE_VEC2); g_type_ensure (GRAPHENE_TYPE_VEC3); g_type_ensure (GRAPHENE_TYPE_VEC4); g_type_ensure (GRAPHENE_TYPE_QUAD); g_type_ensure (GRAPHENE_TYPE_QUATERNION); g_type_ensure (GRAPHENE_TYPE_MATRIX); g_type_ensure (GRAPHENE_TYPE_PLANE); g_type_ensure (GRAPHENE_TYPE_FRUSTUM); g_type_ensure (GRAPHENE_TYPE_SPHERE); g_type_ensure (GRAPHENE_TYPE_BOX); g_type_ensure (GRAPHENE_TYPE_TRIANGLE); g_type_ensure (GRAPHENE_TYPE_EULER); g_type_ensure (GRAPHENE_TYPE_RAY); g_type_ensure (GSK_TYPE_PATH); g_type_ensure (GSK_TYPE_PATH_POINT); g_type_ensure (GSK_TYPE_PATH_MEASURE); g_type_ensure (GSK_TYPE_TRANSFORM); g_type_ensure (GSK_TYPE_FILL_RULE); g_type_ensure (GSK_TYPE_LINE_CAP); g_type_ensure (GSK_TYPE_LINE_JOIN); /* Ensure GTK names are available for the parser */ g_type_ensure (gtk_at_context_get_type ()); g_type_ensure (gtk_about_dialog_get_type ()); g_type_ensure (gtk_accessible_get_type ()); g_type_ensure (gtk_accessible_announcement_priority_get_type ()); g_type_ensure (gtk_accessible_autocomplete_get_type ()); g_type_ensure (gtk_accessible_invalid_state_get_type ()); g_type_ensure (gtk_accessible_list_get_type ()); g_type_ensure (gtk_accessible_platform_state_get_type ()); g_type_ensure (gtk_accessible_property_get_type ()); g_type_ensure (gtk_accessible_range_get_type ()); g_type_ensure (gtk_accessible_relation_get_type ()); g_type_ensure (gtk_accessible_role_get_type ()); g_type_ensure (gtk_accessible_sort_get_type ()); g_type_ensure (gtk_accessible_state_get_type ()); g_type_ensure (gtk_accessible_text_get_type ()); g_type_ensure (gtk_accessible_text_content_change_get_type ()); g_type_ensure (gtk_accessible_text_granularity_get_type ()); g_type_ensure (gtk_accessible_tristate_get_type ()); g_type_ensure (gtk_action_bar_get_type ()); g_type_ensure (gtk_actionable_get_type ()); g_type_ensure (gtk_activate_action_get_type ()); g_type_ensure (gtk_adjustment_get_type ()); g_type_ensure (gtk_alert_dialog_get_type ()); g_type_ensure (gtk_align_get_type ()); g_type_ensure (gtk_alternative_trigger_get_type ()); g_type_ensure (gtk_any_filter_get_type ()); g_type_ensure (gtk_app_chooser_get_type ()); g_type_ensure (gtk_app_chooser_button_get_type ()); g_type_ensure (gtk_app_chooser_dialog_get_type ()); g_type_ensure (gtk_app_chooser_widget_get_type ()); g_type_ensure (gtk_application_get_type ()); g_type_ensure (gtk_application_inhibit_flags_get_type ()); g_type_ensure (gtk_application_window_get_type ()); g_type_ensure (gtk_arrow_type_get_type ()); g_type_ensure (gtk_aspect_frame_get_type ()); g_type_ensure (gtk_assistant_get_type ()); g_type_ensure (gtk_assistant_page_get_type ()); g_type_ensure (gtk_assistant_page_type_get_type ()); g_type_ensure (gtk_baseline_position_get_type ()); g_type_ensure (gtk_bin_layout_get_type ()); g_type_ensure (gtk_bitset_get_type ()); g_type_ensure (gtk_bitset_iter_get_type ()); g_type_ensure (gtk_bookmark_list_get_type ()); g_type_ensure (gtk_bool_filter_get_type ()); g_type_ensure (gtk_border_get_type ()); g_type_ensure (gtk_border_style_get_type ()); g_type_ensure (gtk_box_get_type ()); g_type_ensure (gtk_box_layout_get_type ()); g_type_ensure (gtk_buildable_get_type ()); g_type_ensure (gtk_builder_get_type ()); g_type_ensure (gtk_builder_cscope_get_type ()); g_type_ensure (gtk_builder_closure_flags_get_type ()); g_type_ensure (gtk_builder_error_get_type ()); g_type_ensure (gtk_builder_list_item_factory_get_type ()); g_type_ensure (gtk_builder_scope_get_type ()); g_type_ensure (gtk_button_get_type ()); g_type_ensure (gtk_buttons_type_get_type ()); g_type_ensure (gtk_cclosure_expression_get_type ()); g_type_ensure (gtk_calendar_get_type ()); g_type_ensure (gtk_callback_action_get_type ()); g_type_ensure (gtk_cell_area_get_type ()); g_type_ensure (gtk_cell_area_box_get_type ()); g_type_ensure (gtk_cell_area_context_get_type ()); g_type_ensure (gtk_cell_editable_get_type ()); g_type_ensure (gtk_cell_layout_get_type ()); g_type_ensure (gtk_cell_renderer_get_type ()); g_type_ensure (gtk_cell_renderer_accel_get_type ()); g_type_ensure (gtk_cell_renderer_accel_mode_get_type ()); g_type_ensure (gtk_cell_renderer_combo_get_type ()); g_type_ensure (gtk_cell_renderer_mode_get_type ()); g_type_ensure (gtk_cell_renderer_pixbuf_get_type ()); g_type_ensure (gtk_cell_renderer_progress_get_type ()); g_type_ensure (gtk_cell_renderer_spin_get_type ()); g_type_ensure (gtk_cell_renderer_spinner_get_type ()); g_type_ensure (gtk_cell_renderer_state_get_type ()); g_type_ensure (gtk_cell_renderer_text_get_type ()); g_type_ensure (gtk_cell_renderer_toggle_get_type ()); g_type_ensure (gtk_cell_view_get_type ()); g_type_ensure (gtk_center_box_get_type ()); g_type_ensure (gtk_center_layout_get_type ()); g_type_ensure (gtk_check_button_get_type ()); g_type_ensure (gtk_closure_expression_get_type ()); g_type_ensure (gtk_collation_get_type ()); g_type_ensure (gtk_color_button_get_type ()); g_type_ensure (gtk_color_chooser_get_type ()); g_type_ensure (gtk_color_chooser_dialog_get_type ()); g_type_ensure (gtk_color_chooser_widget_get_type ()); g_type_ensure (gtk_color_dialog_get_type ()); g_type_ensure (gtk_color_dialog_button_get_type ()); g_type_ensure (gtk_column_view_get_type ()); g_type_ensure (gtk_column_view_cell_get_type ()); g_type_ensure (gtk_column_view_column_get_type ()); g_type_ensure (gtk_column_view_row_get_type ()); g_type_ensure (gtk_column_view_sorter_get_type ()); g_type_ensure (gtk_combo_box_get_type ()); g_type_ensure (gtk_combo_box_text_get_type ()); g_type_ensure (gtk_constant_expression_get_type ()); g_type_ensure (gtk_constraint_get_type ()); g_type_ensure (gtk_constraint_attribute_get_type ()); g_type_ensure (gtk_constraint_guide_get_type ()); g_type_ensure (gtk_constraint_layout_get_type ()); g_type_ensure (gtk_constraint_layout_child_get_type ()); g_type_ensure (gtk_constraint_relation_get_type ()); g_type_ensure (gtk_constraint_strength_get_type ()); g_type_ensure (gtk_constraint_target_get_type ()); g_type_ensure (gtk_constraint_vfl_parser_error_get_type ()); g_type_ensure (gtk_content_fit_get_type ()); g_type_ensure (gtk_corner_type_get_type ()); g_type_ensure (gtk_css_provider_get_type ()); g_type_ensure (gtk_css_section_get_type ()); g_type_ensure (gtk_custom_filter_get_type ()); g_type_ensure (gtk_custom_layout_get_type ()); g_type_ensure (gtk_custom_sorter_get_type ()); g_type_ensure (gtk_debug_flags_get_type ()); g_type_ensure (gtk_delete_type_get_type ()); g_type_ensure (gtk_dialog_get_type ()); g_type_ensure (gtk_dialog_error_get_type ()); g_type_ensure (gtk_dialog_flags_get_type ()); g_type_ensure (gtk_direction_type_get_type ()); g_type_ensure (gtk_directory_list_get_type ()); g_type_ensure (gtk_drag_icon_get_type ()); g_type_ensure (gtk_drag_source_get_type ()); g_type_ensure (gtk_drawing_area_get_type ()); g_type_ensure (gtk_drop_controller_motion_get_type ()); g_type_ensure (gtk_drop_down_get_type ()); g_type_ensure (gtk_drop_target_get_type ()); g_type_ensure (gtk_drop_target_async_get_type ()); g_type_ensure (gtk_editable_get_type ()); g_type_ensure (gtk_editable_label_get_type ()); g_type_ensure (gtk_editable_properties_get_type ()); g_type_ensure (gtk_emoji_chooser_get_type ()); g_type_ensure (gtk_entry_get_type ()); g_type_ensure (gtk_entry_buffer_get_type ()); g_type_ensure (gtk_entry_completion_get_type ()); g_type_ensure (gtk_entry_icon_position_get_type ()); g_type_ensure (gtk_event_controller_get_type ()); g_type_ensure (gtk_event_controller_focus_get_type ()); g_type_ensure (gtk_event_controller_key_get_type ()); g_type_ensure (gtk_event_controller_legacy_get_type ()); g_type_ensure (gtk_event_controller_motion_get_type ()); g_type_ensure (gtk_event_controller_scroll_get_type ()); g_type_ensure (gtk_event_controller_scroll_flags_get_type ()); g_type_ensure (gtk_event_sequence_state_get_type ()); g_type_ensure (gtk_every_filter_get_type ()); g_type_ensure (gtk_expander_get_type ()); g_type_ensure (gtk_expression_get_type ()); g_type_ensure (gtk_expression_watch_get_type ()); g_type_ensure (gtk_file_chooser_get_type ()); g_type_ensure (gtk_file_chooser_action_get_type ()); g_type_ensure (gtk_file_chooser_dialog_get_type ()); g_type_ensure (gtk_file_chooser_error_get_type ()); g_type_ensure (gtk_file_chooser_native_get_type ()); g_type_ensure (gtk_file_chooser_widget_get_type ()); g_type_ensure (gtk_file_dialog_get_type ()); g_type_ensure (gtk_file_filter_get_type ()); g_type_ensure (gtk_file_launcher_get_type ()); g_type_ensure (gtk_filter_get_type ()); g_type_ensure (gtk_filter_change_get_type ()); g_type_ensure (gtk_filter_list_model_get_type ()); g_type_ensure (gtk_filter_match_get_type ()); g_type_ensure (gtk_fixed_get_type ()); g_type_ensure (gtk_fixed_layout_get_type ()); g_type_ensure (gtk_fixed_layout_child_get_type ()); g_type_ensure (gtk_flatten_list_model_get_type ()); g_type_ensure (gtk_flow_box_get_type ()); g_type_ensure (gtk_flow_box_child_get_type ()); g_type_ensure (gtk_font_button_get_type ()); g_type_ensure (gtk_font_chooser_get_type ()); g_type_ensure (gtk_font_chooser_dialog_get_type ()); g_type_ensure (gtk_font_chooser_level_get_type ()); g_type_ensure (gtk_font_chooser_widget_get_type ()); g_type_ensure (gtk_font_dialog_get_type ()); g_type_ensure (gtk_font_dialog_button_get_type ()); g_type_ensure (gtk_font_level_get_type ()); g_type_ensure (gtk_font_rendering_get_type ()); g_type_ensure (gtk_frame_get_type ()); g_type_ensure (gtk_gl_area_get_type ()); g_type_ensure (gtk_gesture_get_type ()); g_type_ensure (gtk_gesture_click_get_type ()); g_type_ensure (gtk_gesture_drag_get_type ()); g_type_ensure (gtk_gesture_long_press_get_type ()); g_type_ensure (gtk_gesture_pan_get_type ()); g_type_ensure (gtk_gesture_rotate_get_type ()); g_type_ensure (gtk_gesture_single_get_type ()); g_type_ensure (gtk_gesture_stylus_get_type ()); g_type_ensure (gtk_gesture_swipe_get_type ()); g_type_ensure (gtk_gesture_zoom_get_type ()); g_type_ensure (gtk_graphics_offload_get_type ()); g_type_ensure (gtk_graphics_offload_enabled_get_type ()); g_type_ensure (gtk_grid_get_type ()); g_type_ensure (gtk_grid_layout_get_type ()); g_type_ensure (gtk_grid_layout_child_get_type ()); g_type_ensure (gtk_grid_view_get_type ()); g_type_ensure (gtk_header_bar_get_type ()); g_type_ensure (gtk_im_context_get_type ()); g_type_ensure (gtk_im_context_simple_get_type ()); g_type_ensure (gtk_im_multicontext_get_type ()); g_type_ensure (gtk_icon_lookup_flags_get_type ()); g_type_ensure (gtk_icon_paintable_get_type ()); g_type_ensure (gtk_icon_size_get_type ()); g_type_ensure (gtk_icon_theme_get_type ()); g_type_ensure (gtk_icon_theme_error_get_type ()); g_type_ensure (gtk_icon_view_get_type ()); g_type_ensure (gtk_icon_view_drop_position_get_type ()); g_type_ensure (gtk_image_get_type ()); g_type_ensure (gtk_image_type_get_type ()); g_type_ensure (gtk_info_bar_get_type ()); g_type_ensure (gtk_input_hints_get_type ()); g_type_ensure (gtk_input_purpose_get_type ()); g_type_ensure (gtk_inscription_get_type ()); g_type_ensure (gtk_inscription_overflow_get_type ()); g_type_ensure (gtk_interface_color_scheme_get_type ()); g_type_ensure (gtk_interface_contrast_get_type ()); g_type_ensure (gtk_justification_get_type ()); g_type_ensure (gtk_keyval_trigger_get_type ()); g_type_ensure (gtk_label_get_type ()); g_type_ensure (gtk_layout_child_get_type ()); g_type_ensure (gtk_layout_manager_get_type ()); g_type_ensure (gtk_level_bar_get_type ()); g_type_ensure (gtk_level_bar_mode_get_type ()); g_type_ensure (gtk_license_get_type ()); g_type_ensure (gtk_link_button_get_type ()); g_type_ensure (gtk_list_base_get_type ()); g_type_ensure (gtk_list_box_get_type ()); g_type_ensure (gtk_list_box_row_get_type ()); g_type_ensure (gtk_list_header_get_type ()); g_type_ensure (gtk_list_item_get_type ()); g_type_ensure (gtk_list_item_factory_get_type ()); g_type_ensure (gtk_list_scroll_flags_get_type ()); g_type_ensure (gtk_list_store_get_type ()); g_type_ensure (gtk_list_tab_behavior_get_type ()); g_type_ensure (gtk_list_view_get_type ()); g_type_ensure (gtk_lock_button_get_type ()); g_type_ensure (gtk_map_list_model_get_type ()); g_type_ensure (gtk_media_controls_get_type ()); g_type_ensure (gtk_media_file_get_type ()); g_type_ensure (gtk_media_stream_get_type ()); g_type_ensure (gtk_menu_button_get_type ()); g_type_ensure (gtk_message_dialog_get_type ()); g_type_ensure (gtk_message_type_get_type ()); g_type_ensure (gtk_mnemonic_action_get_type ()); g_type_ensure (gtk_mnemonic_trigger_get_type ()); g_type_ensure (gtk_mount_operation_get_type ()); g_type_ensure (gtk_movement_step_get_type ()); g_type_ensure (gtk_multi_filter_get_type ()); g_type_ensure (gtk_multi_selection_get_type ()); g_type_ensure (gtk_multi_sorter_get_type ()); g_type_ensure (gtk_named_action_get_type ()); g_type_ensure (gtk_native_get_type ()); g_type_ensure (gtk_native_dialog_get_type ()); g_type_ensure (gtk_natural_wrap_mode_get_type ()); g_type_ensure (gtk_never_trigger_get_type ()); g_type_ensure (gtk_no_selection_get_type ()); g_type_ensure (gtk_notebook_get_type ()); g_type_ensure (gtk_notebook_page_get_type ()); g_type_ensure (gtk_notebook_tab_get_type ()); g_type_ensure (gtk_nothing_action_get_type ()); g_type_ensure (gtk_number_up_layout_get_type ()); g_type_ensure (gtk_numeric_sorter_get_type ()); g_type_ensure (gtk_object_expression_get_type ()); g_type_ensure (gtk_ordering_get_type ()); g_type_ensure (gtk_orientable_get_type ()); g_type_ensure (gtk_orientation_get_type ()); g_type_ensure (gtk_overflow_get_type ()); g_type_ensure (gtk_overlay_get_type ()); g_type_ensure (gtk_overlay_layout_get_type ()); g_type_ensure (gtk_overlay_layout_child_get_type ()); g_type_ensure (gtk_pack_type_get_type ()); g_type_ensure (gtk_pad_action_type_get_type ()); g_type_ensure (gtk_pad_controller_get_type ()); g_type_ensure (gtk_page_orientation_get_type ()); g_type_ensure (gtk_page_set_get_type ()); g_type_ensure (gtk_page_setup_get_type ()); g_type_ensure (gtk_pan_direction_get_type ()); g_type_ensure (gtk_paned_get_type ()); g_type_ensure (gtk_paper_size_get_type ()); g_type_ensure (gtk_param_expression_get_type ()); g_type_ensure (gtk_password_entry_get_type ()); g_type_ensure (gtk_password_entry_buffer_get_type ()); g_type_ensure (gtk_pick_flags_get_type ()); g_type_ensure (gtk_picture_get_type ()); g_type_ensure (gtk_policy_type_get_type ()); g_type_ensure (gtk_popover_get_type ()); g_type_ensure (gtk_popover_menu_get_type ()); g_type_ensure (gtk_popover_menu_bar_get_type ()); g_type_ensure (gtk_popover_menu_flags_get_type ()); g_type_ensure (gtk_position_type_get_type ()); g_type_ensure (gtk_print_context_get_type ()); g_type_ensure (gtk_print_dialog_get_type ()); g_type_ensure (gtk_print_duplex_get_type ()); g_type_ensure (gtk_print_error_get_type ()); g_type_ensure (gtk_print_operation_get_type ()); g_type_ensure (gtk_print_operation_action_get_type ()); g_type_ensure (gtk_print_operation_preview_get_type ()); g_type_ensure (gtk_print_operation_result_get_type ()); g_type_ensure (gtk_print_pages_get_type ()); g_type_ensure (gtk_print_quality_get_type ()); g_type_ensure (gtk_print_settings_get_type ()); g_type_ensure (gtk_print_setup_get_type ()); g_type_ensure (gtk_print_status_get_type ()); g_type_ensure (gtk_progress_bar_get_type ()); g_type_ensure (gtk_propagation_limit_get_type ()); g_type_ensure (gtk_propagation_phase_get_type ()); g_type_ensure (gtk_property_expression_get_type ()); g_type_ensure (gtk_range_get_type ()); g_type_ensure (gtk_recent_info_get_type ()); g_type_ensure (gtk_recent_manager_get_type ()); g_type_ensure (gtk_recent_manager_error_get_type ()); g_type_ensure (gtk_requisition_get_type ()); g_type_ensure (gtk_response_type_get_type ()); g_type_ensure (gtk_revealer_get_type ()); g_type_ensure (gtk_revealer_transition_type_get_type ()); g_type_ensure (gtk_root_get_type ()); g_type_ensure (gtk_scale_get_type ()); g_type_ensure (gtk_scale_button_get_type ()); g_type_ensure (gtk_scroll_info_get_type ()); g_type_ensure (gtk_scroll_step_get_type ()); g_type_ensure (gtk_scroll_type_get_type ()); g_type_ensure (gtk_scrollable_get_type ()); g_type_ensure (gtk_scrollable_policy_get_type ()); g_type_ensure (gtk_scrollbar_get_type ()); g_type_ensure (gtk_scrolled_window_get_type ()); g_type_ensure (gtk_search_bar_get_type ()); g_type_ensure (gtk_search_entry_get_type ()); g_type_ensure (gtk_section_model_get_type ()); g_type_ensure (gtk_selection_filter_model_get_type ()); g_type_ensure (gtk_selection_mode_get_type ()); g_type_ensure (gtk_selection_model_get_type ()); g_type_ensure (gtk_sensitivity_type_get_type ()); g_type_ensure (gtk_separator_get_type ()); g_type_ensure (gtk_settings_get_type ()); g_type_ensure (gtk_shortcut_get_type ()); g_type_ensure (gtk_shortcut_action_get_type ()); g_type_ensure (gtk_shortcut_action_flags_get_type ()); g_type_ensure (gtk_shortcut_controller_get_type ()); g_type_ensure (gtk_shortcut_label_get_type ()); g_type_ensure (gtk_shortcut_manager_get_type ()); g_type_ensure (gtk_shortcut_scope_get_type ()); g_type_ensure (gtk_shortcut_trigger_get_type ()); g_type_ensure (gtk_shortcut_type_get_type ()); g_type_ensure (gtk_shortcuts_group_get_type ()); g_type_ensure (gtk_shortcuts_section_get_type ()); g_type_ensure (gtk_shortcuts_shortcut_get_type ()); g_type_ensure (gtk_shortcuts_window_get_type ()); g_type_ensure (gtk_signal_action_get_type ()); g_type_ensure (gtk_signal_list_item_factory_get_type ()); g_type_ensure (gtk_single_selection_get_type ()); g_type_ensure (gtk_size_group_get_type ()); g_type_ensure (gtk_size_group_mode_get_type ()); g_type_ensure (gtk_size_request_mode_get_type ()); g_type_ensure (gtk_slice_list_model_get_type ()); g_type_ensure (gtk_snapshot_get_type ()); g_type_ensure (gtk_sort_list_model_get_type ()); g_type_ensure (gtk_sort_type_get_type ()); g_type_ensure (gtk_sorter_get_type ()); g_type_ensure (gtk_sorter_change_get_type ()); g_type_ensure (gtk_sorter_order_get_type ()); g_type_ensure (gtk_spin_button_get_type ()); g_type_ensure (gtk_spin_button_update_policy_get_type ()); g_type_ensure (gtk_spin_type_get_type ()); g_type_ensure (gtk_spinner_get_type ()); g_type_ensure (gtk_stack_get_type ()); g_type_ensure (gtk_stack_page_get_type ()); g_type_ensure (gtk_stack_sidebar_get_type ()); g_type_ensure (gtk_stack_switcher_get_type ()); g_type_ensure (gtk_stack_transition_type_get_type ()); g_type_ensure (gtk_state_flags_get_type ()); g_type_ensure (gtk_statusbar_get_type ()); g_type_ensure (gtk_string_filter_get_type ()); g_type_ensure (gtk_string_filter_match_mode_get_type ()); g_type_ensure (gtk_string_list_get_type ()); g_type_ensure (gtk_string_object_get_type ()); g_type_ensure (gtk_string_sorter_get_type ()); g_type_ensure (gtk_style_context_get_type ()); g_type_ensure (gtk_style_context_print_flags_get_type ()); g_type_ensure (gtk_style_provider_get_type ()); g_type_ensure (gtk_switch_get_type ()); g_type_ensure (gtk_symbolic_color_get_type ()); g_type_ensure (gtk_symbolic_paintable_get_type ()); g_type_ensure (gtk_system_setting_get_type ()); g_type_ensure (gtk_text_get_type ()); g_type_ensure (gtk_text_buffer_get_type ()); g_type_ensure (gtk_text_buffer_notify_flags_get_type ()); g_type_ensure (gtk_text_child_anchor_get_type ()); g_type_ensure (gtk_text_direction_get_type ()); g_type_ensure (gtk_text_extend_selection_get_type ()); g_type_ensure (gtk_text_iter_get_type ()); g_type_ensure (gtk_text_mark_get_type ()); g_type_ensure (gtk_text_search_flags_get_type ()); g_type_ensure (gtk_text_tag_get_type ()); g_type_ensure (gtk_text_tag_table_get_type ()); g_type_ensure (gtk_text_view_get_type ()); g_type_ensure (gtk_text_view_layer_get_type ()); g_type_ensure (gtk_text_window_type_get_type ()); g_type_ensure (gtk_toggle_button_get_type ()); g_type_ensure (gtk_tooltip_get_type ()); g_type_ensure (gtk_tree_expander_get_type ()); g_type_ensure (gtk_tree_iter_get_type ()); g_type_ensure (gtk_tree_list_model_get_type ()); g_type_ensure (gtk_tree_list_row_get_type ()); g_type_ensure (gtk_tree_list_row_sorter_get_type ()); g_type_ensure (gtk_tree_model_get_type ()); g_type_ensure (gtk_tree_model_filter_get_type ()); g_type_ensure (gtk_tree_model_flags_get_type ()); g_type_ensure (gtk_tree_model_sort_get_type ()); g_type_ensure (gtk_tree_path_get_type ()); g_type_ensure (gtk_tree_row_reference_get_type ()); g_type_ensure (gtk_tree_selection_get_type ()); g_type_ensure (gtk_tree_sortable_get_type ()); g_type_ensure (gtk_tree_store_get_type ()); g_type_ensure (gtk_tree_view_get_type ()); g_type_ensure (gtk_tree_view_column_get_type ()); g_type_ensure (gtk_tree_view_column_sizing_get_type ()); g_type_ensure (gtk_tree_view_drop_position_get_type ()); g_type_ensure (gtk_tree_view_grid_lines_get_type ()); g_type_ensure (gtk_unit_get_type ()); g_type_ensure (gtk_uri_launcher_get_type ()); g_type_ensure (gtk_video_get_type ()); g_type_ensure (gtk_viewport_get_type ()); g_type_ensure (gtk_volume_button_get_type ()); g_type_ensure (gtk_widget_get_type ()); g_type_ensure (gtk_widget_paintable_get_type ()); g_type_ensure (gtk_window_get_type ()); g_type_ensure (gtk_window_controls_get_type ()); g_type_ensure (gtk_window_gravity_get_type ()); g_type_ensure (gtk_window_group_get_type ()); g_type_ensure (gtk_window_handle_get_type ()); g_type_ensure (gtk_wrap_mode_get_type ()); } static void bge_wdgt_spec_init (BgeWdgtSpec *self) { self->values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, value_data_unref); self->values_stack = g_ptr_array_new_with_free_func ((GDestroyNotify) g_hash_table_unref); self->foreaches = g_ptr_array_new_with_free_func (foreach_data_unref); self->foreach_stack = g_ptr_array_new_with_free_func (foreach_data_unref); self->anon_values = g_ptr_array_new_with_free_func (value_data_unref); self->track_transition_values = g_ptr_array_new_with_free_func (value_data_unref); self->states = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, state_data_unref); self->children = g_ptr_array_new_with_free_func (value_data_unref); self->nonchildren = g_ptr_array_new_with_free_func (value_data_unref); self->init_state = state_data_new (); self->init_state->name = g_strdup ("init"); self->init_state->setters = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, value_data_unref); self->init_state->transitions = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, transition_data_unref); self->init_state->expressions = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, (GDestroyNotify) gtk_expression_unref); self->init_state->snapshot_deps = g_ptr_array_new_with_free_func ( (GDestroyNotify) gtk_expression_unref); self->init_state->values_need_tick = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, NULL); ensure_state_snapshot (self->init_state); g_hash_table_replace (self->states, g_strdup ("init"), state_data_ref (self->init_state)); self->ready = FALSE; } BgeWdgtSpec * bge_wdgt_spec_new (void) { return g_object_new (BGE_TYPE_WDGT_SPEC, NULL); } BgeWdgtSpec * bge_wdgt_spec_new_for_string (const char *string, GError **error) { g_return_val_if_fail (string != NULL, NULL); return bge_wdgt_parse_string (string, error); } BgeWdgtSpec * bge_wdgt_spec_new_for_resource (const char *resource, GError **error) { g_autoptr (GBytes) bytes = NULL; gsize size = 0; gconstpointer data = NULL; g_return_val_if_fail (resource != NULL, NULL); bytes = g_resources_lookup_data (resource, G_RESOURCE_LOOKUP_FLAGS_NONE, error); if (bytes == NULL) return NULL; data = g_bytes_get_data (bytes, &size); return bge_wdgt_parse_string ((const char *) data, error); } const char * bge_wdgt_spec_get_name (BgeWdgtSpec *self) { g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), NULL); return self->name; } void bge_wdgt_spec_set_name (BgeWdgtSpec *self, const char *name) { g_return_if_fail (BGE_IS_WDGT_SPEC (self)); if (name == self->name || (name != NULL && self->name != NULL && g_strcmp0 (name, self->name) == 0)) return; 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]); } void bge_wdgt_spec_set_name_take (BgeWdgtSpec *self, char *name) { g_return_if_fail (BGE_IS_WDGT_SPEC (self)); if (name != NULL && self->name != NULL && g_strcmp0 (name, self->name) == 0) { g_free (name); return; } g_clear_pointer (&self->name, g_free); if (name != NULL) self->name = name; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_NAME]); } gboolean bge_wdgt_spec_add_constant_source_value (BgeWdgtSpec *self, const char *name, const GValue *constant, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (constant != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = constant->g_type; value->kind = VALUE_CONSTANT; g_value_copy (constant, g_value_init (&value->constant.value, constant->g_type)); g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_component_source_value (BgeWdgtSpec *self, const char *name, GType type, const char *const *components, guint n_components, GError **error) { GType expected_types[ARGBUF_SIZE] = { 0 }; g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (components != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } if (type == GRAPHENE_TYPE_POINT) { if (n_components != 2) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "composed point value needs 2 arguments"); return FALSE; } expected_types[0] = G_TYPE_DOUBLE; expected_types[1] = G_TYPE_DOUBLE; } else if (type == GRAPHENE_TYPE_POINT3D) { if (n_components != 3) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "composed 3d point value needs 3 arguments"); return FALSE; } expected_types[0] = G_TYPE_DOUBLE; expected_types[1] = G_TYPE_DOUBLE; expected_types[2] = G_TYPE_DOUBLE; } else if (type == GRAPHENE_TYPE_SIZE) { if (n_components != 2) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "composed 2d size value needs 2 arguments"); return FALSE; } expected_types[0] = G_TYPE_DOUBLE; expected_types[1] = G_TYPE_DOUBLE; } else if (type == GRAPHENE_TYPE_RECT) { if (n_components != 4) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "composed rectangle value needs 4 arguments"); return FALSE; } expected_types[0] = G_TYPE_DOUBLE; expected_types[1] = G_TYPE_DOUBLE; expected_types[2] = G_TYPE_DOUBLE; expected_types[3] = G_TYPE_DOUBLE; } else if (type == GSK_TYPE_STROKE) { if (n_components != 4) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "composed rectangle value needs 4 arguments"); return FALSE; } expected_types[0] = G_TYPE_DOUBLE; /* line width */ expected_types[1] = GSK_TYPE_LINE_CAP; expected_types[2] = GSK_TYPE_LINE_JOIN; expected_types[3] = G_TYPE_DOUBLE; /* miter limit */ } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type '%s' is not elligible for a component value", g_type_name (type)); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = type; value->kind = VALUE_COMPONENT; value->component.params = g_ptr_array_new_with_free_func (value_data_unref); for (guint i = 0; i < n_components; i++) { ValueData *value_data = NULL; value_data = g_hash_table_lookup (self->values, components[i]); if (value_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", components[i]); return FALSE; } if (!g_type_is_a (value_data->type, expected_types[i])) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "component %u for type %s " "must be of type %s, got %s", i, g_type_name (type), g_type_name (expected_types[i]), g_type_name (value_data->type)); return FALSE; } g_ptr_array_add (value->component.params, value_data_ref (value_data)); } g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_transform_source_value (BgeWdgtSpec *self, const char *name, const char *next, const char *instruction, const char *const *args, guint n_args, GError **error) { gboolean result = FALSE; ValueData *next_data = NULL; g_autoptr (ValueData) value = NULL; TransformInstr match = { 0 }; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (next != NULL, FALSE); g_return_val_if_fail (instruction != NULL, FALSE); g_return_val_if_fail (n_args == 0 || args != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } next_data = g_hash_table_lookup (self->values, next); if (next_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", next); return FALSE; } if (next_data->type != GSK_TYPE_TRANSFORM) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' must be of type %s to " "build a transform, got %s", next, g_type_name (GSK_TYPE_TRANSFORM), g_type_name (next_data->type)); return FALSE; } result = lookup_transform_instr (instruction, &match); if (!result) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "\"%s\" is not a valid transform builder instruction", instruction); return FALSE; } if (n_args != match.n_args) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "transform builder function %s requires %u " "arguments, got %u", match.name, match.n_args, n_args); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = GSK_TYPE_TRANSFORM; value->kind = VALUE_TRANSFORM; value->transform.func = match.call; value->transform.next = value_data_ref (next_data); value->transform.args = g_ptr_array_new_with_free_func (value_data_unref); for (guint i = 0; i < n_args; i++) { ValueData *value_data = NULL; value_data = g_hash_table_lookup (self->values, args[i]); if (value_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", args[i]); return FALSE; } if (!g_type_is_a (value_data->type, match.args[i])) { if (check_can_coerce_type (match.args[i], value_data->type)) g_ptr_array_add (value->transform.args, wrap_coerce_value (self, value_data, match.args[i])); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "argument %u for snapshot instruction %s " "must be of type %s, got %s", i, match.name, g_type_name (match.args[i]), g_type_name (value_data->type)); return FALSE; } } else g_ptr_array_add (value->transform.args, value_data_ref (value_data)); } g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_path_source_value (BgeWdgtSpec *self, const char *name, const char *const *instructions, const char *const *const *argss, const guint *n_argss, guint n_args, GError **error) { gboolean result = FALSE; g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (instructions != NULL, FALSE); g_return_val_if_fail (argss != NULL, FALSE); g_return_val_if_fail (n_argss != NULL, FALSE); g_return_val_if_fail (n_args > 0, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = GSK_TYPE_PATH; value->kind = VALUE_PATH; value->path.funcs = g_ptr_array_new (); value->path.argss = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_ptr_array_unref); for (guint i = 0; i < n_args; i++) { PathBuilderInstr match = { 0 }; g_autoptr (GPtrArray) args = NULL; result = lookup_path_builder_instr (instructions[i], &match); if (!result) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "\"%s\" is not a valid path builder instruction", instructions[i]); return FALSE; } if (n_argss[i] != match.n_args) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "path builder instructions %s requires %u " "arguments, got %u", match.name, match.n_args, n_argss[i]); return FALSE; } args = g_ptr_array_new_with_free_func (value_data_unref); for (guint j = 0; j < n_argss[i]; j++) { ValueData *value_data = NULL; value_data = g_hash_table_lookup (self->values, argss[i][j]); if (value_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", argss[i][j]); return FALSE; } if (!g_type_is_a (value_data->type, match.args[j])) { if (check_can_coerce_type (match.args[j], value_data->type)) g_ptr_array_add (args, wrap_coerce_value (self, value_data, match.args[j])); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "argument %u for path builder instruction %s " "must be of type %s, got %s", j, match.name, g_type_name (match.args[j]), g_type_name (value_data->type)); return FALSE; } } else g_ptr_array_add (args, value_data_ref (value_data)); } g_ptr_array_add (value->path.funcs, match.call); g_ptr_array_add (value->path.argss, g_steal_pointer (&args)); } g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_instance_source_value (BgeWdgtSpec *self, const char *name, GType type, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } if (!g_type_is_a (type, G_TYPE_OBJECT)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type '%s' is not an object type", g_type_name (type)); return FALSE; } if (!G_TYPE_IS_INSTANTIATABLE (type) || G_TYPE_IS_ABSTRACT (type)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type '%s' is not instantiable", g_type_name (type)); return FALSE; } value = value_data_new (); value->kind = VALUE_OBJECT; value->type = type; value->name = g_strdup (name); g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); g_ptr_array_add (self->nonchildren, value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_child_source_value (BgeWdgtSpec *self, const char *name, GType type, const char *parent, const char *builder_type, const char *const *css_classes, guint n_css_classes, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } if (!g_type_is_a (type, GTK_TYPE_WIDGET)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type '%s' does not derive from GtkWidget", g_type_name (type)); return FALSE; } if (!G_TYPE_IS_INSTANTIATABLE (type) || G_TYPE_IS_ABSTRACT (type)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type '%s' is not instantiable", g_type_name (type)); return FALSE; } value = value_data_new (); value->kind = VALUE_CHILD; value->type = type; value->name = g_strdup (name); value->child.builder_type = builder_type != NULL ? g_strdup (builder_type) : NULL; if (n_css_classes > 0 && css_classes != NULL) { value->child.css_classes = g_ptr_array_new_with_free_func (g_free); g_ptr_array_set_size (value->child.css_classes, n_css_classes); for (guint i = 0; i < n_css_classes; i++) { g_ptr_array_index (value->child.css_classes, i) = g_strdup (css_classes[i]); } } if (parent != NULL) { ValueData *parent_data = NULL; parent_data = g_hash_table_lookup (self->values, parent); if (parent_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", parent); return FALSE; } if (!g_type_is_a (parent_data->type, GTK_TYPE_BUILDABLE)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "parent widget '%s' is not of type %s", g_type_name (GTK_TYPE_BUILDABLE), parent); return FALSE; } value->child.parent_widget = value_data_ref (parent_data); } g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); g_ptr_array_add (self->children, value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_cclosure_source_value (BgeWdgtSpec *self, const char *name, GType type, GClosureMarshal marshal, GCallback func, const char *const *args, const GType *arg_types, guint n_args, gpointer user_data, GDestroyNotify destroy_user_data, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (func != NULL, FALSE); g_return_val_if_fail (args != NULL, FALSE); g_return_val_if_fail (n_args > 0, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); if (user_data != NULL && destroy_user_data != NULL) destroy_user_data (user_data); return FALSE; } if (!G_TYPE_IS_VALUE (type)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "invalid type '%s'", g_type_name (type)); if (user_data != NULL && destroy_user_data != NULL) destroy_user_data (user_data); return FALSE; } value = value_data_new (); value->kind = VALUE_CLOSURE; value->name = g_strdup (name); value->type = type; value->closure.marshal = marshal; value->closure.func = func; value->closure.args = g_ptr_array_new_with_free_func (value_data_unref); value->closure.user_data = user_data; value->closure.destroy_user_data = destroy_user_data; for (guint i = 0; i < n_args; i++) { ValueData *value_data = NULL; value_data = g_hash_table_lookup (self->values, args[i]); if (value_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", args[i]); return FALSE; } if (arg_types != NULL && !g_type_is_a (value_data->type, arg_types[i])) { if (check_can_coerce_type (arg_types[i], value_data->type)) g_ptr_array_add (value->closure.args, wrap_coerce_value (self, value_data, arg_types[i])); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "component %u for type %s " "must be of type %s, got %s", i, g_type_name (type), g_type_name (arg_types[i]), g_type_name (value_data->type)); return FALSE; } } else g_ptr_array_add (value->closure.args, value_data_ref (value_data)); } g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_measure_for_size_source_value (BgeWdgtSpec *self, const char *name, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->kind = VALUE_MEASURE_FOR_SIZE; value->type = G_TYPE_INT; g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_widget_width_source_value (BgeWdgtSpec *self, const char *name, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->kind = VALUE_WIDGET_WIDTH; value->type = G_TYPE_DOUBLE; g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_widget_height_source_value (BgeWdgtSpec *self, const char *name, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->kind = VALUE_WIDGET_HEIGHT; value->type = G_TYPE_DOUBLE; g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_tick_time_source_value (BgeWdgtSpec *self, const char *name, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->kind = VALUE_TICK_TIME; value->type = G_TYPE_DOUBLE; g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_track_transition_source_value (BgeWdgtSpec *self, const char *name, const char *src, const char *damping_ratio, const char *mass, const char *stiffness, GError **error) { ValueData *src_value = NULL; g_autoptr (ValueData) coerced_src_value = NULL; ValueData *damping_ratio_value = NULL; g_autoptr (ValueData) coerced_damping_ratio_value = NULL; ValueData *mass_value = NULL; g_autoptr (ValueData) coerced_mass_value = NULL; ValueData *stiffness_value = NULL; g_autoptr (ValueData) coerced_stiffness_value = NULL; g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (src != NULL, FALSE); g_return_val_if_fail (damping_ratio != NULL, FALSE); g_return_val_if_fail (mass != NULL, FALSE); g_return_val_if_fail (stiffness != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } /* TODO clean up type checking process */ src_value = g_hash_table_lookup (self->values, src); if (src_value == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", src); return FALSE; } if (src_value->type != G_TYPE_DOUBLE) { if (check_can_coerce_type (G_TYPE_DOUBLE, src_value->type)) coerced_src_value = wrap_coerce_value (self, src_value, src_value->type); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "source type %s cannot be transitioned", g_type_name (src_value->type)); return FALSE; } } damping_ratio_value = g_hash_table_lookup (self->values, damping_ratio); if (damping_ratio_value == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", damping_ratio); return FALSE; } if (damping_ratio_value->type != G_TYPE_DOUBLE) { if (check_can_coerce_type (G_TYPE_DOUBLE, damping_ratio_value->type)) coerced_damping_ratio_value = wrap_coerce_value (self, damping_ratio_value, damping_ratio_value->type); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "damping ratio must be a double, got type %s", g_type_name (damping_ratio_value->type)); return FALSE; } } mass_value = g_hash_table_lookup (self->values, mass); if (mass_value == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", mass); return FALSE; } if (mass_value->type != G_TYPE_DOUBLE) { if (check_can_coerce_type (G_TYPE_DOUBLE, mass_value->type)) coerced_mass_value = wrap_coerce_value (self, mass_value, mass_value->type); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "mass must be a double, got type %s", g_type_name (mass_value->type)); return FALSE; } } stiffness_value = g_hash_table_lookup (self->values, stiffness); if (stiffness_value == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", stiffness); return FALSE; } if (stiffness_value->type != G_TYPE_DOUBLE) { if (check_can_coerce_type (G_TYPE_DOUBLE, stiffness_value->type)) coerced_stiffness_value = wrap_coerce_value (self, stiffness_value, stiffness_value->type); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "stiffness must be a double, got type %s", g_type_name (stiffness_value->type)); return FALSE; } } value = value_data_new (); value->name = g_strdup (name); value->kind = VALUE_TRACK_TRANSITION; value->type = G_TYPE_DOUBLE; value->track_transition.src = coerced_src_value != NULL ? value_data_ref (coerced_src_value) : value_data_ref (src_value); value->track_transition.spring.damping_ratio = coerced_damping_ratio_value != NULL ? value_data_ref (coerced_damping_ratio_value) : value_data_ref (damping_ratio_value); value->track_transition.spring.mass = coerced_mass_value != NULL ? value_data_ref (coerced_mass_value) : value_data_ref (mass_value); value->track_transition.spring.stiffness = coerced_stiffness_value != NULL ? value_data_ref (coerced_stiffness_value) : value_data_ref (stiffness_value); g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); g_ptr_array_add (self->track_transition_values, value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_variable_value (BgeWdgtSpec *self, GType type, const char *name, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); if (!G_TYPE_IS_VALUE (type)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type '%s' cannot be stored in value '%s'", g_type_name (type), name); return FALSE; } if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = type; value->kind = VALUE_VARIABLE; g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_reference_object_value (BgeWdgtSpec *self, GType type, const char *name, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); if (self->reference != NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "an object reference value has already been defined"); return FALSE; } if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } if (!g_type_is_a (type, G_TYPE_OBJECT)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type '%s' cannot be stored in reference object value '%s'", g_type_name (type), name); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = type; value->kind = VALUE_REFERENCE_OBJECT; g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); self->reference = value_data_ref (value); return TRUE; } gboolean bge_wdgt_spec_add_property_value (BgeWdgtSpec *self, const char *name, const char *object, const char *property, GType *type_out, GError **error) { ValueData *object_value = NULL; ValueData *existing_value = NULL; g_autoptr (GTypeClass) type_class = NULL; GParamSpec *pspec = NULL; g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (object != NULL, FALSE); g_return_val_if_fail (property != NULL, FALSE); object_value = g_hash_table_lookup (self->values, object); if (object_value == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", object); return FALSE; } if (!g_type_is_a (object_value->type, G_TYPE_OBJECT)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is not an object", object); return FALSE; } existing_value = g_hash_table_lookup (self->values, name); if (existing_value != NULL) { if (existing_value->kind == VALUE_PROPERTY && existing_value->property.object == object_value && g_strcmp0 (existing_value->property.prop_name, property) == 0) return TRUE; else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } } type_class = g_type_class_ref (object_value->type); pspec = g_object_class_find_property (G_OBJECT_CLASS (type_class), property); if (pspec == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "property '%s' doesn't exist on type %s", property, g_type_name (object_value->type)); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = pspec->value_type; value->kind = VALUE_PROPERTY; value->property.object = value_data_ref (object_value); value->property.prop_name = g_strdup (property); value->property.pspec_flags = pspec->flags; g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); if (type_out != NULL) *type_out = pspec->value_type; return TRUE; } gboolean bge_wdgt_spec_add_allocation_width_value (BgeWdgtSpec *self, const char *name, const char *child, GError **error) { ValueData *child_value = NULL; g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (child != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } child_value = g_hash_table_lookup (self->values, child); if (child_value == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", child); return FALSE; } if (!g_type_is_a (child_value->type, GTK_TYPE_WIDGET)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is not a widget", child); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = G_TYPE_INT; value->kind = VALUE_ALLOCATION_WIDTH; value->allocation.widget = value_data_ref (child_value); g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_allocation_height_value (BgeWdgtSpec *self, const char *name, const char *child, GError **error) { ValueData *child_value = NULL; g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (child != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } child_value = g_hash_table_lookup (self->values, child); if (child_value == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", child); return FALSE; } if (!g_type_is_a (child_value->type, GTK_TYPE_WIDGET)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is not a widget", child); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = G_TYPE_INT; value->kind = VALUE_ALLOCATION_HEIGHT; value->allocation.widget = value_data_ref (child_value); g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_allocation_transform_value (BgeWdgtSpec *self, const char *name, const char *child, GError **error) { ValueData *child_value = NULL; g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (child != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } child_value = g_hash_table_lookup (self->values, child); if (child_value == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", child); return FALSE; } if (!g_type_is_a (child_value->type, GTK_TYPE_WIDGET)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is not a widget", child); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = GSK_TYPE_TRANSFORM; value->kind = VALUE_ALLOCATION_TRANSFORM; value->allocation.widget = value_data_ref (child_value); g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_measure_value (BgeWdgtSpec *self, const char *name, BgeWdgtMeasureKind kind, GError **error) { g_autoptr (ValueData) value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); if (g_hash_table_contains (self->values, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", name); return FALSE; } value = value_data_new (); value->name = g_strdup (name); value->type = G_TYPE_INT; switch (kind) { case BGE_WDGT_MEASURE_MINIMUM_WIDTH: value->kind = VALUE_MEASURE_MINIMUM_WIDTH; break; case BGE_WDGT_MEASURE_NATURAL_WIDTH: value->kind = VALUE_MEASURE_NATURAL_WIDTH; break; case BGE_WDGT_MEASURE_MINIMUM_HEIGHT: value->kind = VALUE_MEASURE_MINIMUM_HEIGHT; break; case BGE_WDGT_MEASURE_NATURAL_HEIGHT: value->kind = VALUE_MEASURE_NATURAL_HEIGHT; break; default: { g_critical ("Passed an invalid measure kind"); return FALSE; } } g_hash_table_replace (self->values, g_strdup (name), value_data_ref (value)); return TRUE; } gboolean bge_wdgt_spec_add_state (BgeWdgtSpec *self, const char *name, gboolean default_state, GError **error) { g_autoptr (StateData) state = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (name != NULL, FALSE); if (g_hash_table_contains (self->states, name)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "state '%s' already exists", name); return FALSE; } if (default_state && self->default_state != NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "default state already specified"); return FALSE; } state = state_data_new (); state->name = g_strdup (name); state->setters = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, value_data_unref); state->transitions = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, transition_data_unref); state->expressions = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, (GDestroyNotify) gtk_expression_unref); state->snapshot_deps = g_ptr_array_new_with_free_func ( (GDestroyNotify) gtk_expression_unref); state->values_need_tick = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, NULL); g_hash_table_replace (self->states, g_strdup (name), state_data_ref (state)); if (default_state) self->default_state = state_data_ref (state); return TRUE; } gboolean bge_wdgt_spec_set_value (BgeWdgtSpec *self, const char *state, const char *dest_value, const char *src_value, GError **error) { StateData *state_data = NULL; ValueData *dest_data = NULL; ValueData *src_data = NULL; g_autoptr (ValueData) coerced_src_data = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (dest_value != NULL, FALSE); g_return_val_if_fail (src_value != NULL, FALSE); if (state != NULL) state_data = g_hash_table_lookup (self->states, state); else state_data = self->init_state; dest_data = g_hash_table_lookup (self->values, dest_value); src_data = g_hash_table_lookup (self->values, src_value); if (state_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "state '%s' is undefined", state); return FALSE; } if (dest_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", dest_value); return FALSE; } if (src_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", src_value); return FALSE; } if (dest_data == src_data) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "cannot assign '%s' to itself", src_value); return FALSE; } if (!g_type_is_a (src_data->type, dest_data->type)) { if (check_can_coerce_type (dest_data->type, src_data->type)) coerced_src_data = wrap_coerce_value (self, src_data, dest_data->type); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "source type %s cannot be assigned to destination type %s", g_type_name (src_data->type), g_type_name (dest_data->type)); return FALSE; } } if (dest_data->kind == VALUE_CONSTANT) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "cannot assign to a constant source value"); return FALSE; } if (dest_data->kind == VALUE_PROPERTY && !(dest_data->property.pspec_flags & G_PARAM_WRITABLE)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "property %s on type %s is not writable", dest_data->property.prop_name, g_type_name (dest_data->type)); return FALSE; } if (src_data->kind == VALUE_PROPERTY && !(src_data->property.pspec_flags & G_PARAM_READABLE)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "property %s on type %s is not writable", src_data->property.prop_name, g_type_name (src_data->type)); return FALSE; } g_hash_table_replace ( state_data->setters, value_data_ref (dest_data), coerced_src_data != NULL ? value_data_ref (coerced_src_data) : value_data_ref (src_data)); return TRUE; } gboolean bge_wdgt_spec_transition_value (BgeWdgtSpec *self, const char *state, const char *value, const char *seconds, const char *easing, GError **error) { StateData *state_data = NULL; ValueData *value_data = NULL; ValueData *seconds_data = NULL; ValueData *easing_data = NULL; g_autoptr (TransitionData) transition = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); /* state is required for transitions */ g_return_val_if_fail (state != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE); g_return_val_if_fail (seconds != NULL, FALSE); g_return_val_if_fail (easing != NULL, FALSE); state_data = g_hash_table_lookup (self->states, state); if (state_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "state '%s' is undefined", state); return FALSE; } value_data = g_hash_table_lookup (self->values, value); seconds_data = g_hash_table_lookup (self->values, seconds); easing_data = g_hash_table_lookup (self->values, easing); if (value_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", value); return FALSE; } if (value_data->type != G_TYPE_DOUBLE) /* TODO: support more types */ { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type %s cannot be transitioned", g_type_name (value_data->type)); return FALSE; } if (seconds_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", value); return FALSE; } if (seconds_data->type != G_TYPE_DOUBLE) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "transition ease seconds value must be a double, got %s", g_type_name (seconds_data->type)); return FALSE; } if (easing_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", value); return FALSE; } if (easing_data->type != BGE_TYPE_EASING) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "transition ease easing value must be of type %s, got %s", g_type_name (BGE_TYPE_EASING), g_type_name (easing_data->type)); return FALSE; } transition = transition_data_new (); transition->kind = TRANSITION_EASE; transition->ease.seconds = value_data_ref (seconds_data); transition->ease.easing = value_data_ref (easing_data); g_hash_table_replace ( state_data->transitions, value_data_ref (value_data), transition_data_ref (transition)); /* We want the init state to track the transition as well in case of value overlays */ g_hash_table_replace ( self->init_state->transitions, value_data_ref (value_data), transition_data_ref (transition)); return TRUE; } gboolean bge_wdgt_spec_transition_value_spring (BgeWdgtSpec *self, const char *state, const char *value, const char *damping_ratio, const char *mass, const char *stiffness, GError **error) { StateData *state_data = NULL; ValueData *value_data = NULL; ValueData *damping_ratio_data = NULL; ValueData *mass_data = NULL; ValueData *stiffness_data = NULL; g_autoptr (TransitionData) transition = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); /* state is required for transitions */ g_return_val_if_fail (state != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE); g_return_val_if_fail (damping_ratio != NULL, FALSE); g_return_val_if_fail (mass != NULL, FALSE); g_return_val_if_fail (stiffness != NULL, FALSE); state_data = g_hash_table_lookup (self->states, state); value_data = g_hash_table_lookup (self->values, value); damping_ratio_data = g_hash_table_lookup (self->values, damping_ratio); mass_data = g_hash_table_lookup (self->values, mass); stiffness_data = g_hash_table_lookup (self->values, stiffness); if (state_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "state '%s' is undefined", state); return FALSE; } if (value_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", value); return FALSE; } if (damping_ratio_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", damping_ratio); return FALSE; } if (mass_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", mass); return FALSE; } if (stiffness_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", stiffness); return FALSE; } if (value_data->type != G_TYPE_DOUBLE) /* TODO: support more types */ { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type %s cannot be transitioned", g_type_name (value_data->type)); return FALSE; } if (damping_ratio_data->type != G_TYPE_DOUBLE) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "transition damping ratio must of type %s, got %s", g_type_name (G_TYPE_DOUBLE), g_type_name (damping_ratio_data->type)); return FALSE; } if (mass_data->type != G_TYPE_DOUBLE) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "transition mass must of type %s, got %s", g_type_name (G_TYPE_DOUBLE), g_type_name (mass_data->type)); return FALSE; } if (stiffness_data->type != G_TYPE_DOUBLE) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "transition stiffness must of type %s, got %s", g_type_name (G_TYPE_DOUBLE), g_type_name (stiffness_data->type)); return FALSE; } transition = transition_data_new (); transition->kind = TRANSITION_SPRING; transition->spring.damping_ratio = value_data_ref (damping_ratio_data); transition->spring.mass = value_data_ref (mass_data); transition->spring.stiffness = value_data_ref (stiffness_data); g_hash_table_replace ( state_data->transitions, value_data_ref (value_data), transition_data_ref (transition)); /* We want the init state to track the transition as well in case of value overlays */ g_hash_table_replace ( self->init_state->transitions, value_data_ref (value_data), transition_data_ref (transition)); return TRUE; } gboolean bge_wdgt_spec_append_snapshot_instr (BgeWdgtSpec *self, const char *state, BgeWdgtSnapshotInstrKind kind, const char *instr, const char *const *args, guint n_args, guint *n_pops_out, GError **error) { gboolean result = FALSE; StateData *state_data = NULL; ForeachData *foreach_context = NULL; SnapshotInstr match = { 0 }; guint match_rest_start = 0; g_autoptr (SnapshotCallData) call = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (instr != NULL, FALSE); g_return_val_if_fail (n_args == 0 || args != NULL, FALSE); if (state != NULL) { state_data = g_hash_table_lookup (self->states, state); if (state_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "state '%s' is undefined", state); return FALSE; } } else state_data = self->init_state; if (self->foreach_stack->len > 0) foreach_context = g_ptr_array_index ( self->foreach_stack, self->foreach_stack->len - 1); switch (kind) { case BGE_WDGT_SNAPSHOT_INSTR_PUSH: result = lookup_snapshot_push_instr (instr, &match); if (!result) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "\"%s\" is not a valid snapshot push instruction", instr); return FALSE; } if (n_pops_out != NULL) *n_pops_out = match.n_pops; break; case BGE_WDGT_SNAPSHOT_INSTR_TRANSFORM: result = lookup_snapshot_transform_instr (instr, &match); if (!result) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "\"%s\" is not a valid snapshot transform instruction", instr); return FALSE; } break; case BGE_WDGT_SNAPSHOT_INSTR_APPEND: result = lookup_snapshot_append_instr (instr, &match); if (!result) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "\"%s\" is not a valid snapshot append instruction", instr); return FALSE; } break; case BGE_WDGT_SNAPSHOT_INSTR_POP: case BGE_WDGT_SNAPSHOT_INSTR_SAVE: case BGE_WDGT_SNAPSHOT_INSTR_RESTORE: { call = snapshot_call_data_new (); call->kind = kind; if (foreach_context != NULL) call->foreach_context = foreach_data_ref (foreach_context); ensure_state_snapshot (state_data); g_ptr_array_add (state_data->snapshot->calls, snapshot_call_data_ref (call)); } return TRUE; case BGE_WDGT_SNAPSHOT_INSTR_SNAPSHOT_CHILD: { ValueData *child = NULL; if (n_args != 1) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "child snapshot instruction requires " "a single argument"); return FALSE; } child = g_hash_table_lookup (self->values, args[0]); if (child == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", args[0]); return FALSE; } if (!g_type_is_a (child->type, GTK_TYPE_WIDGET)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is not a child", args[0]); return FALSE; } call = snapshot_call_data_new (); call->kind = kind; call->child = value_data_ref (child); if (foreach_context != NULL) call->foreach_context = foreach_data_ref (foreach_context); ensure_state_snapshot (state_data); g_ptr_array_add (state_data->snapshot->calls, snapshot_call_data_ref (call)); } return TRUE; default: g_critical ("invalid snapshot instruction kind specified"); return FALSE; } match_rest_start = match.n_args - match.n_rest; if (n_args != match.n_args) { if (match.n_rest > 0 && n_args > match.n_args) { if ((n_args - match.n_args) % match.n_rest != 0) g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "snapshot instruction %s cannot handle %u " "trailing arguments", match.name, n_args - match.n_args); } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "snapshot instruction %s requires %u " "arguments, got %u", match.name, match.n_args, n_args); return FALSE; } } call = snapshot_call_data_new (); call->kind = kind; call->func = match.call; call->args = g_ptr_array_new_with_free_func (value_data_unref); call->rest = g_ptr_array_new_with_free_func (value_data_unref); if (foreach_context != NULL) call->foreach_context = foreach_data_ref (foreach_context); for (guint i = 0; i < n_args; i++) { ValueData *value_data = NULL; gboolean in_rest = FALSE; GType expected_type = 0; value_data = g_hash_table_lookup (self->values, args[i]); if (value_data == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", args[i]); return FALSE; } in_rest = i >= match_rest_start; if (in_rest) expected_type = match.args[match_rest_start + ((i - match_rest_start) % match.n_rest)]; else expected_type = match.args[i]; if (!g_type_is_a (value_data->type, expected_type)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "argument %u for snapshot instruction %s " "must be of type %s, got %s", i, match.name, g_type_name (expected_type), g_type_name (value_data->type)); return FALSE; } if (in_rest) g_ptr_array_add (call->rest, value_data_ref (value_data)); else g_ptr_array_add (call->args, value_data_ref (value_data)); } ensure_state_snapshot (state_data); g_ptr_array_add (state_data->snapshot->calls, snapshot_call_data_ref (call)); return TRUE; } gboolean bge_wdgt_spec_push_foreach (BgeWdgtSpec *self, const char *model, const char *value_iterator, const char *index_iterator, GType iterator_type, GError **error) { ValueData *model_value = NULL; g_autoptr (GHashTable) values_copy = NULL; GHashTableIter iter = { 0 }; g_autoptr (ForeachData) foreach_context = NULL; g_autoptr (ValueData) value_iterator_value = NULL; g_autoptr (ValueData) index_iterator_value = NULL; g_return_val_if_fail (BGE_IS_WDGT_SPEC (self), FALSE); g_return_val_if_fail (!self->ready, FALSE); g_return_val_if_fail (model != NULL, FALSE); g_return_val_if_fail (value_iterator != NULL, FALSE); g_return_val_if_fail (index_iterator != NULL, FALSE); model_value = g_hash_table_lookup (self->values, model); if (model_value == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' is undefined", model); return FALSE; } if (!g_type_is_a (model_value->type, G_TYPE_LIST_MODEL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' does not implement GListModel", model); return FALSE; } if (g_hash_table_contains (self->values, value_iterator)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", value_iterator); return FALSE; } if (g_hash_table_contains (self->values, index_iterator)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "value '%s' already exists", index_iterator); return FALSE; } if (!g_type_is_a (iterator_type, G_TYPE_OBJECT)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "iterator type does not derive from GObject"); return FALSE; } values_copy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, value_data_unref); g_hash_table_iter_init (&iter, self->values); for (;;) { char *name = NULL; ValueData *value = NULL; if (!g_hash_table_iter_next ( &iter, (gpointer *) &name, (gpointer *) &value)) break; g_hash_table_replace (values_copy, g_strdup (name), value_data_ref (value)); } g_ptr_array_add (self->values_stack, g_steal_pointer (&self->values)); self->values = g_hash_table_ref (values_copy); foreach_context = foreach_data_new (); foreach_context->model = value_data_ref (model_value); foreach_context->values = g_hash_table_ref (values_copy); if (self->foreach_stack->len > 0) { ForeachData *parent = NULL; parent = g_ptr_array_index ( self->foreach_stack, self->foreach_stack->len - 1); foreach_context->parent = foreach_data_ref (parent); } g_ptr_array_add (self->foreach_stack, foreach_data_ref (foreach_context)); g_ptr_array_add (self->foreaches, foreach_data_ref (foreach_context)); value_iterator_value = value_data_new (); value_iterator_value->kind = VALUE_ITERATOR; value_iterator_value->name = g_strdup (value_iterator); value_iterator_value->type = iterator_type; value_iterator_value->iterator.context = foreach_data_ref (foreach_context); g_hash_table_replace (values_copy, g_strdup (value_iterator), value_data_ref (value_iterator_value)); index_iterator_value = value_data_new (); index_iterator_value->kind = VALUE_ITERATOR; index_iterator_value->name = g_strdup (index_iterator); index_iterator_value->type = G_TYPE_UINT; index_iterator_value->iterator.context = foreach_data_ref (foreach_context); g_hash_table_replace (values_copy, g_strdup (index_iterator), value_data_ref (index_iterator_value)); return TRUE; } gboolean bge_wdgt_spec_pop_foreach (BgeWdgtSpec *self) { GHashTable *restore_values = NULL; g_return_val_if_fail (self->foreach_stack->len > 0, FALSE); g_assert (self->values_stack->len > 0); g_clear_pointer (&self->values, g_hash_table_unref); restore_values = g_ptr_array_index (self->values_stack, self->values_stack->len - 1); self->values = g_hash_table_ref (restore_values); g_ptr_array_set_size (self->values_stack, self->values_stack->len - 1); g_ptr_array_set_size (self->foreach_stack, self->foreach_stack->len - 1); return TRUE; } static gboolean check_can_coerce_type (GType dest, GType src) { const struct { GType dest; GType src; } valid_pairings[] = { { G_TYPE_INT, G_TYPE_UINT }, { G_TYPE_INT, G_TYPE_FLOAT }, { G_TYPE_INT, G_TYPE_DOUBLE }, { G_TYPE_UINT, G_TYPE_INT }, { G_TYPE_UINT, G_TYPE_FLOAT }, { G_TYPE_UINT, G_TYPE_DOUBLE }, { G_TYPE_INT64, G_TYPE_INT }, { G_TYPE_INT64, G_TYPE_UINT }, { G_TYPE_INT64, G_TYPE_FLOAT }, { G_TYPE_INT64, G_TYPE_DOUBLE }, { G_TYPE_UINT64, G_TYPE_INT }, { G_TYPE_UINT64, G_TYPE_UINT }, { G_TYPE_UINT64, G_TYPE_INT64 }, { G_TYPE_UINT64, G_TYPE_FLOAT }, { G_TYPE_UINT64, G_TYPE_DOUBLE }, { G_TYPE_FLOAT, G_TYPE_INT }, { G_TYPE_FLOAT, G_TYPE_UINT }, { G_TYPE_FLOAT, G_TYPE_DOUBLE }, { G_TYPE_DOUBLE, G_TYPE_INT }, { G_TYPE_DOUBLE, G_TYPE_UINT }, { G_TYPE_DOUBLE, G_TYPE_FLOAT }, { G_TYPE_STRING, G_TYPE_INT }, { G_TYPE_STRING, G_TYPE_UINT }, { G_TYPE_STRING, G_TYPE_INT64 }, { G_TYPE_STRING, G_TYPE_UINT64 }, { G_TYPE_STRING, G_TYPE_FLOAT }, { G_TYPE_STRING, G_TYPE_DOUBLE }, }; for (guint i = 0; i < G_N_ELEMENTS (valid_pairings); i++) { if (dest == valid_pairings[i].dest && src == valid_pairings[i].src) return TRUE; } return FALSE; } static void coerce_value (const GValue *in, GType dest_type, GValue *out) { /* Not a switch for style, though not the case here GType macros can sometimes be non-compile-time constants */ if (dest_type == G_TYPE_INT) { int val = 0; if (in->g_type == G_TYPE_UINT) val = g_value_get_uint (in); else if (in->g_type == G_TYPE_FLOAT) val = round (g_value_get_float (in)); else if (in->g_type == G_TYPE_DOUBLE) val = round (g_value_get_double (in)); g_value_set_int (out, val); } else if (dest_type == G_TYPE_UINT) { guint val = 0; if (in->g_type == G_TYPE_INT) val = g_value_get_int (in); else if (in->g_type == G_TYPE_FLOAT) val = round (g_value_get_float (in)); else if (in->g_type == G_TYPE_DOUBLE) val = round (g_value_get_double (in)); g_value_set_uint (out, val); } else if (dest_type == G_TYPE_INT64) { gint64 val = 0; if (in->g_type == G_TYPE_INT) val = g_value_get_int (in); else if (in->g_type == G_TYPE_UINT) val = g_value_get_uint (in); else if (in->g_type == G_TYPE_FLOAT) val = round (g_value_get_float (in)); else if (in->g_type == G_TYPE_DOUBLE) val = round (g_value_get_double (in)); g_value_set_int64 (out, val); } else if (dest_type == G_TYPE_UINT64) { guint64 val = 0; if (in->g_type == G_TYPE_INT) val = g_value_get_int (in); else if (in->g_type == G_TYPE_UINT) val = g_value_get_uint (in); else if (in->g_type == G_TYPE_INT64) val = g_value_get_int64 (in); else if (in->g_type == G_TYPE_UINT64) val = round (g_value_get_float (in)); else if (in->g_type == G_TYPE_DOUBLE) val = round (g_value_get_double (in)); g_value_set_uint64 (out, val); } else if (dest_type == G_TYPE_FLOAT) { float val = 0; if (in->g_type == G_TYPE_INT) val = g_value_get_int (in); else if (in->g_type == G_TYPE_UINT) val = g_value_get_uint (in); else if (in->g_type == G_TYPE_DOUBLE) val = round (g_value_get_double (in)); g_value_set_float (out, val); } else if (dest_type == G_TYPE_DOUBLE) { double val = 0; if (in->g_type == G_TYPE_INT) val = g_value_get_int (in); else if (in->g_type == G_TYPE_UINT) val = g_value_get_uint (in); else if (in->g_type == G_TYPE_FLOAT) val = round (g_value_get_float (in)); g_value_set_double (out, val); } else if (dest_type == G_TYPE_STRING) { g_autofree char *val = NULL; if (in->g_type == G_TYPE_INT) val = g_strdup_printf ("%d", g_value_get_int (in)); else if (in->g_type == G_TYPE_UINT) val = g_strdup_printf ("%u", g_value_get_uint (in)); else if (in->g_type == G_TYPE_INT64) val = g_strdup_printf ("%zd", g_value_get_int64 (in)); else if (in->g_type == G_TYPE_UINT64) val = g_strdup_printf ("%zu", g_value_get_uint64 (in)); else if (in->g_type == G_TYPE_FLOAT) val = g_strdup_printf ("%f", g_value_get_float (in)); else if (in->g_type == G_TYPE_DOUBLE) val = g_strdup_printf ("%f", g_value_get_double (in)); g_value_take_string (out, g_steal_pointer (&val)); } } static ValueData * wrap_coerce_value (BgeWdgtSpec *self, ValueData *value, GType dest_type) { g_autoptr (ValueData) coerced = NULL; g_assert (!g_type_is_a (value->type, dest_type)); coerced = value_data_new (); coerced->type = dest_type; coerced->kind = VALUE_COERCION; coerced->coercion.value = value_data_ref (value); g_ptr_array_add (self->anon_values, value_data_ref (coerced)); return g_steal_pointer (&coerced); } static void ensure_state_snapshot (StateData *state) { if (state->snapshot != NULL) return; state->snapshot = snapshot_data_new (); state->snapshot->calls = g_ptr_array_new_with_free_func ( snapshot_call_data_unref); } /* ------------------------------ */ /* Widget Renderer Implementation */ /* ------------------------------ */ #define BGE_TYPE_WDGT_NOTIFIER (bge_wdgt_notifier_get_type ()) G_DECLARE_FINAL_TYPE (BgeWdgtNotifier, bge_wdgt_notifier, BGE, WDGT_NOTIFIER, GObject) struct _BgeWdgtNotifier { GObject parent_instance; double value; }; G_DEFINE_FINAL_TYPE (BgeWdgtNotifier, bge_wdgt_notifier, G_TYPE_OBJECT); enum { NOTIFIER_PROP_0, NOTIFIER_PROP_VALUE, LAST_NOTIFIER_PROP }; static GParamSpec *notifier_props[LAST_NOTIFIER_PROP] = { 0 }; static void bge_wdgt_notifier_dispose (GObject *object) { BgeWdgtNotifier *self = BGE_WDGT_NOTIFIER (object); (void) self; G_OBJECT_CLASS (bge_wdgt_notifier_parent_class)->dispose (object); } static void bge_wdgt_notifier_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BgeWdgtNotifier *self = BGE_WDGT_NOTIFIER (object); switch (prop_id) { case NOTIFIER_PROP_VALUE: g_value_set_double (value, self->value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bge_wdgt_notifier_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BgeWdgtNotifier *self = BGE_WDGT_NOTIFIER (object); switch (prop_id) { case NOTIFIER_PROP_VALUE: self->value = g_value_get_double (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bge_wdgt_notifier_class_init (BgeWdgtNotifierClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bge_wdgt_notifier_set_property; object_class->get_property = bge_wdgt_notifier_get_property; object_class->dispose = bge_wdgt_notifier_dispose; notifier_props[NOTIFIER_PROP_VALUE] = g_param_spec_double ( "value", NULL, NULL, G_MININT, G_MAXINT, 0.0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, notifier_props); } static void bge_wdgt_notifier_init (BgeWdgtNotifier *self) { } /* --- */ BGE_DEFINE_DATA ( foreach_instance, ForeachInstance, { guint current_idx; BgeWdgtNotifier *notifier; }, BGE_RELEASE_DATA (notifier, g_object_unref)) BGE_DEFINE_DATA ( state_instance, StateInstance, { GHashTable *transitions; }, BGE_RELEASE_DATA (transitions, g_hash_table_unref)); struct _BgeWdgtRenderer { GtkWidget parent_instance; BgeWdgtSpec *spec; char *state; GObject *reference; GtkWidget *child; StateInstanceData *init_instance; GPtrArray *init_watches; StateData *active_state; StateInstanceData *active_instance; SnapshotData *active_snapshot; StateData *last_state; StateInstanceData *last_instance; GTimer *since_last_state; guint tick; gboolean had_tick_since_state_switch; GHashTable *objects; GPtrArray *nonchildren; GPtrArray *children; GHashTable *allocations; GHashTable *foreach_instances; GHashTable *state_instances; GHashTable *transition_instances; GHashTable *transition_closure_instances; GHashTable *track_transition_closure_instances; GPtrArray *track_transitions; GPtrArray *bindings; GPtrArray *watches; BgeWdgtNotifier *reference_notifier; int measure_minimum_width; int measure_natural_width; int measure_minimum_height; int measure_natural_height; int current_measure_for_size; BgeWdgtNotifier *measure_for_size_notifier; int widget_width; int widget_height; BgeWdgtNotifier *widget_width_notifier; BgeWdgtNotifier *widget_height_notifier; GTimer *tick_time; BgeWdgtNotifier *tick_time_notifier; }; G_DEFINE_FINAL_TYPE (BgeWdgtRenderer, bge_wdgt_renderer, GTK_TYPE_WIDGET); enum { RENDERER_PROP_0, RENDERER_PROP_SPEC, RENDERER_PROP_RESOURCE, RENDERER_PROP_STATE, RENDERER_PROP_REFERENCE, RENDERER_PROP_CHILD, LAST_RENDERER_PROP }; static GParamSpec *renderer_props[LAST_RENDERER_PROP] = { 0 }; BGE_DEFINE_DATA ( watch_setter, WatchSetter, { BgeWdgtRenderer *self; StateData *state; StateInstanceData *instance; ValueData *dest; ValueData *src; }, BGE_RELEASE_DATA (state, state_data_unref); BGE_RELEASE_DATA (instance, state_instance_data_unref); BGE_RELEASE_DATA (dest, value_data_unref); BGE_RELEASE_DATA (src, value_data_unref)) BGE_DEFINE_DATA ( allocation, Allocation, { ValueData *width; ValueData *height; ValueData *transform; }, BGE_RELEASE_DATA (width, value_data_unref); BGE_RELEASE_DATA (height, value_data_unref); BGE_RELEASE_DATA (transform, value_data_unref)) typedef struct { double velocity; double est_duration; double cache_damping_ratio; double cache_mass; double cache_stiffness; } SpringCache; BGE_DEFINE_DATA ( transition_instance, TransitionInstance, { double value; double elapsed; BgeWdgtNotifier *notifier; struct { BgeEasing easing; double seconds; } ease; SpringCache spring; }, BGE_RELEASE_DATA (notifier, g_object_unref)) BGE_DEFINE_DATA ( transition_closure, TransitionClosure, { StateData *state; StateInstanceData *instance; ValueData *value; }, BGE_RELEASE_DATA (state, state_data_unref); BGE_RELEASE_DATA (instance, state_instance_data_unref); BGE_RELEASE_DATA (value, value_data_unref)); BGE_DEFINE_DATA ( track_transition_closure, TrackTransitionClosure, { ValueData *value; GTimer *timer; BgeWdgtNotifier *notifier; double elapsed; double current; double target; double last; SpringCache spring; }, BGE_RELEASE_DATA (value, value_data_unref); BGE_RELEASE_DATA (notifier, g_object_unref); BGE_RELEASE_DATA (timer, g_timer_destroy)); static void regenerate (BgeWdgtRenderer *self); static void spawn_nonchild (BgeWdgtRenderer *self, ValueData *value); static void spawn_child (BgeWdgtRenderer *self, ValueData *value, GtkBuilder *dummy_builder); static void apply_state (BgeWdgtRenderer *self); static GtkExpression * ensure_expressions (BgeWdgtSpec *self, ValueData *value, StateData *state, gboolean *value_needs_tick); static void set_value (BgeWdgtRenderer *self, StateData *state, StateInstanceData *instance, ValueData *dest, ValueData *src, GPtrArray *watches); static int resolve_value_int (BgeWdgtRenderer *self, ValueData *value, StateData *state); static double resolve_value_double (BgeWdgtRenderer *self, ValueData *value, StateData *state); static gint resolve_value_enum (BgeWdgtRenderer *self, ValueData *value, StateData *state); static gpointer resolve_value_boxed_dup (BgeWdgtRenderer *self, ValueData *value, StateData *state); static gpointer resolve_value_object_dup (BgeWdgtRenderer *self, ValueData *value, StateData *state); static void discard_binding (gpointer ptr); static void discard_watch (gpointer ptr); static void prop_change_queue_draw (BgeWdgtRenderer *self); static void reset_setter (WatchSetterData *data); static void wdgt_renderer_set_from_resource (BgeWdgtRenderer *self, const char *resource); static void bge_wdgt_renderer_dispose (GObject *object) { BgeWdgtRenderer *self = BGE_WDGT_RENDERER (object); if (self->tick > 0) { gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick); self->tick = 0; } g_clear_pointer (&self->spec, g_object_unref); g_clear_pointer (&self->state, g_free); g_clear_pointer (&self->reference, g_object_unref); g_clear_pointer (&self->child, gtk_widget_unparent); g_clear_pointer (&self->init_instance, state_instance_data_unref); g_clear_pointer (&self->init_watches, g_ptr_array_unref); g_clear_pointer (&self->active_state, state_data_unref); g_clear_pointer (&self->active_instance, state_instance_data_unref); g_clear_pointer (&self->active_snapshot, snapshot_data_unref); g_clear_pointer (&self->last_state, state_data_unref); g_clear_pointer (&self->last_instance, state_instance_data_unref); g_clear_pointer (&self->since_last_state, g_timer_destroy); g_clear_pointer (&self->objects, g_hash_table_unref); g_clear_pointer (&self->children, g_ptr_array_unref); g_clear_pointer (&self->allocations, g_hash_table_unref); g_clear_pointer (&self->nonchildren, g_ptr_array_unref); g_clear_pointer (&self->foreach_instances, g_hash_table_unref); g_clear_pointer (&self->state_instances, g_hash_table_unref); g_clear_pointer (&self->transition_instances, g_hash_table_unref); g_clear_pointer (&self->transition_closure_instances, g_hash_table_unref); g_clear_pointer (&self->track_transition_closure_instances, g_hash_table_unref); g_clear_pointer (&self->track_transitions, g_ptr_array_unref); g_clear_pointer (&self->bindings, g_ptr_array_unref); g_clear_pointer (&self->watches, g_ptr_array_unref); g_clear_pointer (&self->reference_notifier, g_object_unref); g_clear_pointer (&self->measure_for_size_notifier, g_object_unref); g_clear_pointer (&self->widget_width_notifier, g_object_unref); g_clear_pointer (&self->widget_height_notifier, g_object_unref); g_clear_pointer (&self->tick_time, g_timer_destroy); g_clear_pointer (&self->tick_time_notifier, g_object_unref); G_OBJECT_CLASS (bge_wdgt_renderer_parent_class)->dispose (object); } static void bge_wdgt_renderer_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BgeWdgtRenderer *self = BGE_WDGT_RENDERER (object); switch (prop_id) { case RENDERER_PROP_SPEC: g_value_set_object (value, bge_wdgt_renderer_get_spec (self)); break; case RENDERER_PROP_STATE: g_value_set_string (value, bge_wdgt_renderer_get_state (self)); break; case RENDERER_PROP_REFERENCE: g_value_set_object (value, bge_wdgt_renderer_get_reference (self)); break; case RENDERER_PROP_CHILD: g_value_set_object (value, bge_wdgt_renderer_get_child (self)); break; case RENDERER_PROP_RESOURCE: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bge_wdgt_renderer_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BgeWdgtRenderer *self = BGE_WDGT_RENDERER (object); switch (prop_id) { case RENDERER_PROP_SPEC: bge_wdgt_renderer_set_spec (self, g_value_get_object (value)); break; case RENDERER_PROP_RESOURCE: wdgt_renderer_set_from_resource (self, g_value_get_string (value)); break; case RENDERER_PROP_STATE: bge_wdgt_renderer_set_state (self, g_value_get_string (value)); break; case RENDERER_PROP_REFERENCE: bge_wdgt_renderer_set_reference (self, g_value_get_object (value)); break; case RENDERER_PROP_CHILD: bge_wdgt_renderer_set_child (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bge_wdgt_renderer_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BgeWdgtRenderer *self = BGE_WDGT_RENDERER (widget); gboolean wdgt_measured = FALSE; self->current_measure_for_size = for_size; /* This will update our measurement values in self */ g_object_notify_by_pspec ( G_OBJECT (self->measure_for_size_notifier), notifier_props[NOTIFIER_PROP_VALUE]); switch (orientation) { case GTK_ORIENTATION_HORIZONTAL: if (self->measure_minimum_width > 0 || self->measure_natural_width > 0) { *minimum = self->measure_minimum_width; *natural = self->measure_natural_width; wdgt_measured = TRUE; } break; case GTK_ORIENTATION_VERTICAL: if (self->measure_minimum_height > 0 || self->measure_natural_height > 0) { *minimum = self->measure_minimum_height; *natural = self->measure_natural_height; wdgt_measured = TRUE; } break; default: g_assert_not_reached (); } if (!wdgt_measured) { GtkWidget *child = NULL; child = gtk_widget_get_first_child (GTK_WIDGET (self)); if (child != NULL) gtk_widget_measure ( GTK_WIDGET (child), orientation, for_size, minimum, natural, minimum_baseline, natural_baseline); } } static void bge_wdgt_renderer_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BgeWdgtRenderer *self = BGE_WDGT_RENDERER (widget); self->widget_width = width; self->widget_height = height; g_object_notify_by_pspec ( G_OBJECT (self->widget_width_notifier), notifier_props[NOTIFIER_PROP_VALUE]); g_object_notify_by_pspec ( G_OBJECT (self->widget_height_notifier), notifier_props[NOTIFIER_PROP_VALUE]); 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->children->len; i++) { GtkWidget *child = NULL; AllocationData *allocation = NULL; int alloc_width = width; int alloc_height = height; g_autoptr (GskTransform) transform = NULL; child = g_ptr_array_index (self->children, i); allocation = g_hash_table_lookup (self->allocations, child); alloc_width = resolve_value_int ( self, allocation->width, self->active_instance != NULL ? self->active_state : self->spec->init_state); alloc_height = resolve_value_int ( self, allocation->height, self->active_state != NULL ? self->active_state : self->spec->init_state); transform = resolve_value_boxed_dup ( self, allocation->transform, self->active_state != NULL ? self->active_state : self->spec->init_state); gtk_widget_allocate ( child, MAX (alloc_width, 0.0), MAX (alloc_height, 0.0), baseline, g_steal_pointer (&transform)); } } static gboolean recurse_snapshot (BgeWdgtRenderer *self, GtkSnapshot *snapshot, GPtrArray *calls, guint *idx, ForeachData *foreach_context, ForeachData *parent_foreach, gboolean skip_foreach) { gboolean result = FALSE; guint start_idx = 0; guint n_iters = 0; ForeachData *next_foreach = NULL; ForeachInstanceData *foreach_instance = NULL; g_autoptr (GListModel) model = NULL; start_idx = *idx; if (foreach_context != NULL) { for (ForeachData *data = foreach_context->parent; data != NULL && data != parent_foreach; data = data->parent) { next_foreach = foreach_context; foreach_context = data; } foreach_instance = g_hash_table_lookup ( self->foreach_instances, foreach_context); g_assert (foreach_instance != NULL); model = resolve_value_object_dup ( self, foreach_context->model, self->active_state); if (model != NULL) n_iters = g_list_model_get_n_items (model); else { n_iters = 1; skip_foreach = TRUE; } } else n_iters = 1; for (guint i = 0; i < n_iters; i++) { if (foreach_instance != NULL) { foreach_instance->current_idx = i; g_object_notify_by_pspec ( G_OBJECT (foreach_instance->notifier), notifier_props[NOTIFIER_PROP_VALUE]); } *idx = start_idx; if (next_foreach != NULL) { result = recurse_snapshot ( self, snapshot, calls, idx, next_foreach, foreach_context, skip_foreach); if (!result) return FALSE; } for (; *idx < calls->len; (*idx)++) { SnapshotCallData *call = NULL; call = g_ptr_array_index (calls, *idx); if ((call->foreach_context != NULL || parent_foreach != NULL) && call->foreach_context == parent_foreach) break; else if (call->foreach_context != foreach_context) { result = recurse_snapshot ( self, snapshot, calls, idx, call->foreach_context, foreach_context, skip_foreach); if (!result) return FALSE; } else if (!skip_foreach) { switch (call->kind) { case BGE_WDGT_SNAPSHOT_INSTR_POP: gtk_snapshot_pop (snapshot); break; case BGE_WDGT_SNAPSHOT_INSTR_SAVE: gtk_snapshot_save (snapshot); break; case BGE_WDGT_SNAPSHOT_INSTR_RESTORE: gtk_snapshot_restore (snapshot); break; case BGE_WDGT_SNAPSHOT_INSTR_APPEND: case BGE_WDGT_SNAPSHOT_INSTR_PUSH: case BGE_WDGT_SNAPSHOT_INSTR_TRANSFORM: { GValue arg_values[ARGBUF_SIZE] = { 0 }; guint n_arg_values = 0; GValue rest_values[ARGBUF_SIZE] = { 0 }; guint n_rest_values = 0; n_arg_values = MIN (call->args->len, G_N_ELEMENTS (arg_values)); n_rest_values = MIN (call->rest->len, G_N_ELEMENTS (rest_values)); for (guint j = 0; j < n_arg_values; j++) { ValueData *value = NULL; GtkExpression *expression = NULL; value = g_ptr_array_index (call->args, j); expression = g_hash_table_lookup (self->active_state->expressions, value); result = gtk_expression_evaluate (expression, self, &arg_values[j]); if (!result) return FALSE; } for (guint j = 0; j < n_rest_values; j++) { ValueData *value = NULL; GtkExpression *expression = NULL; value = g_ptr_array_index (call->rest, j); expression = g_hash_table_lookup (self->active_state->expressions, value); result = gtk_expression_evaluate (expression, self, &rest_values[j]); if (!result) return FALSE; } call->func (snapshot, arg_values, rest_values, n_rest_values); for (guint j = 0; j < n_rest_values; j++) { g_value_unset (&rest_values[j]); } for (guint j = 0; j < n_arg_values; j++) { g_value_unset (&arg_values[j]); } } break; case BGE_WDGT_SNAPSHOT_INSTR_SNAPSHOT_CHILD: { GtkExpression *expression = NULL; GValue child_value = G_VALUE_INIT; GtkWidget *child = NULL; expression = g_hash_table_lookup ( self->active_state->expressions, call->child); gtk_expression_evaluate (expression, self, &child_value); child = g_value_get_object (&child_value); if (child != NULL) { if (gtk_widget_get_parent (child) == GTK_WIDGET (self)) gtk_widget_snapshot_child (GTK_WIDGET (self), child, snapshot); else g_critical ("Trying to snapshot a widget which is " "not a direct child of this spec! Skipping"); } g_value_unset (&child_value); } break; default: break; } } } } return TRUE; } static void bge_wdgt_renderer_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BgeWdgtRenderer *self = BGE_WDGT_RENDERER (widget); GPtrArray *calls = NULL; guint call_idx = 0; if (self->active_state == NULL || self->active_instance == NULL || self->active_snapshot == NULL) goto done; calls = self->active_snapshot->calls; recurse_snapshot (self, snapshot, calls, &call_idx, NULL, NULL, FALSE); done: if (self->child != NULL) gtk_widget_snapshot_child (GTK_WIDGET (self), self->child, snapshot); // for (guint i = 0; i < self->children->len; i++) // { // GtkWidget *child = NULL; // // child = g_ptr_array_index (self->children, i); // gtk_widget_snapshot_child (GTK_WIDGET (self), child, snapshot); // } } static void bge_wdgt_renderer_class_init (BgeWdgtRendererClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bge_wdgt_renderer_set_property; object_class->get_property = bge_wdgt_renderer_get_property; object_class->dispose = bge_wdgt_renderer_dispose; renderer_props[RENDERER_PROP_SPEC] = g_param_spec_object ( "spec", NULL, NULL, BGE_TYPE_WDGT_SPEC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); renderer_props[RENDERER_PROP_RESOURCE] = g_param_spec_string ( "resource", NULL, NULL, NULL, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); renderer_props[RENDERER_PROP_STATE] = g_param_spec_string ( "state", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); renderer_props[RENDERER_PROP_REFERENCE] = g_param_spec_object ( "reference", NULL, NULL, G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); renderer_props[RENDERER_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_RENDERER_PROP, renderer_props); widget_class->measure = bge_wdgt_renderer_measure; widget_class->size_allocate = bge_wdgt_renderer_size_allocate; widget_class->snapshot = bge_wdgt_renderer_snapshot; g_type_ensure (BGE_TYPE_WDGT_NOTIFIER); } static gboolean tick_cb (BgeWdgtRenderer *self, GdkFrameClock *frame_clock, gpointer user_data) { gboolean should_animate = FALSE; GHashTableIter iter = { 0 }; gboolean finished_all_state_transitions = TRUE; self->had_tick_since_state_switch = TRUE; g_object_notify_by_pspec ( G_OBJECT (self->tick_time_notifier), notifier_props[NOTIFIER_PROP_VALUE]); should_animate = bge_should_animate (GTK_WIDGET (self)); for (guint i = 0; i < self->track_transitions->len;) { TrackTransitionClosureData *data = NULL; double elapsed = 0.0; data = g_ptr_array_index (self->track_transitions, i); elapsed = g_timer_elapsed (data->timer, NULL); g_object_notify_by_pspec ( G_OBJECT (data->notifier), notifier_props[NOTIFIER_PROP_VALUE]); if (should_animate && elapsed <= data->spring.est_duration) i++; else g_ptr_array_remove_index (self->track_transitions, i); } if (should_animate && self->spec != NULL && self->active_state != NULL && self->active_instance != NULL && self->last_state != NULL && self->last_instance != NULL) { double elapsed = 0.0; elapsed = g_timer_elapsed (self->since_last_state, NULL); g_hash_table_iter_init (&iter, self->active_state->transitions); for (;;) { ValueData *value = NULL; TransitionData *transition = NULL; TransitionInstanceData *transition_instance = NULL; TransitionInstanceData *init_transition_instance = NULL; if (!g_hash_table_iter_next ( &iter, (gpointer *) &value, (gpointer *) &transition)) break; transition_instance = g_hash_table_lookup (self->active_instance->transitions, value); if (transition_instance != NULL) g_object_notify_by_pspec ( G_OBJECT (transition_instance->notifier), notifier_props[NOTIFIER_PROP_VALUE]); init_transition_instance = g_hash_table_lookup (self->init_instance->transitions, value); if (init_transition_instance != NULL) g_object_notify_by_pspec ( G_OBJECT (init_transition_instance->notifier), notifier_props[NOTIFIER_PROP_VALUE]); switch (transition->kind) { case TRANSITION_EASE: if (elapsed <= transition_instance->ease.seconds) finished_all_state_transitions = FALSE; break; case TRANSITION_SPRING: if (transition_instance->spring.est_duration < 0.0 || elapsed <= transition_instance->spring.est_duration) finished_all_state_transitions = FALSE; break; default: g_assert_not_reached (); } } } if (finished_all_state_transitions) { g_clear_pointer (&self->last_state, state_data_unref); g_clear_pointer (&self->last_instance, state_instance_data_unref); } if ((self->active_state == NULL || !self->active_state->needs_tick) && self->track_transitions->len == 0 && finished_all_state_transitions) { gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick); self->tick = 0; return G_SOURCE_REMOVE; } return G_SOURCE_CONTINUE; } static void bge_wdgt_renderer_init (BgeWdgtRenderer *self) { self->init_watches = g_ptr_array_new_with_free_func (discard_watch); self->objects = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, g_object_unref); self->children = g_ptr_array_new_with_free_func ( (GDestroyNotify) gtk_widget_unparent); self->nonchildren = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_object_unref); self->allocations = g_hash_table_new_full ( g_direct_hash, g_direct_equal, g_object_unref, allocation_data_unref); self->foreach_instances = g_hash_table_new_full ( g_direct_hash, g_direct_equal, foreach_data_unref, NULL); self->state_instances = g_hash_table_new_full ( g_direct_hash, g_direct_equal, state_data_unref, state_instance_data_unref); self->transition_instances = g_hash_table_new_full ( g_direct_hash, g_direct_equal, transition_data_unref, transition_instance_data_unref); self->transition_closure_instances = g_hash_table_new_full ( g_direct_hash, g_direct_equal, transition_data_unref, transition_closure_data_unref); self->track_transition_closure_instances = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, track_transition_closure_data_unref); self->track_transitions = g_ptr_array_new_with_free_func ( track_transition_closure_data_unref); self->bindings = g_ptr_array_new_with_free_func (discard_binding); self->watches = g_ptr_array_new_with_free_func (discard_watch); self->since_last_state = g_timer_new (); self->tick_time = g_timer_new (); self->reference_notifier = g_object_new (BGE_TYPE_WDGT_NOTIFIER, NULL); self->measure_for_size_notifier = g_object_new (BGE_TYPE_WDGT_NOTIFIER, NULL); self->widget_width_notifier = g_object_new (BGE_TYPE_WDGT_NOTIFIER, NULL); self->widget_height_notifier = g_object_new (BGE_TYPE_WDGT_NOTIFIER, NULL); self->tick_time_notifier = g_object_new (BGE_TYPE_WDGT_NOTIFIER, NULL); } BgeWdgtRenderer * bge_wdgt_renderer_new (void) { return g_object_new (BGE_TYPE_WDGT_RENDERER, NULL); } BgeWdgtSpec * bge_wdgt_renderer_get_spec (BgeWdgtRenderer *self) { g_return_val_if_fail (BGE_IS_WDGT_RENDERER (self), NULL); return self->spec; } const char * bge_wdgt_renderer_get_state (BgeWdgtRenderer *self) { g_return_val_if_fail (BGE_IS_WDGT_RENDERER (self), NULL); return self->state; } GObject * bge_wdgt_renderer_get_reference (BgeWdgtRenderer *self) { g_return_val_if_fail (BGE_IS_WDGT_RENDERER (self), NULL); return self->reference; } GtkWidget * bge_wdgt_renderer_get_child (BgeWdgtRenderer *self) { g_return_val_if_fail (BGE_IS_WDGT_RENDERER (self), NULL); return self->child; } void bge_wdgt_renderer_set_spec (BgeWdgtRenderer *self, BgeWdgtSpec *spec) { GBinding *name_binding = NULL; g_return_if_fail (BGE_IS_WDGT_RENDERER (self)); g_return_if_fail (spec == NULL || BGE_IS_WDGT_SPEC (spec)); if (spec == self->spec) return; g_clear_pointer (&self->spec, g_object_unref); if (spec != NULL) self->spec = g_object_ref (spec); regenerate (self); apply_state (self); if (spec != NULL) { name_binding = g_object_bind_property (spec, "name", self, "name", G_BINDING_SYNC_CREATE); g_ptr_array_add (self->bindings, g_object_ref (name_binding)); } else gtk_widget_set_name (GTK_WIDGET (self), NULL); g_object_notify_by_pspec (G_OBJECT (self), renderer_props[RENDERER_PROP_SPEC]); } void bge_wdgt_renderer_set_state (BgeWdgtRenderer *self, const char *state) { g_return_if_fail (BGE_IS_WDGT_RENDERER (self)); if (state == self->state || (state != NULL && self->state != NULL && g_strcmp0 (state, self->state) == 0)) return; g_clear_pointer (&self->state, g_free); if (state != NULL) self->state = g_strdup (state); apply_state (self); g_object_notify_by_pspec (G_OBJECT (self), renderer_props[RENDERER_PROP_STATE]); } void bge_wdgt_renderer_set_reference (BgeWdgtRenderer *self, GObject *reference) { g_return_if_fail (BGE_IS_WDGT_RENDERER (self)); if (reference == self->reference) return; g_clear_pointer (&self->reference, g_object_unref); if (reference != NULL) self->reference = g_object_ref (reference); g_object_notify_by_pspec (G_OBJECT (self), renderer_props[RENDERER_PROP_REFERENCE]); g_object_notify_by_pspec (G_OBJECT (self->reference_notifier), notifier_props[NOTIFIER_PROP_VALUE]); } void bge_wdgt_renderer_set_child (BgeWdgtRenderer *self, GtkWidget *child) { g_return_if_fail (BGE_IS_WDGT_RENDERER (self)); 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), renderer_props[RENDERER_PROP_CHILD]); } void bge_wdgt_renderer_set_state_take (BgeWdgtRenderer *self, char *state) { g_return_if_fail (BGE_IS_WDGT_RENDERER (self)); if (state != NULL && self->state != NULL && g_strcmp0 (state, self->state) == 0) { g_free (state); return; } g_clear_pointer (&self->state, g_free); if (state != NULL) self->state = state; g_object_notify_by_pspec (G_OBJECT (self), renderer_props[RENDERER_PROP_STATE]); } gpointer bge_wdgt_renderer_lookup_object (BgeWdgtRenderer *self, const char *name) { ValueData *value = NULL; g_return_val_if_fail (BGE_IS_WDGT_RENDERER (self), NULL); g_return_val_if_fail (name != NULL, NULL); if (self->spec == NULL) return NULL; value = g_hash_table_lookup (self->spec->values, name); if (value == NULL) return NULL; if (!g_type_is_a (value->type, G_TYPE_OBJECT)) return NULL; return resolve_value_object_dup ( self, value, self->active_state != NULL ? self->active_state : self->spec->init_state); } static void regenerate (BgeWdgtRenderer *self) { BgeWdgtSpec *spec = self->spec; g_autoptr (GtkBuilder) dummy_builder = NULL; GHashTableIter state_iter = { 0 }; GHashTableIter setters_iter = { 0 }; g_clear_pointer (&self->init_instance, state_instance_data_unref); g_ptr_array_set_size (self->init_watches, 0); g_hash_table_remove_all (self->state_instances); g_hash_table_remove_all (self->objects); g_ptr_array_set_size (self->children, 0); g_ptr_array_set_size (self->nonchildren, 0); g_hash_table_remove_all (self->allocations); g_hash_table_remove_all (self->foreach_instances); g_ptr_array_set_size (self->track_transitions, 0); g_clear_pointer (&self->last_state, state_data_unref); g_clear_pointer (&self->last_instance, state_instance_data_unref); g_clear_pointer (&self->active_state, state_data_unref); g_clear_pointer (&self->active_instance, state_instance_data_unref); g_clear_pointer (&self->active_snapshot, snapshot_data_unref); g_ptr_array_set_size (self->bindings, 0); g_ptr_array_set_size (self->watches, 0); self->measure_minimum_width = -1; self->measure_natural_width = -1; self->measure_minimum_height = -1; self->measure_natural_height = -1; if (self->spec == NULL) return; for (guint i = 0; i < spec->foreaches->len; i++) { ForeachData *data = NULL; g_autoptr (ForeachInstanceData) foreach_instance = NULL; data = g_ptr_array_index (spec->foreaches, i); foreach_instance = foreach_instance_data_new (); foreach_instance->notifier = g_object_new (BGE_TYPE_WDGT_NOTIFIER, NULL); g_hash_table_replace (self->foreach_instances, foreach_data_ref (data), foreach_instance_data_ref (foreach_instance)); } for (guint i = 0; i < spec->nonchildren->len; i++) { ValueData *value = NULL; value = g_ptr_array_index (spec->nonchildren, i); spawn_nonchild (self, value); } dummy_builder = gtk_builder_new (); for (guint i = 0; i < spec->children->len; i++) { ValueData *value = NULL; value = g_ptr_array_index (spec->children, i); spawn_child (self, value, dummy_builder); } g_hash_table_iter_init (&state_iter, spec->states); for (;;) { char *state_name = NULL; StateData *state = NULL; g_autoptr (StateInstanceData) instance = NULL; GHashTableIter transitions_iter = { 0 }; if (!g_hash_table_iter_next ( &state_iter, (gpointer *) &state_name, (gpointer *) &state)) break; instance = state_instance_data_new (); instance->transitions = g_hash_table_new_full ( g_direct_hash, g_direct_equal, value_data_unref, transition_instance_data_unref); g_hash_table_replace (self->state_instances, state_data_ref (state), state_instance_data_ref (instance)); g_hash_table_iter_init (&transitions_iter, state->transitions); for (;;) { ValueData *value = NULL; TransitionData *transition = NULL; g_autoptr (BgeWdgtNotifier) notifier_object = NULL; g_autoptr (TransitionInstanceData) instance_data = NULL; g_autoptr (TransitionClosureData) closure_data = NULL; if (!g_hash_table_iter_next ( &transitions_iter, (gpointer *) &value, (gpointer *) &transition)) break; notifier_object = g_object_new (BGE_TYPE_WDGT_NOTIFIER, NULL); instance_data = transition_instance_data_new (); instance_data->notifier = g_object_ref (notifier_object); switch (transition->kind) { case TRANSITION_EASE: instance_data->elapsed = G_MAXINT; break; case TRANSITION_SPRING: instance_data->spring.est_duration = -1.0; break; default: g_assert_not_reached (); } g_hash_table_replace (instance->transitions, value_data_ref (value), transition_instance_data_ref (instance_data)); g_hash_table_replace (self->transition_instances, transition_data_ref (transition), transition_instance_data_ref (instance_data)); closure_data = transition_closure_data_new (); closure_data->state = state_data_ref (state); closure_data->instance = state_instance_data_ref (instance); closure_data->value = value_data_ref (value); g_hash_table_replace (self->transition_closure_instances, transition_data_ref (transition), transition_closure_data_ref (closure_data)); } for (guint i = 0; i < spec->track_transition_values->len; i++) { ValueData *value = NULL; g_autoptr (TrackTransitionClosureData) closure_data = NULL; value = g_ptr_array_index (spec->track_transition_values, i); closure_data = track_transition_closure_data_new (); closure_data->value = value_data_ref (value); closure_data->timer = g_timer_new (); closure_data->notifier = g_object_new (BGE_TYPE_WDGT_NOTIFIER, NULL); g_hash_table_replace (self->track_transition_closure_instances, value_data_ref (value), track_transition_closure_data_ref (closure_data)); } if (state == spec->init_state) self->init_instance = state_instance_data_ref (instance); } /* Separate to ensure `self->init_instance` has been set */ if (!spec->ready) { g_hash_table_iter_init (&state_iter, spec->states); for (;;) { GHashTableIter value_iter = { 0 }; char *state_name = NULL; StateData *state = NULL; if (!g_hash_table_iter_next ( &state_iter, (gpointer *) &state_name, (gpointer *) &state)) break; g_hash_table_iter_init (&value_iter, spec->values); for (;;) { char *value_name = NULL; ValueData *value = NULL; g_autoptr (GtkExpression) expression = NULL; if (!g_hash_table_iter_next ( &value_iter, (gpointer *) &value_name, (gpointer *) &value)) break; expression = ensure_expressions (spec, value, state, NULL); } for (guint i = 0; i < spec->anon_values->len; i++) { ValueData *value = NULL; g_autoptr (GtkExpression) expression = NULL; value = g_ptr_array_index (spec->anon_values, i); expression = ensure_expressions (spec, value, state, NULL); } for (guint i = 0; i < spec->foreaches->len; i++) { ForeachData *data = NULL; data = g_ptr_array_index (spec->foreaches, i); { g_autoptr (GtkExpression) expression = ensure_expressions (spec, data->model, state, NULL); } g_hash_table_iter_init (&value_iter, data->values); for (;;) { char *value_name = NULL; ValueData *value = NULL; g_autoptr (GtkExpression) expression = NULL; if (!g_hash_table_iter_next ( &value_iter, (gpointer *) &value_name, (gpointer *) &value)) break; expression = ensure_expressions (spec, value, state, NULL); } } } g_hash_table_iter_init (&state_iter, spec->states); for (;;) { char *state_name = NULL; StateData *state = NULL; StateData *snapshot_state = NULL; if (!g_hash_table_iter_next ( &state_iter, (gpointer *) &state_name, (gpointer *) &state)) break; g_hash_table_iter_init ( &setters_iter, state->setters); for (;;) { ValueData *dest = NULL; ValueData *src = NULL; if (!g_hash_table_iter_next ( &setters_iter, (gpointer *) &dest, (gpointer *) &src)) break; if (g_hash_table_contains (state->values_need_tick, src)) state->needs_tick = TRUE; } if (state->snapshot != NULL) snapshot_state = state; else /* If this state doesn't have snapshot instructions specified, fallback on using the init state */ snapshot_state = self->spec->init_state; for (guint i = 0; i < snapshot_state->snapshot->calls->len; i++) { SnapshotCallData *call = NULL; call = g_ptr_array_index (snapshot_state->snapshot->calls, i); if (call->args == NULL) /* pop, save, restore... */ continue; for (guint j = 0; j < call->args->len; j++) { ValueData *arg = NULL; gboolean found = FALSE; GtkExpression *expression = NULL; arg = g_ptr_array_index (call->args, j); expression = g_hash_table_lookup (state->expressions, arg); g_assert (expression != NULL); for (guint k = 0; k < state->snapshot_deps->len; k++) { GtkExpression *other = NULL; other = g_ptr_array_index (state->snapshot_deps, k); if (expression == other) { found = TRUE; break; } } if (found) /* Ensure we don't duplicate deps */ continue; if (g_hash_table_contains (state->values_need_tick, arg)) state->needs_tick = TRUE; g_ptr_array_add (state->snapshot_deps, gtk_expression_ref (expression)); } } } spec->ready = TRUE; } g_hash_table_iter_init ( &setters_iter, self->spec->init_state->setters); for (;;) { ValueData *dest = NULL; ValueData *src = NULL; if (!g_hash_table_iter_next ( &setters_iter, (gpointer *) &dest, (gpointer *) &src)) break; set_value ( self, self->spec->init_state, self->init_instance, dest, src, self->init_watches); } gtk_widget_queue_allocate (GTK_WIDGET (self)); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void spawn_nonchild (BgeWdgtRenderer *self, ValueData *value) { g_autoptr (GObject) object = NULL; g_assert (value->kind == VALUE_OBJECT); object = g_object_new (value->type, NULL); if (g_type_is_a (value->type, G_TYPE_INITIALLY_UNOWNED)) g_object_ref_sink (object); g_hash_table_replace (self->objects, value_data_ref (value), g_object_ref (object)); g_ptr_array_add (self->nonchildren, g_object_ref (object)); } static void spawn_child (BgeWdgtRenderer *self, ValueData *value, GtkBuilder *dummy_builder) { GtkWidget *widget = NULL; g_autoptr (AllocationData) allocation = NULL; g_assert (value->kind == VALUE_CHILD); widget = g_object_new ( value->type, "name", value->name, NULL); if (value->child.css_classes != NULL) { for (guint j = 0; j < value->child.css_classes->len; j++) { const char *class = NULL; class = g_ptr_array_index (value->child.css_classes, j); gtk_widget_add_css_class (widget, class); } } if (value->child.parent_widget != NULL) { GtkWidget *parent_widget = NULL; g_autoptr (GtkBuilder) tmp_builder = NULL; parent_widget = g_hash_table_lookup ( self->objects, value->child.parent_widget); g_assert (parent_widget != NULL); if (dummy_builder == NULL) tmp_builder = gtk_builder_new (); GTK_BUILDABLE_GET_IFACE (parent_widget) ->add_child ( GTK_BUILDABLE (parent_widget), dummy_builder != NULL ? dummy_builder : tmp_builder, G_OBJECT (widget), value->child.builder_type); } else { gtk_widget_set_parent (widget, GTK_WIDGET (self)); g_ptr_array_add (self->children, g_object_ref (widget)); } g_hash_table_replace (self->objects, value_data_ref (value), g_object_ref (widget)); allocation = allocation_data_new (); g_hash_table_replace (self->allocations, g_object_ref (widget), allocation_data_ref (allocation)); } static void apply_state (BgeWdgtRenderer *self) { BgeWdgtSpec *spec = self->spec; StateData *state = NULL; StateInstanceData *instance = NULL; GHashTableIter iter = { 0 }; if (self->had_tick_since_state_switch) { g_clear_pointer (&self->last_state, state_data_unref); g_clear_pointer (&self->last_instance, state_instance_data_unref); if (self->active_state != NULL && self->active_instance != NULL) { self->last_state = g_steal_pointer (&self->active_state); self->last_instance = g_steal_pointer (&self->active_instance); } g_timer_start (self->since_last_state); self->had_tick_since_state_switch = FALSE; } g_clear_pointer (&self->active_state, state_data_unref); g_clear_pointer (&self->active_instance, state_instance_data_unref); g_clear_pointer (&self->active_snapshot, snapshot_data_unref); g_ptr_array_set_size (self->bindings, 0); g_ptr_array_set_size (self->watches, 0); gtk_widget_queue_draw (GTK_WIDGET (self)); if (self->spec == NULL || self->state == NULL) return; state = g_hash_table_lookup (spec->states, self->state); if (state == NULL) { g_critical ("state \"%s\" doesn't exist on spec \"%s\"", self->state, spec->name); return; } instance = g_hash_table_lookup (self->state_instances, state); g_assert (instance != NULL); self->active_state = state_data_ref (state); self->active_instance = state_instance_data_ref (instance); if (state->snapshot != NULL) self->active_snapshot = snapshot_data_ref (state->snapshot); else if (self->spec->init_state->snapshot != NULL) self->active_snapshot = snapshot_data_ref (self->spec->init_state->snapshot); g_hash_table_iter_init (&iter, state->setters); for (;;) { ValueData *dest = NULL; ValueData *src = NULL; TransitionInstanceData *transition_instance = NULL; if (!g_hash_table_iter_next ( &iter, (gpointer *) &dest, (gpointer *) &src)) break; set_value ( self, state, instance, dest, src, self->watches); transition_instance = g_hash_table_lookup (instance->transitions, dest); if (transition_instance != NULL) transition_instance->spring.est_duration = -1.0; } g_hash_table_iter_init (&iter, spec->init_state->setters); for (;;) { ValueData *dest = NULL; ValueData *src = NULL; if (!g_hash_table_iter_next ( &iter, (gpointer *) &dest, (gpointer *) &src)) break; set_value ( self, state, instance, dest, src, self->watches); } for (guint i = 0; i < state->snapshot_deps->len; i++) { GtkExpression *expression = NULL; GtkExpressionWatch *watch = NULL; expression = g_ptr_array_index (state->snapshot_deps, i); watch = gtk_expression_watch ( expression, self, (GtkExpressionNotify) prop_change_queue_draw, self, NULL); g_ptr_array_add (self->watches, watch); } gtk_widget_queue_allocate (GTK_WIDGET (self)); gtk_widget_queue_draw (GTK_WIDGET (self)); if (self->tick == 0) self->tick = gtk_widget_add_tick_callback ( GTK_WIDGET (self), (GtkTickCallback) tick_cb, NULL, NULL); } static graphene_point_t * expression_create_point (gpointer object, double x, double y, gpointer user_data) { graphene_point_t *point = NULL; point = graphene_point_alloc (); point->x = x; point->y = y; return point; } static graphene_size_t * expression_create_size (gpointer object, double width, double height, gpointer user_data) { graphene_size_t *size = NULL; size = graphene_size_alloc (); size->width = width; size->height = height; return size; } static graphene_point3d_t * expression_create_point3d (gpointer object, double x, double y, double z, gpointer user_data) { graphene_point3d_t *point3d = NULL; point3d = graphene_point3d_alloc (); point3d->x = x; point3d->y = y; point3d->z = z; return point3d; } static graphene_rect_t * expression_create_rect (gpointer object, double x, double y, double width, double height, gpointer user_data) { graphene_rect_t *rect = NULL; rect = graphene_rect_alloc (); rect->origin.x = x; rect->origin.y = y; rect->size.width = width; rect->size.height = height; return rect; } static GskStroke * expression_create_stroke (gpointer object, double line_width, GskLineCap line_cap, GskLineJoin line_join, double miter_limit, gpointer user_data) { GskStroke *stroke = NULL; stroke = gsk_stroke_new (line_width); gsk_stroke_set_line_cap (stroke, line_cap); gsk_stroke_set_line_join (stroke, line_join); gsk_stroke_set_miter_limit (stroke, miter_limit); return stroke; } static void expression_coerce_type (gpointer this, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer dest_type_ptr) { GType dest_type = GPOINTER_TO_SIZE (dest_type_ptr); coerce_value (¶m_values[0], dest_type, return_value); } static gpointer expression_lookup_object (BgeWdgtRenderer *this, ValueData *value) { return g_object_ref (g_hash_table_lookup (this->objects, value)); } static gpointer expression_get_reference_notifier (BgeWdgtRenderer *this, gpointer user_data) { return g_object_ref (this->reference_notifier); } static gpointer expression_get_measure_for_size_notifier (BgeWdgtRenderer *this, gpointer user_data) { return g_object_ref (this->measure_for_size_notifier); } static gpointer expression_get_widget_width_notifier (BgeWdgtRenderer *this, gpointer user_data) { return g_object_ref (this->widget_width_notifier); } static gpointer expression_get_widget_height_notifier (BgeWdgtRenderer *this, gpointer user_data) { return g_object_ref (this->widget_height_notifier); } static gpointer expression_get_tick_time_notifier (BgeWdgtRenderer *this, gpointer user_data) { return g_object_ref (this->tick_time_notifier); } static gpointer expression_get_foreach_instance_notifier (BgeWdgtRenderer *this, ForeachData *data) { ForeachInstanceData *instance = NULL; instance = g_hash_table_lookup (this->foreach_instances, data); g_assert (instance != NULL); return g_object_ref (instance->notifier); } static gpointer expression_get_transition_instance_notifier (BgeWdgtRenderer *this, TransitionData *data) { TransitionInstanceData *instance = NULL; instance = g_hash_table_lookup (this->transition_instances, data); g_assert (instance != NULL); return g_object_ref (instance->notifier); } static gpointer expression_get_track_transition_closure_instance_notifier (BgeWdgtRenderer *this, ValueData *value) { TrackTransitionClosureData *instance = NULL; instance = g_hash_table_lookup (this->track_transition_closure_instances, value); g_assert (instance != NULL); return g_object_ref (instance->notifier); } static guint expression_get_foreach_index (BgeWdgtRenderer *this, double notify, ForeachData *data) { ForeachInstanceData *instance = NULL; instance = g_hash_table_lookup (this->foreach_instances, data); g_assert (instance != NULL); return instance->current_idx; } static gpointer expression_get_model_item (BgeWdgtRenderer *this, GListModel *model, guint idx, double notify, gpointer user_data) { return g_list_model_get_item (model, idx); } static int expression_get_measure_for_size (BgeWdgtRenderer *this, double notify, gpointer user_data) { return this->current_measure_for_size; } static double expression_get_widget_width (BgeWdgtRenderer *this, double notify, gpointer user_data) { return (double) this->widget_width; } static double expression_get_widget_height (BgeWdgtRenderer *this, double notify, gpointer user_data) { return (double) this->widget_height; } static double expression_get_tick_time (BgeWdgtRenderer *this, double notify, gpointer user_data) { return g_timer_elapsed (this->tick_time, NULL); } static gpointer expression_get_reference_object (BgeWdgtRenderer *this, double notify, gpointer user_data) { return this->reference != NULL ? g_object_ref (this->reference) : NULL; } static double expression_adjust_state_transition (BgeWdgtRenderer *this, double in, double notifier, TransitionData *data) { TransitionClosureData *closure_data = NULL; TransitionData *transition = NULL; TransitionData *last_transition = NULL; TransitionInstanceData *transition_instance = NULL; TransitionInstanceData *last_transition_instance = NULL; ValueData *last_in_value = NULL; double last_in = 0.0; double elapsed = 0.0; double progress = 0.0; double interpolated_number = 0.0; closure_data = g_hash_table_lookup (this->transition_closure_instances, data); g_assert (closure_data != NULL); g_assert (closure_data->value->type == G_TYPE_DOUBLE); if (!bge_should_animate (GTK_WIDGET (this))) return in; if (this->active_state == NULL || this->active_instance == NULL || this->last_state == NULL || this->last_instance == NULL) return in; transition = g_hash_table_lookup ( this->active_state->transitions, closure_data->value); if (transition == NULL) return in; last_transition = g_hash_table_lookup ( this->last_state->transitions, closure_data->value); transition_instance = g_hash_table_lookup ( this->active_instance->transitions, closure_data->value); g_assert (transition_instance != NULL); last_transition_instance = g_hash_table_lookup ( this->last_instance->transitions, closure_data->value); if (last_transition != NULL && last_transition_instance != NULL && last_transition->kind == TRANSITION_EASE && last_transition_instance->elapsed < last_transition_instance->ease.seconds) last_in = last_transition_instance->value; else { last_in_value = g_hash_table_lookup (this->last_state->setters, closure_data->value); if (last_in_value == NULL) return in; last_in = resolve_value_double (this, last_in_value, this->last_state); } elapsed = g_timer_elapsed (this->since_last_state, NULL); transition_instance->elapsed = elapsed; switch (transition->kind) { case TRANSITION_EASE: { BgeEasing easing = 0; double seconds = 0.0; easing = resolve_value_enum ( this, transition->ease.easing, this->active_state); seconds = resolve_value_double ( this, transition->ease.seconds, this->active_state); if (elapsed >= seconds) interpolated_number = in; else { progress = bge_easing_ease (easing, elapsed / seconds); interpolated_number = last_in + progress * (in - last_in); } transition_instance->ease.easing = easing; transition_instance->ease.seconds = seconds; } break; case TRANSITION_SPRING: { double damping_ratio = 0.0; double mass = 0.0; double stiffness = 0.0; double damping = 0.0; damping_ratio = resolve_value_double ( this, transition->spring.damping_ratio, this->active_state); mass = resolve_value_double ( this, transition->spring.mass, this->active_state); stiffness = resolve_value_double ( this, transition->spring.stiffness, this->active_state); damping = damping_ratio * (/* critical damping */ 2 * sqrt (mass * stiffness)); if (transition_instance->spring.est_duration < 0.0 || damping_ratio != transition_instance->spring.cache_damping_ratio || mass != transition_instance->spring.cache_mass || stiffness != transition_instance->spring.cache_stiffness) { if (last_transition != NULL && last_transition->kind == TRANSITION_SPRING) transition_instance->spring.velocity = last_transition_instance->spring.velocity; else transition_instance->spring.velocity = 0.0; transition_instance->spring.est_duration = spring_calculate_duration ( damping, mass, stiffness, last_in, in, FALSE); transition_instance->spring.cache_damping_ratio = damping_ratio; transition_instance->spring.cache_mass = mass; transition_instance->spring.cache_stiffness = stiffness; } if (elapsed >= transition_instance->spring.est_duration) interpolated_number = in; else interpolated_number = spring_oscillate ( damping, mass, stiffness, last_in, in, elapsed, &transition_instance->spring.velocity); } break; default: g_assert_not_reached (); } transition_instance->value = interpolated_number; return interpolated_number; } static double expression_adjust_track_transition (BgeWdgtRenderer *this, double in, double damping_ratio, double mass, double stiffness, double notifier, ValueData *value) { TrackTransitionClosureData *closure_data = NULL; guint idx = 0; gboolean registered = FALSE; double damping = 0.0; g_assert (value->type == G_TYPE_DOUBLE); if (!bge_should_animate (GTK_WIDGET (this))) return in; closure_data = g_hash_table_lookup (this->track_transition_closure_instances, value); g_assert (closure_data != NULL); registered = g_ptr_array_find (this->track_transitions, closure_data, &idx); if (!registered) { g_ptr_array_add (this->track_transitions, track_transition_closure_data_ref (closure_data)); if (this->tick == 0) this->tick = gtk_widget_add_tick_callback ( GTK_WIDGET (this), (GtkTickCallback) tick_cb, NULL, NULL); } damping = damping_ratio * (/* critical damping */ 2 * sqrt (mass * stiffness)); if (!registered || closure_data->target != in || damping_ratio != closure_data->spring.cache_damping_ratio || mass != closure_data->spring.cache_mass || stiffness != closure_data->spring.cache_stiffness) { closure_data->target = in; closure_data->last = closure_data->current; closure_data->elapsed = 0.0; g_timer_start (closure_data->timer); closure_data->spring.est_duration = spring_calculate_duration ( damping, mass, stiffness, closure_data->last, closure_data->target, FALSE); closure_data->spring.cache_damping_ratio = damping_ratio; closure_data->spring.cache_mass = mass; closure_data->spring.cache_stiffness = stiffness; } else closure_data->elapsed = g_timer_elapsed (closure_data->timer, NULL); if (closure_data->elapsed >= closure_data->spring.est_duration) { closure_data->current = closure_data->target; closure_data->last = closure_data->target; } else closure_data->current = spring_oscillate ( damping, mass, stiffness, closure_data->last, closure_data->target, closure_data->elapsed, &closure_data->spring.velocity); return closure_data->current; } static GskTransform * expression_perform_transform (gpointer this, guint n_param_values, const GValue *param_values, TransformCallFunc func) { return func (g_value_dup_boxed (¶m_values[0]), param_values + 1); } static GskPath * expression_perform_path_build (gpointer this, guint n_param_values, const GValue *param_values, ValueData *path_value) { g_autoptr (GskPathBuilder) builder = NULL; const GValue *cursor = 0; g_assert (path_value->kind == VALUE_PATH); builder = gsk_path_builder_new (); cursor = param_values; for (guint i = 0; i < path_value->path.argss->len; i++) { PathBuilderCallFunc func = NULL; GPtrArray *args = NULL; func = g_ptr_array_index (path_value->path.funcs, i); args = g_ptr_array_index (path_value->path.argss, i); func (builder, cursor); cursor += args->len; } return gsk_path_builder_to_path (builder); } static GtkExpression * ensure_expressions (BgeWdgtSpec *self, ValueData *value, StateData *state, gboolean *value_needs_tick) { GtkExpression *cached = NULL; g_autoptr (GtkExpression) expression = NULL; TransitionData *transition = NULL; gboolean need_tick = FALSE; cached = g_hash_table_lookup (state->expressions, value); if (cached != NULL) { if (value_needs_tick != NULL && g_hash_table_contains (state->values_need_tick, value)) *value_needs_tick = TRUE; return gtk_expression_ref (cached); } switch (value->kind) { case VALUE_CONSTANT: expression = gtk_constant_expression_new_for_value (&value->constant.value); break; case VALUE_OBJECT: case VALUE_CHILD: expression = gtk_cclosure_expression_new ( value->type, bge_marshal_OBJECT__VOID, 0, (GtkExpression *[]){}, G_CALLBACK (expression_lookup_object), value_data_ref (value), value_data_unref_closure); break; case VALUE_REFERENCE_OBJECT: { GtkExpression *notifier_constant = NULL; GtkExpression *notify_expression = NULL; notifier_constant = gtk_cclosure_expression_new ( BGE_TYPE_WDGT_NOTIFIER, bge_marshal_OBJECT__VOID, 0, (GtkExpression *[]){}, G_CALLBACK (expression_get_reference_notifier), NULL, NULL); notify_expression = gtk_property_expression_new_for_pspec ( notifier_constant, notifier_props[NOTIFIER_PROP_VALUE]); expression = gtk_cclosure_expression_new ( value->type, bge_marshal_OBJECT__DOUBLE, 1, (GtkExpression *[]){ notify_expression }, G_CALLBACK (expression_get_reference_object), GSIZE_TO_POINTER (value->type), NULL); } break; case VALUE_ITERATOR: { GtkExpression *notifier_constant = NULL; GtkExpression *notify_expression = NULL; notifier_constant = gtk_cclosure_expression_new ( BGE_TYPE_WDGT_NOTIFIER, bge_marshal_OBJECT__VOID, 0, (GtkExpression *[]){}, G_CALLBACK (expression_get_foreach_instance_notifier), foreach_data_ref (value->iterator.context), foreach_data_unref_closure); notify_expression = gtk_property_expression_new_for_pspec ( notifier_constant, notifier_props[NOTIFIER_PROP_VALUE]); expression = gtk_cclosure_expression_new ( G_TYPE_UINT, bge_marshal_UINT__DOUBLE, 1, (GtkExpression *[]){ notify_expression }, G_CALLBACK (expression_get_foreach_index), foreach_data_ref (value->iterator.context), foreach_data_unref_closure); if (value->type != G_TYPE_UINT) { GtkExpression *model_expression = NULL; g_assert (g_type_is_a (value->type, G_TYPE_OBJECT)); model_expression = ensure_expressions ( self, value->iterator.context->model, state, &need_tick); expression = gtk_cclosure_expression_new ( value->type, bge_marshal_OBJECT__OBJECT_UINT_DOUBLE, 3, (GtkExpression *[]){ model_expression, expression, notify_expression }, G_CALLBACK (expression_get_model_item), NULL, NULL); } } break; case VALUE_VARIABLE: case VALUE_ALLOCATION_WIDTH: case VALUE_ALLOCATION_HEIGHT: case VALUE_ALLOCATION_TRANSFORM: case VALUE_MEASURE_MINIMUM_WIDTH: case VALUE_MEASURE_NATURAL_WIDTH: case VALUE_MEASURE_MINIMUM_HEIGHT: case VALUE_MEASURE_NATURAL_HEIGHT: { ValueData *holds = NULL; holds = g_hash_table_lookup (state->setters, value); if (holds == NULL) holds = g_hash_table_lookup (self->init_state->setters, value); if (holds != NULL) expression = ensure_expressions ( self, holds, state, &need_tick); else { GValue empty_value = G_VALUE_INIT; g_value_init (&empty_value, value->type); expression = gtk_constant_expression_new_for_value (&empty_value); g_value_unset (&empty_value); } } break; case VALUE_MEASURE_FOR_SIZE: { GtkExpression *notifier_constant = NULL; GtkExpression *notify_expression = NULL; notifier_constant = gtk_cclosure_expression_new ( BGE_TYPE_WDGT_NOTIFIER, bge_marshal_OBJECT__VOID, 0, (GtkExpression *[]){}, G_CALLBACK (expression_get_measure_for_size_notifier), NULL, NULL); notify_expression = gtk_property_expression_new_for_pspec ( notifier_constant, notifier_props[NOTIFIER_PROP_VALUE]); expression = gtk_cclosure_expression_new ( value->type, bge_marshal_INT__DOUBLE, 1, (GtkExpression *[]){ notify_expression }, G_CALLBACK (expression_get_measure_for_size), GSIZE_TO_POINTER (value->type), NULL); } break; case VALUE_WIDGET_WIDTH: { GtkExpression *notifier_constant = NULL; GtkExpression *notify_expression = NULL; notifier_constant = gtk_cclosure_expression_new ( BGE_TYPE_WDGT_NOTIFIER, bge_marshal_OBJECT__VOID, 0, (GtkExpression *[]){}, G_CALLBACK (expression_get_widget_width_notifier), NULL, NULL); notify_expression = gtk_property_expression_new_for_pspec ( notifier_constant, notifier_props[NOTIFIER_PROP_VALUE]); expression = gtk_cclosure_expression_new ( value->type, bge_marshal_DOUBLE__DOUBLE, 1, (GtkExpression *[]){ notify_expression }, G_CALLBACK (expression_get_widget_width), GSIZE_TO_POINTER (value->type), NULL); } break; case VALUE_WIDGET_HEIGHT: { GtkExpression *notifier_constant = NULL; GtkExpression *notify_expression = NULL; notifier_constant = gtk_cclosure_expression_new ( BGE_TYPE_WDGT_NOTIFIER, bge_marshal_OBJECT__VOID, 0, (GtkExpression *[]){}, G_CALLBACK (expression_get_widget_height_notifier), NULL, NULL); notify_expression = gtk_property_expression_new_for_pspec ( notifier_constant, notifier_props[NOTIFIER_PROP_VALUE]); expression = gtk_cclosure_expression_new ( value->type, bge_marshal_DOUBLE__DOUBLE, 1, (GtkExpression *[]){ notify_expression }, G_CALLBACK (expression_get_widget_height), GSIZE_TO_POINTER (value->type), NULL); } break; case VALUE_TICK_TIME: { GtkExpression *notifier_constant = NULL; GtkExpression *notify_expression = NULL; notifier_constant = gtk_cclosure_expression_new ( BGE_TYPE_WDGT_NOTIFIER, bge_marshal_OBJECT__VOID, 0, (GtkExpression *[]){}, G_CALLBACK (expression_get_tick_time_notifier), NULL, NULL); notify_expression = gtk_property_expression_new_for_pspec ( notifier_constant, notifier_props[NOTIFIER_PROP_VALUE]); expression = gtk_cclosure_expression_new ( value->type, bge_marshal_DOUBLE__DOUBLE, 1, (GtkExpression *[]){ notify_expression }, G_CALLBACK (expression_get_tick_time), GSIZE_TO_POINTER (value->type), NULL); need_tick = TRUE; } break; case VALUE_COERCION: { expression = ensure_expressions ( self, value->coercion.value, state, &need_tick); expression = gtk_cclosure_expression_new ( value->type, _marshal_DIRECT__ARGS_DIRECT, 1, (GtkExpression *[]){ expression }, G_CALLBACK (expression_coerce_type), GSIZE_TO_POINTER (value->type), NULL); } break; case VALUE_TRACK_TRANSITION: { g_autoptr (BgeWdgtNotifier) notifier_object = NULL; GtkExpression *notifier_constant = NULL; GtkExpression *notify_expression = NULL; GtkExpression *damping_ratio_expression = NULL; GtkExpression *mass_expression = NULL; GtkExpression *stiffness_expression = NULL; notifier_constant = gtk_cclosure_expression_new ( BGE_TYPE_WDGT_NOTIFIER, bge_marshal_OBJECT__VOID, 0, (GtkExpression *[]){}, G_CALLBACK (expression_get_track_transition_closure_instance_notifier), value_data_ref (value), value_data_unref_closure); notify_expression = gtk_property_expression_new_for_pspec ( notifier_constant, notifier_props[NOTIFIER_PROP_VALUE]); damping_ratio_expression = ensure_expressions ( self, value->track_transition.spring.damping_ratio, state, &need_tick); mass_expression = ensure_expressions ( self, value->track_transition.spring.mass, state, &need_tick); stiffness_expression = ensure_expressions ( self, value->track_transition.spring.stiffness, state, &need_tick); expression = ensure_expressions ( self, value->track_transition.src, state, &need_tick); expression = gtk_cclosure_expression_new ( value->type, bge_marshal_DOUBLE__DOUBLE_DOUBLE_DOUBLE_DOUBLE_DOUBLE, 5, (GtkExpression *[]){ expression, damping_ratio_expression, mass_expression, stiffness_expression, notify_expression }, G_CALLBACK (expression_adjust_track_transition), value_data_ref (value), value_data_unref_closure); } break; case VALUE_COMPONENT: { g_autoptr (GPtrArray) params = NULL; GClosureMarshal marshal = NULL; GCallback callback = NULL; params = g_ptr_array_new (); for (guint i = 0; i < value->component.params->len; i++) { ValueData *member = NULL; g_autoptr (GtkExpression) member_expr = NULL; member = g_ptr_array_index (value->component.params, i); member_expr = ensure_expressions (self, member, state, &need_tick); g_ptr_array_add (params, g_steal_pointer (&member_expr)); } if (value->type == GRAPHENE_TYPE_POINT) { marshal = bge_marshal_BOXED__DOUBLE_DOUBLE; callback = G_CALLBACK (expression_create_point); } else if (value->type == GRAPHENE_TYPE_SIZE) { marshal = bge_marshal_BOXED__DOUBLE_DOUBLE; callback = G_CALLBACK (expression_create_size); } else if (value->type == GRAPHENE_TYPE_POINT3D) { marshal = bge_marshal_BOXED__DOUBLE_DOUBLE_DOUBLE; callback = G_CALLBACK (expression_create_point3d); } else if (value->type == GRAPHENE_TYPE_RECT) { marshal = bge_marshal_BOXED__DOUBLE_DOUBLE_DOUBLE_DOUBLE; callback = G_CALLBACK (expression_create_rect); } else if (value->type == GSK_TYPE_STROKE) { marshal = bge_marshal_BOXED__DOUBLE_ENUM_ENUM_DOUBLE; callback = G_CALLBACK (expression_create_stroke); } else g_assert_not_reached (); expression = gtk_cclosure_expression_new ( value->type, marshal, params->len, (GtkExpression **) params->pdata, callback, self, NULL); } break; case VALUE_TRANSFORM: { g_autoptr (GPtrArray) params = NULL; g_autoptr (GtkExpression) next_expr = NULL; params = g_ptr_array_new (); next_expr = ensure_expressions (self, value->transform.next, state, &need_tick); g_ptr_array_add (params, g_steal_pointer (&next_expr)); for (guint i = 0; i < value->transform.args->len; i++) { ValueData *arg = NULL; g_autoptr (GtkExpression) arg_expr = NULL; arg = g_ptr_array_index (value->transform.args, i); arg_expr = ensure_expressions (self, arg, state, &need_tick); g_ptr_array_add (params, g_steal_pointer (&arg_expr)); } expression = gtk_cclosure_expression_new ( value->type, _marshal_BOXED__ARGS_DIRECT, params->len, (GtkExpression **) params->pdata, G_CALLBACK (expression_perform_transform), value->transform.func, NULL); } break; case VALUE_PATH: { g_autoptr (GPtrArray) params = NULL; g_autoptr (GtkExpression) next_expr = NULL; params = g_ptr_array_new (); g_assert (value->path.funcs->len == value->path.argss->len); for (guint i = 0; i < value->path.argss->len; i++) { GPtrArray *args = NULL; args = g_ptr_array_index (value->path.argss, i); for (guint j = 0; j < args->len; j++) { ValueData *arg = NULL; g_autoptr (GtkExpression) arg_expr = NULL; arg = g_ptr_array_index (args, j); arg_expr = ensure_expressions (self, arg, state, &need_tick); g_ptr_array_add (params, g_steal_pointer (&arg_expr)); } } expression = gtk_cclosure_expression_new ( value->type, _marshal_BOXED__ARGS_DIRECT, params->len, (GtkExpression **) params->pdata, G_CALLBACK (expression_perform_path_build), value_data_ref (value), value_data_unref_closure); } break; case VALUE_CLOSURE: { g_autoptr (GPtrArray) params = NULL; params = g_ptr_array_new (); for (guint i = 0; i < value->closure.args->len; i++) { ValueData *arg = NULL; g_autoptr (GtkExpression) arg_expr = NULL; arg = g_ptr_array_index (value->closure.args, i); arg_expr = ensure_expressions (self, arg, state, &need_tick); g_ptr_array_add (params, g_steal_pointer (&arg_expr)); } expression = gtk_cclosure_expression_new ( value->type, value->closure.marshal, params->len, (GtkExpression **) params->pdata, value->closure.func, value->closure.user_data, NULL); } break; case VALUE_PROPERTY: { g_autoptr (GtkExpression) object_expression = NULL; /* Mark subproperty values as dependencies as well */ object_expression = ensure_expressions ( self, value->property.object, state, &need_tick); expression = gtk_property_expression_new ( value->property.object->type, g_steal_pointer (&object_expression), value->property.prop_name); } break; default: g_assert_not_reached (); break; } transition = g_hash_table_lookup (state->transitions, value); if (value->type == G_TYPE_DOUBLE && transition != NULL) { GtkExpression *notifier_constant = NULL; GtkExpression *notify_expression = NULL; notifier_constant = gtk_cclosure_expression_new ( BGE_TYPE_WDGT_NOTIFIER, bge_marshal_OBJECT__VOID, 0, (GtkExpression *[]){}, G_CALLBACK (expression_get_transition_instance_notifier), transition_data_ref (transition), transition_data_unref_closure); notify_expression = gtk_property_expression_new_for_pspec ( notifier_constant, notifier_props[NOTIFIER_PROP_VALUE]); expression = gtk_cclosure_expression_new ( value->type, bge_marshal_DOUBLE__DOUBLE_DOUBLE, 2, (GtkExpression *[]){ expression, notify_expression }, G_CALLBACK (expression_adjust_state_transition), transition_data_ref (transition), transition_data_unref_closure); } g_hash_table_replace ( state->expressions, value_data_ref (value), gtk_expression_ref (expression)); if (need_tick) { /* We need to track this so we know not to remove the animation tick callback when transitions are not active */ g_hash_table_replace ( state->values_need_tick, value_data_ref (value), NULL); if (value_needs_tick != NULL) *value_needs_tick = TRUE; } return gtk_expression_ref (expression); } static void set_value (BgeWdgtRenderer *self, StateData *state, StateInstanceData *instance, ValueData *dest, ValueData *src, GPtrArray *watches) { GtkExpression *src_expression = NULL; GtkExpression *dest_expression = NULL; src_expression = g_hash_table_lookup (state->expressions, src); g_assert (src_expression != NULL); dest_expression = g_hash_table_lookup (state->expressions, dest); g_assert (dest_expression != NULL); switch (dest->kind) { case VALUE_PROPERTY: { GtkExpression *dest_obj_expression = NULL; GValue dest_obj_resolved = G_VALUE_INIT; GObject *dest_obj = NULL; dest_obj_expression = g_hash_table_lookup (state->expressions, dest->property.object); g_assert (dest_obj_expression != NULL); gtk_expression_evaluate ( dest_obj_expression, self, &dest_obj_resolved); dest_obj = g_value_get_object (&dest_obj_resolved); if (dest_obj != NULL) { gboolean resolved = FALSE; GValue src_resolved = G_VALUE_INIT; resolved = gtk_expression_evaluate ( src_expression, self, &src_resolved); if (resolved) g_object_set_property ( dest_obj, dest->property.prop_name, &src_resolved); g_value_unset (&src_resolved); } g_value_unset (&dest_obj_resolved); } break; case VALUE_ALLOCATION_WIDTH: case VALUE_ALLOCATION_HEIGHT: case VALUE_ALLOCATION_TRANSFORM: { GtkExpression *dest_widget_expression = NULL; GValue dest_widget_resolved = G_VALUE_INIT; GtkWidget *dest_widget = NULL; dest_widget_expression = g_hash_table_lookup (state->expressions, dest->allocation.widget); g_assert (dest_widget_expression != NULL); gtk_expression_evaluate ( dest_widget_expression, self, &dest_widget_resolved); dest_widget = g_value_get_object (&dest_widget_resolved); if (dest_widget != NULL) { AllocationData *allocation = NULL; allocation = g_hash_table_lookup (self->allocations, dest_widget); if (allocation != NULL) { switch (dest->kind) { case VALUE_ALLOCATION_WIDTH: g_clear_pointer (&allocation->width, value_data_unref); allocation->width = value_data_ref (src); break; case VALUE_ALLOCATION_HEIGHT: g_clear_pointer (&allocation->height, value_data_unref); allocation->height = value_data_ref (src); break; case VALUE_ALLOCATION_TRANSFORM: g_clear_pointer (&allocation->transform, value_data_unref); allocation->transform = value_data_ref (src); break; case VALUE_CHILD: case VALUE_CLOSURE: case VALUE_COERCION: case VALUE_COMPONENT: case VALUE_CONSTANT: case VALUE_ITERATOR: case VALUE_MEASURE_FOR_SIZE: case VALUE_MEASURE_MINIMUM_HEIGHT: case VALUE_MEASURE_MINIMUM_WIDTH: case VALUE_MEASURE_NATURAL_HEIGHT: case VALUE_MEASURE_NATURAL_WIDTH: case VALUE_OBJECT: case VALUE_PATH: case VALUE_PROPERTY: case VALUE_REFERENCE_OBJECT: case VALUE_TICK_TIME: case VALUE_TRACK_TRANSITION: case VALUE_TRANSFORM: case VALUE_VARIABLE: case VALUE_WIDGET_HEIGHT: case VALUE_WIDGET_WIDTH: default: g_assert_not_reached (); } gtk_widget_queue_allocate (GTK_WIDGET (self)); } } g_value_unset (&dest_widget_resolved); } break; case VALUE_MEASURE_MINIMUM_WIDTH: case VALUE_MEASURE_NATURAL_WIDTH: case VALUE_MEASURE_MINIMUM_HEIGHT: case VALUE_MEASURE_NATURAL_HEIGHT: { GValue src_resolved = G_VALUE_INIT; gtk_expression_evaluate ( src_expression, self, &src_resolved); switch (dest->kind) { case VALUE_MEASURE_MINIMUM_WIDTH: self->measure_minimum_width = g_value_get_int (&src_resolved); break; case VALUE_MEASURE_NATURAL_WIDTH: self->measure_natural_width = g_value_get_int (&src_resolved); break; case VALUE_MEASURE_MINIMUM_HEIGHT: self->measure_minimum_height = g_value_get_int (&src_resolved); break; case VALUE_MEASURE_NATURAL_HEIGHT: self->measure_natural_height = g_value_get_int (&src_resolved); break; case VALUE_ALLOCATION_HEIGHT: case VALUE_ALLOCATION_TRANSFORM: case VALUE_ALLOCATION_WIDTH: case VALUE_CHILD: case VALUE_CLOSURE: case VALUE_COERCION: case VALUE_COMPONENT: case VALUE_CONSTANT: case VALUE_ITERATOR: case VALUE_MEASURE_FOR_SIZE: case VALUE_OBJECT: case VALUE_PATH: case VALUE_PROPERTY: case VALUE_REFERENCE_OBJECT: case VALUE_TICK_TIME: case VALUE_TRACK_TRANSITION: case VALUE_TRANSFORM: case VALUE_VARIABLE: case VALUE_WIDGET_HEIGHT: case VALUE_WIDGET_WIDTH: default: g_assert_not_reached (); } g_value_unset (&src_resolved); gtk_widget_queue_resize (GTK_WIDGET (self)); } break; case VALUE_CHILD: case VALUE_CLOSURE: case VALUE_COERCION: case VALUE_COMPONENT: case VALUE_CONSTANT: case VALUE_ITERATOR: case VALUE_MEASURE_FOR_SIZE: case VALUE_OBJECT: case VALUE_PATH: case VALUE_REFERENCE_OBJECT: case VALUE_TICK_TIME: case VALUE_TRACK_TRANSITION: case VALUE_TRANSFORM: case VALUE_VARIABLE: case VALUE_WIDGET_HEIGHT: case VALUE_WIDGET_WIDTH: break; default: g_assert_not_reached (); } if (watches != NULL) { g_autoptr (WatchSetterData) watch_data = NULL; GtkExpressionWatch *watch = NULL; watch_data = watch_setter_data_new (); watch_data->self = self; watch_data->state = state_data_ref (state); watch_data->instance = state_instance_data_ref (instance); watch_data->dest = value_data_ref (dest); watch_data->src = value_data_ref (src); watch = gtk_expression_watch ( src_expression, self, (GtkExpressionNotify) reset_setter, watch_setter_data_ref (watch_data), watch_setter_data_unref); g_ptr_array_add (watches, watch); } } static int resolve_value_int (BgeWdgtRenderer *self, ValueData *value, StateData *state) { GtkExpression *expression = NULL; GValue resolved = G_VALUE_INIT; int ret = 0.0; expression = g_hash_table_lookup (state->expressions, value); g_assert (expression != NULL); gtk_expression_evaluate ( expression, self, &resolved); ret = g_value_get_int (&resolved); g_value_unset (&resolved); return ret; } static double resolve_value_double (BgeWdgtRenderer *self, ValueData *value, StateData *state) { GtkExpression *expression = NULL; GValue resolved = G_VALUE_INIT; double ret = 0.0; expression = g_hash_table_lookup (state->expressions, value); g_assert (expression != NULL); gtk_expression_evaluate ( expression, self, &resolved); ret = g_value_get_double (&resolved); g_value_unset (&resolved); return ret; } static gint resolve_value_enum (BgeWdgtRenderer *self, ValueData *value, StateData *state) { GtkExpression *expression = NULL; GValue resolved = G_VALUE_INIT; gint ret = 0; expression = g_hash_table_lookup (state->expressions, value); g_assert (expression != NULL); gtk_expression_evaluate ( expression, self, &resolved); ret = g_value_get_enum (&resolved); g_value_unset (&resolved); return ret; } static gpointer resolve_value_boxed_dup (BgeWdgtRenderer *self, ValueData *value, StateData *state) { GtkExpression *expression = NULL; GValue resolved = G_VALUE_INIT; gpointer ret = NULL; expression = g_hash_table_lookup (state->expressions, value); g_assert (expression != NULL); gtk_expression_evaluate ( expression, self, &resolved); ret = g_value_dup_boxed (&resolved); g_value_unset (&resolved); return ret; } static gpointer resolve_value_object_dup (BgeWdgtRenderer *self, ValueData *value, StateData *state) { GtkExpression *expression = NULL; GValue resolved = G_VALUE_INIT; gpointer ret = NULL; expression = g_hash_table_lookup (state->expressions, value); g_assert (expression != NULL); gtk_expression_evaluate ( expression, self, &resolved); ret = g_value_dup_object (&resolved); g_value_unset (&resolved); return ret; } static void discard_binding (gpointer ptr) { GBinding *binding = ptr; g_binding_unbind (binding); g_object_unref (binding); } static void discard_watch (gpointer ptr) { GtkExpressionWatch *watch = ptr; /* unrefs for us */ gtk_expression_watch_unwatch (watch); } static void prop_change_queue_draw (BgeWdgtRenderer *self) { gtk_widget_queue_draw (GTK_WIDGET (self)); } static void reset_setter (WatchSetterData *data) { BgeWdgtRenderer *self = data->self; /* Active state watchers are "overlayed" over the permanent init state. Thus, if this is the init state and the active state also sets this value, we should avoid touching it */ if (self->active_state != NULL /* ? */ && data->state == self->spec->init_state && g_hash_table_contains ( self->active_state->setters, data->dest)) return; set_value ( data->self, data->state, data->instance, data->dest, data->src, NULL); } static GHashTable *renderer_resource_cache = NULL; // static void // cache_weak_notify (char *resource, // GObject *where_the_object_was) // { // g_hash_table_remove (renderer_resource_cache, resource); // g_free (resource); // } static void wdgt_renderer_set_from_resource (BgeWdgtRenderer *self, const char *resource) { g_autoptr (GError) local_error = NULL; g_autoptr (GBytes) bytes = NULL; BgeWdgtSpec *cached = NULL; gsize buffer_size = 0; gconstpointer buffer = NULL; g_autoptr (BgeWdgtSpec) spec = NULL; if (g_once_init_enter_pointer (&renderer_resource_cache)) { GHashTable *tmp = NULL; tmp = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, g_object_unref); g_once_init_leave_pointer (&renderer_resource_cache, tmp); } cached = g_hash_table_lookup ( renderer_resource_cache, resource); if (cached == NULL) { bytes = g_resources_lookup_data ( resource, G_RESOURCE_LOOKUP_FLAGS_NONE, &local_error); if (bytes == NULL) { g_critical ("failed to set renderer spec from resource: %s", local_error->message); bge_wdgt_renderer_set_spec (self, NULL); return; } buffer = g_bytes_get_data (bytes, &buffer_size); spec = bge_wdgt_spec_new_for_string (buffer, &local_error); if (spec == NULL) { g_critical ("failed to set renderer spec from resource %s: %s", resource, local_error->message); bge_wdgt_renderer_set_spec (self, NULL); return; } g_hash_table_replace ( renderer_resource_cache, g_strdup (resource), g_object_ref (spec)); // g_object_weak_ref ( // G_OBJECT (spec), // (GWeakNotify) cache_weak_notify, // g_strdup (resource)); cached = spec; } bge_wdgt_renderer_set_spec (self, cached); } static void _marshal_DIRECT__ARGS_DIRECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data) { typedef void (*GMarshalFunc_DIRECT__ARGS_DIRECT) (gpointer data1, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer data2); GCClosure *cc = (GCClosure *) closure; gpointer data1, data2; GMarshalFunc_DIRECT__ARGS_DIRECT callback; g_return_if_fail (return_value != NULL); g_return_if_fail (n_param_values >= 1); if (G_CCLOSURE_SWAP_DATA (closure)) { data1 = closure->data; data2 = g_value_peek_pointer (param_values + 0); } else { data1 = g_value_peek_pointer (param_values + 0); data2 = closure->data; } callback = (GMarshalFunc_DIRECT__ARGS_DIRECT) (marshal_data ? marshal_data : cc->callback); callback (data1, return_value, n_param_values - 1, param_values + 1, data2); } static void _marshal_BOXED__ARGS_DIRECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data) { typedef gpointer (*GMarshalFunc_BOXED__ARGS_DIRECT) (gpointer data1, guint n_param_values, const GValue *param_values, gpointer data2); GCClosure *cc = (GCClosure *) closure; gpointer data1, data2; GMarshalFunc_BOXED__ARGS_DIRECT callback; gpointer v_return; g_return_if_fail (return_value != NULL); g_return_if_fail (n_param_values >= 1); if (G_CCLOSURE_SWAP_DATA (closure)) { data1 = closure->data; data2 = g_value_peek_pointer (param_values + 0); } else { data1 = g_value_peek_pointer (param_values + 0); data2 = closure->data; } callback = (GMarshalFunc_BOXED__ARGS_DIRECT) (marshal_data ? marshal_data : cc->callback); v_return = callback (data1, n_param_values - 1, param_values + 1, data2); g_value_take_boxed (return_value, v_return); } /* End of bge-wdgt-spec.c */ bazaar-org-bazaar-43ce9f7/bge/wdgt/bge-wdgt-spec.h000066400000000000000000000034141520414637400217360ustar00rootroot00000000000000/* bge-wdgt-spec.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 #ifndef BGE_INSIDE #error "Only can be included directly." #endif G_BEGIN_DECLS #define BGE_TYPE_WDGT_SPEC (bge_wdgt_spec_get_type ()) G_DECLARE_FINAL_TYPE (BgeWdgtSpec, bge_wdgt_spec, BGE, WDGT_SPEC, GObject) BGE_AVAILABLE_IN_ALL BgeWdgtSpec * bge_wdgt_spec_new (void); BGE_AVAILABLE_IN_ALL BgeWdgtSpec * bge_wdgt_spec_new_for_string (const char *string, GError **error); BGE_AVAILABLE_IN_ALL BgeWdgtSpec * bge_wdgt_spec_new_for_resource (const char *resource, GError **error); BGE_AVAILABLE_IN_ALL const char * bge_wdgt_spec_get_name (BgeWdgtSpec *self); BGE_AVAILABLE_IN_ALL void bge_wdgt_spec_set_name (BgeWdgtSpec *self, const char *name); BGE_AVAILABLE_IN_ALL void bge_wdgt_spec_set_name_take (BgeWdgtSpec *self, char *name); #define bge_wdgt_spec_set_name_take_printf(self, ...) bge_wdgt_spec_set_name_take (self, g_strdup_printf (__VA_ARGS__)) G_END_DECLS /* End of bge-wdgt-spec.h */ bazaar-org-bazaar-43ce9f7/bge/wdgt/fmt/000077500000000000000000000000001520414637400177215ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/bge/wdgt/fmt/meson.build000066400000000000000000000000461520414637400220630ustar00rootroot00000000000000bge_sources += files( 'parser.c', ) bazaar-org-bazaar-43ce9f7/bge/wdgt/fmt/parser.c000066400000000000000000003440211520414637400213650ustar00rootroot00000000000000/* parser.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 "BGE::WDGT-PARSE" #include #include #include "../bge-wdgt-spec-private.h" #include "bge-marshalers.h" #include "parser.h" #include "util.h" #define IS_EOF(_p) ((_p) == NULL || *(_p) == '\0') #define SINGLE_CHAR_TOKENS "{}()=:;," #define EVAL_SINGLE_CHAR_TOKENS "#(),+-*/^%" #define STR_DEFARRAY "defarray" #define STR_DEFWIDGET "defwidget" #define STR_FOREACH "%FOREACH" #define STR_VARIABLE "var" #define STR_REFERENCE "reference" #define STR_INIT "init" #define STR_STATE "state" #define STR_DEFAULT_STATE "state-default" #define STR_SET "set" #define STR_TRANSITION "transition" #define STR_TRANSITION_SPRING "transition-spring" #define STR_ALLOCATE "allocate" #define STR_MEASURE "measure" #define STR_SNAPSHOT "snapshot" typedef enum { TOKEN_PARSE_DEFAULT = 0, TOKEN_PARSE_QUOTED = 1 << 0, } TokenParseFlags; typedef enum { ARGS_PARSE_PARENS = 0, ARGS_PARSE_LEFT_ASSIGN, ARGS_PARSE_RIGHT_ASSIGN, } ArgsParseKind; typedef enum { OPERATOR_ADD = 0, OPERATOR_SUBTRACT, OPERATOR_MULTIPLY, OPERATOR_DIVIDE, OPERATOR_MODULUS, OPERATOR_POWER, } Operator; static const int operator_precedence[] = { [OPERATOR_ADD] = 0, [OPERATOR_SUBTRACT] = 0, [OPERATOR_MULTIPLY] = 1, [OPERATOR_DIVIDE] = 1, [OPERATOR_MODULUS] = 1, [OPERATOR_POWER] = 2, }; typedef struct { Operator op; guint pos; } EvalOperator; BGE_DEFINE_DATA ( eval_closure, EvalClosure, { GArray *ops; gdouble *workbuf0; gdouble *workbuf1; }, BGE_RELEASE_DATA (ops, g_array_unref); BGE_RELEASE_DATA (workbuf0, g_free); BGE_RELEASE_DATA (workbuf1, g_free)); static BgeWdgtSpec * parse_string_inner (const char *string, guint *line, guint *column, GError **error); static const char * parse_widget_block (const char *p, BgeWdgtSpec *spec, GHashTable *macro_arrays, GHashTable *macro_replacements, guint *n_anon_vals, GHashTable *type_hints, guint *line, guint *column, GError **error); static const char * parse_snapshot_block (const char *p, BgeWdgtSpec *spec, const char *state, GHashTable *macro_replacements, guint *n_anon_vals, GHashTable *type_hints, guint *line, guint *column, GError **error); static const char * parse_eval (const char *p, BgeWdgtSpec *spec, const char *state, GHashTable *macro_replacements, guint *n_anon_vals, GHashTable *type_hints, guint *line, guint *column, char **value_out, GError **error); static const char * parse_args (const char *p, BgeWdgtSpec *spec, const char *state, const char *enclosing_object, GHashTable *macro_replacements, guint *n_anon_vals, GHashTable *type_hints, guint *line, guint *column, const char *const *destinations, GType destinations_types[], guint n_destinations, char ***values_out, GType **types_out, guint *n_out, ArgsParseKind parse_kind, GError **error); static char * parse_token_fundamental (const char *token, BgeWdgtSpec *spec, guint *n_anon_vals, guint *line, guint *column, GError **error); static char * consume_token (const char **pp, const char *single_chars, TokenParseFlags flags, gboolean *was_quoted, GHashTable *macro_replacements, guint *line, guint *column, GError **error); static char * consume_token_inner (const char **pp, const char *single_chars, TokenParseFlags flags, gboolean *was_quoted, guint *line, guint *column, GError **error); static gdouble eval_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data); static char * make_object_property_name (const char *object, const char *property, guint n); static char * make_widget_allocation_name (const char *widget, guint n); static char * make_widget_measurement_name (guint n); static char * make_anon_name (guint n); static gint cmp_operator (EvalOperator *a, EvalOperator *b); static void _marshal_DIRECT__ARGS_DIRECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data); static void _marshal_BOOL__ARGS_DIRECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data); static void _marshal_DOUBLE__ARGS_DIRECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data); BgeWdgtSpec * bge_wdgt_parse_string (const char *string, GError **error) { g_autoptr (GError) local_error = NULL; guint line = 0; guint column = 0; g_autoptr (BgeWdgtSpec) spec = NULL; g_return_val_if_fail (string != NULL, FALSE); spec = parse_string_inner (string, &line, &column, &local_error); if (spec == NULL) { g_set_error ( error, local_error->domain, local_error->code, "wdgt parser error in string input " "at line:%u, offset:%u : %s", line, column, local_error->message); return NULL; } return g_steal_pointer (&spec); } static BgeWdgtSpec * parse_string_inner (const char *string, guint *line, guint *column, GError **error) { g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autoptr (BgeWdgtSpec) spec = NULL; g_autoptr (GHashTable) macro_arrays = NULL; g_autoptr (GHashTable) macro_replacements = NULL; guint n_anon_vals = 0; g_autoptr (GHashTable) type_hints = NULL; spec = bge_wdgt_spec_new (); macro_arrays = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref); macro_replacements = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, g_free); type_hints = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, NULL); #define RETURN_ERROR_UNLESS(_cond) \ G_STMT_START \ { \ if (!(_cond)) \ { \ g_set_error ( \ error, \ G_IO_ERROR, \ G_IO_ERROR_UNKNOWN, \ "%s", \ local_error != NULL \ ? local_error->message \ : "???"); \ return NULL; \ } \ } \ G_STMT_END #define EXPECT_TOKEN(_string, _token) \ G_STMT_START \ { \ if (g_strcmp0 ((_string), (_token)) != 0) \ { \ g_set_error ( \ error, \ G_IO_ERROR, \ G_IO_ERROR_UNKNOWN, \ "expected token \"%s\", got \"%s\"", \ (_token), (_string)); \ return NULL; \ } \ } \ G_STMT_END #define UNEXPECTED_TOKEN(_token) \ G_STMT_START \ { \ g_set_error ( \ error, \ G_IO_ERROR, \ G_IO_ERROR_UNKNOWN, \ "unexpected token \"%s\"", (_token)); \ return NULL; \ } \ G_STMT_END result = bge_wdgt_spec_add_measure_for_size_source_value ( spec, "%for-size%", &local_error); RETURN_ERROR_UNLESS (result); g_hash_table_replace ( type_hints, g_strdup ("%for-size%"), GSIZE_TO_POINTER (G_TYPE_INT)); result = bge_wdgt_spec_add_widget_width_source_value ( spec, "%width%", &local_error); RETURN_ERROR_UNLESS (result); g_hash_table_replace ( type_hints, g_strdup ("%width%"), GSIZE_TO_POINTER (G_TYPE_INT)); result = bge_wdgt_spec_add_widget_height_source_value ( spec, "%height%", &local_error); RETURN_ERROR_UNLESS (result); g_hash_table_replace ( type_hints, g_strdup ("%height%"), GSIZE_TO_POINTER (G_TYPE_INT)); result = bge_wdgt_spec_add_tick_time_source_value ( spec, "%tick%", &local_error); RETURN_ERROR_UNLESS (result); g_hash_table_replace ( type_hints, g_strdup ("%tick%"), GSIZE_TO_POINTER (G_TYPE_DOUBLE)); for (const char *p = string; !IS_EOF (p);) { g_autofree char *token = NULL; token = consume_token ( &p, SINGLE_CHAR_TOKENS, TOKEN_PARSE_DEFAULT, NULL, NULL, line, column, NULL); if (token == NULL) break; #define GET_TOKEN_FULL(_token_out, _flags, _single_chars, _was_quoted) \ G_STMT_START \ { \ g_clear_pointer ((_token_out), g_free); \ *(_token_out) = consume_token ( \ &p, \ (_single_chars), \ (_flags), \ (_was_quoted), \ macro_replacements, \ line, column, \ &local_error); \ RETURN_ERROR_UNLESS (*(_token_out) != NULL); \ } \ G_STMT_END #define GET_TOKEN(_token_out, _flags) \ GET_TOKEN_FULL (_token_out, _flags, SINGLE_CHAR_TOKENS, NULL) #define GET_TOKEN_EXPECT(_token_out, _flags, _expect) \ G_STMT_START \ { \ GET_TOKEN ((_token_out), (_flags)); \ EXPECT_TOKEN (*(_token_out), (_expect)); \ } \ G_STMT_END if (g_strcmp0 (token, STR_DEFWIDGET) == 0) { g_autofree char *widget_name = NULL; GET_TOKEN (&widget_name, TOKEN_PARSE_QUOTED); bge_wdgt_spec_set_name (spec, widget_name); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "{"); p = parse_widget_block ( p, spec, macro_arrays, macro_replacements, &n_anon_vals, type_hints, line, column, &local_error); RETURN_ERROR_UNLESS (p != NULL); } else if (g_strcmp0 (token, STR_DEFARRAY) == 0) { g_autofree char *array_name = NULL; guint n_elements = 0; g_auto (GStrv) elements = NULL; g_autoptr (GPtrArray) array = NULL; GET_TOKEN (&array_name, TOKEN_PARSE_DEFAULT); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, NULL, NULL, macro_replacements, &n_anon_vals, type_hints, line, column, NULL, NULL, 0, &elements, NULL, &n_elements, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); array = g_ptr_array_new_take_null_terminated ( (gpointer *) g_steal_pointer (&elements), g_free); g_hash_table_replace ( macro_arrays, g_steal_pointer (&array_name), g_steal_pointer (&array)); } else UNEXPECTED_TOKEN (token); } return g_steal_pointer (&spec); } static const char * parse_widget_block (const char *p, BgeWdgtSpec *spec, GHashTable *macro_arrays, GHashTable *macro_replacements, guint *n_anon_vals, GHashTable *type_hints, guint *line, guint *column, GError **error) { g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autofree char *token = NULL; for (;;) { GET_TOKEN (&token, TOKEN_PARSE_DEFAULT); if (g_strcmp0 (token, "}") == 0) return p; else if (g_strcmp0 (token, STR_FOREACH) == 0) { g_autofree char *var_name = NULL; g_autofree char *iterator_name = NULL; g_autofree char *iterator_paste_name = NULL; g_autofree char *array_name = NULL; GPtrArray *array = NULL; const char *fixed_p = NULL; GET_TOKEN (&var_name, TOKEN_PARSE_DEFAULT); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ","); GET_TOKEN (&iterator_name, TOKEN_PARSE_DEFAULT); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ","); GET_TOKEN (&iterator_paste_name, TOKEN_PARSE_DEFAULT); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "IN"); GET_TOKEN (&array_name, TOKEN_PARSE_DEFAULT); array = g_hash_table_lookup (macro_arrays, array_name); if (array == NULL) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "macro array \"%s\" is undefined", array_name); return NULL; } GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "{"); fixed_p = p; for (guint i = 0; i < array->len; i++) { const char *element = NULL; g_autofree char *iterator = NULL; g_autofree char *iterator_paste = NULL; GValue iter_value = G_VALUE_INIT; element = g_ptr_array_index (array, i); g_hash_table_replace ( macro_replacements, g_strdup (var_name), g_strdup (element)); iterator = make_anon_name ((*n_anon_vals)++); g_value_set_uint (g_value_init (&iter_value, G_TYPE_UINT), i); result = bge_wdgt_spec_add_constant_source_value ( spec, iterator, &iter_value, &local_error); g_value_unset (&iter_value); RETURN_ERROR_UNLESS (result); g_hash_table_replace ( macro_replacements, g_strdup (iterator_name), g_steal_pointer (&iterator)); iterator_paste = g_strdup_printf ("%u", i); g_hash_table_replace ( macro_replacements, g_strdup (iterator_paste_name), g_steal_pointer (&iterator_paste)); p = parse_widget_block ( fixed_p, spec, macro_arrays, macro_replacements, n_anon_vals, type_hints, line, column, &local_error); RETURN_ERROR_UNLESS (p != NULL); } g_hash_table_remove (macro_replacements, var_name); g_hash_table_remove (macro_replacements, iterator_name); g_hash_table_remove (macro_replacements, iterator_paste_name); } else if (g_strcmp0 (token, STR_VARIABLE) == 0) { g_autofree char *name = NULL; g_autofree char *type_string = NULL; GType type = 0; GET_TOKEN (&name, TOKEN_PARSE_DEFAULT); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ":"); GET_TOKEN (&type_string, TOKEN_PARSE_QUOTED); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ";"); type = g_type_from_name (type_string); result = bge_wdgt_spec_add_variable_value ( spec, type, name, &local_error); RETURN_ERROR_UNLESS (result); g_hash_table_replace (type_hints, g_steal_pointer (&name), GSIZE_TO_POINTER (type)); } else if (g_strcmp0 (token, STR_REFERENCE) == 0) { g_autofree char *name = NULL; g_autofree char *type_string = NULL; GType type = 0; GET_TOKEN (&name, TOKEN_PARSE_DEFAULT); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ":"); GET_TOKEN (&type_string, TOKEN_PARSE_QUOTED); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ";"); type = g_type_from_name (type_string); result = bge_wdgt_spec_add_reference_object_value ( spec, type, name, &local_error); RETURN_ERROR_UNLESS (result); g_hash_table_replace (type_hints, g_steal_pointer (&name), GSIZE_TO_POINTER (type)); } else if (g_strcmp0 (token, STR_INIT) == 0 || g_strcmp0 (token, STR_STATE) == 0 || g_strcmp0 (token, STR_DEFAULT_STATE) == 0) { g_autofree char *state_name = NULL; if (g_strcmp0 (token, STR_INIT) != 0) { GET_TOKEN (&state_name, TOKEN_PARSE_QUOTED); result = bge_wdgt_spec_add_state ( spec, state_name, g_strcmp0 (token, STR_DEFAULT_STATE) == 0, &local_error); /* TODO: allow states to be redefined for macros, so they are just concatenated */ g_clear_error (&local_error); // RETURN_ERROR_UNLESS (result); } GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "{"); for (;;) { GET_TOKEN (&token, TOKEN_PARSE_DEFAULT); if (g_strcmp0 (token, "}") == 0) break; else if (g_strcmp0 (token, STR_SNAPSHOT) == 0) { GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "{"); p = parse_snapshot_block (p, spec, state_name, macro_replacements, n_anon_vals, type_hints, line, column, &local_error); RETURN_ERROR_UNLESS (p != NULL); } else if (g_strcmp0 (token, STR_SET) == 0) { guint n_dest_values = 0; g_auto (GStrv) dest_values = NULL; g_autofree GType *dest_types = NULL; guint n_src_values = 0; g_auto (GStrv) src_values = NULL; p = parse_args (p, spec, state_name, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, NULL, 0, &dest_values, &dest_types, &n_dest_values, ARGS_PARSE_LEFT_ASSIGN, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_dest_values == 0) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Left assignment needs at least one argument"); return NULL; } p = parse_args (p, spec, state_name, NULL, macro_replacements, n_anon_vals, type_hints, line, column, (const char *const *) dest_values, dest_types, n_dest_values, &src_values, NULL, &n_src_values, ARGS_PARSE_RIGHT_ASSIGN, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_src_values != n_dest_values) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Right assignment needs %d argument(s) " "to match the left side", n_dest_values); return NULL; } for (guint i = 0; i < n_dest_values; i++) { result = bge_wdgt_spec_set_value ( spec, state_name, dest_values[i], src_values[i], &local_error); RETURN_ERROR_UNLESS (result); } } else if (g_strcmp0 (token, STR_TRANSITION) == 0) { g_autofree char *transition_value = NULL; guint n_spec_values = 0; g_auto (GStrv) spec_values = NULL; GET_TOKEN (&transition_value, TOKEN_PARSE_DEFAULT); p = parse_args (p, spec, state_name, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ G_TYPE_DOUBLE, BGE_TYPE_EASING }, 2, &spec_values, NULL, &n_spec_values, ARGS_PARSE_RIGHT_ASSIGN, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_spec_values != 2) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "transition spec needs 2 arguments " "(animation length in seconds, easing type), got %u", n_spec_values); return NULL; } result = bge_wdgt_spec_transition_value ( spec, state_name, transition_value, spec_values[0], spec_values[1], &local_error); RETURN_ERROR_UNLESS (result); } else if (g_strcmp0 (token, STR_TRANSITION_SPRING) == 0) { g_autofree char *transition_value = NULL; guint n_spec_values = 0; g_auto (GStrv) spec_values = NULL; GET_TOKEN (&transition_value, TOKEN_PARSE_DEFAULT); p = parse_args (p, spec, state_name, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE }, 3, &spec_values, NULL, &n_spec_values, ARGS_PARSE_RIGHT_ASSIGN, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_spec_values != 3) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "spring transition spec needs 3 arguments " "(damping-ratio, mass, stiffness), got %u", n_spec_values); return NULL; } result = bge_wdgt_spec_transition_value_spring ( spec, state_name, transition_value, spec_values[0], spec_values[1], spec_values[2], &local_error); RETURN_ERROR_UNLESS (result); } else if (g_strcmp0 (token, STR_ALLOCATE) == 0) { g_autofree char *child_value = NULL; guint n_allocation_values = 0; g_auto (GStrv) allocation_values = NULL; GET_TOKEN (&child_value, TOKEN_PARSE_DEFAULT); p = parse_args (p, spec, state_name, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ G_TYPE_INT, G_TYPE_INT, GSK_TYPE_TRANSFORM }, 3, &allocation_values, NULL, &n_allocation_values, ARGS_PARSE_RIGHT_ASSIGN, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_allocation_values != 2 && n_allocation_values != 3) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "allocation needs 2 or 3 values, a width " "and height and one transform, got %u", n_allocation_values); return NULL; } for (guint i = 0; i < n_allocation_values; i++) { g_autofree char *allocation_key = NULL; allocation_key = make_widget_allocation_name (child_value, (*n_anon_vals)++); switch (i) { case 0: result = bge_wdgt_spec_add_allocation_width_value ( spec, allocation_key, child_value, &local_error); break; case 1: result = bge_wdgt_spec_add_allocation_height_value ( spec, allocation_key, child_value, &local_error); break; case 2: result = bge_wdgt_spec_add_allocation_transform_value ( spec, allocation_key, child_value, &local_error); break; default: g_assert_not_reached (); } RETURN_ERROR_UNLESS (result); result = bge_wdgt_spec_set_value ( spec, state_name, allocation_key, allocation_values[i], &local_error); RETURN_ERROR_UNLESS (result); } } else if (g_strcmp0 (token, STR_MEASURE) == 0) { guint n_measurement_values = 0; g_auto (GStrv) measurement_values = NULL; p = parse_args (p, spec, state_name, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT }, 4, &measurement_values, NULL, &n_measurement_values, ARGS_PARSE_RIGHT_ASSIGN, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_measurement_values != 4) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "measurement needs 4 values, a " "minimum width, " "natural width, " "minimum height, " "and " "natural height, " "got %u", n_measurement_values); return NULL; } for (guint i = 0; i < n_measurement_values; i++) { g_autofree char *measurement_key = NULL; measurement_key = make_widget_measurement_name ((*n_anon_vals)++); switch (i) { case 0: result = bge_wdgt_spec_add_measure_value ( spec, measurement_key, BGE_WDGT_MEASURE_MINIMUM_WIDTH, &local_error); break; case 1: result = bge_wdgt_spec_add_measure_value ( spec, measurement_key, BGE_WDGT_MEASURE_NATURAL_WIDTH, &local_error); break; case 2: result = bge_wdgt_spec_add_measure_value ( spec, measurement_key, BGE_WDGT_MEASURE_MINIMUM_HEIGHT, &local_error); break; case 3: result = bge_wdgt_spec_add_measure_value ( spec, measurement_key, BGE_WDGT_MEASURE_NATURAL_HEIGHT, &local_error); break; default: g_assert_not_reached (); } RETURN_ERROR_UNLESS (result); result = bge_wdgt_spec_set_value ( spec, state_name, measurement_key, measurement_values[i], &local_error); RETURN_ERROR_UNLESS (result); } } else UNEXPECTED_TOKEN (token); } } else UNEXPECTED_TOKEN (token); } return p; } static const char * parse_snapshot_block (const char *p, BgeWdgtSpec *spec, const char *state, GHashTable *macro_replacements, guint *n_anon_vals, GHashTable *type_hints, guint *line, guint *column, GError **error) { g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autofree char *token = NULL; for (;;) { g_autofree char *action = NULL; BgeWdgtSnapshotInstrKind kind = 0; g_autofree char *instr = NULL; guint n_args = 0; g_auto (GStrv) args = NULL; guint n_pops = 0; GET_TOKEN (&action, TOKEN_PARSE_DEFAULT); if (g_strcmp0 (action, "}") == 0) break; else if (g_strcmp0 (action, "foreach") == 0) { g_autofree char *var = NULL; g_autofree char *element_type_string = NULL; g_autofree char *idx_var = NULL; g_autofree char *model = NULL; GType element_type = G_TYPE_INVALID; GET_TOKEN (&var, TOKEN_PARSE_DEFAULT); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ":"); GET_TOKEN (&element_type_string, TOKEN_PARSE_DEFAULT); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ","); GET_TOKEN (&idx_var, TOKEN_PARSE_DEFAULT); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "in"); GET_TOKEN (&model, TOKEN_PARSE_DEFAULT); element_type = g_type_from_name (element_type_string); result = bge_wdgt_spec_push_foreach ( spec, model, var, idx_var, element_type, &local_error); RETURN_ERROR_UNLESS (result); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "{"); p = parse_snapshot_block (p, spec, state, macro_replacements, n_anon_vals, type_hints, line, column, &local_error); RETURN_ERROR_UNLESS (p != NULL); bge_wdgt_spec_pop_foreach (spec); continue; } else if (g_strcmp0 (action, "save") == 0) kind = BGE_WDGT_SNAPSHOT_INSTR_SAVE; else if (g_strcmp0 (action, "with") == 0) kind = BGE_WDGT_SNAPSHOT_INSTR_PUSH; else if (g_strcmp0 (action, "add") == 0) kind = BGE_WDGT_SNAPSHOT_INSTR_APPEND; else if (g_strcmp0 (action, "move") == 0) kind = BGE_WDGT_SNAPSHOT_INSTR_TRANSFORM; else if (g_strcmp0 (action, "do-child") == 0) kind = BGE_WDGT_SNAPSHOT_INSTR_SNAPSHOT_CHILD; else UNEXPECTED_TOKEN (action); if (kind == BGE_WDGT_SNAPSHOT_INSTR_SAVE) { result = bge_wdgt_spec_append_snapshot_instr ( spec, state, BGE_WDGT_SNAPSHOT_INSTR_SAVE, "save", NULL, 0, NULL, &local_error); RETURN_ERROR_UNLESS (result); } else if (kind == BGE_WDGT_SNAPSHOT_INSTR_SNAPSHOT_CHILD) { p = parse_args (p, spec, state, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, NULL, 0, &args, NULL, &n_args, ARGS_PARSE_RIGHT_ASSIGN, &local_error); RETURN_ERROR_UNLESS (p != NULL); result = bge_wdgt_spec_append_snapshot_instr ( spec, state, BGE_WDGT_SNAPSHOT_INSTR_SNAPSHOT_CHILD, "do-child", (const char *const *) args, n_args, NULL, &local_error); RETURN_ERROR_UNLESS (result); } else { GET_TOKEN (&instr, TOKEN_PARSE_DEFAULT); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, state, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, NULL, 0, &args, NULL, &n_args, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); result = bge_wdgt_spec_append_snapshot_instr ( spec, state, kind, instr, (const char *const *) args, n_args, &n_pops, &local_error); RETURN_ERROR_UNLESS (result); } if (kind == BGE_WDGT_SNAPSHOT_INSTR_APPEND || kind == BGE_WDGT_SNAPSHOT_INSTR_TRANSFORM) GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ";"); else if (kind == BGE_WDGT_SNAPSHOT_INSTR_PUSH) { for (guint i = 0; i < n_pops; i++) { if (i > 0) GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "then"); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "{"); p = parse_snapshot_block (p, spec, state, macro_replacements, n_anon_vals, type_hints, line, column, &local_error); RETURN_ERROR_UNLESS (p != NULL); result = bge_wdgt_spec_append_snapshot_instr ( spec, state, BGE_WDGT_SNAPSHOT_INSTR_POP, "pop", NULL, 0, NULL, &local_error); RETURN_ERROR_UNLESS (result); } } else if (kind == BGE_WDGT_SNAPSHOT_INSTR_SAVE) { GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "{"); p = parse_snapshot_block (p, spec, state, macro_replacements, n_anon_vals, type_hints, line, column, &local_error); RETURN_ERROR_UNLESS (p != NULL); result = bge_wdgt_spec_append_snapshot_instr ( spec, state, BGE_WDGT_SNAPSHOT_INSTR_RESTORE, "restore", NULL, 0, NULL, &local_error); RETURN_ERROR_UNLESS (result); } } return p; } static gdouble floor_closure (gpointer this, gdouble x, gpointer data) { return floor (x); } static gdouble ceil_closure (gpointer this, gdouble x, gpointer data) { return ceil (x); } static gdouble sin_closure (gpointer this, gdouble x, gpointer data) { return sin (x); } static gdouble cos_closure (gpointer this, gdouble x, gpointer data) { return cos (x); } static const char * parse_eval (const char *p, BgeWdgtSpec *spec, const char *state, GHashTable *macro_replacements, guint *n_anon_vals, GHashTable *type_hints, guint *line, guint *column, char **value_out, GError **error) { g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autofree char *token = NULL; g_autoptr (GPtrArray) values = NULL; g_autoptr (GArray) ops = NULL; g_autoptr (GArray) value_types = NULL; g_autofree char *key = NULL; g_autoptr (EvalClosureData) data = NULL; values = g_ptr_array_new_with_free_func (g_free); ops = g_array_new (FALSE, FALSE, sizeof (EvalOperator)); value_types = g_array_new (FALSE, FALSE, sizeof (GType)); #define GET_TOKEN_EVAL(_token_out, _flags) \ GET_TOKEN_FULL (_token_out, _flags, EVAL_SINGLE_CHAR_TOKENS, NULL) #define GET_TOKEN_EVAL_EXPECT(_token_out, _flags, _expect) \ G_STMT_START \ { \ GET_TOKEN_EVAL ((_token_out), (_flags)); \ EXPECT_TOKEN (*(_token_out), (_expect)); \ } \ G_STMT_END for (gboolean apply_negative = FALSE;;) { g_autofree char *value = NULL; Operator op = -1; gboolean expected_value = FALSE; GET_TOKEN_EVAL (&token, TOKEN_PARSE_DEFAULT); if (g_strcmp0 (token, ")") == 0) break; else if (g_strcmp0 (token, "(") == 0) { p = parse_eval (p, spec, state, macro_replacements, n_anon_vals, type_hints, line, column, &value, &local_error); RETURN_ERROR_UNLESS (p != NULL); } else if (g_strcmp0 (token, "#") == 0) { g_auto (GStrv) escape_args = NULL; guint n_escape_args = 0; GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, state, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ G_TYPE_DOUBLE }, 1, &escape_args, NULL, &n_escape_args, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_escape_args != 1) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "evaluation escape " "needs a single argument"); return NULL; } value = g_strdup (escape_args[0]); } else if (g_strcmp0 (token, "ceil") == 0 || g_strcmp0 (token, "floor") == 0 || g_strcmp0 (token, "sin") == 0 || g_strcmp0 (token, "cos") == 0) { GCallback cb = NULL; g_autofree char *arg = NULL; g_autofree char *math_func_key = NULL; if (g_strcmp0 (token, "ceil") == 0) cb = G_CALLBACK (ceil_closure); else if (g_strcmp0 (token, "floor") == 0) cb = G_CALLBACK (floor_closure); else if (g_strcmp0 (token, "sin") == 0) cb = G_CALLBACK (sin_closure); else if (g_strcmp0 (token, "cos") == 0) cb = G_CALLBACK (cos_closure); GET_TOKEN_EVAL_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_eval (p, spec, state, macro_replacements, n_anon_vals, type_hints, line, column, &arg, &local_error); RETURN_ERROR_UNLESS (p != NULL); math_func_key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_cclosure_source_value ( spec, math_func_key, G_TYPE_DOUBLE, bge_marshal_DOUBLE__DOUBLE, cb, (const char *const[]){ arg }, (GType[]){ G_TYPE_DOUBLE }, 1, NULL, NULL, &local_error); RETURN_ERROR_UNLESS (result); value = g_steal_pointer (&math_func_key); } else if (g_strcmp0 (token, "+") == 0) op = OPERATOR_ADD; else if (g_strcmp0 (token, "-") == 0) op = OPERATOR_SUBTRACT; else if (g_strcmp0 (token, "*") == 0) op = OPERATOR_MULTIPLY; else if (g_strcmp0 (token, "/") == 0) op = OPERATOR_DIVIDE; else if (g_strcmp0 (token, "%") == 0) op = OPERATOR_MODULUS; else if (g_strcmp0 (token, "^") == 0) op = OPERATOR_POWER; else { value = parse_token_fundamental ( token, spec, n_anon_vals, line, column, &local_error); RETURN_ERROR_UNLESS (value != NULL); } expected_value = values->len == ops->len; if (value != NULL) { GType type_double = G_TYPE_DOUBLE; if (!expected_value) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Expected operator, got \"%s\"", token); return NULL; } if (apply_negative) { GValue gvalue = G_VALUE_INIT; g_autofree char *negative_key = NULL; EvalOperator append = { 0 }; g_value_set_double (g_value_init (&gvalue, G_TYPE_DOUBLE), -1.0); negative_key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_constant_source_value ( spec, negative_key, &gvalue, &local_error); g_value_unset (&gvalue); RETURN_ERROR_UNLESS (result); g_ptr_array_add (values, g_steal_pointer (&negative_key)); g_array_append_val (value_types, type_double); append.op = OPERATOR_MULTIPLY; append.pos = ops->len; g_array_append_val (ops, append); apply_negative = FALSE; } g_ptr_array_add (values, g_steal_pointer (&value)); g_array_append_val (value_types, type_double); } else if (op >= 0) { EvalOperator append = { 0 }; if (expected_value) { if (op == OPERATOR_SUBTRACT) apply_negative = !apply_negative; else if (op != OPERATOR_ADD) /* Allow adding `+` in front of numbers for alignment with negatives etc */ { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Expected value, got \"%s\"", token); return NULL; } } else { append.op = op; append.pos = ops->len; g_array_append_val (ops, append); } } } if (values->len == 0) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Empty evaluation block"); return NULL; } if (ops->len != values->len - 1) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Invalid syntax in evaluation block"); return NULL; } if (values->len == 1) { *value_out = g_ptr_array_steal_index (values, 0); return p; } g_array_sort (ops, (GCompareFunc) cmp_operator); data = eval_closure_data_new (); data->ops = g_array_ref (ops); data->workbuf0 = g_malloc0_n (values->len, sizeof (gdouble)); data->workbuf1 = g_malloc0_n (values->len, sizeof (gdouble)); key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_cclosure_source_value ( spec, key, G_TYPE_DOUBLE, _marshal_DOUBLE__ARGS_DIRECT, G_CALLBACK (eval_closure), (const char *const *) values->pdata, (const GType *) (void *) value_types->data, values->len, eval_closure_data_ref (data), eval_closure_data_unref, &local_error); RETURN_ERROR_UNLESS (result); *value_out = g_steal_pointer (&key); return p; } static gboolean not_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { for (guint i = 0; i < n_param_values; i++) { if (!g_value_get_boolean (¶m_values[i])) return TRUE; } return FALSE; } static gboolean and_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { for (guint i = 0; i < n_param_values; i++) { if (!g_value_get_boolean (¶m_values[i])) return FALSE; } return TRUE; } static gboolean or_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { for (guint i = 0; i < n_param_values; i++) { if (g_value_get_boolean (¶m_values[i])) return TRUE; } return FALSE; } static gboolean lt_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { gdouble cmp_with = 0.0; cmp_with = g_value_get_double (param_values); for (guint i = 1; i < n_param_values; i++) { if (!(cmp_with < g_value_get_double (¶m_values[i]))) return FALSE; } return TRUE; } static gboolean gt_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { gdouble cmp_with = 0.0; cmp_with = g_value_get_double (param_values); for (guint i = 1; i < n_param_values; i++) { if (!(cmp_with > g_value_get_double (¶m_values[i]))) return FALSE; } return TRUE; } static gboolean lte_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { gdouble cmp_with = 0.0; cmp_with = g_value_get_double (param_values); for (guint i = 1; i < n_param_values; i++) { if (!(cmp_with <= g_value_get_double (¶m_values[i]))) return FALSE; } return TRUE; } static gboolean gte_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { gdouble cmp_with = 0.0; cmp_with = g_value_get_double (param_values); for (guint i = 1; i < n_param_values; i++) { if (!(cmp_with >= g_value_get_double (¶m_values[i]))) return FALSE; } return TRUE; } static gboolean eq_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { gdouble cmp_with = 0.0; cmp_with = g_value_get_double (param_values); for (guint i = 1; i < n_param_values; i++) { if (!(cmp_with == g_value_get_double (¶m_values[i]))) return FALSE; } return TRUE; } static gboolean neq_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { gdouble cmp_with = 0.0; cmp_with = g_value_get_double (param_values); for (guint i = 1; i < n_param_values; i++) { if (!(cmp_with != g_value_get_double (¶m_values[i]))) return FALSE; } return TRUE; } static gboolean aeq_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { gdouble cmp_with = 0.0; cmp_with = g_value_get_double (param_values); for (guint i = 1; i < n_param_values; i++) { if (!(G_APPROX_VALUE (cmp_with, g_value_get_double (¶m_values[i]), 0.00001))) return FALSE; } return TRUE; } static gboolean aneq_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { gdouble cmp_with = 0.0; cmp_with = g_value_get_double (param_values); for (guint i = 1; i < n_param_values; i++) { if (!(!G_APPROX_VALUE (cmp_with, g_value_get_double (¶m_values[i]), 0.00001))) return FALSE; } return TRUE; } static void ifelse_closure (gpointer this, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer dest_type_ptr) { if (g_value_get_boolean (param_values)) g_value_copy (¶m_values[1], return_value); else g_value_copy (¶m_values[2], return_value); } static void measure_path_closure (gpointer this, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer dest_type_ptr) { GskPathMeasure *measure = NULL; measure = gsk_path_measure_new ( g_value_get_boxed (param_values)); g_value_take_boxed (return_value, measure); } static void path_length_closure (gpointer this, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer dest_type_ptr) { gdouble length = 0.0; length = gsk_path_measure_get_length ( g_value_get_boxed (param_values)); g_value_set_double (return_value, length); } static void path_point_closure (gpointer this, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer dest_type_ptr) { gboolean result = FALSE; GskPathPoint point = { 0 }; result = gsk_path_measure_get_point ( g_value_get_boxed (¶m_values[0]), g_value_get_double (¶m_values[1]), &point); if (!result) return; g_value_set_boxed (return_value, &point); } static const char * parse_args (const char *p, BgeWdgtSpec *spec, const char *state, const char *enclosing_object, GHashTable *macro_replacements, guint *n_anon_vals, GHashTable *type_hints, guint *line, guint *column, const char *const *destinations, GType destinations_types[], guint n_destinations, char ***values_out, GType **types_out, guint *n_out, ArgsParseKind parse_kind, GError **error) { g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autofree char *token = NULL; guint n_args = 0; g_autoptr (GStrvBuilder) builder = NULL; g_autoptr (GArray) types_array = NULL; builder = g_strv_builder_new (); types_array = g_array_new (FALSE, TRUE, sizeof (GType)); for (gboolean need_comma = FALSE, get_token = TRUE, was_quoted = FALSE; ;) { if (get_token) GET_TOKEN_FULL (&token, TOKEN_PARSE_DEFAULT, SINGLE_CHAR_TOKENS, &was_quoted); get_token = TRUE; if (was_quoted) { g_autofree char *tmp_token = NULL; g_autofree char *key = NULL; GValue value = { 0 }; g_value_set_string (g_value_init (&value, G_TYPE_STRING), token); key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_constant_source_value ( spec, key, &value, &local_error); g_value_unset (&value); RETURN_ERROR_UNLESS (result); g_strv_builder_take (builder, g_steal_pointer (&key)); n_args++; need_comma = TRUE; } else if ((parse_kind == ARGS_PARSE_LEFT_ASSIGN && g_strcmp0 (token, "=") == 0) || (parse_kind == ARGS_PARSE_RIGHT_ASSIGN && g_strcmp0 (token, ";") == 0) || (parse_kind == ARGS_PARSE_PARENS && g_strcmp0 (token, ")") == 0)) break; else if (need_comma) { if (g_strcmp0 (token, ",") == 0) { need_comma = FALSE; continue; } else { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Arguments must be comma-separated"); return NULL; } } else if (g_strcmp0 (token, "_") == 0 || g_strcmp0 (token, "C_") == 0) /* gettext translations */ { gboolean have_context = FALSE; g_autofree char *context_text = NULL; g_autofree char *source_text = NULL; GValue value = G_VALUE_INIT; g_autofree char *key = NULL; have_context = g_strcmp0 (token, "C_") == 0; GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); if (have_context) { GET_TOKEN (&context_text, TOKEN_PARSE_QUOTED); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ","); } GET_TOKEN (&source_text, TOKEN_PARSE_QUOTED); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ")"); g_value_init (&value, G_TYPE_STRING); if (have_context) { g_autofree char *query = NULL; query = g_strdup_printf ("%s\004%s", context_text, source_text); g_value_set_string (&value, g_dpgettext (NULL, query, strlen (context_text) + 1)); } else g_value_set_string (&value, gettext (source_text)); key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_constant_source_value ( spec, key, &value, &local_error); g_value_unset (&value); RETURN_ERROR_UNLESS (result); g_strv_builder_take (builder, g_steal_pointer (&key)); n_args++; need_comma = TRUE; } else if (g_strcmp0 (token, "#eval") == 0) { g_autofree char *key = NULL; GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_eval (p, spec, state, macro_replacements, n_anon_vals, type_hints, line, column, &key, &local_error); RETURN_ERROR_UNLESS (p != NULL); g_strv_builder_take (builder, g_steal_pointer (&key)); n_args++; need_comma = TRUE; } else if (g_strcmp0 (token, "#not") == 0 || g_strcmp0 (token, "#!") == 0 || g_strcmp0 (token, "#and") == 0 || g_strcmp0 (token, "#or") == 0 || g_strcmp0 (token, "#<") == 0 || g_strcmp0 (token, "#>") == 0 || g_strcmp0 (token, "#eq") == 0 || g_strcmp0 (token, "#eq") == 0 || g_strcmp0 (token, "#neq") == 0 || g_strcmp0 (token, "#~eq") == 0 || g_strcmp0 (token, "#~neq") == 0) { g_autofree char *key = NULL; GCallback cb = NULL; GType all_type = G_TYPE_INVALID; guint require_n_cmp_values = 0; guint n_cmp_values = 0; g_auto (GStrv) cmp_values = NULL; g_autofree GType *all_types = NULL; if (g_strcmp0 (token, "#not") == 0 || g_strcmp0 (token, "#!") == 0) { cb = G_CALLBACK (not_closure); all_type = G_TYPE_BOOLEAN; require_n_cmp_values = 1; } else if (g_strcmp0 (token, "#and") == 0) { cb = G_CALLBACK (and_closure); all_type = G_TYPE_BOOLEAN; require_n_cmp_values = 2; } else if (g_strcmp0 (token, "#or") == 0) { cb = G_CALLBACK (or_closure); all_type = G_TYPE_BOOLEAN; require_n_cmp_values = 2; } else if (g_strcmp0 (token, "#<") == 0) { cb = G_CALLBACK (lt_closure); all_type = G_TYPE_DOUBLE; require_n_cmp_values = 2; } else if (g_strcmp0 (token, "#>") == 0) { cb = G_CALLBACK (gt_closure); all_type = G_TYPE_DOUBLE; require_n_cmp_values = 2; } else if (g_strcmp0 (token, "#eq") == 0) { cb = G_CALLBACK (gte_closure); all_type = G_TYPE_DOUBLE; require_n_cmp_values = 2; } else if (g_strcmp0 (token, "#eq") == 0) { cb = G_CALLBACK (eq_closure); all_type = G_TYPE_DOUBLE; require_n_cmp_values = 2; } else if (g_strcmp0 (token, "#neq") == 0) { cb = G_CALLBACK (neq_closure); all_type = G_TYPE_DOUBLE; require_n_cmp_values = 2; } else if (g_strcmp0 (token, "#~eq") == 0) { cb = G_CALLBACK (aeq_closure); all_type = G_TYPE_DOUBLE; require_n_cmp_values = 2; } else if (g_strcmp0 (token, "#~neq") == 0) { cb = G_CALLBACK (aneq_closure); all_type = G_TYPE_DOUBLE; require_n_cmp_values = 2; } else g_assert_not_reached (); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, state, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, NULL, 0, &cmp_values, NULL, &n_cmp_values, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_cmp_values < require_n_cmp_values) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "%s() needs at least %u argument(s), " "got %u", token, require_n_cmp_values, n_cmp_values); return NULL; } all_types = g_new (GType, n_cmp_values); for (guint i = 0; i < n_cmp_values; i++) { all_types[i] = all_type; } key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_cclosure_source_value ( spec, key, G_TYPE_BOOLEAN, _marshal_BOOL__ARGS_DIRECT, cb, (const char *const *) cmp_values, all_types, n_cmp_values, NULL, NULL, &local_error); RETURN_ERROR_UNLESS (result); g_strv_builder_take (builder, g_steal_pointer (&key)); n_args++; need_comma = TRUE; } else if (g_strcmp0 (token, "#ifelse") == 0) { g_autofree char *key = NULL; GType type_hint = G_TYPE_INVALID; guint n_expr_values = 0; g_auto (GStrv) expr_values = NULL; g_autofree GType *expr_types = NULL; if (n_args < n_destinations) { if (destinations != NULL) type_hint = GPOINTER_TO_SIZE (g_hash_table_lookup ( type_hints, destinations[n_args])); if (type_hint == G_TYPE_INVALID && destinations_types != NULL) type_hint = destinations_types[n_args]; } GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, state, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ G_TYPE_BOOLEAN }, 1, &expr_values, &expr_types, &n_expr_values, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_expr_values != 3) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "#ifelse() needs exactly 3 argument(s), " "got %u", n_expr_values); return NULL; } if (type_hint == G_TYPE_INVALID) /* Use the return type of the TRUE value and coerce the FALSE value to this if necessary */ type_hint = expr_types[1]; key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_cclosure_source_value ( spec, key, type_hint, _marshal_DIRECT__ARGS_DIRECT, G_CALLBACK (ifelse_closure), (const char *const *) expr_values, (GType[]){ G_TYPE_BOOLEAN, type_hint, type_hint }, n_expr_values, NULL, NULL, &local_error); RETURN_ERROR_UNLESS (result); g_strv_builder_take (builder, g_steal_pointer (&key)); n_args++; need_comma = TRUE; } else if (g_strcmp0 (token, "#measure-path") == 0) { g_autofree char *key = NULL; guint n_expr_values = 0; g_auto (GStrv) expr_values = NULL; g_autofree GType *expr_types = NULL; GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, state, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ GSK_TYPE_PATH }, 1, &expr_values, &expr_types, &n_expr_values, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_expr_values != 1) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "#measure-path() needs exactly 1 argument of type %s," "got %u", g_type_name (GSK_TYPE_PATH), n_expr_values); return NULL; } key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_cclosure_source_value ( spec, key, GSK_TYPE_PATH_MEASURE, _marshal_DIRECT__ARGS_DIRECT, G_CALLBACK (measure_path_closure), (const char *const *) expr_values, (GType[]){ GSK_TYPE_PATH }, n_expr_values, NULL, NULL, &local_error); RETURN_ERROR_UNLESS (result); g_strv_builder_take (builder, g_steal_pointer (&key)); n_args++; need_comma = TRUE; } else if (g_strcmp0 (token, "#path-length") == 0) { g_autofree char *key = NULL; guint n_expr_values = 0; g_auto (GStrv) expr_values = NULL; g_autofree GType *expr_types = NULL; GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, state, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ GSK_TYPE_PATH_MEASURE }, 1, &expr_values, &expr_types, &n_expr_values, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_expr_values != 1) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "#path-length() needs exactly 1 argument of type %s," "got %u", g_type_name (GSK_TYPE_PATH_MEASURE), n_expr_values); return NULL; } key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_cclosure_source_value ( spec, key, G_TYPE_DOUBLE, _marshal_DIRECT__ARGS_DIRECT, G_CALLBACK (path_length_closure), (const char *const *) expr_values, (GType[]){ GSK_TYPE_PATH_MEASURE }, n_expr_values, NULL, NULL, &local_error); RETURN_ERROR_UNLESS (result); g_strv_builder_take (builder, g_steal_pointer (&key)); n_args++; need_comma = TRUE; } else if (g_strcmp0 (token, "#path-point") == 0) { g_autofree char *key = NULL; guint n_expr_values = 0; g_auto (GStrv) expr_values = NULL; g_autofree GType *expr_types = NULL; GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, state, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ GSK_TYPE_PATH_MEASURE, G_TYPE_DOUBLE }, 2, &expr_values, &expr_types, &n_expr_values, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_expr_values != 2) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "#path-point() needs exactly 2 arguments " "of types %s and %s," "got %u", g_type_name (GSK_TYPE_PATH_MEASURE), g_type_name (G_TYPE_DOUBLE), n_expr_values); return NULL; } key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_cclosure_source_value ( spec, key, GSK_TYPE_PATH_POINT, _marshal_DIRECT__ARGS_DIRECT, G_CALLBACK (path_point_closure), (const char *const *) expr_values, (GType[]){ GSK_TYPE_PATH_MEASURE, G_TYPE_DOUBLE }, n_expr_values, NULL, NULL, &local_error); RETURN_ERROR_UNLESS (result); g_strv_builder_take (builder, g_steal_pointer (&key)); n_args++; need_comma = TRUE; } else if (g_strcmp0 (token, "#transition") == 0) { g_autofree char *key = NULL; guint n_spec_values = 0; g_auto (GStrv) spec_values = NULL; GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, state, NULL, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE }, 4, &spec_values, NULL, &n_spec_values, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_spec_values != 4) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "#transition() needs 4 arguments " "(variable, damping-ratio, mass, stiffness), " "got %u", n_spec_values); return NULL; } key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_track_transition_source_value ( spec, key, spec_values[0], spec_values[1], spec_values[2], spec_values[3], &local_error); RETURN_ERROR_UNLESS (result); g_strv_builder_take (builder, g_steal_pointer (&key)); n_args++; need_comma = TRUE; } else { g_autofree char *key = NULL; GType type = G_TYPE_INVALID; if (g_hash_table_contains (type_hints, token) || /* A macro placed this here */ g_utf8_strchr (token, -1, '@') != NULL) key = g_steal_pointer (&token); else { GType type_hint = G_TYPE_INVALID; gboolean expect_closing_paren = FALSE; gboolean is_child = FALSE; gboolean constant = FALSE; GValue value = G_VALUE_INIT; if (n_args < n_destinations) { if (destinations != NULL) type_hint = GPOINTER_TO_SIZE (g_hash_table_lookup ( type_hints, destinations[n_args])); if (type_hint == G_TYPE_INVALID && destinations_types != NULL) type_hint = destinations_types[n_args]; } if (g_str_has_prefix (token, "#")) { const char *type_name = token + 1; if (g_str_has_prefix (type_name, "child/")) { is_child = TRUE; type_name += strlen ("child/"); } if (*type_name == '\0') { if (type_hint == G_TYPE_INVALID) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Unable to guess type for value"); return NULL; } type = type_hint; } else { type = g_type_from_name (type_name); if (type == G_TYPE_INVALID) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Unknown type name \"%s\"", type_name); return NULL; } } GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); expect_closing_paren = TRUE; } else type = type_hint; if (is_child && !g_type_is_a (type, GTK_TYPE_WIDGET)) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Children must be a widget type"); return NULL; } if (type == G_TYPE_INVALID) { if (expect_closing_paren) GET_TOKEN (&token, TOKEN_PARSE_DEFAULT); key = parse_token_fundamental (token, spec, n_anon_vals, line, column, &local_error); RETURN_ERROR_UNLESS (key != NULL); } else if (type == G_TYPE_STRING) { if (expect_closing_paren) GET_TOKEN (&token, TOKEN_PARSE_DEFAULT); g_value_set_string (g_value_init (&value, G_TYPE_STRING), token); constant = TRUE; if (expect_closing_paren) GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ")"); } else if (type == G_TYPE_BOOLEAN) { if (expect_closing_paren) GET_TOKEN (&token, TOKEN_PARSE_DEFAULT); if (g_strcmp0 (token, "true") == 0) g_value_set_boolean (g_value_init (&value, G_TYPE_BOOLEAN), TRUE); else if (g_strcmp0 (token, "false") == 0) g_value_set_boolean (g_value_init (&value, G_TYPE_BOOLEAN), FALSE); else { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "a boolean value must be 'true' " "or 'false', got \"%s\"", token); return NULL; } constant = TRUE; if (expect_closing_paren) GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ")"); } else if (type == G_TYPE_INT || type == G_TYPE_INT64 || type == G_TYPE_UINT || type == G_TYPE_UINT64 || type == G_TYPE_FLOAT || type == G_TYPE_DOUBLE) { const GVariantType *variant_type = NULL; g_autoptr (GVariant) variant = NULL; if (type == G_TYPE_INT) variant_type = G_VARIANT_TYPE_INT32; else if (type == G_TYPE_INT64) variant_type = G_VARIANT_TYPE_INT64; else if (type == G_TYPE_UINT) variant_type = G_VARIANT_TYPE_UINT32; else if (type == G_TYPE_UINT64) variant_type = G_VARIANT_TYPE_UINT64; else if (type == G_TYPE_FLOAT || type == G_TYPE_DOUBLE) variant_type = G_VARIANT_TYPE_DOUBLE; if (expect_closing_paren) GET_TOKEN (&token, TOKEN_PARSE_DEFAULT); variant = g_variant_parse (variant_type, token, NULL, NULL, &local_error); RETURN_ERROR_UNLESS (variant != NULL); if (type == G_TYPE_INT) g_value_set_int (g_value_init (&value, G_TYPE_INT), g_variant_get_int32 (variant)); else if (type == G_TYPE_INT64) g_value_set_int64 (g_value_init (&value, G_TYPE_INT64), g_variant_get_int64 (variant)); else if (type == G_TYPE_UINT) g_value_set_uint (g_value_init (&value, G_TYPE_UINT), g_variant_get_uint32 (variant)); else if (type == G_TYPE_UINT64) g_value_set_uint64 (g_value_init (&value, G_TYPE_UINT64), g_variant_get_uint64 (variant)); else if (type == G_TYPE_FLOAT) g_value_set_float (g_value_init (&value, G_TYPE_FLOAT), g_variant_get_double (variant)); else if (type == G_TYPE_DOUBLE) g_value_set_double (g_value_init (&value, G_TYPE_DOUBLE), g_variant_get_double (variant)); constant = TRUE; if (expect_closing_paren) GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ")"); } else if (g_type_is_a (type, G_TYPE_ENUM)) { g_autoptr (GEnumClass) enum_class = NULL; GEnumValue *enum_value = NULL; if (expect_closing_paren) GET_TOKEN (&token, TOKEN_PARSE_DEFAULT); enum_class = g_type_class_ref (type); enum_value = g_enum_get_value_by_nick (enum_class, token); if (enum_value == NULL) enum_value = g_enum_get_value_by_name (enum_class, token); if (enum_value == NULL) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "\"%s\" not found in enum type %s", token, g_type_name (type)); return NULL; } g_value_set_enum (g_value_init (&value, type), enum_value->value); constant = TRUE; if (expect_closing_paren) GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ")"); } else if (type == GDK_TYPE_RGBA) { GdkRGBA rgba = { 0 }; if (expect_closing_paren) GET_TOKEN (&token, TOKEN_PARSE_DEFAULT); result = gdk_rgba_parse (&rgba, token); if (!result) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "#color() specifier failed to " "parse color from string"); return NULL; } g_value_set_boxed (g_value_init (&value, GDK_TYPE_RGBA), &rgba); constant = TRUE; if (expect_closing_paren) GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ")"); } else if (type == GRAPHENE_TYPE_POINT || type == GRAPHENE_TYPE_SIZE || type == GRAPHENE_TYPE_RECT) { g_auto (GStrv) component_args = NULL; guint n_component_args = 0; GType component_type = 0; if (!expect_closing_paren) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type %s must be wrapped in #(...)", g_type_name (type)); return NULL; } p = parse_args (p, spec, state, enclosing_object, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE }, 4, &component_args, NULL, &n_component_args, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (type == GRAPHENE_TYPE_POINT) { switch (n_component_args) { case 2: component_type = GRAPHENE_TYPE_POINT; break; case 3: component_type = GRAPHENE_TYPE_POINT3D; break; default: g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "#point() specifier can have 2 or 3 arguments, got %u", n_component_args); return NULL; } } else if (type == GRAPHENE_TYPE_SIZE) { switch (n_component_args) { case 2: component_type = GRAPHENE_TYPE_SIZE; break; default: g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "#size() specifier can have 2 arguments, got %u", n_component_args); return NULL; } } else if (type == GRAPHENE_TYPE_RECT) { switch (n_component_args) { case 4: component_type = GRAPHENE_TYPE_RECT; break; default: g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "#rect() specifier can have 4 arguments, got %u", n_component_args); return NULL; } } key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_component_source_value ( spec, key, component_type, (const char *const *) component_args, n_component_args, &local_error); RETURN_ERROR_UNLESS (result); } else if (g_type_is_a (type, G_TYPE_OBJECT)) { if (!expect_closing_paren) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type %s must be wrapped in #(...)", g_type_name (type)); return NULL; } key = make_anon_name ((*n_anon_vals)++); if (is_child) { g_autofree char *builder_type = NULL; g_autoptr (GPtrArray) css_classes = NULL; GET_TOKEN (&builder_type, TOKEN_PARSE_QUOTED); if (*builder_type == '\0') g_clear_pointer (&builder_type, g_free); css_classes = g_ptr_array_new_with_free_func (g_free); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); for (;;) { GET_TOKEN (&token, TOKEN_PARSE_DEFAULT); if (g_strcmp0 (token, ")") == 0) break; g_ptr_array_add (css_classes, g_steal_pointer (&token)); } result = bge_wdgt_spec_add_child_source_value ( spec, key, type, enclosing_object, builder_type, (const char *const *) css_classes->pdata, css_classes->len, &local_error); RETURN_ERROR_UNLESS (result); } else { result = bge_wdgt_spec_add_instance_source_value ( spec, key, type, &local_error); RETURN_ERROR_UNLESS (result); } for (;;) { g_autofree char *property_name = NULL; g_autofree char *set_key = NULL; GType prop_type = G_TYPE_INVALID; g_auto (GStrv) value_args = NULL; guint n_value_args = 0; GET_TOKEN (&property_name, TOKEN_PARSE_DEFAULT); if (g_strcmp0 (property_name, ")") == 0) break; else if (g_strcmp0 (property_name, "%set") == 0) { GET_TOKEN (&set_key, TOKEN_PARSE_DEFAULT); prop_type = GPOINTER_TO_SIZE (g_hash_table_lookup (type_hints, set_key)); } else if (g_strcmp0 (property_name, "_") != 0) { set_key = make_object_property_name (key, property_name, (*n_anon_vals)++); result = bge_wdgt_spec_add_property_value ( spec, set_key, key, property_name, &prop_type, &local_error); RETURN_ERROR_UNLESS (result); } GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "="); p = parse_args (p, spec, state, key, macro_replacements, n_anon_vals, type_hints, line, column, NULL, (GType[]){ prop_type }, 1, &value_args, NULL, &n_value_args, ARGS_PARSE_RIGHT_ASSIGN, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_value_args != 1) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "property/child assignment " "needs a single argument, got %u", n_value_args); return NULL; } if (set_key != NULL) { result = bge_wdgt_spec_set_value (spec, state, set_key, value_args[0], &local_error); RETURN_ERROR_UNLESS (result); } } } else if (type == GSK_TYPE_TRANSFORM) { g_autofree char *last_key = NULL; if (!expect_closing_paren) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type %s must be wrapped in #(...)", g_type_name (type)); return NULL; } last_key = make_anon_name ((*n_anon_vals)++); g_value_take_boxed (g_value_init (&value, GSK_TYPE_TRANSFORM), gsk_transform_new ()); result = bge_wdgt_spec_add_constant_source_value ( spec, last_key, &value, error); g_value_unset (&value); if (!result) return NULL; for (;;) { g_autofree char *instr = NULL; g_auto (GStrv) value_args = NULL; guint n_value_args = 0; g_autofree char *tmp_key = NULL; GET_TOKEN (&instr, TOKEN_PARSE_DEFAULT); if (g_strcmp0 (instr, ")") == 0) break; GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, state, enclosing_object, macro_replacements, n_anon_vals, type_hints, line, column, NULL, NULL, 0, &value_args, NULL, &n_value_args, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ";"); tmp_key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_transform_source_value ( spec, tmp_key, last_key, instr, (const char *const *) value_args, n_value_args, &local_error); RETURN_ERROR_UNLESS (result); g_clear_pointer (&last_key, g_free); last_key = g_steal_pointer (&tmp_key); } key = g_steal_pointer (&last_key); } else if (type == GSK_TYPE_PATH) { g_autoptr (GPtrArray) instrs = NULL; g_autoptr (GPtrArray) argss = NULL; g_autoptr (GArray) n_argss = NULL; instrs = g_ptr_array_new_with_free_func (g_free); argss = g_ptr_array_new_with_free_func ((GDestroyNotify) g_strfreev); n_argss = g_array_new (FALSE, FALSE, sizeof (guint)); if (!expect_closing_paren) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type %s must be wrapped in #(...)", g_type_name (type)); return NULL; } for (;;) { g_autofree char *instr = NULL; g_auto (GStrv) call_args = NULL; guint n_call_args = 0; GET_TOKEN (&instr, TOKEN_PARSE_DEFAULT); if (g_strcmp0 (instr, ")") == 0) break; GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, "("); p = parse_args (p, spec, state, enclosing_object, macro_replacements, n_anon_vals, type_hints, line, column, NULL, NULL, 0, &call_args, NULL, &n_call_args, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); GET_TOKEN_EXPECT (&token, TOKEN_PARSE_DEFAULT, ";"); g_ptr_array_add (instrs, g_steal_pointer (&instr)); g_ptr_array_add (argss, g_steal_pointer (&call_args)); g_array_append_val (n_argss, n_call_args); } if (instrs->len == 0) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "not enough path builder instructions"); return NULL; } key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_path_source_value ( spec, key, (const char *const *) instrs->pdata, (const char *const *const *) argss->pdata, (const guint *) (void *) n_argss->data, instrs->len, &local_error); RETURN_ERROR_UNLESS (result); } else if (type == GSK_TYPE_STROKE) { g_auto (GStrv) component_args = NULL; guint n_component_args = 0; GType types[] = { G_TYPE_DOUBLE, /* line width */ GSK_TYPE_LINE_CAP, GSK_TYPE_LINE_JOIN, G_TYPE_DOUBLE, /* miter limit */ }; if (!expect_closing_paren) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "type %s must be wrapped in #(...)", g_type_name (type)); return NULL; } p = parse_args (p, spec, state, enclosing_object, macro_replacements, n_anon_vals, type_hints, line, column, NULL, types, G_N_ELEMENTS (types), &component_args, NULL, &n_component_args, ARGS_PARSE_PARENS, &local_error); RETURN_ERROR_UNLESS (p != NULL); if (n_component_args != G_N_ELEMENTS (types)) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "%s type initializer can have %d arguments, got %u", g_type_name (GSK_TYPE_STROKE), (int) G_N_ELEMENTS (types), n_component_args); return NULL; } key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_component_source_value ( spec, key, GSK_TYPE_STROKE, (const char *const *) component_args, n_component_args, &local_error); RETURN_ERROR_UNLESS (result); } else { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Can't parse type %s", g_type_name (type)); return NULL; } if (constant) { key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_constant_source_value ( spec, key, &value, &local_error); g_value_unset (&value); RETURN_ERROR_UNLESS (result); } } for (;;) { GET_TOKEN (&token, TOKEN_PARSE_DEFAULT); if (g_strcmp0 (token, ":") == 0) { g_autofree char *property = NULL; g_autofree char *name = NULL; GET_TOKEN (&property, TOKEN_PARSE_DEFAULT); name = make_object_property_name (key, property, (*n_anon_vals)++); result = bge_wdgt_spec_add_property_value ( spec, name, key, property, &type, &local_error); RETURN_ERROR_UNLESS (result); g_clear_pointer (&key, g_free); key = g_steal_pointer (&name); } else break; } get_token = FALSE; g_strv_builder_add (builder, key); g_array_append_val (types_array, type); n_args++; need_comma = TRUE; } } if (n_out != NULL) *n_out = n_args; if (values_out != NULL) *values_out = g_strv_builder_end (builder); if (types_out != NULL) *types_out = g_array_steal (types_array, NULL); return p; } #undef GET_TOKEN_EXPECT #undef GET_TOKEN #undef UNEXPECTED_TOKEN #undef EXPECT_TOKEN #undef RETURN_ERROR_UNLESS static char * parse_token_fundamental (const char *token, BgeWdgtSpec *spec, guint *n_anon_vals, guint *line, guint *column, GError **error) { g_autoptr (GError) local_error = NULL; gboolean result = FALSE; gunichar ch = 0; GValue value = { 0 }; g_autofree char *key = NULL; ch = g_utf8_get_char (token); if (ch == '-' || g_unichar_isdigit (ch)) { gboolean is_double = FALSE; g_autoptr (GVariant) variant = NULL; is_double = g_utf8_strchr (token, -1, '.') != NULL; if (is_double) variant = g_variant_parse (G_VARIANT_TYPE_DOUBLE, token, NULL, NULL, &local_error); else variant = g_variant_parse (G_VARIANT_TYPE_INT32, token, NULL, NULL, &local_error); if (variant == NULL) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Unable to parse number value '%s': %s", token, local_error->message); return NULL; } if (is_double) g_value_set_double (g_value_init (&value, G_TYPE_DOUBLE), g_variant_get_double (variant)); else g_value_set_int (g_value_init (&value, G_TYPE_INT), g_variant_get_int32 (variant)); } else if (g_strcmp0 (token, "true") == 0) g_value_set_boolean (g_value_init (&value, G_TYPE_BOOLEAN), TRUE); else if (g_strcmp0 (token, "false") == 0) g_value_set_boolean (g_value_init (&value, G_TYPE_BOOLEAN), FALSE); else return g_strdup (token); if (key == NULL) key = make_anon_name ((*n_anon_vals)++); result = bge_wdgt_spec_add_constant_source_value ( spec, key, &value, error); g_value_unset (&value); if (!result) return NULL; return g_steal_pointer (&key); } static char * consume_token (const char **pp, const char *single_chars, TokenParseFlags flags, gboolean *was_quoted, GHashTable *macro_replacements, guint *line, guint *column, GError **error) { g_autofree char *token = NULL; token = consume_token_inner (pp, single_chars, flags, was_quoted, line, column, error); if (token == NULL) return NULL; if (macro_replacements != NULL) { const char *replacement = NULL; replacement = g_hash_table_lookup (macro_replacements, token); if (replacement != NULL) return g_strdup (replacement); else { const char *replace_start = NULL; replace_start = g_utf8_strchr (token, -1, '@'); if (replace_start != NULL) { const char *last_end = token; g_autoptr (GString) string = NULL; string = g_string_new (NULL); for (;;) { g_autofree char *replace = NULL; const char *with = NULL; if (replace_start - last_end > 0) g_string_append_len (string, last_end, replace_start - last_end); replace_start++; last_end = g_utf8_strchr (replace_start, -1, '@'); if (last_end == NULL) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "error in macro expansion: " "unterminated replacement"); return NULL; } replace = g_strndup (replace_start, last_end - replace_start); with = g_hash_table_lookup (macro_replacements, replace); if (with == NULL) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "error in macro expansion: " "undefined string \"%s\"", replace); return NULL; } g_string_append (string, with); last_end++; replace_start = g_utf8_strchr (last_end, '@', -1); if (replace_start == NULL) break; } if (*last_end != '\0') g_string_append (string, last_end); return g_string_free_and_steal (g_steal_pointer (&string)); } } } return g_steal_pointer (&token); } static char * consume_token_inner (const char **pp, const char *single_chars, TokenParseFlags flags, gboolean *was_quoted, guint *line, guint *column, GError **error) { const char *p = *pp; gboolean hit_non_space = FALSE; if (was_quoted != NULL) *was_quoted = FALSE; #define UNEXPECTED_EOF \ G_STMT_START \ { \ g_set_error ( \ error, \ G_IO_ERROR, \ G_IO_ERROR_UNKNOWN, \ "Unexpected EOF"); \ return NULL; \ } \ G_STMT_END #define RETURN_TOKEN \ G_STMT_START \ { \ g_autofree char *_ret = NULL; \ \ _ret = g_strndup (*pp, p - *pp); \ *pp = p; \ return g_steal_pointer (&_ret); \ } \ G_STMT_END #define RETURN_TOKEN_ADJUST_NEXT_CHAR \ G_STMT_START \ { \ g_autofree char *_ret = NULL; \ \ _ret = g_strndup (*pp, p - *pp); \ *pp = g_utf8_next_char (p); \ return g_steal_pointer (&_ret); \ } \ G_STMT_END if (IS_EOF (p)) UNEXPECTED_EOF; for (; !IS_EOF (p); p = g_utf8_next_char (p)) { gunichar ch = 0; gboolean is_whitespace = FALSE; gboolean is_quotes = FALSE; ch = g_utf8_get_char (p); if (ch == '\n') { (*line)++; *column = 0; } else (*column)++; is_whitespace = ch == '\n' || g_unichar_isspace (ch); is_quotes = ch == '"'; if (is_whitespace) { if (!(flags & TOKEN_PARSE_QUOTED) && hit_non_space) RETURN_TOKEN; } else { if (is_quotes) { if (hit_non_space) { if (was_quoted != NULL) *was_quoted = TRUE; if (flags & TOKEN_PARSE_QUOTED) RETURN_TOKEN_ADJUST_NEXT_CHAR; else RETURN_TOKEN; } else { flags |= TOKEN_PARSE_QUOTED; *pp = g_utf8_next_char (p); if (IS_EOF (*pp)) UNEXPECTED_EOF; hit_non_space = TRUE; } } else if (flags & TOKEN_PARSE_QUOTED) { if (!hit_non_space) { g_set_error ( error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Expected quote"); return NULL; } } else if (single_chars != NULL && g_utf8_strchr (single_chars, -1, ch) != NULL) { if (hit_non_space) RETURN_TOKEN; else { char buf[16] = { 0 }; g_unichar_to_utf8 (ch, buf); *pp = g_utf8_next_char (p); return g_strdup (buf); } } if (!hit_non_space) { *pp = p; hit_non_space = TRUE; } } } if (!(flags & TOKEN_PARSE_QUOTED) && hit_non_space) RETURN_TOKEN; UNEXPECTED_EOF; #undef RETURN_TOKEN_ADJUST_NEXT_CHAR #undef RETURN_TOKEN #undef UNEXPECTED_EOF } static gdouble eval_closure (gpointer this, guint n_param_values, const GValue *param_values, EvalClosureData *data) { GArray *ops = data->ops; gdouble *workbuf0 = data->workbuf0; gdouble *workbuf1 = data->workbuf1; gdouble result = 0.0; for (guint i = 0; i < n_param_values; i++) { workbuf0[i] = g_value_get_double (¶m_values[i]); workbuf1[i] = 1.0; } for (guint i = 0; i < ops->len; i++) { EvalOperator *op = NULL; guint left_idx = 0; guint right_idx = 0; gdouble left = 0.0; gdouble right = 0.0; op = &g_array_index (ops, EvalOperator, i); left_idx = op->pos; while (workbuf1[left_idx] < 0.0) { left_idx--; } right_idx = op->pos + 1; while (workbuf1[right_idx] < 0.0) { right_idx++; } left = workbuf0[left_idx]; right = workbuf0[right_idx]; switch (op->op) { case OPERATOR_ADD: result = left + right; break; case OPERATOR_SUBTRACT: result = left - right; break; case OPERATOR_MULTIPLY: result = left * right; break; case OPERATOR_DIVIDE: result = left / right; break; case OPERATOR_MODULUS: result = fmod (left, right); break; case OPERATOR_POWER: result = pow (left, right); break; default: g_assert_not_reached (); } workbuf0[left_idx] = result; workbuf1[left_idx] = 1.0; workbuf1[right_idx] = -1.0; } return result; } static char * make_object_property_name (const char *object, const char *property, guint n) { return g_strdup_printf ("prop@%u(%s).%s", n, object, property); } static char * make_widget_allocation_name (const char *widget, guint n) { return g_strdup_printf ("allocation@%u(%s)", n, widget); } static char * make_widget_measurement_name (guint n) { return g_strdup_printf ("measurement@%u", n); } static char * make_anon_name (guint n) { return g_strdup_printf ("anon@%u", n); } static gint cmp_operator (EvalOperator *a, EvalOperator *b) { int a_prec = 0; int b_prec = 0; a_prec = operator_precedence[a->op]; b_prec = operator_precedence[b->op]; return a_prec > b_prec ? -1 : 1; } static void _marshal_DIRECT__ARGS_DIRECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data) { typedef void (*GMarshalFunc_DIRECT__ARGS_DIRECT) (gpointer data1, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer data2); GCClosure *cc = (GCClosure *) closure; gpointer data1, data2; GMarshalFunc_DIRECT__ARGS_DIRECT callback; g_return_if_fail (return_value != NULL); g_return_if_fail (n_param_values >= 1); if (G_CCLOSURE_SWAP_DATA (closure)) { data1 = closure->data; data2 = g_value_peek_pointer (param_values + 0); } else { data1 = g_value_peek_pointer (param_values + 0); data2 = closure->data; } callback = (GMarshalFunc_DIRECT__ARGS_DIRECT) (marshal_data ? marshal_data : cc->callback); callback (data1, return_value, n_param_values - 1, param_values + 1, data2); } static void _marshal_BOOL__ARGS_DIRECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data) { typedef gboolean (*GMarshalFunc_BOOL__ARGS_DIRECT) (gpointer data1, guint n_param_values, const GValue *param_values, gpointer data2); GCClosure *cc = (GCClosure *) closure; gpointer data1, data2; GMarshalFunc_BOOL__ARGS_DIRECT callback; gboolean v_return; g_return_if_fail (return_value != NULL); g_return_if_fail (n_param_values >= 1); if (G_CCLOSURE_SWAP_DATA (closure)) { data1 = closure->data; data2 = g_value_peek_pointer (param_values + 0); } else { data1 = g_value_peek_pointer (param_values + 0); data2 = closure->data; } callback = (GMarshalFunc_BOOL__ARGS_DIRECT) (marshal_data ? marshal_data : cc->callback); v_return = callback (data1, n_param_values - 1, param_values + 1, data2); g_value_set_boolean (return_value, v_return); } static void _marshal_DOUBLE__ARGS_DIRECT (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data) { typedef gdouble (*GMarshalFunc_DOUBLE__ARGS_DIRECT) (gpointer data1, guint n_param_values, const GValue *param_values, gpointer data2); GCClosure *cc = (GCClosure *) closure; gpointer data1, data2; GMarshalFunc_DOUBLE__ARGS_DIRECT callback; gdouble v_return; g_return_if_fail (return_value != NULL); g_return_if_fail (n_param_values >= 1); if (G_CCLOSURE_SWAP_DATA (closure)) { data1 = closure->data; data2 = g_value_peek_pointer (param_values + 0); } else { data1 = g_value_peek_pointer (param_values + 0); data2 = closure->data; } callback = (GMarshalFunc_DOUBLE__ARGS_DIRECT) (marshal_data ? marshal_data : cc->callback); v_return = callback (data1, n_param_values - 1, param_values + 1, data2); g_value_set_double (return_value, v_return); } bazaar-org-bazaar-43ce9f7/bge/wdgt/fmt/parser.h000066400000000000000000000015701520414637400213710ustar00rootroot00000000000000/* parser.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 */ #include "bge.h" G_BEGIN_DECLS BgeWdgtSpec * bge_wdgt_parse_string (const char *string, GError **error); G_END_DECLS bazaar-org-bazaar-43ce9f7/bge/wdgt/lookup/000077500000000000000000000000001520414637400204445ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/bge/wdgt/lookup/lookup.h000066400000000000000000000047171520414637400221370ustar00rootroot00000000000000/* lookup.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 */ #pragma once #include #include "bge.h" G_BEGIN_DECLS #define ARGBUF_SIZE 128 typedef GskTransform *(*TransformCallFunc) (GskTransform *next, const GValue args[]); typedef struct { const char *name; guint n_args; GType args[16]; gpointer func; TransformCallFunc call; } TransformInstr; gboolean lookup_transform_instr (const char *lookup_name, TransformInstr *out); typedef void (*PathBuilderCallFunc) (GskPathBuilder *builder, const GValue args[]); typedef struct { const char *name; guint n_args; GType args[16]; gpointer func; PathBuilderCallFunc call; } PathBuilderInstr; gboolean lookup_path_builder_instr (const char *lookup_name, PathBuilderInstr *out); typedef void (*SnapshotCallFunc) (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest); typedef struct { const char *name; guint n_args; guint n_rest; GType args[16]; gpointer func; SnapshotCallFunc call; /* for push instrs only */ guint n_pops; } SnapshotInstr; gboolean lookup_snapshot_push_instr (const char *lookup_name, SnapshotInstr *out); gboolean lookup_snapshot_transform_instr (const char *lookup_name, SnapshotInstr *out); gboolean lookup_snapshot_append_instr (const char *lookup_name, SnapshotInstr *out); G_END_DECLS bazaar-org-bazaar-43ce9f7/bge/wdgt/lookup/meson.build000066400000000000000000000001151520414637400226030ustar00rootroot00000000000000bge_sources += files( 'path-builder.c', 'snapshot.c', 'transform.c', ) bazaar-org-bazaar-43ce9f7/bge/wdgt/lookup/path-builder.c000066400000000000000000000322151520414637400231730ustar00rootroot00000000000000/* path-builder.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 "lookup.h" static void path_builder_instr_add_circle (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_add_circle ( builder, g_value_get_boxed (&args[0]), g_value_get_double (&args[1])); } static void path_builder_instr_add_layout (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_add_layout ( builder, g_value_get_object (&args[0])); } static void path_builder_instr_add_path (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_add_path ( builder, g_value_get_boxed (&args[0])); } static void path_builder_instr_add_rect (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_add_rect ( builder, g_value_get_boxed (&args[0])); } static void path_builder_instr_add_reverse_path (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_add_reverse_path ( builder, g_value_get_boxed (&args[0])); } static void path_builder_instr_add_rounded_rect (GskPathBuilder *builder, const GValue args[]) { GskRoundedRect rrect = { 0 }; rrect.bounds = *(graphene_rect_t *) g_value_get_boxed (&args[0]); rrect.corner[0] = *(graphene_size_t *) g_value_get_boxed (&args[1]); rrect.corner[1] = *(graphene_size_t *) g_value_get_boxed (&args[2]); rrect.corner[2] = *(graphene_size_t *) g_value_get_boxed (&args[3]); rrect.corner[3] = *(graphene_size_t *) g_value_get_boxed (&args[4]); gsk_path_builder_add_rounded_rect ( builder, &rrect); } static void path_builder_instr_add_segment (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_add_segment ( builder, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1]), g_value_get_boxed (&args[2])); } static void path_builder_instr_arc_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_arc_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3])); } static void path_builder_instr_close (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_close (builder); } static void path_builder_instr_conic_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_conic_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3]), g_value_get_double (&args[4])); } static void path_builder_instr_cubic_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_cubic_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3]), g_value_get_double (&args[4]), g_value_get_double (&args[5])); } static void path_builder_instr_rel_arc_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_rel_arc_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3])); } static void path_builder_instr_html_arc_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_html_arc_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3]), g_value_get_double (&args[4])); } static void path_builder_instr_line_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_line_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1])); } static void path_builder_instr_move_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_move_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1])); } static void path_builder_instr_quad_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_quad_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3])); } static void path_builder_instr_rel_conic_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_rel_conic_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3]), g_value_get_double (&args[4])); } static void path_builder_instr_rel_cubic_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_rel_cubic_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3]), g_value_get_double (&args[4]), g_value_get_double (&args[5])); } static void path_builder_instr_rel_html_arc_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_rel_html_arc_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3]), g_value_get_double (&args[4])); } static void path_builder_instr_rel_line_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_rel_line_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1])); } static void path_builder_instr_rel_move_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_rel_move_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1])); } static void path_builder_instr_rel_quad_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_rel_quad_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3])); } static void path_builder_instr_svg_arc_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_svg_arc_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_boolean (&args[3]), g_value_get_boolean (&args[4]), g_value_get_double (&args[5]), g_value_get_double (&args[6])); } static void path_builder_instr_rel_svg_arc_to (GskPathBuilder *builder, const GValue args[]) { gsk_path_builder_rel_svg_arc_to ( builder, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_boolean (&args[3]), g_value_get_boolean (&args[4]), g_value_get_double (&args[5]), g_value_get_double (&args[6])); } gboolean lookup_path_builder_instr (const char *lookup_name, PathBuilderInstr *out) { PathBuilderInstr instrs[] = { { "add-circle", 2, { GRAPHENE_TYPE_POINT, G_TYPE_DOUBLE, }, gsk_path_builder_add_circle, path_builder_instr_add_circle, }, { "add-layout", 1, { PANGO_TYPE_LAYOUT, }, gsk_path_builder_add_layout, path_builder_instr_add_layout, }, { "add-path", 1, { GSK_TYPE_PATH, }, gsk_path_builder_add_path, path_builder_instr_add_path, }, { "add-rect", 1, { GRAPHENE_TYPE_RECT, }, gsk_path_builder_add_rect, path_builder_instr_add_rect, }, { "add-reverse-path", 1, { GSK_TYPE_PATH, }, gsk_path_builder_add_reverse_path, path_builder_instr_add_reverse_path, }, { "add-rounded-rect", 5, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, }, gsk_path_builder_add_rounded_rect, path_builder_instr_add_rounded_rect, }, { "add-segment", 3, { GSK_TYPE_PATH, GSK_TYPE_PATH_POINT, GSK_TYPE_PATH_POINT, }, gsk_path_builder_add_segment, path_builder_instr_add_segment, }, { "arc-to", 4, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_arc_to, path_builder_instr_arc_to, }, { "close", 0, {}, gsk_path_builder_close, path_builder_instr_close, }, { "conic-to", 5, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_conic_to, path_builder_instr_conic_to, }, { "cubic-to", 6, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_cubic_to, path_builder_instr_cubic_to, }, { "html-arc-to", 5, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_html_arc_to, path_builder_instr_html_arc_to, }, { "line-to", 2, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_line_to, path_builder_instr_line_to, }, { "move-to", 2, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_move_to, path_builder_instr_move_to, }, { "quad-to", 4, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_quad_to, path_builder_instr_quad_to, }, { "rel-arc-to", 4, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_rel_arc_to, path_builder_instr_rel_arc_to, }, { "rel-conic-to", 5, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_rel_conic_to, path_builder_instr_rel_conic_to, }, { "rel-cubic-to", 6, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_rel_cubic_to, path_builder_instr_rel_cubic_to, }, { "rel-html-arc-to", 5, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_rel_html_arc_to, path_builder_instr_rel_html_arc_to, }, { "rel-line-to", 2, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_rel_line_to, path_builder_instr_rel_line_to, }, { "rel-move-to", 2, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_rel_move_to, path_builder_instr_rel_move_to, }, { "rel-quad-to", 4, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_rel_quad_to, path_builder_instr_rel_quad_to, }, { "rel-svg-arc-to", 7, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_rel_svg_arc_to, path_builder_instr_rel_svg_arc_to, }, { "svg-arc-to", 7, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_path_builder_svg_arc_to, path_builder_instr_svg_arc_to, }, }; for (guint i = 0; i < G_N_ELEMENTS (instrs); i++) { if (g_strcmp0 (lookup_name, instrs[i].name) == 0) { *out = instrs[i]; return TRUE; } } return FALSE; } bazaar-org-bazaar-43ce9f7/bge/wdgt/lookup/snapshot.c000066400000000000000000000731561520414637400224630ustar00rootroot00000000000000/* snapshot.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 "lookup.h" static void snapshot_push_instr_opacity (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_opacity ( snapshot, g_value_get_double (&args[0])); } static void snapshot_push_instr_isolation (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_isolation ( snapshot, g_value_get_flags (&args[0])); } static void snapshot_push_instr_blur (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_blur ( snapshot, g_value_get_double (&args[0])); } static void snapshot_push_instr_color_matrix (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_color_matrix ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1])); } static void snapshot_push_instr_component_transfer (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_component_transfer ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1]), g_value_get_boxed (&args[2]), g_value_get_boxed (&args[3])); } static void snapshot_push_instr_repeat (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_repeat ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1])); } static void snapshot_push_instr_clip (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_clip ( snapshot, g_value_get_boxed (&args[0])); } static void snapshot_push_instr_rounded_clip (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { GskRoundedRect rrect = { 0 }; rrect.bounds = *(graphene_rect_t *) g_value_get_boxed (&args[0]); rrect.corner[0] = *(graphene_size_t *) g_value_get_boxed (&args[1]); rrect.corner[1] = *(graphene_size_t *) g_value_get_boxed (&args[2]); rrect.corner[2] = *(graphene_size_t *) g_value_get_boxed (&args[3]); rrect.corner[3] = *(graphene_size_t *) g_value_get_boxed (&args[4]); gtk_snapshot_push_rounded_clip ( snapshot, &rrect); } static void snapshot_push_instr_fill (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_fill ( snapshot, g_value_get_boxed (&args[0]), g_value_get_enum (&args[1])); } static void snapshot_push_instr_stroke (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_stroke ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1])); } static void snapshot_push_instr_shadow (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { guint n_shadows = 0; GskShadow shadows[ARGBUF_SIZE] = { 0 }; n_shadows = MIN (n_rest / 4, G_N_ELEMENTS (shadows)); for (guint i = 0; i < n_shadows; i++) { shadows[i].color = *(GdkRGBA *) g_value_get_boxed (&rest[i * 4 + 0]); shadows[i].dx = g_value_get_double (&rest[i * 4 + 1]); shadows[i].dy = g_value_get_double (&rest[i * 4 + 2]); shadows[i].radius = g_value_get_double (&rest[i * 4 + 3]); } gtk_snapshot_push_shadow ( snapshot, shadows, n_shadows); } static void snapshot_push_instr_blend (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_blend ( snapshot, g_value_get_enum (&args[0])); } static void snapshot_push_instr_mask (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_mask ( snapshot, g_value_get_enum (&args[0])); } static void snapshot_push_instr_copy (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_copy ( snapshot); } static void snapshot_push_instr_composite (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_composite ( snapshot, g_value_get_enum (&args[0])); } static void snapshot_push_instr_cross_fade (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_push_cross_fade ( snapshot, g_value_get_double (&args[0])); } gboolean lookup_snapshot_push_instr (const char *lookup_name, SnapshotInstr *out) { SnapshotInstr instrs[] = { { "opacity", 1, 0, { G_TYPE_DOUBLE, }, gtk_snapshot_push_opacity, snapshot_push_instr_opacity, 1, }, { "isolation", 1, 0, { GSK_TYPE_ISOLATION, }, gtk_snapshot_push_isolation, snapshot_push_instr_isolation, 1, }, { "blur", 1, 0, { G_TYPE_DOUBLE, }, gtk_snapshot_push_blur, snapshot_push_instr_blur, 1, }, { "color-matrix", 2, 0, { GRAPHENE_TYPE_MATRIX, GRAPHENE_TYPE_VEC4, }, gtk_snapshot_push_color_matrix, snapshot_push_instr_color_matrix, 2, }, { "component-transfer", 4, 0, { GSK_TYPE_COMPONENT_TRANSFER, GSK_TYPE_COMPONENT_TRANSFER, GSK_TYPE_COMPONENT_TRANSFER, GSK_TYPE_COMPONENT_TRANSFER, }, gtk_snapshot_push_component_transfer, snapshot_push_instr_component_transfer, 2, }, { "repeat", 2, 0, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_RECT, }, gtk_snapshot_push_repeat, snapshot_push_instr_repeat, 2, }, { "clip", 1, 0, { GRAPHENE_TYPE_RECT, }, gtk_snapshot_push_clip, snapshot_push_instr_clip, 1, }, { "rounded-clip", 5, 0, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, }, gtk_snapshot_push_rounded_clip, snapshot_push_instr_rounded_clip, 1, }, { "fill", 2, 0, { GSK_TYPE_PATH, GSK_TYPE_FILL_RULE, }, gtk_snapshot_push_fill, snapshot_push_instr_fill, 1, }, { "stroke", 2, 0, { GSK_TYPE_PATH, GSK_TYPE_STROKE, }, gtk_snapshot_push_stroke, snapshot_push_instr_stroke, 1, }, { "shadow", 4, 4, { GDK_TYPE_RGBA, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gtk_snapshot_push_shadow, snapshot_push_instr_shadow, 1, }, { "blend", 1, 0, { GSK_TYPE_BLEND_MODE, }, gtk_snapshot_push_blend, snapshot_push_instr_blend, 2, }, { "mask", 1, 0, { GSK_TYPE_MASK_MODE, }, gtk_snapshot_push_mask, snapshot_push_instr_mask, 2, }, { "copy", 0, 0, {}, gtk_snapshot_push_copy, snapshot_push_instr_copy, 1, }, { "composite", 1, 0, { GSK_TYPE_PORTER_DUFF, }, gtk_snapshot_push_composite, snapshot_push_instr_composite, 2, }, { "cross-fade", 1, 0, { G_TYPE_DOUBLE, }, gtk_snapshot_push_cross_fade, snapshot_push_instr_cross_fade, 2, }, }; for (guint i = 0; i < G_N_ELEMENTS (instrs); i++) { if (g_strcmp0 (lookup_name, instrs[i].name) == 0) { *out = instrs[i]; return TRUE; } } return FALSE; } static void snapshot_transform_instr_transform (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_transform ( snapshot, g_value_get_boxed (&args[0])); } static void snapshot_transform_instr_transform_matrix (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_transform_matrix ( snapshot, g_value_get_boxed (&args[0])); } static void snapshot_transform_instr_translate (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_translate ( snapshot, g_value_get_boxed (&args[0])); } static void snapshot_transform_instr_translate_3d (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_translate_3d ( snapshot, g_value_get_boxed (&args[0])); } static void snapshot_transform_instr_rotate (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_rotate ( snapshot, g_value_get_double (&args[0])); } static void snapshot_transform_instr_rotate_3d (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_rotate_3d ( snapshot, g_value_get_double (&args[0]), g_value_get_boxed (&args[1])); } static void snapshot_transform_instr_scale (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_scale ( snapshot, g_value_get_double (&args[0]), g_value_get_double (&args[1])); } static void snapshot_transform_instr_scale_3d (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_scale_3d ( snapshot, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2])); } static void snapshot_transform_instr_perspective (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_scale_3d ( snapshot, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2])); } gboolean lookup_snapshot_transform_instr (const char *lookup_name, SnapshotInstr *out) { SnapshotInstr instrs[] = { { "transform", 1, 0, { GSK_TYPE_TRANSFORM, }, gtk_snapshot_transform, snapshot_transform_instr_transform, }, { "transform-matrix", 1, 0, { GRAPHENE_TYPE_MATRIX, }, gtk_snapshot_transform_matrix, snapshot_transform_instr_transform_matrix, }, { "translate", 1, 0, { GRAPHENE_TYPE_POINT, }, gtk_snapshot_translate, snapshot_transform_instr_translate, }, { "translate-3d", 1, 0, { GRAPHENE_TYPE_POINT3D, }, gtk_snapshot_translate_3d, snapshot_transform_instr_translate_3d, }, { "rotate", 1, 0, { G_TYPE_DOUBLE, }, gtk_snapshot_rotate, snapshot_transform_instr_rotate, }, { "rotate-3d", 2, 0, { G_TYPE_DOUBLE, GRAPHENE_TYPE_VEC3, }, gtk_snapshot_rotate_3d, snapshot_transform_instr_rotate_3d, }, { "scale", 2, 0, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gtk_snapshot_scale, snapshot_transform_instr_scale, }, { "scale-3d", 3, 0, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gtk_snapshot_scale_3d, snapshot_transform_instr_scale_3d, }, { "perspective", 1, 0, { G_TYPE_DOUBLE, }, gtk_snapshot_perspective, snapshot_transform_instr_perspective, }, }; for (guint i = 0; i < G_N_ELEMENTS (instrs); i++) { if (g_strcmp0 (lookup_name, instrs[i].name) == 0) { *out = instrs[i]; return TRUE; } } return FALSE; } static void snapshot_append_instr_node (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_append_node ( snapshot, g_value_get_boxed (&args[0])); } static void snapshot_append_instr_texture (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_append_texture ( snapshot, g_value_get_object (&args[0]), g_value_get_boxed (&args[1])); } static void snapshot_append_instr_scaled_texture (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_append_scaled_texture ( snapshot, g_value_get_object (&args[0]), g_value_get_enum (&args[1]), g_value_get_boxed (&args[2])); } static void snapshot_append_instr_color (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_append_color ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1])); } static void snapshot_append_instr_linear_gradient (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { guint n_stops = 0; GskColorStop stops[ARGBUF_SIZE] = { 0 }; n_stops = MIN (n_rest / 2, G_N_ELEMENTS (stops)); for (guint i = 0; i < n_stops; i++) { stops[i].offset = g_value_get_double (&rest[i * 2 + 0]); stops[i].color = *(GdkRGBA *) g_value_get_boxed (&rest[i * 2 + 1]); } gtk_snapshot_append_linear_gradient ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1]), g_value_get_boxed (&args[2]), stops, n_stops); } static void snapshot_append_instr_repeating_linear_gradient (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { guint n_stops = 0; GskColorStop stops[ARGBUF_SIZE] = { 0 }; n_stops = MIN (n_rest / 2, G_N_ELEMENTS (stops)); for (guint i = 0; i < n_stops; i++) { stops[i].offset = g_value_get_double (&rest[i * 2 + 0]); stops[i].color = *(GdkRGBA *) g_value_get_boxed (&rest[i * 2 + 1]); } gtk_snapshot_append_repeating_linear_gradient ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1]), g_value_get_boxed (&args[2]), stops, n_stops); } static void snapshot_append_instr_radial_gradient (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { guint n_stops = 0; GskColorStop stops[ARGBUF_SIZE] = { 0 }; n_stops = MIN (n_rest / 2, G_N_ELEMENTS (stops)); for (guint i = 0; i < n_stops; i++) { stops[i].offset = g_value_get_double (&rest[i * 2 + 0]); stops[i].color = *(GdkRGBA *) g_value_get_boxed (&rest[i * 2 + 1]); } gtk_snapshot_append_radial_gradient ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3]), g_value_get_double (&args[4]), g_value_get_double (&args[5]), stops, n_stops); } static void snapshot_append_instr_repeating_radial_gradient (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { guint n_stops = 0; GskColorStop stops[ARGBUF_SIZE] = { 0 }; n_stops = MIN (n_rest / 2, G_N_ELEMENTS (stops)); for (guint i = 0; i < n_stops; i++) { stops[i].offset = g_value_get_double (&rest[i * 2 + 0]); stops[i].color = *(GdkRGBA *) g_value_get_boxed (&rest[i * 2 + 1]); } gtk_snapshot_append_repeating_radial_gradient ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3]), g_value_get_double (&args[4]), g_value_get_double (&args[5]), stops, n_stops); } static void snapshot_append_instr_conic_gradient (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { guint n_stops = 0; GskColorStop stops[ARGBUF_SIZE] = { 0 }; n_stops = MIN (n_rest / 2, G_N_ELEMENTS (stops)); for (guint i = 0; i < n_stops; i++) { stops[i].offset = g_value_get_double (&rest[i * 2 + 0]); stops[i].color = *(GdkRGBA *) g_value_get_boxed (&rest[i * 2 + 1]); } gtk_snapshot_append_conic_gradient ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1]), g_value_get_double (&args[2]), stops, n_stops); } static void snapshot_append_instr_border (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { GskRoundedRect rrect = { 0 }; float border_width[4] = { 0 }; GdkRGBA border_color[4] = { 0 }; rrect.bounds = *(graphene_rect_t *) g_value_get_boxed (&args[0]); rrect.corner[0] = *(graphene_size_t *) g_value_get_boxed (&args[1]); rrect.corner[1] = *(graphene_size_t *) g_value_get_boxed (&args[2]); rrect.corner[2] = *(graphene_size_t *) g_value_get_boxed (&args[3]); rrect.corner[3] = *(graphene_size_t *) g_value_get_boxed (&args[4]); border_width[0] = g_value_get_double (&args[5]); border_width[1] = g_value_get_double (&args[6]); border_width[2] = g_value_get_double (&args[7]); border_width[3] = g_value_get_double (&args[8]); border_color[0] = *(GdkRGBA *) g_value_get_boxed (&args[9]); border_color[1] = *(GdkRGBA *) g_value_get_boxed (&args[10]); border_color[2] = *(GdkRGBA *) g_value_get_boxed (&args[11]); border_color[3] = *(GdkRGBA *) g_value_get_boxed (&args[12]); gtk_snapshot_append_border ( snapshot, &rrect, border_width, border_color); } static void snapshot_append_instr_inset_shadow (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { GskRoundedRect rrect = { 0 }; rrect.bounds = *(graphene_rect_t *) g_value_get_boxed (&args[0]); rrect.corner[0] = *(graphene_size_t *) g_value_get_boxed (&args[1]); rrect.corner[1] = *(graphene_size_t *) g_value_get_boxed (&args[2]); rrect.corner[2] = *(graphene_size_t *) g_value_get_boxed (&args[3]); rrect.corner[3] = *(graphene_size_t *) g_value_get_boxed (&args[4]); gtk_snapshot_append_inset_shadow ( snapshot, &rrect, g_value_get_boxed (&args[5]), g_value_get_double (&args[6]), g_value_get_double (&args[7]), g_value_get_double (&args[8]), g_value_get_double (&args[9])); } static void snapshot_append_instr_outset_shadow (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { GskRoundedRect rrect = { 0 }; rrect.bounds = *(graphene_rect_t *) g_value_get_boxed (&args[0]); rrect.corner[0] = *(graphene_size_t *) g_value_get_boxed (&args[1]); rrect.corner[1] = *(graphene_size_t *) g_value_get_boxed (&args[2]); rrect.corner[2] = *(graphene_size_t *) g_value_get_boxed (&args[3]); rrect.corner[3] = *(graphene_size_t *) g_value_get_boxed (&args[4]); gtk_snapshot_append_outset_shadow ( snapshot, &rrect, g_value_get_boxed (&args[5]), g_value_get_double (&args[6]), g_value_get_double (&args[7]), g_value_get_double (&args[8]), g_value_get_double (&args[9])); } static void snapshot_append_instr_layout (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_append_layout ( snapshot, g_value_get_object (&args[0]), g_value_get_boxed (&args[1])); } static void snapshot_append_instr_fill (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_append_fill ( snapshot, g_value_get_boxed (&args[0]), g_value_get_enum (&args[1]), g_value_get_boxed (&args[2])); } static void snapshot_append_instr_stroke (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_append_stroke ( snapshot, g_value_get_boxed (&args[0]), g_value_get_boxed (&args[1]), g_value_get_boxed (&args[2])); } static void snapshot_append_instr_paste (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { gtk_snapshot_append_paste ( snapshot, g_value_get_boxed (&args[0]), g_value_get_uint64 (&args[1])); } static void snapshot_append_instr_paintable (GtkSnapshot *snapshot, const GValue args[], const GValue rest[], guint n_rest) { graphene_rect_t rect = { 0 }; rect = *(graphene_rect_t *) g_value_get_boxed (&args[1]); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &rect.origin); gdk_paintable_snapshot ( g_value_get_object (&args[0]), snapshot, rect.size.width, rect.size.height); gtk_snapshot_restore (snapshot); } gboolean lookup_snapshot_append_instr (const char *lookup_name, SnapshotInstr *out) { SnapshotInstr instrs[] = { { "node", 1, 0, { GSK_TYPE_RENDER_NODE, }, gtk_snapshot_append_node, snapshot_append_instr_node, }, { "texture", 2, 0, { GDK_TYPE_TEXTURE, GRAPHENE_TYPE_RECT, }, gtk_snapshot_append_texture, snapshot_append_instr_texture, }, { "scaled-texture", 3, 0, { GDK_TYPE_TEXTURE, GSK_TYPE_SCALING_FILTER, GRAPHENE_TYPE_RECT, }, gtk_snapshot_append_scaled_texture, snapshot_append_instr_scaled_texture, }, { "color", 2, 0, { GDK_TYPE_RGBA, GRAPHENE_TYPE_RECT, }, gtk_snapshot_append_color, snapshot_append_instr_color, }, { "linear-gradient", 5, 2, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_POINT, GRAPHENE_TYPE_POINT, G_TYPE_DOUBLE, GDK_TYPE_RGBA, }, gtk_snapshot_append_linear_gradient, snapshot_append_instr_linear_gradient, }, { "repeating-linear-gradient", 5, 2, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_POINT, GRAPHENE_TYPE_POINT, G_TYPE_DOUBLE, GDK_TYPE_RGBA, }, gtk_snapshot_append_repeating_linear_gradient, snapshot_append_instr_repeating_linear_gradient, }, { "radial-gradient", 8, 2, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_POINT, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, GDK_TYPE_RGBA, }, gtk_snapshot_append_radial_gradient, snapshot_append_instr_radial_gradient, }, { "repeating-radial-gradient", 8, 2, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_POINT, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, GDK_TYPE_RGBA, }, gtk_snapshot_append_repeating_radial_gradient, snapshot_append_instr_repeating_radial_gradient, }, { "conic-gradient", 5, 2, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_POINT, G_TYPE_DOUBLE, G_TYPE_DOUBLE, GDK_TYPE_RGBA, }, gtk_snapshot_append_conic_gradient, snapshot_append_instr_conic_gradient, }, { "border", 13, 0, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, GDK_TYPE_RGBA, GDK_TYPE_RGBA, GDK_TYPE_RGBA, GDK_TYPE_RGBA, }, gtk_snapshot_append_border, snapshot_append_instr_border, }, { "inset-shadow", 10, 0, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GDK_TYPE_RGBA, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gtk_snapshot_append_inset_shadow, snapshot_append_instr_inset_shadow, }, { "outset-shadow", 10, 0, { GRAPHENE_TYPE_RECT, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GRAPHENE_TYPE_SIZE, GDK_TYPE_RGBA, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gtk_snapshot_append_outset_shadow, snapshot_append_instr_outset_shadow, }, { "layout", 2, 0, { PANGO_TYPE_LAYOUT, GDK_TYPE_RGBA, }, gtk_snapshot_append_layout, snapshot_append_instr_layout, }, { "fill", 3, 0, { GSK_TYPE_PATH, GSK_TYPE_FILL_RULE, GDK_TYPE_RGBA, }, gtk_snapshot_append_fill, snapshot_append_instr_fill, }, { "stroke", 3, 0, { GSK_TYPE_PATH, GSK_TYPE_STROKE, GDK_TYPE_RGBA, }, gtk_snapshot_append_stroke, snapshot_append_instr_stroke, }, { "paste", 2, 0, { GRAPHENE_TYPE_RECT, G_TYPE_UINT64, }, gtk_snapshot_append_paste, snapshot_append_instr_paste, }, { "paintable", 2, 0, { GDK_TYPE_PAINTABLE, GRAPHENE_TYPE_RECT, }, gdk_paintable_snapshot, snapshot_append_instr_paintable, }, }; for (guint i = 0; i < G_N_ELEMENTS (instrs); i++) { if (g_strcmp0 (lookup_name, instrs[i].name) == 0) { *out = instrs[i]; return TRUE; } } return FALSE; } bazaar-org-bazaar-43ce9f7/bge/wdgt/lookup/transform.c000066400000000000000000000131641520414637400226300ustar00rootroot00000000000000/* transform.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 "lookup.h" static GskTransform * transform_instr_transform (GskTransform *next, const GValue args[]) { return gsk_transform_transform ( next, g_value_get_boxed (&args[0])); } static GskTransform * transform_instr_invert (GskTransform *next, const GValue args[]) { return gsk_transform_transform ( next, g_value_get_boxed (&args[0])); } static GskTransform * transform_instr_matrix (GskTransform *next, const GValue args[]) { return gsk_transform_matrix ( next, g_value_get_boxed (&args[0])); } static GskTransform * transform_instr_matrix_2d (GskTransform *next, const GValue args[]) { return gsk_transform_matrix_2d ( next, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2]), g_value_get_double (&args[3]), g_value_get_double (&args[4]), g_value_get_double (&args[5])); } static GskTransform * transform_instr_translate (GskTransform *next, const GValue args[]) { return gsk_transform_translate ( next, g_value_get_boxed (&args[0])); } static GskTransform * transform_instr_translate_3d (GskTransform *next, const GValue args[]) { return gsk_transform_translate_3d ( next, g_value_get_boxed (&args[0])); } static GskTransform * transform_instr_skew (GskTransform *next, const GValue args[]) { return gsk_transform_skew ( next, g_value_get_double (&args[0]), g_value_get_double (&args[1])); } static GskTransform * transform_instr_rotate (GskTransform *next, const GValue args[]) { return gsk_transform_rotate ( next, g_value_get_double (&args[0])); } static GskTransform * transform_instr_rotate_3d (GskTransform *next, const GValue args[]) { return gsk_transform_rotate_3d ( next, g_value_get_double (&args[0]), g_value_get_boxed (&args[1])); } static GskTransform * transform_instr_scale (GskTransform *next, const GValue args[]) { return gsk_transform_scale ( next, g_value_get_double (&args[0]), g_value_get_double (&args[1])); } static GskTransform * transform_instr_scale_3d (GskTransform *next, const GValue args[]) { return gsk_transform_scale_3d ( next, g_value_get_double (&args[0]), g_value_get_double (&args[1]), g_value_get_double (&args[2])); } static GskTransform * transform_instr_perspective (GskTransform *next, const GValue args[]) { return gsk_transform_perspective ( next, g_value_get_double (&args[0])); } gboolean lookup_transform_instr (const char *lookup_name, TransformInstr *out) { TransformInstr instrs[] = { { "transform", 1, { GSK_TYPE_TRANSFORM, }, gsk_transform_transform, transform_instr_transform, }, { "invert", 0, {}, gsk_transform_invert, transform_instr_invert, }, { "matrix", 1, { GRAPHENE_TYPE_MATRIX, }, gsk_transform_matrix, transform_instr_matrix, }, { "matrix-2d", 6, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_transform_matrix_2d, transform_instr_matrix_2d, }, { "translate", 1, { GRAPHENE_TYPE_POINT, }, gsk_transform_translate, transform_instr_translate, }, { "translate-3d", 1, { GRAPHENE_TYPE_POINT3D, }, gsk_transform_translate_3d, transform_instr_translate_3d, }, { "skew", 2, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_transform_skew, transform_instr_skew, }, { "rotate", 1, { G_TYPE_DOUBLE, }, gsk_transform_rotate, transform_instr_rotate, }, { "rotate-3d", 2, { G_TYPE_DOUBLE, GRAPHENE_TYPE_VEC3, }, gsk_transform_rotate_3d, transform_instr_rotate_3d, }, { "scale", 2, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_transform_scale, transform_instr_scale, }, { "scale-3d", 3, { G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, }, gsk_transform_scale_3d, transform_instr_scale_3d, }, { "perspective", 1, { G_TYPE_DOUBLE, }, gsk_transform_perspective, transform_instr_perspective, }, }; for (guint i = 0; i < G_N_ELEMENTS (instrs); i++) { if (g_strcmp0 (lookup_name, instrs[i].name) == 0) { *out = instrs[i]; return TRUE; } } return FALSE; } bazaar-org-bazaar-43ce9f7/bge/wdgt/meson.build000066400000000000000000000002671520414637400213020ustar00rootroot00000000000000bge_sources += files( 'bge-wdgt-spec.c', 'bge-easing.c', ) bge_headers += files( 'bge-wdgt-spec.h', 'bge-wdgt-renderer.h', 'bge-easing.h', ) subdir('lookup') subdir('fmt') bazaar-org-bazaar-43ce9f7/build-aux/000077500000000000000000000000001520414637400173235ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/build-aux/flatpak/000077500000000000000000000000001520414637400207455ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/build-aux/flatpak/flatpak-builder-tools/000077500000000000000000000000001520414637400251515ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/build-aux/flatpak/fuse-2.9.2-closefrom.patch000066400000000000000000000007001520414637400253620ustar00rootroot00000000000000--- 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; bazaar-org-bazaar-43ce9f7/build-aux/flatpak/fuse-2.9.2-namespace-conflict-fix.patch000066400000000000000000000010641520414637400277140ustar00rootroot00000000000000diff -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: bazaar-org-bazaar-43ce9f7/build-aux/flatpak/fuse-disable-sys-mount-under-flatpak.patch000066400000000000000000000011671520414637400310450ustar00rootroot00000000000000From 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 bazaar-org-bazaar-43ce9f7/build-aux/flatpak/fusermount-wrapper.sh000066400000000000000000000006431520414637400251710ustar00rootroot00000000000000#!/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" "$@" bazaar-org-bazaar-43ce9f7/build-aux/flatpak/io.github.kolunmi.Bazaar.json000066400000000000000000000425071520414637400264140ustar00rootroot00000000000000{ "id": "io.github.kolunmi.Bazaar", "runtime": "org.gnome.Platform", "runtime-version": "50", "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", "--talk-name=org.freedesktop.Flatpak", "--system-talk-name=org.freedesktop.Flatpak.SystemHelper", "--filesystem=/var/tmp", "--filesystem=~/.var/app", "--system-talk-name=org.freedesktop.Accounts", "--talk-name=org.freedesktop.impl.portal.PermissionStore" ], "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": "472c417005c2c71b8617de4f7b8d6b30411d78f4", "tag": "release-0.5.3", "x-checker-data": { "type": "git", "tag-pattern": "^release-([\\d.]+)$" } } ] }, { "name": "malcontent", "buildsystem": "meson", "config-opts": [ "-Dui=disabled", "-Dinstalled_tests=false" ], "sources": [ { "type": "git", "url": "https://gitlab.freedesktop.org/pwithnall/malcontent.git", "commit": "3ba80995bb25b7aeda7e21d547f9e39ff9a81736", "tag": "0.12.0" }, { "type": "shell", "commands": [ "sed -i \"/subdir('tests')/d\" libmalcontent/meson.build", "sed -i \"/subdir('tests')/d\" meson.build", "sed -i \"/subdir('pam')/d\" meson.build" ] } ] }, { "name": "flatpak", "buildsystem": "meson", "config-opts": [ "-Dgtkdoc=disabled", "-Ddocbook_docs=disabled", "-Dtests=false", "-Dman=disabled", "-Dseccomp=disabled", "-Dselinux_module=disabled", "-Dmalcontent=enabled", "-Dsandboxed_triggers=false", "-Dsystem_helper=enabled", "-Dsystemd=disabled", "-Dsystem_install_dir=/var/lib/flatpak", "-Dsystem_bubblewrap=bwrap", "-Dsystem_dbus_proxy=xdg-dbus-proxy", "--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": "b4c53a4cfffd5dd471589249e35be6ab9e08b6a5", "tag": "1.17.7", "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/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", "sha256": "c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", "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": "python3-babel", "buildsystem": "simple", "cleanup": [ "*" ], "build-commands": [ "pip3 install --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} --no-build-isolation babel" ], "sources": [ { "type": "file", "url": "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", "sha256": "b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", "x-checker-data": { "type": "pypi", "name": "babel" } } ] }, { "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": "9e4894c969eecf26a3ba762f4f7a268aa0fb3e51", "tag": "127", "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": "v2026.1", "commit": "84fcfe17adcc69b926e8205782c1f735c09bfdd9", "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": "6a170fa77e3cbecb48f9dd2478fe5c0a119eb467", "tag": "0.1.7", "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": "1b80120ef26a28e065e67f89bfef873f13bdd317", "tag": "v0.11.2", "x-checker-data": { "type": "git", "url-template": "$version" } } ] } ] } bazaar-org-bazaar-43ce9f7/data/000077500000000000000000000000001520414637400163425ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/data/dbus/000077500000000000000000000000001520414637400172775ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/data/dbus/io.github.kolunmi.Bazaar.service.in000066400000000000000000000001731520414637400260330ustar00rootroot00000000000000[D-BUS Service] Name=io.github.kolunmi.Bazaar SystemdService=io.github.kolunmi.Bazaar.service Exec=@bindir@/bazaar service bazaar-org-bazaar-43ce9f7/data/dbus/meson.build000066400000000000000000000004701520414637400214420ustar00rootroot00000000000000service_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' ) bazaar-org-bazaar-43ce9f7/data/icons/000077500000000000000000000000001520414637400174555ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/data/icons/hicolor/000077500000000000000000000000001520414637400211145ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/data/icons/hicolor/scalable/000077500000000000000000000000001520414637400226625ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/data/icons/hicolor/scalable/apps/000077500000000000000000000000001520414637400236255ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/data/icons/hicolor/scalable/apps/io.github.kolunmi.Bazaar.Devel.svg000066400000000000000000000102551520414637400321530ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/data/icons/hicolor/scalable/apps/io.github.kolunmi.Bazaar.svg000066400000000000000000000103051520414637400311110ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/data/icons/hicolor/symbolic/000077500000000000000000000000001520414637400227355ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/data/icons/hicolor/symbolic/apps/000077500000000000000000000000001520414637400237005ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/data/icons/hicolor/symbolic/apps/io.github.kolunmi.Bazaar-symbolic.svg000066400000000000000000000047301520414637400330100ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/data/icons/io.github.kolunmi.Bazaar.Source.svg000066400000000000000000007446121520414637400262170ustar00rootroot00000000000000 Adwaita Icon Template image/svg+xml GNOME Design Team Adwaita Icon Template Hicolor Symbolic bazaar-org-bazaar-43ce9f7/data/icons/meson.build000066400000000000000000000010731520414637400216200ustar00rootroot00000000000000application_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 ) bazaar-org-bazaar-43ce9f7/data/io.github.kolunmi.Bazaar.desktop.in000066400000000000000000000010351520414637400251050ustar00rootroot00000000000000[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;application/vnd.flatpak;application/vnd.flatpak.ref; Actions=new-window; X-Purism-FormFactor=Workstation;Mobile; [Desktop Action new-window] Name=New Window Exec=bazaar %U bazaar-org-bazaar-43ce9f7/data/io.github.kolunmi.Bazaar.gschema.xml000066400000000000000000000062301520414637400252370ustar00rootroot00000000000000 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 true Force Adwaita Icon Theme Override the icon theme with Adwaita true Show Permission Warning Banner Show a warning banner on the permissions page bazaar-org-bazaar-43ce9f7/data/io.github.kolunmi.Bazaar.metainfo.xml.in000066400000000000000000000546601520414637400260510ustar00rootroot00000000000000 io.github.kolunmi.Bazaar CC0-1.0 GPL-3.0-or-later Bazaar Discover and manage applications

A fast and modern app store for Linux with a focus on discovering and installing Flatpak apps and addons, particularly from Flathub.

  • Queue multiple installs and keep browsing
  • Easily view app permissions
  • Sign in to Flathub to view and manage your favorites
  • Search apps directly from GNOME Shell
pointing keyboard touch 360 The Bazaar Contributors https://usebazaar.org/ https://github.com/bazaar-org/bazaar https://github.com/bazaar-org/bazaar/issues https://github.com/bazaar-org/bazaar/tree/master/po https://github.com/bazaar-org/bazaar/blob/master/README.md https://github.com/bazaar-org/bazaar/discussions https://github.com/sponsors/kolunmi https://github.com/kolunmi https://github.com/bazaar-org/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/a25269a3-0560-4d75-9166-a38bc7a7f429 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/bazaar-org/bazaar/releases/tag/v0.8.1

Hot fix for an issue where updates would not show. Also adds a cancel button to the app tiles on the search page.

Other Fixes

  • Fix Flathub page svg graphics being rendered with a solid fill
  • Disable broken graphs for very new Flathub apps
  • Add workaround for KRunner sending broken app IDs

Thanks for reading, and have a great day!

https://github.com/bazaar-org/bazaar/releases/tag/v0.8.0

New Features

  • Add support for installing (.flatpak) bundles
  • New progress indicators
  • The ability to view and delete app caches

Fixes

  • Fix the download context tile not displaying a label for non-Flathub apps
  • Reduce RAM usage when no windows are open
  • Fix an issue where a window could open at the wrong size while a transaction was running
  • Many other bug fixes

Thanks for reading, and have a great day!

https://github.com/bazaar-org/bazaar/releases/tag/v0.7.15

New Features

  • Add support for previewing metainfo files
  • Show total installed apps number in the library view
  • Make exported desktop search provider app icon sizes adjustable

Fixes

  • Fix download timeline graph rerendering too much
  • Fix animated widget ticks not being in sync with fps
  • Fix progress animation for vertical pride flag stripes
  • Many other bug fixes

Thanks for reading, and have a great day!

https://github.com/bazaar-org/bazaar/releases/tag/v0.7.14

New Features

  • Rework the add-ons dialog
  • Add a gradient under the download timeline
  • Add a filter button to the search page
  • Add a button to show the EULA for some proprietary apps
  • Make the names of verified developers clickable links

Fixes

  • Fix the colours of the update card
  • Make the update banner follow the accent colour

Thanks for reading, and have a great day!

https://github.com/bazaar-org/bazaar/releases/tag/v0.7.13

Changes

  • Update to GNOME 50 Runtime
  • Force Adwaita icon theme to ensure consistency
  • Add support for clickable links in app descriptions
  • Add timed lingering cache to async textures, thereby reducing image flickering
  • Add ability to sort installed apps by size in library view
  • Add BAZAAR_N_DOWNLOAD_WORKERS envvar support

Bug Fixes

  • Fix double shadow around update cards
  • Fix global progress button displaying a focus ring when invisible
  • Fix incorrect total size displayed on update tasks
  • Fix empty UI when Flathub hasn't finished syncing yet

Thanks for reading and have a great day!

https://github.com/bazaar-org/bazaar/releases/tag/v0.7.11

This release contains many technical improvements. This changelog reflects roughly 2 weeks of work.

Changes

  • Respect system parental controls settings
  • Reap download workers when all windows are closed, reducing total memory usage
  • Add mnemonics to full app view
  • Many updates to language translations

Bug Fixes

  • Fix broken library page when backing installed apps model is empty
  • Fix int casting bug that was causing RetroDeck to appear to be 18.4 exabytes
  • Make "all apps" category pages respect global filters
  • Fix some text wrapping issues

Thanks for reading and have a great day!

https://github.com/bazaar-org/bazaar/releases/tag/v0.7.10

This release fixes some bugs and greatly improves search functionality.

If you missed the previous release, in 0.7.9 we also added the ability to cancel transactions in the library view, a brand new screenshots carousel, search suggestion buttons, and app runtime size information. You can also now skip confirmation dialogs by holding shift as you start a transaction.

Thanks for reading!

https://github.com/bazaar-org/bazaar/releases/tag/v0.7.9

**New Features**

  • Search suggestion pills
  • **Cancel installation** transactions
  • Skip dialogs by pressing shift
  • Runtime size info for app pages

**Updated**

  • Redesigned "What's New" dialog
  • Improved search results by utilizing Flathub rankings
  • Improved screenshots carousel
https://github.com/bazaar-org/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/bazaar-org/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/bazaar-org/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/bazaar-org/bazaar/releases/tag/v0.7.5

Minor bugfix release

https://github.com/bazaar-org/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/bazaar-org/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/bazaar-org/bazaar/releases/tag/v0.7.2

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

https://github.com/bazaar-org/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/bazaar-org/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/bazaar-org/bazaar/releases/tag/v0.6.3

Another quick release to restore alphabetical sorting on the installed page

https://github.com/bazaar-org/bazaar/releases/tag/v0.6.2

Quick release to allow manual refresh if flathub is being flaky

https://github.com/bazaar-org/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/bazaar-org/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/bazaar-org/bazaar/releases/tag/v0.5.10 https://github.com/bazaar-org/bazaar/releases/tag/v0.5.9 https://github.com/bazaar-org/bazaar/releases/tag/v0.5.8 https://github.com/bazaar-org/bazaar/releases/tag/v0.5.7 https://github.com/bazaar-org/bazaar/releases/tag/v0.5.6 https://github.com/bazaar-org/bazaar/releases/tag/v0.5.5 https://github.com/bazaar-org/bazaar/releases/tag/v0.5.4 https://github.com/bazaar-org/bazaar/releases/tag/v0.5.3 https://github.com/bazaar-org/bazaar/releases/tag/v0.5.2 https://github.com/bazaar-org/bazaar/releases/tag/v0.5.1 https://github.com/bazaar-org/bazaar/releases/tag/v0.5.0 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.11 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.10 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.9 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.8 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.7 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.6 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.5 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.4 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.3 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.2 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.1 https://github.com/bazaar-org/bazaar/releases/tag/v0.4.0 https://github.com/bazaar-org/bazaar/releases/tag/v0.3.2 https://github.com/bazaar-org/bazaar/releases/tag/v0.3.1 https://github.com/bazaar-org/bazaar/releases/tag/v0.3.0 https://github.com/bazaar-org/bazaar/releases/tag/v0.2.3 https://github.com/bazaar-org/bazaar/releases/tag/v0.2.2 https://github.com/bazaar-org/bazaar/releases/tag/v0.2.1 https://github.com/bazaar-org/bazaar/releases/tag/v0.2.0 https://github.com/bazaar-org/bazaar/releases/tag/v0.1.0
bazaar-org-bazaar-43ce9f7/data/io.github.kolunmi.Bazaar.search-provider.ini.in000066400000000000000000000002411520414637400273050ustar00rootroot00000000000000[Shell Search Provider] DesktopId=io.github.kolunmi.Bazaar.desktop BusName=io.github.kolunmi.Bazaar ObjectPath=/io/github/kolunmi/Bazaar/SearchProvider Version=2bazaar-org-bazaar-43ce9f7/data/io.github.kolunmi.Bazaar.service.in000066400000000000000000000002361520414637400250760ustar00rootroot00000000000000[Unit] Description=Bazaar Service PartOf=graphical-session.target [Service] Type=dbus BusName=io.github.kolunmi.Bazaar ExecStart=@bindir@/bazaar --no-window bazaar-org-bazaar-43ce9f7/data/meson.build000066400000000000000000000034411520414637400205060ustar00rootroot00000000000000desktop_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') bazaar-org-bazaar-43ce9f7/docs/000077500000000000000000000000001520414637400163615ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/docs/debugging.md000066400000000000000000000040121520414637400206330ustar00rootroot00000000000000# Debugging Bazaar ## Running Bazaar with Debug Messages Enabled You do this the same as with any other GLib application: ```sh pkill bazaar; env G_MESSAGES_DEBUG=all bazaar ``` This will produce a flood of output. If you know the specific log domain you want to see, you can replace `all` with that domain name, such as `flatpak` or `BAZAAR::CORE`. ## Bazaar Inspector Bazaar has its own inspector window, which you can spawn with the key combo `control+alt+shift+i`. This is meant to be useful for developers and distributors. The global debug mode toggle in this window basically just enables a bottom bar in each Bazaar window which displays useful information particular to that window and allows you to easily inspect the UI entry for the visible application. You can also disable blocklists from this window. This is a temporary internal property, not a configuration option; It will not be saved for the next Bazaar process. The rest of the contents of this window should be self-explanatory. ## Debugging Crashes ### Flatpak #### Installing the Debug Symbols This is mostly based on [flatpak docs](https://docs.flatpak.org/en/latest/debugging.html). Installing debug extensions so the stacktrace is actually useful for developers: ```sh flatpak install --include-debug --include-sdk io.github.kolunmi.Bazaar ``` You can remove all the gnome sdk and debug extensions again when you are finished with debugging. This is quite a big download, please have patience. #### Actually Start Debugging Bazaar starts a background service once started, make sure it is not running first: ```sh flatpak kill io.github.kolunmi.Bazaar ``` ```sh flatpak run --devel --command=bash io.github.kolunmi.Bazaar ``` This will get you a shell inside the flatpak sandbox: run this: `gdb /app/bin/bazaar` ```sh [📦 io.github.kolunmi.Bazaar ~]$ gdb /app/bin/bazaar ``` Actually run bazaar: ```sh $ (gdb) run ``` (reproduce the bug here so it crashes) after it crashed, retrieve the useful information: ```sh $ (gdb) thread apply all backtrace ``` bazaar-org-bazaar-43ce9f7/docs/overview.md000066400000000000000000000750451520414637400205640ustar00rootroot00000000000000# 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. ## Environment Variables Bazaar reads the following environment variables, which may be of interest: * `BAZAAR_DESKTOP_SEARCH_PROVIDER_ICON_SIZE`: may be read as an unsigned integer from 1 to 256 to specify the square pixel size of icons sent to the desktop search provider. This should be configured to be a higher value than its default value of 24x24 when on KDE, as krunner paints result icons as much larger than gnome-shell does. This way, the images will not appear blurry. * `BAZAAR_N_DOWNLOAD_WORKERS`: may be read as an unsigned integer greater than 0 to specify the number of image download worker subprocesses that should be spawned and managed by Bazaar to fetch screenshots, icons, and other images. By default, Bazaar spawns 8 download workers. Download workers are always killed when Bazaar has no active windows and ensured when Bazaar returns to having 1 or more windows. ## 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, these are the event signals you can subscribe to: * `view-app`: run the hook when the user clicks on an app tile or otherwise views an application in the main app page * `before-transaction`: run the hook right as the user invokes a transaction * `after-transaction`: run the hook after a transaction 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_APPID`: if applicable, the appid of the entry Bazaar is currently dealing with. Use this for hooks that are not related to transactions. If your hook deals with transactions, such as `before-transaction` or `after-transaction`, use `BAZAAR_TS_APPID` instead. * `BAZAAR_TS_APPID`: if applicable, the appid of the entry Bazaar is currently dealing with. Use this for hooks that are related to transactions. If your hook does not deal with transactions, such as `view-app`, use `BAZAAR_APPID` instead. * `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 # This gives you the opportunity to add a basic regex check on an incoming # appid before incurring the overhead of spawning a subprocess. This # improves performance and reduces script boilerplate for long lists of # hooks that execute on specific appids. check-appid-regex: ^com\.jetbrains\..*$ ``` `/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 ``` ## Search Biases Search biases are a mechanism provided by Bazaar to influence search results. Given a regex string with which to match a search query, a bias can replace the matched text with a new string and/or adjust the scores of certain appids according to a defined function if a match occurs. This is particularly useful in the following cases: * An application is, for example, an image editor, but doesn't show up in the results for "image editor" because its metadata doesn't contain those search tokens for whatever reason. A search bias can ensure that the app appears despite this. * You want an abbreviation or phrase to be expanded into a version which is more likely to yield better results. For example, Bazaar hardcodes the expansion of the abbreviation `dl` to `download`, which is more helpful when searching metadata. ### Boost Functions Right now, there are two kinds of boost functions you can specify to influence the score of certain appids in the event of a regex match: linear and exponential: #### Linear Linear functions require a `slope` and a `y-intercept` and are evaluated like this: ``` new-score = y-intercept + (slope * original-score) ``` #### Exponential Exponential functions require a `factor` and a `y-intercept` and are evaluated like this: ``` new-score = y-intercept * (factor ^ original-score) ``` ### Examples Search biases 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 search biases: ```yaml search-biases: # Brief regex review: # `^` indicates the beginning of the string # `$` indicates the end of the string # `\b` indicates a word boundary # `(?i)` means case insensitive # Convert queries like "smb server" to "samba server" - regex: \b(?i)smb\b convert-to: samba # Give your favorite matrix clients a simple boost of 100.0 to their score - regex: \b(?i)matrix\b boost-appids: - org.gnome.Fractal - im.riot.Riot linear-boost: slope: 1.0 y-intercept: 100.0 # Convert the search _and_ boost appids - regex: ^(?i)deck$ convert-to: steam deck boost-appids: - com.github.Matoking.protontricks - com.steamgriddb.steam-rom-manager - com.valvesoftware.SteamLink linear-boost: slope: 1.2 y-intercept: 20.0 # Biases are applied in the order that you specify them, so in both the case # that the user types "deck" or "steam deck launcher", the following will be # applied: - regex: \bsteam deck\b boost-appids: - net.retrodeck.retrodeck exponential-boost: factor: 2.0 y-intercept: 5.0 ``` Pro tip: pressing `ctrl-alt-d` in Bazaar activates debug mode, which enables you to see the scores of app results on the search page. This is useful for debugging search biases! ## 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) bazaar-org-bazaar-43ce9f7/funding.json000066400000000000000000000064011520414637400177570ustar00rootroot00000000000000{ "$schema": "https://fundingjson.org/schema/v1.1.0.json", "version": "v1.0.0", "entity": { "type": "individual", "role": "maintainer", "name": "Adam Masciola", "email": "kolunmi@posteo.net", "phone": "", "description": "Adam is the creator and lead programmer of Bazaar.", "webpageUrl": { "url": "https://www.kolunmi.net/" } }, "projects": [ { "guid": "bazaar", "name": "Bazaar", "description": "Bazaar is a vertically-integrated App Store for Linux desktop applications, tightly integrating with Flatpak application packages and flathub.org, the central Flatpak repository. It provides a beautiful and high-performance frontend to these open standards and open infrastructure for Linux desktop apps.", "webpageUrl": { "url": "https://usebazaar.org/" }, "repositoryUrl": { "url": "https://github.com/bazaar-org/bazaar", "wellKnown": "https://github.com/bazaar-org/bazaar/blob/main/.well-known/funding-manifest-urls" }, "licenses": ["spdx:GPL-3.0"], "tags": ["app-store", "flatpak"] } ], "funding": { "channels": [ { "guid": "kolunmi-bank", "type": "bank", "address": "", "description": "Direct bank transfers to USA bank. Please e-mail me for details." } ], "plans": [ { "guid": "curation", "status": "active", "name": "Curation", "description": "Bazaar acts as both a software frontend and a curated frontend to flathub.org, which requires a small amount of continuous curation of applications (in the form of presentation layer tweaks) as they flow through Flathub.", "amount": 200, "currency": "USD", "frequency": "monthly", "channels": ["kolunmi-bank"] }, { "guid": "developer-time", "status": "active", "name": "Developer Compensation", "description": "This will cover the cost of kolunmi's full-time contribution to Bazaar and integration with other projects.", "amount": 2000, "currency": "USD", "frequency": "monthly", "channels": ["kolunmi-bank"] }, { "guid": "donations", "status": "active", "name": "Donation GUI Enhancements", "description": "Because Bazaar is increasingly the default Linux App Store, and many desktop Linux applications are F/OSS, carefully-designed donation opportunities to those projects will grow the overall Linux desktop.", "amount": 300, "currency": "USD", "frequency": "monthly", "channels": ["kolunmi-bank"] }, { "guid": "gnome-core", "status": "active", "name": "GNOME Circle and Core", "description": "This is an ongoing task to get Bazaar into GNOME Circle and, ultimately, GNOME Core. This will require code review, security concerns, code cleanup, etc. in conjunction with the GNOME Core teams. Some of this work has already begun with the GNOME Design Team. Bazaar is already the default App Store on Bazzite, Nobara, and the other Universal Blue distributions.", "amount": 500, "currency": "USD", "frequency": "monthly", "channels": ["kolunmi-bank"] } ], "history": [] } } bazaar-org-bazaar-43ce9f7/meson.build000066400000000000000000000101641520414637400175750ustar00rootroot00000000000000project('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', ], ) # can't have statements before `project` ... bz_vcs_version = run_command('version.sh', 'get-vcs').stdout().strip() bz_version = run_command('version.sh', 'get-version').stdout().strip() python3 = find_program('python3') i18n = import('i18n') if get_option('im_a_translator') subdir('po') else gnome = import('gnome') cc = meson.get_compiler('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') if get_option('bge_only') subdir('bge') else config_h = configuration_data() config_h.set_quoted('PACKAGE_VERSION', bz_version) config_h.set_quoted('PACKAGE_VCS_VERSION', bz_vcs_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()) refresh_worker_bin_name = 'bazaar-refresh-worker' config_h.set_quoted('REFRESH_WORKER_BIN_NAME', refresh_worker_bin_name) 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') subdir('bge') subdir('data') subdir('src') subdir('po') gnome.post_install( glib_compile_schemas: true, gtk_update_icon_cache: true, update_desktop_database: true, ) endif endif bazaar-org-bazaar-43ce9f7/meson_options.txt000066400000000000000000000021231520414637400210640ustar00rootroot00000000000000option('bge_only', type: 'boolean', value: false, description: 'Whether to restrict the build to libbge') option('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') bazaar-org-bazaar-43ce9f7/po/000077500000000000000000000000001520414637400160475ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/po/.gitignore000066400000000000000000000000121520414637400200300ustar00rootroot00000000000000bazaar.potbazaar-org-bazaar-43ce9f7/po/LINGUAS000066400000000000000000000002171520414637400170740ustar00rootroot00000000000000# Please keep this file sorted alphabetically. ar be bg bs cs de el es eu fa_IR fr ga hu id it ja kw nl pl pt_BR pt_PT ru tr uk vi zh_CN zh_TW bazaar-org-bazaar-43ce9f7/po/POTFILES.in000066400000000000000000000067601520414637400176350ustar00rootroot00000000000000# 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-addon-tile.blp src/bz-addon-tile.c 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-application-map-factory.c src/bz-application.c src/bz-apps-page.blp src/bz-apps-page.c src/bz-appstream-parser.c src/bz-async-texture.c src/bz-backend.c src/bz-bundle-install-dialog.blp src/bz-bundle-install-dialog.c src/bz-content-provider.c src/bz-context-tile-callbacks.c src/bz-context-tile.blp src/bz-context-tile.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-util.c src/bz-entry-group.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-dialog.blp src/bz-error-dialog.c src/bz-error.c src/bz-favorite-button.blp src/bz-favorite-button.c src/bz-favorites-page.blp src/bz-favorites-page.c src/bz-favorites-tile.blp src/bz-favorites-tile.c 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-inspector.blp src/bz-inspector.c src/bz-install-controls.blp src/bz-install-controls.c src/bz-install-controls.wdgt src/bz-installed-tile.blp src/bz-installed-tile.c src/bz-io.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-metainfo-preview.c 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-page.blp src/bz-screenshot.c src/bz-screenshots-carousel.blp src/bz-search-engine.c src/bz-search-filter-popover.blp src/bz-search-filter-popover.c src/bz-search-page.blp src/bz-search-page.c src/bz-search-pill-list.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-transact-icon.wdgt 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.blp src/bz-user-data-page.c src/bz-user-data-tile.blp src/bz-user-data-tile.c src/bz-window.blp src/bz-window.c src/bz-world-map.c src/bz-yaml-parser.c src/dl-worker.c src/main.c src/shortcuts-dialog.blp bazaar-org-bazaar-43ce9f7/po/ar.po000066400000000000000000003044201520414637400170140ustar00rootroot00000000000000# 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: 2026-02-14 09:05+0300\n" "PO-Revision-Date: 2026-02-14 13:41+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.8\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 "بازار" #: 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؛ النظام؛ مدير الحزم؛ اكتشاف؛ فلات باك؛ البرامج؛ المتجر؛" #: 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 "" "متجر تطبيقات جديد للينوكس يركز على استكشاف وتنصيب التطبيقات والإضافات من " "فلاتباك، وبالأخص مستودع فلاتهَب." #: 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:29 src/bz-application.c:703 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "الصفحة الرئيسية وهي تعرض تطبيقات فلاتهَب" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Exhibit app page" msgstr "صفحة معرض التطبيق" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Library page" msgstr "صفحة المكتبة" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Search page" msgstr "صفحة البحث" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:70 msgid "Category page" msgstr "صفحة التصنيفات" #: src/bz-addons-dialog.blp:16 src/bz-full-view.blp:708 #: src/bz-installed-tile.blp:101 msgid "Manage Add-ons" msgstr "أدِر الإضافات" #: src/bz-addons-dialog.c:94 src/bz-full-view.blp:495 #: 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:262 src/bz-full-view.blp:482 #: 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: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:29 #: 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 "ت_برَّع إلى بازار ❤️" #: 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 "_تسجيل الدخول بفلاتهب" #: 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 "_عَنْ بازار" #: 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 "_أخرج من بازار" #: 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:287 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 "Adam Masciola " #: src/bz-application.c:675 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:706 msgid "translator-credits" msgstr "" "أحمد النجماوي \n" "أنس داوود آغا " #: 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 "نصِّب فلاتهب" #: 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 "" "فلاتهب لم يتم تنصيبه على النظام. لن تستطيع تصفح و تنصيب تطبيقات بازار اذا لم " "توجد.\n" "\n" "يمكنك استخدام بازار لتصفح وحذف التطبيقات المحملة." #: 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 "صفحة فلاتهَب" #: 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:61 #: 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 "" "لا تتوفر معلومات عن التنسيق في هذا النظام. لا يزال بإمكانك تصفح التطبيقات " "على فلاتهب" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "تصفح فلاتهَب" #: 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 بواسطة فريق فلاتهب." #: 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 بواسطة %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 "تم التحقق من ملكية معرف التطبيق %1$s باستخدام %2$s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "تم التحقق من ملكية معرف التطبيق %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 "تم إطلاق هذا الإصدار من بازار بفضل مستخدمين مثلك!" #: 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 "" "أحبّ تصميم بازار، لكنني لا أستطيع القيام بذلك بمفردي. إذا كنتم ترغبون في دعم " "تطويره، يُرجى التبرع للمشروع عبر حسابي على Ko-fi:" #: src/bz-donations-dialog.blp:87 msgid "Donate to Bazaar" msgstr "تبرَّع إلى بازار" #. 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 "سجّل الدخول باستخدام فلاتهب لإدارة المفضلة" #: 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:44 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 "لم يُضف فلاتهَب" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "" "لم يتم العثور على جهاز التحكم عن بعد فلاتهب في أي من عمليات تثبيت فلاتباك " "الخاصة بك" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "حصل خطأ في فلاتهب" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "أعد محاولة الاتصال بفلاتهب" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "فلاتهب غير متوفر" #: 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 "ابحث التطبيقات" #: 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 "تطبيقات لأجل هواتف لينكس وأجهزتها اللوحية" #: 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:65 src/bz-library-page.blp:70 #: src/bz-library-page.blp:74 msgid "No Results" msgstr "لا توجد نتائج" #: src/bz-full-view.blp:66 msgid "Try a different search query" msgstr "جرِّب عبارة بحث مختلفة" #: src/bz-full-view.blp:72 msgid "Content" msgstr "المحتوى" #: src/bz-full-view.blp:130 msgid "Installing .flatpak bundles is not yet supported" msgstr "تثبيت حزم فلاتباك غير مدعوم حاليًا" #: src/bz-full-view.blp:223 msgid "Support" msgstr "ادعَم" #: src/bz-full-view.blp:246 src/bz-full-view.blp:506 msgid "Open" msgstr "افتح" #: src/bz-full-view.blp:259 src/bz-full-view.blp:479 msgid "Download & Install Application" msgstr "نزِّل التطبيق ونصِّبه" #: src/bz-full-view.blp:274 msgid "Uninstall Application" msgstr "أزِل التطبيق" #: src/bz-full-view.blp:289 src/bz-full-view.blp:521 msgid "Install Other Version" msgstr "نصِّب إصدارًا آخر" #: src/bz-full-view.blp:443 msgid "Downloads/Month" msgstr "تنزيلات\\شهر" #: src/bz-full-view.blp:540 msgid "Stopped Receiving Core Updates" msgstr "توقف عن تلقي التحديثات الأساسية" #: src/bz-full-view.blp:554 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:643 msgid "Trash Data" msgstr "بيانات المهملات" #: src/bz-full-view.blp:784 msgid "Tags:" msgstr "الوسوم:" #: src/bz-full-view.c:227 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:234 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:241 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:251 #, c-format msgid "%d downloads in the last 30 days" msgstr "عدد التنزيلات %d في آخر 30 يومًا" #: src/bz-full-view.c:263 src/bz-full-view.c:597 src/bz-full-view.c:614 msgid "N/A" msgstr "غير متوفر" #. Translators: . #: src/bz-full-view.c:287 msgid "Download" msgstr "تحميل" #: src/bz-full-view.c:307 msgid "Size information unavailable" 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:132 msgid "Proprietary" msgstr "محتكرة" #: src/bz-full-view.c:441 src/bz-license-dialog.c:134 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 "" "هذا التطبيق مرخص تحت رخصة حرَّة، مما يعني أنه يمكن فحص المصدر البرمجي أمنيًا." #: 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: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 تطبيق" msgstr[1] "%d تطبيق" msgstr[2] "%d تطبيقات" msgstr[3] "%d تطبيقات" msgstr[4] "%d تطبيقات" msgstr[5] "%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-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:153 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "لا يوجد نتائج للبحث عن \"%s\" في التطبيقات المنصبة" #: src/bz-library-page.c:166 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 تحديثات متوفر" msgstr[3] "%u تحديثات متوفر" msgstr[4] "%u تحديثات متوفر" msgstr[5] "%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 "اربط بفلاتهب" #: 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 "اربط حسابك على فلاتهب ببازار لادارة تطبيقاتك المفضلة." #: src/bz-login-page.blp:108 msgid "Finish" msgstr "انتهاء" #: src/bz-login-page.c:664 #, 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 "نتائج من فلاتهب فقط" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "قيِّد نتائج البحث إلى التطبيقات المتوفرة على فلاتهَب فقط" #: 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 "استبعِد النتائج التي ليست موثقة من فلاتهَب" #: 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 "معرف التطبيق" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "حزمة التطوير البرمجية" #: 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 "" "يستخدم هذا التطبيق إصدارًا قديمًا من منصة البرامج (حزمة تطوير برمجية) وقد " "يحتوي على أخطاء أو ثغرات أمنية لن يتم إصلاحها." #: 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:112 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\" في فلاتهب" #: 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" "لأن التطبيق محتكر، فلا يمكن تدقيقه لمعرفة ما يفعله بهذه الأذونات." #: 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 التطبيقات؟" msgstr[3] "أتُنصِّب %u التطبيقات؟" msgstr[4] "أتُنصِّب %u التطبيقات؟" msgstr[5] "أتُنصِّب %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 "بالإضافة إلى ذلك، ستنصَّب %d من بيئات التشغيل و\\أو الإضافات." #: 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:226 msgid "Error" msgstr "خطأ" #: src/bz-transaction-tile.blp:267 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 تحديثات وقت التشغيل" msgstr[3] "%u تحديثات وقت التشغيل" msgstr[4] "%u تحديثات وقت التشغيل" msgstr[5] "%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 "فلاتهَب" #: 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 "انت تشغل نسخة حديثة من بازار!" #: 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 "لديك اتصال بالشبكة ولكن يتم عرض نسخة مسجلة من فلاتهب" #: src/bz-window.blp:449 msgid "Log Out" msgstr "تسجيل الخروج" #: src/bz-window.c:683 msgid "You can't remove Bazaar from Bazaar!" msgstr "لا يمكنك حذف بازار من بازار!" #: 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 "Show Git Forge Star Counts" #~ msgstr "إظهار نجوم مستودع جِت" #~ msgid "" #~ "Whether to attempt to detect and show \"star counts\" for projects in the " #~ "full view" #~ msgstr "أيظهر مقدار نجوم مستودع جِت للمشروع أم لا؟" #~ msgid "Only Show Free Software" #~ msgstr "إظهار البرمجيات الحرة حصرًا" #~ msgid "Hide proprietary software when searching" #~ msgstr "يخفي البرمجيات المحتكرة عند البحث" #~ msgid "Filter search results to only show applications available on Flathub" #~ msgstr "يرشِّح نتائج البحث لتظهر التطبيقات المتوفرة على فلاتهَب حصرًا" #~ 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 "أبعاد النافذة التي ستستخدمها نافذة بازار التالية" #~ msgid "Nucleus app page" #~ msgstr "صفحة تطبيق «Nucleus»" #~ msgid "Manage Addons" #~ msgstr "أدِر الإضافات" #~ msgid "Of the size of human DNA" #~ msgstr "من حجم الحمض الريبي النووي منزوع الأكسجين للإنسان" #~ msgid "3 billion base pairs" #~ msgstr "3 مليارات زوج قاعدي" #~ msgid "Of the Linux Kernel" #~ msgstr "من نواة لينكس" #~ msgid "linux-6.17.tar.xz" #~ msgstr "linux-6.17.tar.xz" #~ msgid "Of the Apollo 11 guidance computer" #~ msgstr "من حاسوب توجيه أبولو 11" #~ msgid "Total ROM and RAM" #~ msgstr "إجمالي ذاكرة القراءة والذاكرة العشوائية" #~ msgid "Of the original Super Mario Bros" #~ msgstr "من لعبة «سوبر ماريو بروز» الأصلية" #~ msgid "Of the size of Wikipedia" #~ msgstr "من حجم ويكيبيديا" #~ msgid "Without any media" #~ msgstr "دون أي وسائط" #~ msgid "" #~ "This functionality is currently disabled. It is recommended you download " #~ "and install Flatseal to manage app permissions." #~ msgstr "" #~ "هذه الوظيفة معطَّلة حاليًا. ينصح بتنصيب «فلاتسيل» لإدارة أذونات التطبيق." #~ msgctxt "About Dialog Translator Credit" #~ msgid "Ahmed Najmawi" #~ msgstr "أحمد النجماوي" #~ msgctxt "About Dialog Translator Credit" #~ msgid "AtomHare" #~ msgstr "AtomHare" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Azenyr" #~ msgstr "AtomHare" #~ 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" #~ msgid "Constructing Flatpak instance..." #~ msgstr "تُبنى نسخة فلاتباك..." #~ msgid "Reusing last Flatpak instance..." #~ msgstr "يعاد استخدام آخر نسخة فلاتباك..." #~ msgid "Flathub is not registered on this system" #~ msgstr "لم يُسجِّل فلاتهَب على هذا النظام" #~ 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 "" #~ "أتود إضافة فلاتهَب كمستودع؟ لن تتوفر صفحة فلاتهَب إن رفضت ذلك. يمكنك تغيير " #~ "ذلك لاحقًا." #~ msgid "Add Flathub" #~ msgstr "أضِف فلاتهَب" #, 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 "" #~ "لم يُزوَّد بازار بإعدادات محتوى منتقى. تواصل مع قنوات دعم نظام تشغيلك للحصول " #~ "على المساعدة." #~ msgid "Entry Inspector" #~ msgstr "فاحص المدخلات" #~ msgid "Serialize" #~ msgstr "سَلسِل" #~ msgid "Convert to JSON" #~ msgstr "حوِّل إلى JSON" #~ msgid "Graphics" #~ msgstr "رسوميات" #~ msgid "Office" #~ msgstr "مكتب" #~ msgctxt "Project URL Type" #~ msgid "Homepage" #~ msgstr "الصفحة الرئيسة" #~ msgid "This flatpak is verified by the original developers of the software." #~ msgstr "وثَّق مطوروا البرمجية فلاتباك هذا." #~ msgid "Repository Star Count" #~ 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 "%B %-d, %Y" #~ msgstr "%-Od %B، %OY" #~ msgid "%B %-d" #~ msgstr "%-Od %B" #~ msgid "Bazaar Inspector" #~ msgstr "متعقب «بازار»" #~ msgid "Active Blocklists" #~ msgstr "قوائم الحجب النشطة" #~ msgid "Active Curated-Configs" #~ msgstr "ضبط التطبيقات «المنتقاة» النشط" #~ msgid "All Entry Groups" #~ msgstr "جميع مجموعات المدخلات" #~ msgid "Filter..." #~ msgstr "رشِّح..." #~ msgid "Decache and Inspect" #~ msgstr "امحُ الاختزان وافحص" #~ msgid "No Flatpaks Installed" #~ msgstr "لا حزم فلاتباك منصَّبة" #~ msgid "Run this application" #~ msgstr "شغِّل هذا التطبيق" #~ msgid "Run" #~ msgstr "شغِّل" #~ msgid "Application Details" #~ msgstr "تفاصيل التطبيق" #~ msgid "Git Forge Star Counts" #~ msgstr "نجوم مستودع جِت" #~ msgid "Not having a GitHub access token may trigger rate limits" #~ msgstr "قد يُحدّ وصولك إن لم يكن لديك رمز وصول جِت‌هَب" #~ msgid "Show Only Flathub Apps" #~ msgstr "إظهار تطبيقات فلاتهَب حصرًا" #~ msgid "Wait for a brief pause to reduce system load" #~ msgstr "ينتظر وهلة لتخفيف حِمل النظام عند البحث" #~ msgid "Theme" #~ msgstr "السمة" #~ msgid "Pride Rainbow Flag" #~ msgstr "علم فخر قوس قزح" #~ msgid "Bisexual Flag" #~ msgstr "علم ازدواج التوجه الجنسي" #~ msgid "Asexual Flag" #~ msgstr "علم اللاجنسية" #~ msgid "Share" #~ msgstr "شارِك" #, c-format #~ msgid "Transferred %s so far" #~ msgstr "نُقِل %s حتى الآن" #~ 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 من بيئات التشغيل و\\أو الإضافات. أتنصبها؟" #~ msgid "Transactions" #~ msgstr "العمليات" #~ msgid "Toggle transaction sidebar" #~ msgstr "بدِّل الشريط الجانبي للعمليات" #~ msgid "Stop Active Tasks" #~ msgstr "أوقف المهام النشطة" #~ msgid "Clear History" #~ msgstr "امحُ التأريخ" #~ msgid "No Tasks Yet" #~ msgstr "لا توجد مهام حتى الآن" #~ msgid "Browse" #~ msgstr "تصفَّح" #~ msgid "App View" #~ msgstr "منظور التطبيق" #~ msgid "Go Back" #~ msgstr "ارجِع" #~ msgid "View curated applications" #~ msgstr "اعرِض التطبيقات المنتقاة" #~ msgid "View the latest on Flathub" #~ msgstr "اعرِض آخر المستجدات على فلاتهَب" #~ msgid "_Quit Service" #~ msgstr "أ_نهِ الخدمة" #~ msgid "Up to date!" #~ 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 "Settings & user data will be kept" #~ msgstr "ستبقى الإعدادات وبيانات المستخدم مخزَّنة" #~ msgid "Resume Current Tasks" #~ msgstr "استأنف المهام الحالية" #~ msgid "Pause Current Tasks" #~ msgstr "ألبث المهام الحالية" #, c-format #~ msgid "%s: %'u downloads" #~ msgstr "%s: %'u تنزيل" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "أعِد التحميل" #~ msgctxt "shortcut window" #~ msgid "Toggle Transaction Manager" #~ 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 "Download Statistics" #~ 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 "Apps Of The Week" #~ 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 "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 "Installing" #~ 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 "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 "Main Bazaar window showing Blender" #~ msgstr "نافذة بازار الرئيسية تعرض تطبيق بلندر" #~ msgid "Match using regular expressions" #~ msgstr "طابِق باستخدام التعابير النمطية" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "أخفِ الترشيح والفرز خلف تأثير التلاشي المتداخل" bazaar-org-bazaar-43ce9f7/po/be.po000066400000000000000000003061371520414637400170070ustar00rootroot00000000000000# Belarusian 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. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-01 06:45+0100\n" "PO-Revision-Date: 2026-03-01 21:34+0100\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: be\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.8\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:110 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:699 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 "Exhibit app page" msgstr "Дэманстрацыйная старонка праграмы" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Library page" msgstr "Старонка бібліятэкі" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Search page" msgstr "Старонка пошуку" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:70 msgid "Category page" msgstr "Старонка катэгорыі" #: src/bz-addons-dialog.blp:16 src/bz-full-view.blp:606 src/bz-installed-tile.blp:101 msgid "Manage Add-Ons" msgstr "Кіраваць дадаткамі" #: src/bz-addons-dialog.c:94 src/bz-install-controls.blp:78 src/bz-install-controls.blp:128 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:159 src/bz-install-controls.blp:34 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:333 #: src/bz-full-view.c:340 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:323 #, 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\" прыдатна для дзяцей школьнага ўзросту (6+)" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "\"%s\" прыдатна для дзяцей школьнага ўзросту (12+)" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "\"%s\" прыдатна для дзяцей старэйшага ўзросту (16+)" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "\"%s\" прыдатна для дарослых (18+)" #: 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:29 src/bz-user-data-page.blp:15 src/bz-window.blp:285 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:374 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:381 msgid "_Refresh" 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:386 msgid "_Preferences" msgstr "_Параметры" #: src/bz-all-apps-page.blp:35 src/bz-apps-page.blp:35 src/bz-user-data-page.blp:36 src/bz-window.blp:391 msgid "_Login With Flathub" msgstr "_Увайсці праз Flathub" #: src/bz-all-apps-page.blp:41 src/bz-apps-page.blp:41 src/bz-user-data-page.blp:42 src/bz-window.blp:397 msgid "_Manage Leftover User Data" 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:402 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:407 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:414 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:125 msgid "Open user data folder" msgstr "Адкрыць папку даных карыстальніка" #: src/bz-app-size-dialog.blp:135 msgid "User Data Size" msgstr "Памер даных карыстальніка" #: src/bz-app-size-dialog.blp:136 msgid "Caches, settings, and other app data" msgstr "Кэш, налады і іншыя даныя праграм" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "Памер усталяванага асяроддзя выканання" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "Памер спрампаванага асяроддзя выканання" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 src/bz-rich-app-tile.blp:103 src/bz-rich-app-tile.c:275 msgid "Verified" msgstr "Спраўджана" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:89 src/bz-full-view.c:282 src/bz-releases-list.c:178 msgid "Installed" msgstr "Усталявана" #: src/bz-apps-page.blp:141 msgid "Show All" msgstr "Паказаць усё" #: src/bz-apps-page.c:229 #, c-format msgid "All \"%s\"" msgstr "Усё \"%s\"" #: src/bz-apps-page.c:498 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "Колькасць праграм: %d" #: src/bz-application.c:678 #, fuzzy msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:679 #, fuzzy 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:702 msgid "translator-credits" msgstr "Аляксандр Клюеў , 2026" #: src/bz-application.c:712 msgid "Special Thanks" msgstr "Асаблівая падзяка" #: src/bz-application.c:770 msgid "Logged Out Successfully!" msgstr "Выхад выкананы!" #: src/bz-application.c:893 msgid "Performing setup…" msgstr "Выконваецца наладжванне…" #: src/bz-application.c:977 msgid "Set Up System Flathub?" msgstr "Наладзіць Flathub на ўзроўні сістэмы?" #: src/bz-application.c:980 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be configured on the system Flatpak installation to browse " "and install applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Аддалены сервер Flathub не наладжаны для гэтай сістэмы. Для прагляду і ўсталёўвання праграм, Bazaar патрабуе канфігурацыі Flathub " "у сістэмнай ўсталёўцы Flatpak.\n" "\n" "Вы ўсё яшчэ зможаце выкарыстоўваць Bazaar для прагляду і выдалення ўжо ўсталяваных праграм." #: src/bz-application.c:987 msgid "Set Up Flathub?" msgstr "Наладзіць Flathub?" #: src/bz-application.c:990 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:996 msgid "Later" msgstr "Пазней" #: src/bz-application.c:997 msgid "Set Up Flathub" msgstr "Наладзіць Flathub" #: src/bz-application.c:1280 msgid "A backend error occurred" msgstr "Адбылася памылка на сервернай частцы" #: src/bz-application.c:1406 src/bz-application.c:3178 src/bz-window.blp:134 msgid "Refreshing…" msgstr "Ідзе абнаўленне…" #: src/bz-application.c:1552 src/bz-application.c:3176 #, c-format msgid "Loading %d apps…" msgstr "Ідзе загрузка праграм (%d)…" #: src/bz-application.c:1556 msgid "Checking for updates…" msgstr "Ідзе праверка абнаўленняў…" #: src/bz-application.c:1612 msgid "Failed to open .flatpakref" msgstr "Не ўдалося адкрыць .flatpakref" #: src/bz-application.c:1666 msgid "An initialization error occurred" msgstr "Адбылася памылка ініцыялізацыі" #: src/bz-application.c:2004 msgid "Failed to check for updates" msgstr "Не ўдалося праверыць абнаўленні" #: src/bz-application.c:2961 msgid "Could not find app" msgstr "Не ўдалося знайсці праграму" #: src/bz-application.c:3180 msgid "Writing to cache…" msgstr "Ідзе запіс у кэш…" #: src/bz-appstream-parser.c:304 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Старонка Flathub" #: src/bz-appstream-parser.c:325 msgctxt "Project URL Type" msgid "Project Website" msgstr "Вэб-сайт праекта" #: src/bz-appstream-parser.c:329 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Трэкер памылак" #: src/bz-appstream-parser.c:333 msgctxt "Project URL Type" msgid "FAQ" msgstr "Пытанні і адказы" #: src/bz-appstream-parser.c:337 msgctxt "Project URL Type" msgid "Help" msgstr "Даведка" #: src/bz-appstream-parser.c:341 msgctxt "Project URL Type" msgid "Donate" msgstr "Ахвяраваць" #: src/bz-appstream-parser.c:347 msgctxt "Project URL Type" msgid "Translate" msgstr "Перакласці" #: src/bz-appstream-parser.c:351 msgctxt "Project URL Type" msgid "Contact" msgstr "Звязацца" #: src/bz-appstream-parser.c:355 msgctxt "Project URL Type" msgid "Source Code" msgstr "Зыходны код" #: src/bz-appstream-parser.c:361 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:61 #: src/bz-library-page.blp:65 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 "Па-за сеткай" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 src/bz-search-pill-list.c:67 msgid "Browser" msgstr "Вэб-браўзер" #: src/bz-developer-badge.c:92 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "Не спраўджана" #: src/bz-developer-badge.c:145 msgid "Developer information not available." msgstr "Звесткі пра распрацоўшчыка недаступныя." #: src/bz-developer-badge.c:151 src/bz-developer-badge.c:165 #, 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:169 #, 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:175 #, c-format msgid "The ownership of the %1$s app ID has been verified by %2$s on %3$s." msgstr "Правы ўласнасці для ідэнтыфікатара праграмы \"%1$s\" былі спраўджаны %2$s %3$s." #: src/bz-developer-badge.c:182 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "Правы ўласнасці для ідэнтыфікатара праграмы \"%1$s\" былі спраўджаны з дапамогай %2$s." #: src/bz-developer-badge.c:186 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Правы ўласнасці для ідэнтыфікатара праграмы \"%s\" былі спраўджаны." #: src/bz-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "Поўныя нататкі да выпуску" #: src/bz-donations-dialog.blp:105 msgid "This release was made possible by users like you!" msgstr "Гэты выпуск Bazaar стаў магчымым дзякуючы такім людзям, як вы!" #: src/bz-donations-dialog.blp:113 msgid "I love making Bazaar, but I cannot do it alone. Help support further development by donating on Ko-Fi." msgstr "" "Мне падабаецца ствараць Bazaar, але я не магу рабіць гэта ўадзіночку. Падтрымайце развіццё праекта ў будучыні, пакінуўшы " "ахвяраванне на старонцы Ko-Fi." #: src/bz-donations-dialog.blp:128 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:227 #, c-format msgid "What's New in %s?" msgstr "Што новага ў версіі %s?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "Выпушчана %e %B %Y" #: 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:69 src/bz-error.c:88 src/bz-error-dialog.blp:36 src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Падрабязныя звесткі" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "Скапіяваць" #: src/bz-error-dialog.c:56 src/bz-share-list.c:64 msgid "Copied!" msgstr "Скапіявана!" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" 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:157 src/bz-rich-app-tile.blp:171 msgid "Uninstall" msgstr "Выдаліць" #: src/bz-favorites-tile.c:357 msgid "Failed to remove favorite" 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:432 msgid "Favorites" msgstr "Упадабаныя" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 src/bz-transaction-dialog.c:579 msgid "Install All" msgstr "Усталяваць усе" #: src/bz-favorites-page.blp:34 src/bz-full-view.blp:44 src/bz-window.blp:301 msgid "Open App Library" 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 "Мікшар" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:92 src/bz-search-pill-list.c:77 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:118 src/bz-flathub-page.blp:151 msgid "Trending" msgstr "У трэндзе" #: src/bz-flathub-category.c:130 msgid "More Trending" msgstr "Больш у трэндзе" #: src/bz-flathub-category.c:131 src/bz-flathub-page.blp:124 src/bz-flathub-page.blp:181 msgid "Popular" msgstr "Папулярныя" #: src/bz-flathub-category.c:131 msgid "More Popular" msgstr "Больш папулярных" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:171 msgid "Recently Added" msgstr "Нядаўна дададзеныя" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:130 msgid "New" msgstr "Новыя" #: src/bz-flathub-category.c:132 msgid "More New" msgstr "Больш новых" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:161 msgid "Recently Updated" msgstr "Нядаўна абноўленыя" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:136 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:261 msgid "On the Go" msgstr "На хаду" #: src/bz-flathub-page.blp:273 msgid "Apps for your Linux phones and tablets" msgstr "Праграмы для вашых тэлефонаў і планшэтаў на Linux" #: src/bz-flathub-page.blp:284 src/bz-flathub-page.blp:319 msgid "More Mobile Apps" msgstr "Больш мабільных праграм" #: src/bz-flathub-page.blp:377 msgid "We​ ♥​ Games" msgstr "Мы​ ♥​ гульні" #: src/bz-flathub-page.blp:390 msgid "Games and apps to run your favorite titles" msgstr "Гульні і праграмы для запуску вашых любімых гульняў" #: src/bz-flathub-page.blp:424 msgid "More Games" msgstr "Больш гульняў" #: src/bz-full-view.blp:65 src/bz-library-page.blp:76 src/bz-library-page.blp:80 msgid "No Results" msgstr "Нічога не знойдзена" #: src/bz-full-view.blp:66 msgid "Try a different search query" msgstr "Паспрабуйце іншы запыт" #: src/bz-full-view.blp:72 msgid "Content" msgstr "Змесціва" #: src/bz-full-view.blp:130 msgid "Installing .flatpak bundles is not yet supported" msgstr "Усталяванне .flatpak-набораў яшчэ не падтрымліваецца" #: src/bz-full-view.blp:234 msgid "Support" msgstr "Падтрымаць" #: src/bz-full-view.blp:404 msgid "Downloads/Month" msgstr "Спампоўванняў у месяц" #: src/bz-full-view.blp:440 msgid "Stopped Receiving Core Updates" msgstr "Атрыманне абнаўленняў ядра спынена" #: src/bz-full-view.blp:454 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:541 msgid "Trash Data" msgstr "Смеццевыя даныя" #: src/bz-full-view.blp:682 msgid "Tags:" msgstr "Цэтлікі:" #: src/bz-full-view.c:215 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:222 #, c-format msgid "%.*fM" msgstr "%.*f млн." #. Translators: K is the suffix for thousands #: src/bz-full-view.c:229 #, c-format msgid "%.*fK" msgstr "%.*f тыс." #: src/bz-full-view.c:239 #, c-format msgid "%d downloads in the last 30 days" msgstr "Спампоўванняў за апошнія 30 дзён: %d" #: src/bz-full-view.c:251 src/bz-full-view.c:592 src/bz-full-view.c:609 msgid "N/A" msgstr "N/A" #: src/bz-full-view.c:279 #, c-format msgid "+%s runtime" msgstr "+%s асяроддзе выканання" #: src/bz-full-view.c:282 msgid "Download" msgstr "Спампаваць" #: src/bz-full-view.c:302 msgid "Size information unavailable" msgstr "Інфармацыя пра памер недаступна" #: src/bz-full-view.c:305 #, c-format msgid "Download size of %s" msgstr "Памер спампоўвання для %s" #: src/bz-full-view.c:338 msgid "All Ages" msgstr "Для ўсіх узростаў" #: src/bz-full-view.c:350 msgid "Age rating information unavailable" msgstr "Інфармацыя пра ўзроставы рэйтынг недаступна" #: src/bz-full-view.c:355 msgid "Suitable for all ages" msgstr "Пасуе для ўсіх узростаў" #: src/bz-full-view.c:357 #, c-format msgid "Suitable for ages %d and up" msgstr "Пасуе для ўсіх узростаў ад %d гадоў" #: src/bz-full-view.c:390 src/bz-full-view.c:395 src/bz-full-view.c:423 src/bz-full-view.c:434 msgid "Unknown" msgstr "Невядомы" #: src/bz-full-view.c:400 #, c-format msgid "Free software licensed under %s" msgstr "Свабоднае ПЗ пад ліцэнзіяй %s" #: src/bz-full-view.c:405 msgid "Free software" msgstr "Свабоднае ПЗ" #: src/bz-full-view.c:408 msgid "Proprietary Software" msgstr "Прапрыетарнае ПЗ" #: src/bz-full-view.c:411 #, c-format msgid "Special License: %s" msgstr "Спецыяльная ліцэнзія: %s" #: src/bz-full-view.c:428 msgid "Free" msgstr "Вольная" #: src/bz-full-view.c:431 src/bz-license-dialog.c:132 msgid "Proprietary" msgstr "Прапрыетарная" #: src/bz-full-view.c:436 src/bz-license-dialog.c:134 msgid "Special License" msgstr "Спецыяльная ліцэнзія" #: src/bz-full-view.c:456 msgid "Adaptive" msgstr "Адаптыўная" #: src/bz-full-view.c:456 msgid "Desktop Only" msgstr "Толькі для настольных камп’ютараў" #: src/bz-full-view.c:462 msgid "Works on desktop, tablets, and phones" msgstr "Працуе на настольных камп’ютарах, планшэтах і тэлефонах" #: src/bz-full-view.c:463 msgid "May not work on mobile devices" msgstr "Можа не працаваць на мабільных прыладах" #: src/bz-full-view.c:474 msgid "No URL" msgstr "Няма URL-адраса" #: src/bz-full-view.c:492 msgid "This application has a FLOSS license, meaning the source code can be audited for safety." msgstr "" "Гэта праграма мае FLOSS-ліцэнзію (свабоднае ПЗ з адкрытым зыходным кодам). Гэта азначае, што магчымы аўдыт бяспекі для зыходнага " "кода праграмы." #: src/bz-full-view.c:493 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:500 msgid "More Apps" msgstr "Больш праграм" #: src/bz-full-view.c:501 #, c-format msgid "More Apps by %s" msgstr "Боль праграм ад %s" #: src/bz-full-view.c:508 msgid "Other Apps by this Developer" msgstr "Іншыя праграмы ад гэтага распрацоўшчыка" #: src/bz-full-view.c:510 src/bz-full-view.c:700 #, c-format msgid "Other Apps by %s" msgstr "Іншыя праграмы ад %s" #: src/bz-full-view.c:519 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "Праграма \"%s\" не ўсталявана, але на прыладзе ўсё яшчэ застаецца %s звязаных з ёю даных." #: src/bz-full-view.c:599 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Бяспечная" #: src/bz-full-view.c:601 src/bz-full-view.c:603 msgid "Low Risk" msgstr "Нізкая рызыка" #: src/bz-full-view.c:605 msgid "Medium Risk" msgstr "Сярэдняя рызыка" #: src/bz-full-view.c:607 msgid "High Risk" msgstr "Высокая рызыка" #: src/bz-full-view.c:702 msgid "Other Apps" msgstr "Іншыя праграмы" #: src/bz-full-view.c:704 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d праграма" msgstr[1] "%d праграмы" msgstr[2] "%d праграм" #: src/bz-full-view.c:931 src/bz-transaction-tile.c:340 msgid "Failed to launch application" msgstr "Не ўдалося запусціць праграму" #: src/bz-full-view.c:996 msgid "Show Less" msgstr "Паказаць менш" #: src/bz-full-view.c:996 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-install-controls.blp:32 msgid "Download & Install Application" msgstr "Спампаваць і ўсталяваць праграму" #: src/bz-install-controls.blp:54 msgid "Open" msgstr "Адкрыць" #: src/bz-install-controls.blp:68 src/bz-install-controls.blp:118 msgid "Uninstall Application" msgstr "Выдаліць праграму" #: src/bz-install-controls.blp:105 src/bz-updates-card.blp:161 src/bz-updates-card.blp:186 msgid "Update" msgstr "Абнавіць" #: src/bz-install-controls.blp:155 msgid "Install Other Version" msgstr "Усталяваць іншую версію" #: src/bz-installed-tile.blp:63 src/bz-rich-app-tile.blp:139 msgid "Stopped Receiving Updates" msgstr "Спынена атрыманне абнаўленняў" #: src/bz-library-page.blp:31 msgid "Search installed apps" msgstr "Пошук усталяваных праграм" #: src/bz-library-page.blp:48 msgid "Clear search" msgstr "Ачысціць пошук" #: src/bz-library-page.blp:69 msgid "No Apps Found" msgstr "Праграм не знойдзена" #. Translators: . #: src/bz-library-page.blp:98 src/bz-window.blp:176 msgid "Library" msgstr "Бібліятэка" #: src/bz-library-page.blp:126 msgid "Pending Updates" msgstr "Абнаўленні ў чаканні" #: src/bz-library-page.blp:153 msgid "Downloads" msgstr "Спампоўкі" #: src/bz-library-page.blp:196 msgid "Recently Uninstalled" msgstr "Нядаўна выдаленае" #: src/bz-library-page.blp:247 msgid "Clear Finished Tasks" msgstr "Ачысціць завершаныя задачы" #: src/bz-library-page.blp:258 msgid "Installed Apps" msgstr "Усталяваныя праграмы" #: src/bz-library-page.c:175 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "У спісе ўсталяваных праграм нічога не знойдзена для запыту \"%s\"" #: src/bz-library-page.c:188 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:664 #, 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 refresh is paused" msgstr "Падключэнне да сеткі з падлікам трафіка — аўтаматычная сінхранізацыя даных крамы прыпынена" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:328 msgid "Refresh 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:191 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 "Гісторыя версій" #. 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-releases-list.c:121 msgid "%e %B" msgstr "%e %B" #. 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-releases-list.c:129 msgid "%e %B %Y" msgstr "%e %B %Y" #: 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:156 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: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:104 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:112 msgid "Open Screenshot Viewer" msgstr "Адкрыць прагляд здымкаў экрана" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "Відэа" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "Офіс" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "Каляндар" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "Паведамленні" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Steam" msgstr "Steam" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "Paint" msgstr "Маляванне" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Torrent" msgstr "Torrent" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:122 msgid "Minecraft" msgstr "Minecraft" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:127 msgid "Emulator" msgstr "Эмулятар" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "Пошук праграм і гульняў" #: src/bz-search-widget.blp:79 msgid "Clear Search" msgstr "Ачысціць пошук" #: src/bz-search-widget.blp:167 msgid "Categories Unavailable" msgstr "Катэгорыі не даступныя" #: src/bz-search-widget.blp:168 msgid "Search for apps using the search bar above." msgstr "Шукайце праграмы, выкарыстоўваючы панэль зверху." #: src/bz-search-widget.blp:193 msgid "Browse Categories" msgstr "Агляд катэгорый" #: src/bz-search-widget.blp:316 msgid "No Applications Found" msgstr "Праграм не знойдзена" #: src/bz-search-widget.c:243 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Для запыту \"%s\" на Flathub нічога не знайшлося" #: 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 User Data" msgstr "Пакінуць даныя карыстальніка" #: src/bz-transaction-dialog.c:156 msgid "Allow restoring personal settings & content" msgstr "Дазволіць аднаўляць персанальныя налады і змесціва" #: src/bz-transaction-dialog.c:165 msgid "Delete All Data" msgstr "Выдаліць усе даныя" #: src/bz-transaction-dialog.c:166 msgid "Permanently erase user 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:331 msgid "Failed to load transaction dialog" 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 праграму?" 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:766 #, c-format msgid "Finished in %.02f seconds" msgstr "Завершана за %.02f сек" #: src/bz-transaction-tile.blp:126 msgid "App Add-On" msgstr "Дадатак да праграмы" #: src/bz-transaction-tile.blp:155 msgid "Runtime" msgstr "Асяроддзе выканання" #: src/bz-transaction-tile.blp:179 msgid "In Queue" msgstr "У чарзе" #: src/bz-transaction-tile.blp:203 msgid "Done" msgstr "Зроблена" #: src/bz-transaction-tile.blp:227 msgid "Error" msgstr "Памылка" #: src/bz-transaction-tile.blp:271 msgid "Open App" msgstr "Адкрыць праграму" #: src/bz-transaction-tile.blp:285 msgid "Cancel Transaction" msgstr "Скасаваць трансакцыю" #: src/bz-transaction-tile.blp:409 msgid "Show Error Info" msgstr "Паказаць звесткі пра памылку" #: src/bz-transaction-tile.c:112 #, c-format msgid "%s Freed" msgstr "Вызвалена месца: %s" #: src/bz-transaction-tile.c:398 src/bz-transaction-tile.c:401 msgid "Transaction Error" msgstr "Памылка трансакцыі" #: src/bz-transaction.c:342 msgid "Pending" msgstr "У чаканні" #: src/bz-updates-card.blp:36 msgid "Update All" 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:152 msgid "Curated" msgstr "Падабраныя" #: src/bz-window.blp:164 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:266 msgid "Refresh completed!" msgstr "Абнаўленне скончана!" #: src/bz-window.blp:319 msgid "You are running a new version of Bazaar!" msgstr "Вы запусцілі новую версію Bazaar!" #: src/bz-window.blp:320 msgid "See What's New" msgstr "Паглядзець, што новага" #: src/bz-window.blp:327 msgid "You have a network connection but are viewing a cached version of Flathub" msgstr "У вас ёсць злучэнне з сеткай, але вы праглядаеце версію Flathub у кэшы" #: src/bz-window.blp:439 msgid "Log Out" msgstr "Выйсці" #: src/bz-window.c:473 msgid "Failed to load add-ons" msgstr "Не ўдалося загрузіць дадаткі" #: src/bz-window.c:763 msgid "You can't remove Bazaar from Bazaar!" msgstr "Вы не можаце выдаліць Bazaar, карыстаючыся Bazaar!" #: src/bz-window.c:1055 src/bz-window.c:1089 msgid "Can't do that right now!" msgstr "У гэты момант дзеянне немагчымае!" #: src/bz-world-map.c:587 msgctxt "As in, \"100 Downloads\"" msgid "Downloads" msgstr "Спампоўкі" #: src/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Асноўнае" #: src/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Refresh" msgstr "Абнавіць" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Адкрыць параметры" #: src/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Адкрыць дыялог пошуку" #: src/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Open Library" msgstr "Адкрыць бібліятэку" #: src/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Паказаць спалучэнні клавіш" #: src/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Close Window" msgstr "Закрыць акно" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "Выйсці з Bazaar" #~ msgid "_Synchronize Remotes" #~ msgstr "Сін_хранізацыя з аддаленымі серверамі" #~ msgid "Synchronizing..." #~ msgstr "Ідзе сінхранізацыя..." #, c-format #~ msgid "Receiving %d entries..." #~ msgstr "Ідзе атрыманне запісаў (%d)..." #~ msgid "Indexing Data..." #~ msgstr "Ідзе індэксаванне даных..." #~ msgid "View the Release Page" #~ msgstr "Праглядзець старонку выпуску" #~ msgid "Close" #~ msgstr "Закрыць" #~ msgid "Copy and Close" #~ msgstr "Скапіяваць і закрыць" #~ msgid "Keep Data" #~ msgstr "Пакінуць даныя" #~ msgid "Refreshing Store Content" #~ msgstr "Ідзе абнаўленне змесціва крамы" #~ msgid "No background tasks!" #~ msgstr "Няма фонавых задач!" #~ msgctxt "shortcut window" #~ msgid "Synchronize Remotes" #~ msgstr "Сінхранізацыя з аддаленымі серверамі" #~ msgctxt "shortcut window" #~ msgid "Quit" #~ msgstr "Выйсці" bazaar-org-bazaar-43ce9f7/po/bg.po000066400000000000000000001102611520414637400170000ustar00rootroot00000000000000# 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" bazaar-org-bazaar-43ce9f7/po/bs.po000066400000000000000000000347111520414637400170210ustar00rootroot00000000000000# 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" bazaar-org-bazaar-43ce9f7/po/cs.po000066400000000000000000002765371520414637400170400ustar00rootroot00000000000000# 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. # Vlastimil Dědek , 2025. # Pavel Borecki , 2026. # Daniel Rusek , 2026. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-05-19 21:49+0200\n" "PO-Revision-Date: 2026-05-20 00:16+0200\n" "Last-Translator: Daniel Rusek \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" "X-Generator: Poedit 3.9\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:45 #: src/bz-window.blp:199 src/bz-window.c:373 src/bz-window.c:374 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "" "Přidávejte, odstraňujte nebo aktualizujte software z flatpaků 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.desktop.in:16 msgid "New Window" msgstr "Nové okno" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and manage applications" msgstr "Objevujte a spravujte aplikace" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "Rychlý a moderní obchod s aplikacemi pro Linux se zaměřením na objevování a " "instalaci aplikací a doplňků Flatpaku, zejména z Flathubu." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "Zařaďte více instalací do fronty a pokračujte v prohlížení" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "Jednoduše si zobrazte oprávnění aplikací" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "" "Přihlaste se pomocí Flathubu pro zobrazení a správu oblíbených aplikací" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "Vyhledávejte aplikace přímo z GNOME Shellu" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:30 src/bz-application.c:759 msgid "The Bazaar Contributors" msgstr "Přispěvatelé aplikace Bazaar" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "The home page displaying Flathub apps" msgstr "Domovská stránka zobrazující aplikace Flathubu" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:59 msgid "Exhibit app page" msgstr "Stránka aplikace Exhibit" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "Stránka knihovny" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "Stránka hledání" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "Stránka kategorií" #: src/bz-addon-tile.blp:64 src/bz-installed-tile.blp:55 #: src/bz-rich-app-tile.blp:141 msgid "Stopped Receiving Updates" msgstr "Příjem aktualizací zastaven" #: src/bz-addon-tile.c:167 src/bz-favorites-tile.c:155 msgctxt "Install Controls" msgid "Uninstall" msgstr "Odinstalovat" #: src/bz-addon-tile.c:169 src/bz-bundle-install-dialog.blp:126 #: src/bz-favorites-tile.c:157 src/bz-install-controls.wdgt:29 msgctxt "Install Controls" msgid "Install" msgstr "Instalovat" #: src/bz-addons-dialog.blp:14 src/bz-addons-dialog.blp:21 #: src/bz-addons-dialog.blp:70 src/bz-full-view.blp:583 #: src/bz-installed-tile.blp:92 msgid "Manage Add-Ons" msgstr "Spravovat doplňky" #: src/bz-addons-dialog.blp:80 msgid "No Add-Ons Visible" msgstr "Žádné viditelné doplňky" #: src/bz-addons-dialog.blp:81 msgid "" "Your current filter preferences are hiding all known add-ons. Try adjusting " "them." msgstr "" "Vaše aktuální nastavení filtrů skrývají všechny známé doplňky. Zkuste je " "upravit." #: src/bz-addons-dialog.blp:88 msgid "Add-on Page" msgstr "Stránka doplňků" #: src/bz-addons-dialog.blp:202 src/bz-full-view.blp:381 msgid "Downloads/Month" msgstr "Stažení/měsíc" #: src/bz-addons-dialog.blp:229 src/bz-full-view.blp:417 msgid "Stopped Receiving Core Updates" msgstr "Příjem základních aktualizací zastaven" #: src/bz-addons-dialog.blp:243 msgid "" "This add-on uses a runtime that no longer receives updates or security " "fixes. It may become unsafe to use." msgstr "" "Tento doplněk používá běhové prostředí, které již nedostává aktualizace ani " "opravy zabezpečení. Jeho používání nemusí být bezpečné." #: src/bz-addons-dialog.c:333 #, c-format msgid "Add-on for %s" msgstr "Doplněk pro %s" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show Less" msgstr "Zobrazit méně" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show More" msgstr "Zobrazit více" #: src/bz-addons-dialog.c:397 msgid "Download Stats" msgstr "Statistiky stahování" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:736 src/bz-context-tile-callbacks.c:186 #: src/bz-context-tile-callbacks.c:193 msgid "Age Rating" msgstr "Vhodné od věku" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Kreslené násilí" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Bez informací o kresleném násilí" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Násilí ve fantasy" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Bez informací o násilí ve fantasy" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Realistické násilí" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Bez informací o realistickém násilí" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Násilí zobrazující krvácení" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Bez informací o krvácení" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Sexuální násilí" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Bez informací o sexuálním násilí" #. 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 "Bez informací o odkazech na alkohol" #. 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 "Bez informací o odkazech na nezákonné drogy" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Tabák" #. 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 "Bez informací o odkazech na tabákové produkty" #. 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 "Nahota" #. 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 "Bez informací o nahotě jakéhokoliv typu" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Sexuální tématika" #. 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 "Bez informací o odkazech na nebo vyobrazení sexuální tématiky" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Vulgarismy" #. 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 "Bez informací o vulgaritách jakéhokoliv typu" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Nepřiměřený 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 "Bez informací o nepřiměřeném humoru" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Diskriminace" #. 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 "Bez informací o diskriminačních projevech jakéhokoliv typu" #. 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 "Bez informací o reklamách jakéhokoliv typu" #. 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 "Bez informací o hazardu jakéhokoliv typu" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Nakupování" #. 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 "Bez informací o možnosti utrácet peníze" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Konverzace mezi uživateli" #. 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 "Bez informací o způsobech konverzace mezi uživateli" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Hlasová konverzace mezi uživateli" #. 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 "Bez informací o způsobech hlasové komunikace mezi uživateli" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Kontaktní údaje" #. 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 "" "Bez informací o sdílení uživatelských jmen ze sociálních sítí nebo e-" "mailových adres" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Identifikační údaje" #. 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 "Bez informací o sdílení údajů o uživatelích se třetími stranami" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Sdílení polohy" #. 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 "Bez informací o sdílení fyzické polohy s ostatními uživateli" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Prostituce" #. 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 "Bez informací o odkazech na prostituci" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Cizoložství" #. 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 "Bez informací o odkazech na cizoložství" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Sexualizované postavy" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Bez informací o sexualizovaných postavách" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "Znesvěcení" #. 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 "Bez informací o odkazech na znesvěcení" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Lidské ostatky" #. 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 "Bez informací o viditelných ostatcích mrtvých lidí" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "Otroctví" #. 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 "Bez informací o odkazech na otroctví" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Neobsahuje odkazy na drogy" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "Neobsahuje nadávky, vulgarity ani jiné hrubé výrazy" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Neobsahuje reklamy ani peněžní operace" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Neobsahuje sex a nahotu" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "Neobsahuje funkci neusměrňované konverzace" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Neobsahuje násilí" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Drogy" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Hrubé výrazy" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Peníze" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Sociální sítě" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Násilí" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:686 src/bz-context-tile-callbacks.c:176 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "Vše" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "Aplikace %s má neznámé věkové hodnocení" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "Aplikace %s je vhodná pro každého" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "Aplikace %s je vhodná pro malé děti" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "Aplikace %s je vhodná pro děti" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "Aplikace %s je vhodná pro dospívající mládež" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "Aplikace %s je vhodná pro dospělé" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "Aplikace %s je vhodná pro %s" #: src/bz-age-rating-dialog.c:862 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Systémová složka %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Podsložka %s v domovské složce" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Složky hostitelského systému" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Konfigurace hostitelského systému z /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Podsložka %s ve složce plochy" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Složka plochy" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Podsložka %s ve složce dokumentů" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Složka dokumentů" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Podsložka %s ve složce hudby" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Složka hudby" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Podsložka %s ve složce obrázků" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Složka obrázků" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Podsložka %s ve složce veřejně sdílených" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Složka veřejně sdílených" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Podsložka %s ve složce videí" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Složka videí" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Podsložka %s ve složce šablon" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Složka šablon" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Podsložka %s ve složce uživatelské mezipaměti" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Složka uživatelské mezipaměti" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Podsložka %s ve složce uživatelské konfigurace" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Složka uživatelské konfigurace" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Podsložka %s ve složce uživatelských dat" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Složka uživatelských dat" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Podsložka %s v uživatelské složce pro běh aplikací" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Uživatelská složka pro běh aplikací" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Přístup k souborovému systému v %s" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Neznámá cesta souborového systému" #: src/bz-app-size-dialog.blp:26 src/bz-app-size-dialog.blp:60 msgid "Download Size" msgstr "Stahovaná velikost" #: src/bz-app-size-dialog.blp:33 src/bz-app-size-dialog.blp:81 msgid "Installed Size" msgstr "Instalovaná velikost" #: src/bz-app-size-dialog.blp:61 msgid "Amount to download from the internet" msgstr "Velikost ke stažení z internetu" #: src/bz-app-size-dialog.blp:82 msgid "Size on Disk" msgstr "Velikost na disku" #: src/bz-app-size-dialog.blp:133 msgid "Open user data folder" msgstr "Otevřít složku uživatelských dat" #: src/bz-app-size-dialog.blp:143 msgid "Your User Data" msgstr "Vaše uživatelská data" #: src/bz-app-size-dialog.blp:144 msgid "Caches, settings, and other app data" msgstr "Mezipaměti, nastavení a další data aplikací" #: src/bz-app-size-dialog.blp:165 msgid "Cache" msgstr "Mezipaměť" #: src/bz-app-size-dialog.blp:166 msgid "Temporary cached data" msgstr "Dočasná data v mezipaměti" #: src/bz-app-size-dialog.blp:176 msgid "Clear Cache" msgstr "Vymazat mezipaměť" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "Instalovaná velikost prostředí" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "Stahovaná velikost prostředí" #: src/bz-app-size-dialog.c:220 msgid "App Size" msgstr "Velikost aplikace" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:105 src/bz-rich-app-tile.c:429 msgid "Verified" msgstr "Ověřeno" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-context-tile-callbacks.c:135 #: src/bz-releases-list.c:206 msgid "Installed" msgstr "Nainstalováno" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:762 msgid "translator-credits" msgstr "" "Vlastimil Dědek , 2025\n" "Pavel Borecki , 2026\n" "Daniel Rusek , 2026" #: src/bz-application.c:772 msgid "Special Thanks" msgstr "Zvláštní poděkování patří" #: src/bz-application.c:830 msgid "Logged Out Successfully!" msgstr "Úspěšně odhlášeni!" #: src/bz-application.c:966 msgid "Performing setup…" msgstr "Provádí se nastavení…" #: src/bz-application.c:1052 msgid "Set Up System Flathub?" msgstr "Nastavit systémový Flathub?" #: src/bz-application.c:1055 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Systémový repozitář Flathub není nastaven. Bazaar vyžaduje, aby byl Flathub " "nastaven na systémové Flatpak instalaci pro procházení a instalaci " "aplikací.\n" "\n" "Bazaar můžete i nadále používat k procházení a odstraňování již " "nainstalovaných aplikací." #: src/bz-application.c:1062 msgid "Set Up Flathub?" msgstr "Nastavit Flathub?" #: src/bz-application.c:1065 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í v tomto systému nastaven. Pokud není k dispozici, nebudete moci " "procházet a instalovat aplikace v Bazaaru.\n" "\n" "Bazaar můžete i nadále používat k procházení a odstraňování již " "nainstalovaných aplikací." #: src/bz-application.c:1071 msgid "Later" msgstr "Později" #: src/bz-application.c:1072 msgid "Set Up Flathub" msgstr "Nastavit Flathub" #: src/bz-application.c:1408 msgid "A backend error occurred" msgstr "Došlo k chybě backendu" #: src/bz-application.c:1608 src/bz-application.c:3765 msgid "Refreshing…" msgstr "Obnovuje se…" #: src/bz-application.c:1772 src/bz-application.c:3763 #, c-format msgid "Loading %d apps…" msgstr "Načítá se %d aplikací…" #: src/bz-application.c:1825 msgid "Failed to open file" msgstr "Nezdařilo se otevřít soubor" #: src/bz-application.c:1930 msgid "An initialization error occurred" msgstr "Došlo k chybě inicializace" #: src/bz-application.c:2296 msgid "Checking for updates…" msgstr "Kontrolují se aktualizace…" #: src/bz-application.c:2352 msgid "Failed to check for updates" msgstr "Nezdařilo se zkontrolovat aktualizace" #: src/bz-application.c:3477 msgid "Malformed Link" msgstr "Špatně formátovaný odkaz" #: src/bz-application.c:3478 msgid "" "The link used to open this app has incorrect capitalisation and may stop " "working in the future.\n" "\n" "This is most likely caused by KRunner sending incorrect app IDs" msgstr "" "Odkaz použitý k otevření této aplikace má nesprávné velké písmeno a v " "budoucnu může přestat fungovat.\n" "\n" "To je pravděpodobně způsobeno tím, že KRunner odesílá nesprávná ID aplikací" #: src/bz-application.c:3485 msgid "Could not find app" msgstr "Nezdařilo se najít aplikaci" #: src/bz-application.c:3516 msgid "Failed to load metainfo" msgstr "Nezdařilo se načíst metainfo" #: src/bz-application.c:3767 msgid "Writing to cache…" msgstr "Zapisuje se do mezipaměti…" #: src/bz-apps-page.blp:99 msgid "Show All" msgstr "Zobrazit vše" #: src/bz-apps-page.c:237 #, c-format msgid "All \"%s\"" msgstr "Všechny „%s“" #: src/bz-apps-page.c:487 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "%d aplikací" #: src/bz-bundle-install-dialog.blp:8 src/bz-bundle-install-dialog.blp:14 msgid "Bundle Installation" msgstr "Instalace balíčku" #: src/bz-bundle-install-dialog.blp:147 msgid "Additional dependencies may take extra space" msgstr "Dodatečné závislosti mohou zabírat další místo" #: src/bz-bundle-install-dialog.blp:181 msgid "" "Installing this app may require adding a new software source. Other apps " "from this source will show up in Bazaar.\n" "\n" "Only add this source if you're sure you trust it." msgstr "" "Instalace této aplikace může vyžadovat přidání nového zdroje softwaru. " "Ostatní aplikace z tohoto zdroje se zobrazí v Bazaaru.\n" "\n" "Tento zdroj přidejte, pouze pokud jste si jisti, že mu důvěřujete." #: src/bz-bundle-install-dialog.blp:357 msgid "Successfully Installed!" msgstr "Úspěšně nainstalováno!" #: src/bz-bundle-install-dialog.blp:381 src/bz-bundle-install-dialog.blp:463 #: src/bz-rich-app-tile.blp:198 src/bz-transaction-tile.blp:298 msgid "Open" msgstr "Otevřít" #: src/bz-bundle-install-dialog.blp:391 src/bz-bundle-install-dialog.blp:473 msgid "Show App Details" msgstr "Zobrazit podrobnosti o aplikaci" #: src/bz-bundle-install-dialog.blp:440 msgid "Already Installed" msgstr "Již nainstalováno" #: src/bz-bundle-install-dialog.blp:485 msgid "Installation Failed" msgstr "Instalace se nezdařila" #: src/bz-bundle-install-dialog.c:169 msgid "Unknown install size" msgstr "Neznámá velikost instalace" #: src/bz-bundle-install-dialog.c:172 #, c-format msgid "About %s to install" msgstr "Přibližně %s k instalaci" #: src/bz-bundle-install-dialog.c:186 src/bz-context-tile-callbacks.c:104 #: src/bz-context-tile-callbacks.c:392 src/bz-context-tile-callbacks.c:409 msgid "N/A" msgstr "N/A" #: src/bz-bundle-install-dialog.c:215 msgid "No special permissions" msgstr "Žádná zvláštní oprávnění" #: src/bz-context-tile-callbacks.c:68 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-context-tile-callbacks.c:75 #, c-format msgid "%.*fM" msgstr "%.*f mil." #. Translators: K is the suffix for thousands #: src/bz-context-tile-callbacks.c:82 #, c-format msgid "%.*fK" msgstr "%.*f tis." #: src/bz-context-tile-callbacks.c:92 #, c-format msgid "%d downloads in the last month" msgstr "%d stažení za poslední měsíc" #: src/bz-context-tile-callbacks.c:132 #, c-format msgid "+%s runtime" msgstr "+ prostředí %s" #: src/bz-context-tile-callbacks.c:135 msgid "Download" msgstr "Stáhnout" #: src/bz-context-tile-callbacks.c:155 msgid "Size information unavailable" msgstr "Informace o velikosti nejsou k dispozici" #: src/bz-context-tile-callbacks.c:158 #, c-format msgid "Download size of %s" msgstr "Stahovaná velikost %s" #: src/bz-context-tile-callbacks.c:191 msgid "All Ages" msgstr "Libovolný věk" #: src/bz-context-tile-callbacks.c:203 msgid "Age rating information unavailable" msgstr "Hodnocení věku není k dispozici" #: src/bz-context-tile-callbacks.c:208 msgid "Suitable for all ages" msgstr "Vhodné pro všechny věkové skupiny" #: src/bz-context-tile-callbacks.c:210 #, c-format msgid "Suitable for ages %d and up" msgstr "Vhodné pro věk %d a více" #: src/bz-context-tile-callbacks.c:243 src/bz-context-tile-callbacks.c:248 #: src/bz-context-tile-callbacks.c:276 src/bz-context-tile-callbacks.c:284 msgid "Unknown" msgstr "Neznámé" #: src/bz-context-tile-callbacks.c:253 #, c-format msgid "Free software licensed under %s" msgstr "Svobodný software licencovaný pod %s" #: src/bz-context-tile-callbacks.c:258 msgid "Free software" msgstr "Svobodný software" #: src/bz-context-tile-callbacks.c:261 msgid "Proprietary Software" msgstr "Uzavřený software" #: src/bz-context-tile-callbacks.c:264 #, c-format msgid "Special License: %s" msgstr "Zvláštní licence: %s" #: src/bz-context-tile-callbacks.c:281 msgid "Free" msgstr "Svobodné" #: src/bz-context-tile-callbacks.c:287 src/bz-license-dialog.c:133 msgid "Proprietary" msgstr "Uzavřené" #: src/bz-context-tile-callbacks.c:289 src/bz-license-dialog.c:135 msgid "Special License" msgstr "Zvláštní licence" #: src/bz-context-tile-callbacks.c:309 msgid "Adaptive" msgstr "Adaptivní" #: src/bz-context-tile-callbacks.c:309 msgid "Desktop Only" msgstr "Pouze pro PC" #: src/bz-context-tile-callbacks.c:315 msgid "Works on desktop, tablets, and phones" msgstr "Funguje na PC, tabletech a telefonech" #: src/bz-context-tile-callbacks.c:316 msgid "May not work on mobile devices" msgstr "Možná nefunguje na mobilních zařízeních" #: src/bz-context-tile-callbacks.c:399 src/bz-safety-dialog.blp:27 msgid "Safe" msgstr "Bezpečné" #: src/bz-context-tile-callbacks.c:401 src/bz-context-tile-callbacks.c:403 msgid "Low Risk" msgstr "Nízké riziko" #: src/bz-context-tile-callbacks.c:405 msgid "Medium Risk" msgstr "Střední riziko" #: src/bz-context-tile-callbacks.c:407 msgid "High Risk" msgstr "Vysoké riziko" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:46 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:30 #: src/bz-library-page.blp:67 src/bz-user-data-page.blp:30 msgid "Empty" msgstr "Prázdné" #: src/bz-curated-view.blp:15 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 "" "V tomto systému nejsou k dispozici žádné informace o vybraných aplikacích. " "Aplikace si stále můžete prohlížet na Flathubu" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Procházet 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 "Off-line" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "Prohlížeč" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "Neověřeno" #: src/bz-developer-badge.c:213 msgid "Developer information not available." msgstr "Informace o vývojáři nejsou k dispozici." #: src/bz-developer-badge.c:219 src/bz-developer-badge.c:233 #, 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 nebylo ověřeno a může se jednat o komunitní " "balíček." #: src/bz-developer-badge.c:237 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "Vlastnictví ID aplikace %s bylo ručně ověřeno týmem Flathubu." #: src/bz-developer-badge.c:253 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "Vlastnictví ID aplikace %1$s bylo ověřeno uživatelem %2$s na %3$s." #: src/bz-developer-badge.c:260 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "Vlastnictví ID aplikace %1$s bylo ověřeno pomocí %2$s." #: src/bz-developer-badge.c:264 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Vlastnictví ID aplikace %s bylo ověřeno." #: src/bz-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "Úplné poznámky k vydání" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "Toto vydání bylo možné díky uživatelům, jako jste vy!" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on Ko-Fi." msgstr "" "Miluji vytváření Bazaaru, ale nedokážu to sám. Pomozte podpořit další vývoj " "darováním na Ko-Fi." #: src/bz-donations-dialog.blp:131 msgid "Donate to Bazaar" msgstr "Podpořit Bazaar" #. Translators: the %s format specifier will be something along the lines of "0.7.6" etc #: src/bz-donations-dialog.c:227 #, c-format msgid "What's New in %s?" msgstr "Co je nového ve verzi %s?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "Vydáno %-e. %B %Y" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Vyberte instalaci" #: 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 "" "Máte nainstalováno několik verzí této aplikace. S kterou chcete pokračovat?" #: src/bz-entry-group-util.c:80 src/bz-rich-app-tile.blp:232 msgid "Cancel" msgstr "Zrušit" #: src/bz-entry-selection-row.blp:17 msgid "For This User Only" msgstr "Pouze pro tohoto uživatele" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "tento uživatel" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "všichni uživatelé" #: src/bz-error-dialog.blp:36 src/bz-error.c:69 src/bz-error.c:88 #: src/bz-safety-dialog.blp:46 msgid "Details" msgstr "Podrobnosti" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "Kopírovat" #: src/bz-error-dialog.c:56 src/bz-share-list.c:94 msgid "Copied!" msgstr "Zkopírováno!" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Počet oblíbených" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" msgstr "Aktualizace oblíbených se nezdařila" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Přihlaste 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-favorites-page.blp:5 src/bz-favorites-page.blp:56 #: src/bz-window.blp:334 msgid "Favorites" msgstr "Oblíbené" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "Instalovat vše" #: src/bz-favorites-page.blp:34 src/bz-user-data-page.blp:19 msgid "Loading" msgstr "Načítání" #: src/bz-favorites-page.blp:49 msgid "No Favorites" msgstr "Žádné oblíbené aplikace" #: src/bz-favorites-page.blp:50 msgid "Applications you mark as favorite will appear here" msgstr "Aplikace, které označíte jako oblíbené, se zobrazí zde" #: src/bz-favorites-tile.blp:60 src/bz-installed-tile.blp:69 msgid "Support This Application" msgstr "Podpořit tuto aplikaci" #: src/bz-favorites-tile.blp:109 msgid "Remove From Favorites" msgstr "Odebrat z oblíbených" #: src/bz-favorites-tile.c:353 msgid "Failed to remove favorite" msgstr "Odebrání z oblíbených se nezdařilo" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Předchozí" #: src/bz-featured-carousel.blp:54 msgid "Next" msgstr "Další" #: src/bz-flathub-category.c:93 msgid "Editing" msgstr "Úprava" #: src/bz-flathub-category.c:94 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:95 msgid "Mixer" msgstr "Mixer" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:96 src/bz-search-pill-list.c:77 msgid "Music" msgstr "Hudba" #: src/bz-flathub-category.c:97 msgid "Player" msgstr "Přehrávač" #: src/bz-flathub-category.c:98 msgid "Recorder" msgstr "Záznamník" #: src/bz-flathub-category.c:99 msgid "Sequencer" msgstr "Sekvencer" #: src/bz-flathub-category.c:100 msgid "Tuner" msgstr "Tuner" #: src/bz-flathub-category.c:101 msgid "TV" msgstr "TV" #: src/bz-flathub-category.c:106 msgid "Emulation" msgstr "Emulace" #: src/bz-flathub-category.c:107 msgid "Action" msgstr "Akční" #: src/bz-flathub-category.c:108 msgid "Adventure" msgstr "Adventury" #: src/bz-flathub-category.c:109 msgid "Arcade" msgstr "Arkádové" #: src/bz-flathub-category.c:110 msgid "Blocks" msgstr "Blokové" #: src/bz-flathub-category.c:111 msgid "Board" msgstr "Deskové" #: src/bz-flathub-category.c:112 msgid "Card" msgstr "Karetní" #: src/bz-flathub-category.c:113 msgid "Kids" msgstr "Dětské" #: src/bz-flathub-category.c:114 msgid "Logic" msgstr "Logické" #: src/bz-flathub-category.c:115 msgid "Role Playing" msgstr "Na hrdiny" #: src/bz-flathub-category.c:116 msgid "Shooter" msgstr "Střílečky" #: src/bz-flathub-category.c:117 msgid "Simulation" msgstr "Simulace" #: src/bz-flathub-category.c:118 msgid "Sports" msgstr "Sporty" #: src/bz-flathub-category.c:119 msgid "Strategy" msgstr "Strategické" #: src/bz-flathub-category.c:124 msgid "Audio & Video" msgstr "Audio a video" #: src/bz-flathub-category.c:124 msgid "Media" msgstr "Multimédia" #: src/bz-flathub-category.c:124 msgid "More Audio & Video" msgstr "Více z Audio a video" #: src/bz-flathub-category.c:125 msgid "Developer Tools" msgstr "Vývojářské nástroje" #: src/bz-flathub-category.c:125 msgid "Develop" msgstr "Vývoj" #: src/bz-flathub-category.c:125 msgid "More Developer Tools" msgstr "Více z Vývojářské nástroje" #: src/bz-flathub-category.c:126 msgid "Education" msgstr "Vzdělávání" #: src/bz-flathub-category.c:126 msgid "Learn" msgstr "Učení" #: src/bz-flathub-category.c:126 msgid "More Education" msgstr "Více z Vzdělávání" #: src/bz-flathub-category.c:127 msgid "Gaming" msgstr "Hraní her" #: src/bz-flathub-category.c:127 msgid "Play" msgstr "Hraní" #: src/bz-flathub-category.c:127 msgid "More Gaming" msgstr "Více z Hraní her" #: src/bz-flathub-category.c:128 msgid "Graphics & Photography" msgstr "Grafika a fotografie" #: src/bz-flathub-category.c:128 msgid "Create" msgstr "Vytváření" #: src/bz-flathub-category.c:128 msgid "More Graphics & Photography" msgstr "Více z Grafika a fotografie" #: src/bz-flathub-category.c:129 msgid "Networking" msgstr "Síť" #: src/bz-flathub-category.c:129 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:129 msgid "More Networking" msgstr "Více z Síť" #: src/bz-flathub-category.c:130 msgid "Productivity" msgstr "Produktivita" #: src/bz-flathub-category.c:130 msgid "Work" msgstr "Práce" #: src/bz-flathub-category.c:130 msgid "More Productivity" msgstr "Více z Produktivita" #: src/bz-flathub-category.c:131 msgid "Science" msgstr "Věda" #: src/bz-flathub-category.c:131 msgid "More Science" msgstr "Více z Věda" #: src/bz-flathub-category.c:132 msgid "System" msgstr "Systém" #: src/bz-flathub-category.c:132 msgid "More System" msgstr "Více z Systém" #: src/bz-flathub-category.c:133 msgid "Utilities" msgstr "Utility" #: src/bz-flathub-category.c:133 msgid "Tools" msgstr "Nástroje" #: src/bz-flathub-category.c:133 msgid "More Utilities" msgstr "Více z Utility" #: src/bz-flathub-category.c:134 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:148 msgid "Trending" msgstr "Trendy" #: src/bz-flathub-category.c:134 msgid "More Trending" msgstr "Více z Trendů" #: src/bz-flathub-category.c:135 src/bz-flathub-page.blp:122 #: src/bz-flathub-page.blp:178 msgid "Popular" msgstr "Populární" #: src/bz-flathub-category.c:135 msgid "More Popular" msgstr "Více z Populárních" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:168 msgid "Recently Added" msgstr "Nedávno přidané" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:128 msgid "New" msgstr "Nové" #: src/bz-flathub-category.c:136 msgid "More New" msgstr "Více z Nových" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:158 msgid "Recently Updated" msgstr "Nedávno aktualizované" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:134 msgid "Updated" msgstr "Aktualizované" #: src/bz-flathub-category.c:137 msgid "More Updated" msgstr "Více z Aktualizovaných" #: src/bz-flathub-category.c:138 msgid "Mobile" msgstr "Mobilní" #: src/bz-flathub-category.c:138 msgid "More Mobile" msgstr "Více z Mobilních" #: src/bz-flathub-category.c:139 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:139 msgid "More Adwaita" msgstr "Více z Adwaita" #: src/bz-flathub-category.c:140 msgid "KDE Apps" msgstr "KDE aplikace" #: src/bz-flathub-category.c:140 msgid "More KDE Apps" msgstr "Více z KDE aplikací" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub nebyl přidán" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "Repozitář Flathubu nebyl nalezen v žádné z vašich instalací Flatpaku" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub vrátil chybu" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Znovu zkusit připojení k Flathubu" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub není k dispozici" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Nepodařilo se nám připojit k Flathubu. Stále však můžete spravovat a " "vyhledávat aplikace." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Hledat aplikace" #: src/bz-flathub-page.blp:205 msgid "App of the Day" msgstr "Aplikace dne" #: src/bz-flathub-page.blp:268 msgid "On the Go" msgstr "Na cestách" #: src/bz-flathub-page.blp:280 msgid "Apps for your Linux phones and tablets" msgstr "Aplikace pro vaše linuxové telefony a tablety" #: src/bz-flathub-page.blp:291 src/bz-flathub-page.blp:326 msgid "More Mobile Apps" msgstr "Více z Mobilních aplikací" #: src/bz-flathub-page.blp:382 msgid "We​ ♥​ Games" msgstr "Máme ♥​ hry" #: src/bz-flathub-page.blp:395 msgid "Games and apps to run your favorite titles" msgstr "Hry a aplikace pro spuštění vašich oblíbených titulů" #: src/bz-flathub-page.blp:429 msgid "More Games" msgstr "Více z Her" #: src/bz-full-view.blp:34 src/bz-library-page.blp:78 #: src/bz-library-page.blp:82 msgid "No Results" msgstr "Žádné výsledky" #: src/bz-full-view.blp:35 msgid "Try a different search query" msgstr "Zkuste jiný dotaz" #: src/bz-full-view.blp:41 msgid "Content" msgstr "Obsah" #: src/bz-full-view.blp:103 msgid "" "This is a local preview, some details may differ from the published listing" msgstr "" "Toto je místní náhled, některé podrobnosti se mohou lišit od zveřejněné verze" #: src/bz-full-view.blp:106 msgid "Preview Store Appearance" msgstr "Náhled vzhledu obchodu" #: src/bz-full-view.blp:232 msgid "_Support" msgstr "_Podpořit" #: src/bz-full-view.blp:431 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á běhové prostředí, které již nedostává aktualizace ani " "opravy zabezpečení. Její používání nemusí být bezpečné." #: src/bz-full-view.blp:518 msgid "Trash Data" msgstr "Vymazat data" #: src/bz-full-view.blp:658 msgid "Tags:" msgstr "Štítky:" #: src/bz-full-view.c:180 msgid "No URL" msgstr "Žádná adresa URL" #: src/bz-full-view.c:198 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Tato aplikace má licenci FLOSS. To znamená, že její zdrojový kód může být " "ověřen pro bezpečnost." #: src/bz-full-view.c:199 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 její zdrojový kód je " "vyvíjen v soukromí a nemůže být ověřen třetí stranou." #: src/bz-full-view.c:206 msgid "More Apps" msgstr "Více aplikací" #: src/bz-full-view.c:207 #, c-format msgid "More Apps by %s" msgstr "Více aplikací od %s" #: src/bz-full-view.c:214 msgid "Other Apps by this Developer" msgstr "Další aplikace od tohoto vývojáře" #: src/bz-full-view.c:216 src/bz-full-view.c:316 #, c-format msgid "Other Apps by %s" msgstr "Další aplikace od %s" #: src/bz-full-view.c:225 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" "Aplikace %s není nainstalována, ale má stále k dispozici %s dat." #: src/bz-full-view.c:318 msgid "Other Apps" msgstr "Další aplikace" #: src/bz-full-view.c:320 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d aplikace" msgstr[1] "%d aplikace" msgstr[2] "%d aplikací" #: src/bz-full-view.c:536 src/bz-user-data-tile.c:144 msgid "Failed to Remove User Data" msgstr "Nezdařilo se odstranit uživatelská data" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Podpora hardwaru" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Podpora klávesnice" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Vyžaduje klávesnice" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Doporučuje klávesnice" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Podporuje klávesnice" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Neznámá podpora klávesnic" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Podpora myši" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Vyžaduje myši nebo ukazovátka" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Doporučuje myši nebo ukazovátka" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Podporuje myši nebo ukazovátka" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Neznámá podpora myší nebo ukazovátek" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Podpora dotykových obrazovek" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Vyžaduje dotykové obrazovky" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Doporučuje dotykové obrazovky" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Podporuje dotykové obrazovky" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Neznámá podpora dotykových obrazovek" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Podpora pro mobilní zařízení" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Funguje na mobilních zařízeních" #: src/bz-hardware-support-dialog.c:161 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:166 msgid "Desktop support" msgstr "Podpora pro PC" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Funguje dobře na velkých obrazovkách" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "Aplikace %s funguje nejlépe na konkrétním hardware" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "Aplikace %s funguje na většině zařízení" #: src/bz-install-controls.blp:62 msgid "_Open" msgstr "_Otevřít" #: src/bz-install-controls.blp:77 src/bz-install-controls.blp:134 msgid "Uninstall Application" msgstr "Odinstalovat aplikaci" #: src/bz-install-controls.blp:87 src/bz-transaction-dialog.c:230 msgid "_Remove" msgstr "Odeb_rat" #: src/bz-install-controls.blp:121 src/bz-updates-card.c:164 #: src/bz-updates-card.c:183 msgid "Update" msgstr "Aktualizovat" #: src/bz-install-controls.blp:144 src/bz-installed-tile.blp:105 msgid "Remove" msgstr "Odebrat" #: src/bz-install-controls.wdgt:32 msgctxt "Install Controls" msgid "Cancel" msgstr "Zrušit" #: src/bz-install-controls.wdgt:35 msgctxt "Install Controls" msgid "Cancelling" msgstr "Ruší se" #: src/bz-library-page.blp:32 msgid "Search installed apps" msgstr "hledat nainstalované aplikace" #: src/bz-library-page.blp:50 msgid "Clear search" msgstr "Vymazat hledání" #: src/bz-library-page.blp:71 msgid "No Apps Found" msgstr "Nenalezeny žádné aplikace" #: src/bz-library-page.blp:90 msgid "Search Store Instead" msgstr "Hledat v obchodě" #. Translators: . #: src/bz-library-page.blp:100 src/bz-window.blp:112 msgid "Library" msgstr "Knihovna" #: src/bz-library-page.blp:128 msgid "Pending Updates" msgstr "Čekající aktualizace" #: src/bz-library-page.blp:155 msgid "Downloads" msgstr "Stažení" #: src/bz-library-page.blp:198 msgid "Recently Uninstalled" msgstr "Nedávno odinstalované" #: src/bz-library-page.blp:249 msgid "Clear Finished Tasks" msgstr "Vymazat dokončené úlohy" #: src/bz-library-page.blp:334 msgid "Sort By" msgstr "Řadit podle" #: src/bz-library-page.blp:348 msgid "Name" msgstr "Název" #: src/bz-library-page.blp:354 msgid "Size" msgstr "Velikost" #: src/bz-library-page.c:180 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "Žádné shody pro výraz „%s“ v seznamu nainstalovaných aplikací" #: src/bz-library-page.c:193 src/bz-updates-card.c:433 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u dostupná aktualizace" msgstr[1] "%u dostupné aktualizace" msgstr[2] "%u dostupných aktualizací" #: src/bz-library-page.c:203 #, c-format msgid "%u Installed App" msgid_plural "%u Installed Apps" msgstr[0] "%u nainstalovaná aplikace" msgstr[1] "%u nainstalované aplikace" msgstr[2] "%u nainstalovaných aplikací" #: src/bz-license-dialog.blp:94 msgid "Get Involved" msgstr "Zapojit se" #: src/bz-license-dialog.blp:111 msgid "Learn More" msgstr "Zjistit více" #: src/bz-license-dialog.c:127 msgid "Unknown License" msgstr "Neznámá licence" #: src/bz-license-dialog.c:130 msgid "Community Built" msgstr "Vybudováno komunitou" #: src/bz-license-dialog.c:203 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Tato aplikace je otevřeně vyvíjena mezinárodní komunitou.\n" "\n" "Můžete se zapojit a pomoci ji ještě vylepšit." #: src/bz-license-dialog.c:206 msgid "The license of this app is not known" msgstr "Licence této aplikace není známa" #: src/bz-license-dialog.c:212 #, 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 "" "Tato aplikace je otevřeně vyvíjena mezinárodní komunitou a je uvolněna pod " "licencí %s.\n" "\n" "Můžete se zapojit a pomoci ji ještě vylepšit." #: src/bz-license-dialog.c:220 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 "" "Tato aplikace není vyvíjena otevřeně, takže o jejím fungování vědí pouze " "její vývojáři. Může být nezabezpečena způsobem, který je těžké odhalit, a " "může se měnit, aniž byste o tom věděli.\n" "\n" "Můžete nebo nemusíte být schopni do této aplikace přispívat." #: src/bz-license-dialog.c:226 #, 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 "" "Tato aplikace je vyvíjena pod zvláštní licencí %s.\n" "\n" "Můžete nebo nemusíte být schopni do této aplikace přispívat." #: src/bz-license-dialog.c:356 src/bz-safety-dialog.blp:49 msgid "License" msgstr "Licence" #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Připojit se k Flathubu" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Něco se pokazilo" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" "Propojte svůj účet Flathub s Bazaarem pro správu svých oblíbených aplikací." #: src/bz-login-page.blp:110 msgid "Finish" msgstr "Dokončit" #: src/bz-login-page.c:664 #, c-format msgid "Hello, %s!" msgstr "Ahoj, %s!" #: src/bz-metainfo-preview.c:84 msgid "Select Metainfo File" msgstr "Vyberte soubor metainfo" #: src/bz-metainfo-preview.c:87 msgid "Metainfo Files" msgstr "Soubory metainfo" #: src/bz-metainfo-preview.c:141 msgid "Select Icon (Optional)" msgstr "Vyberte ikonu (volitelné)" #: src/bz-metainfo-preview.c:144 msgid "Image Files" msgstr "Soubory obrázků" #: src/bz-metainfo-preview.c:231 msgid "Preview" msgstr "Náhled" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Předvolby" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data refresh is paused" msgstr "" "Připojení k síti je měřené – automatické obnovení dat obchodu je pozastaveno" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:232 msgid "Refresh Manually" msgstr "Obnovit ručně" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Filtry obsahu" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Pouze svobodný software" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "Skrýt uzavřené aplikace z výsledků vyhledávání" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Pouze výsledky z Flathubu" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Omezit výsledky vyhledávání a procházení pouze na aplikace dostupné na " "Flathubu" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "Pouze ověřené výsledky" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Skrýt výsledky, které nejsou ověřeny na Flathubu" #: src/bz-preferences-dialog.blp:49 msgid "Hide End-of-Life Apps" msgstr "Skrýt zastaralé aplikace" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "Skrýt aplikace, které již nejsou podporované jejich vývojáři" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:127 msgid "Search" msgstr "Vyhledávání" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Zpozdit výsledky vyhledávání" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "Vylepšit výsledky vyhledávání pomocí odstraňování rušivých dotazů" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "Ukazatel postupu" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "Vyberte téma pro ukazatel postupu!" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "Svislé pruhy" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from left to right" msgstr "Zobrazit barvy vlajky zleva doprava" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Barevný odstín" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Barvy hrdosti" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Barvy lesbické hrdosti" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "Barvy mužské homosexuální hrdosti" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Barvy transgender hrdosti" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Barvy nebinární hrdosti" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "Barvy bisexuální hrdosti" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "Barvy asexuální hrdosti" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Barvy pansexuální hrdosti" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Barvy aromatické hrdosti" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Barvy genderfluidní hrdosti" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Barvy polysexuální hrdosti" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Barvy omnisexuální hrdosti" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "Barvy aroace hrdosti" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "Barvy agenderové hrdosti" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "Barvy genderqueer hrdosti" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "Barvy intersexuální hrdosti" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "Barvy demigenderové hrdosti" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "Barvy biromantické hrdosti" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "Barvy hrdosti invalidů" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "Barvy hrdosti femboyů" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "Barvy neutrois hrdosti" #: src/bz-releases-dialog.blp:5 src/bz-updates-card.c:155 msgid "Version History" msgstr "Historie verzí" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "Historie _verzí" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "dnes" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "včera" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "před %d dnem" msgstr[1] "před %d dny" msgstr[2] "před %d dny" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "před %d týdnem" msgstr[1] "před %d týdny" msgstr[2] "před %d týdny" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "před %d měsícem" msgstr[1] "před %d měsíci" msgstr[2] "před %d měsíci" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "před %d rokem" msgstr[1] "před %d roky" msgstr[2] "před %d lety" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%e. %B %Y" #: src/bz-releases-list.c:196 #, c-format msgid "Version %s" msgstr "Verze %s" #: src/bz-releases-list.c:251 msgid "No details for this release" msgstr "Žádné informace o této verzi" #: src/bz-releases-list.c:263 msgid "Get More Information" msgstr "Získat více informací" #: src/bz-rich-app-tile.blp:217 msgid "Uninstall" msgstr "Odinstalovat" #. Translators: If you can't find a short enough translation, use "/" to use an icon instead. #: src/bz-rich-app-tile.c:369 msgid "Get" msgstr "Získat" #: src/bz-safety-calculator.c:87 msgid "Unknown Permissions" msgstr "Neznámá oprávnění" #: src/bz-safety-calculator.c:88 msgid "Permissions are missing for this app." msgstr "Pro tuto aplikaci chybí oprávnění." #: src/bz-safety-calculator.c:101 msgid "No Permissions" msgstr "Žádná oprávnění" #: src/bz-safety-calculator.c:102 msgid "App is fully sandboxed" msgstr "Aplikace je v plně izolovaném prostředí" #: src/bz-safety-calculator.c:108 msgid "Network Access" msgstr "Přístup k síti" #: src/bz-safety-calculator.c:109 msgid "Can access the internet" msgstr "Může přistupovat k internetu" #: src/bz-safety-calculator.c:111 msgid "No Network Access" msgstr "Žádný přístup k síti" #: src/bz-safety-calculator.c:112 msgid "Cannot access the internet" msgstr "Nemůže přistupovat k internetu" #: src/bz-safety-calculator.c:117 msgid "User Device Access" msgstr "Přístup k uživatelským zařízením" #: src/bz-safety-calculator.c:118 msgid "Can access devices such as webcams or gaming controllers" msgstr "Může přistupovat k zařízením jako jsou webkamery nebo herní ovladače" #: src/bz-safety-calculator.c:120 msgid "No User Device Access" msgstr "Žádný přístup k uživatelským zařízením" #: src/bz-safety-calculator.c:121 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "Nemůže přistupovat k zařízením jako jsou webkamery nebo herní ovladače" #: src/bz-safety-calculator.c:126 msgid "Input Device Access" msgstr "Přístup ke vstupním zařízením" #: src/bz-safety-calculator.c:127 msgid "Can access input devices" msgstr "Může přistupovat ke vstupním zařízením" #: src/bz-safety-calculator.c:133 msgid "Microphone Access and Audio Playback" msgstr "Přístup k mikrofonu a přehrávání zvuku" #: src/bz-safety-calculator.c:134 msgid "Can listen using microphones and play audio without asking permission" msgstr "" "Může poslouchat pomocí mikrofonů a přehrávat zvuk bez žádosti o povolení" #: src/bz-safety-calculator.c:140 msgid "System Device Access" msgstr "Přístup k systémovým zařízením" #: src/bz-safety-calculator.c:141 msgid "Can access system devices which require elevated permissions" msgstr "" "Může přistupovat k systémovým zařízením, která vyžadují zvýšená oprávnění" #: src/bz-safety-calculator.c:147 msgid "Screen Contents Access" msgstr "Přístup k obsahu obrazovky" #: src/bz-safety-calculator.c:148 msgid "Can access the contents of the screen or other windows" msgstr "Může přistupovat k obsahu obrazovky nebo jiných oken" #: src/bz-safety-calculator.c:154 msgid "Legacy Windowing System" msgstr "Zastaralý zobrazovací systém" #: src/bz-safety-calculator.c:155 msgid "Always uses a legacy windowing system (X11)" msgstr "Vždy používá starý zobrazovací systém (X11)" #: src/bz-safety-calculator.c:161 msgid "Arbitrary Permissions" msgstr "Libovolná oprávnění" #: src/bz-safety-calculator.c:162 msgid "Can acquire arbitrary permissions" msgstr "Může získat libovolná oprávnění" #: src/bz-safety-calculator.c:168 msgid "User Settings" msgstr "Nastavení uživatele" #: src/bz-safety-calculator.c:169 msgid "Can access and change user settings" msgstr "Může zobrazovat a měnit uživatelská nastavení" #: src/bz-safety-calculator.c:175 msgid "Full File System Read/Write Access" msgstr "Plný přístup k souborovému systému pro čtení/zápis" #: src/bz-safety-calculator.c:176 msgid "Can read and write all data on the file system" msgstr "Může číst a zapisovat všechna data v souborovém systému" #: src/bz-safety-calculator.c:183 msgid "Home Folder Read/Write Access" msgstr "Přístup k domovské složce pro čtení/zápis" #: src/bz-safety-calculator.c:184 msgid "Can read and write all data in your home directory" msgstr "Může číst a zapisovat všechna data ve vaší domovské složce" #: src/bz-safety-calculator.c:191 msgid "Full File System Read Access" msgstr "Plný přístup k souborovému systému pro čtení" #: src/bz-safety-calculator.c:192 msgid "Can read all data on the file system" msgstr "Může číst všechna data v souborovém systému" #: src/bz-safety-calculator.c:200 msgid "Home Folder Read Access" msgstr "Přístup k domovské složce pro čtení" #: src/bz-safety-calculator.c:201 msgid "Can read all data in your home directory" msgstr "Může číst všechna data ve vaší domovské složce" #: src/bz-safety-calculator.c:209 msgid "Download Folder Read/Write Access" msgstr "Přístup ke složce se staženými soubory pro čtení/zápis" #: src/bz-safety-calculator.c:210 msgid "Can read and write all data in your downloads directory" msgstr "Může číst a zapisovat všechna data ve vaší složce se staženými soubory" #: src/bz-safety-calculator.c:220 msgid "Download Folder Read Access" msgstr "Přístup ke složce se staženými soubory pro čtení" #: src/bz-safety-calculator.c:221 msgid "Can read all data in your downloads directory" msgstr "Může číst všechna data ve vaší složce se staženými soubory" #: src/bz-safety-calculator.c:242 msgid "Can read and write all data in the directory" msgstr "Může číst a zapisovat všechna data ve složce" #: src/bz-safety-calculator.c:266 msgid "Can read all data in the directory" msgstr "Může číst všechna data ve složce" #: src/bz-safety-calculator.c:281 msgid "No File System Access" msgstr "Žádný přístup k souborovému systému" #: src/bz-safety-calculator.c:282 msgid "Cannot access the file system at all" msgstr "Vůbec nemůže přistupovat k souborovému systému" #: src/bz-safety-calculator.c:289 msgid "Uses System Services" msgstr "Využívá služby systému" #: src/bz-safety-calculator.c:290 msgid "Can request data from non-portal system services" msgstr "Může si vyžádat data ze služeb systému mimo portál" #: src/bz-safety-calculator.c:296 msgid "Uses Session Services" msgstr "Využívá služby sezení" #: src/bz-safety-calculator.c:297 msgid "Can request data from non-portal session services" msgstr "Může si vyžádat data ze služeb sezení mimo portál" #: src/bz-safety-calculator.c:345 msgid "No Service Access" msgstr "Žádný přístup ke službám" #: src/bz-safety-calculator.c:346 msgid "Cannot access non-portal session or system services at all" msgstr "Nemůže přistupovat ke službám sezení nebo systému mimo portál" #: src/bz-safety-calculator.c:354 msgid "Verified App Developer" msgstr "Ověřený vývojář aplikace" #: src/bz-safety-calculator.c:355 msgid "The developer of this app has been verified to be who they say they are" msgstr "Vývojář této aplikace byl ověřen jako ten, za koho se vydává" #: src/bz-safety-calculator.c:364 msgid "Proprietary Code" msgstr "Uzavřený kód" #: src/bz-safety-calculator.c:365 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "Zdrojový kód není veřejný, takže jej nelze nezávisle zkontrolovat a nemusí " "být bezpečný" #: src/bz-safety-calculator.c:375 msgid "Auditable Code" msgstr "Otevřený kód" #: src/bz-safety-calculator.c:376 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "Zdrojový kód je veřejný a může být nezávisle kontrolován, což zvyšuje " "pravděpodobnost, že je aplikace bezpečná" #: src/bz-safety-calculator.c:516 #, c-format msgid "Use the %s System Service" msgstr "Použít službu systému %s" #: src/bz-safety-calculator.c:520 #, c-format msgid "Use the %s Session Service" msgstr "Použít službu sezení %s" #: src/bz-safety-calculator.c:524 #, c-format msgid "Use the %s Service" msgstr "Použít službu %s" #: src/bz-safety-calculator.c:534 msgid "Can see the non-portal service" msgstr "Může vidět službu mimo portál" #: src/bz-safety-calculator.c:536 msgid "Can talk to the non-portal service" msgstr "Může komunikovat se službou mimo portál" #: src/bz-safety-calculator.c:538 msgid "Can own the non-portal service" msgstr "Může vlastnit službu mimo portál" #: src/bz-safety-calculator.c:553 msgid "Global Menu Integration" msgstr "Integrace globální nabídky" #: src/bz-safety-calculator.c:554 msgid "Can display its menus in a global menu bar" msgstr "Může zobrazit své nabídky v globálním panelu nabídek" #: src/bz-safety-calculator.c:559 msgid "KDE Settings Integration" msgstr "Integrace nastavení KDE" #: src/bz-safety-calculator.c:560 msgid "Can detect when KDE desktop settings change" msgstr "Může detekovat změnu nastavení plochy KDE" #: src/bz-safety-calculator.c:565 msgid "KDE Global Settings" msgstr "Globální nastavení KDE" #: src/bz-safety-calculator.c:566 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "Může číst nastavení plochy KDE, jako jsou písma a barvy" #: src/bz-safety-calculator.c:571 msgid "Secret Storage Service" msgstr "Úložiště služby utajení" #: src/bz-safety-calculator.c:572 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "Může ukládat a načítat vlastní hesla pomocí systémové klíčenky" #: src/bz-safety-calculator.c:577 msgid "Desktop Notifications Service" msgstr "Služba upozornění plochy" #: src/bz-safety-calculator.c:578 msgid "Can send desktop notifications" msgstr "Může zasílat upozornění plochy" #: src/bz-safety-calculator.c:584 msgid "System Tray Integration" msgstr "Integrace do oznamovací oblasti systému" #: src/bz-safety-calculator.c:585 msgid "Can display an icon in the system tray" msgstr "Může zobrazit ikonu v systémové oznamovací oblasti" #: src/bz-safety-calculator.c:590 msgid "KDE Connect Integration" msgstr "Integrace KDE Connect" #: src/bz-safety-calculator.c:591 msgid "Can interact with devices paired via KDE Connect" msgstr "Může komunikovat se zařízeními spárovanými přes KDE Connect" #: src/bz-safety-dialog.blp:59 msgid "App ID" msgstr "ID aplikace" #: src/bz-safety-dialog.blp:69 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 "" "Tato aplikace používá zastaralou verzi softwarové platformy (SDK) a může " "obsahovat chyby nebo slabá místa zabezpečení, která nebudou opravena." #: src/bz-safety-dialog.c:167 msgid "Safety" msgstr "Bezpečnost" #: src/bz-safety-dialog.c:226 #, c-format msgid "%s is Safe" msgstr "Aplikace %s je bezpečná" #: src/bz-safety-dialog.c:231 #, c-format msgid "%s has no Unsafe Permissions" msgstr "Aplikace %s nemá žádná nebezpečná oprávnění" #: src/bz-safety-dialog.c:236 #, c-format msgid "%s is Probably Safe" msgstr "Aplikace %s je pravděpodobně bezpečná" #: src/bz-safety-dialog.c:241 #, c-format msgid "%s is Possibly Unsafe" msgstr "Aplikace %s pravděpodobně není bezpečná" #: src/bz-safety-dialog.c:246 #, c-format msgid "%s is Unsafe" msgstr "Aplikace %s není bezpečná" #: 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 "Následující snímek obrazovky" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Kopírovat obrázek" #: src/bz-screenshot-page.blp:150 msgid "Reset View" msgstr "Původní" #: src/bz-screenshot-page.blp:161 msgid "Zoom Out" msgstr "Oddálit" #: src/bz-screenshot-page.blp:171 msgid "Zoom In" msgstr "Přiblížit" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Prohlížeč snímků obrazovky" #: src/bz-screenshots-carousel.blp:117 msgid "Open Screenshot Viewer" msgstr "Otevřít prohlížeč snímků obrazovky" #: src/bz-search-filter-popover.blp:18 src/bz-search-page.blp:83 msgid "Filters" msgstr "Filtry" #: src/bz-search-filter-popover.blp:35 msgid "_Verified" msgstr "O_věřené" #: src/bz-search-filter-popover.blp:42 msgid "_Free/Open" msgstr "_Svobodné/otevřené" #: src/bz-search-filter-popover.blp:49 msgid "Non-_EOL" msgstr "N_ezastaralé" #: src/bz-search-filter-popover.blp:52 msgid "Filter out End-of-Life apps" msgstr "Filtrovat zastaralé aplikace" #: src/bz-search-filter-popover.blp:57 msgid "Categories" msgstr "Kategorie" #: src/bz-search-page.blp:58 msgid "Search Apps, Games, Software" msgstr "hledat aplikace, hry, software" #: src/bz-search-page.blp:70 msgid "Search Filters" msgstr "Filtry vyhledávání" #: src/bz-search-page.blp:100 msgid "Clear Search" msgstr "Vymazat hledání" #: src/bz-search-page.blp:192 msgid "Categories Unavailable" msgstr "Kategorie nejsou k dispozici" #: src/bz-search-page.blp:193 msgid "Search for apps using the search bar above." msgstr "Vyhledejte aplikace pomocí vyhledávacího panelu výše." #: src/bz-search-page.blp:219 msgid "Browse Categories" msgstr "Procházet kategorie" #: src/bz-search-page.blp:361 msgid "No Applications Found" msgstr "Nenalezeny žádné aplikace" #: src/bz-search-page.c:247 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Žádné výsledky pro „%s“ v Flathubu" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "Video" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "Kancelář" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "Kalendář" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "Zasílání zpráv" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Paint" msgstr "Malování" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "Torrent" msgstr "Torrent" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Emulator" msgstr "Emulátor" #: src/bz-share-list.c:55 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Stránka na Flathubu" #: src/bz-share-list.c:56 msgctxt "Project URL Type" msgid "Project Website" msgstr "Stránky projektu" #: src/bz-share-list.c:57 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Sledování problémů" #: src/bz-share-list.c:58 msgctxt "Project URL Type" msgid "FAQ" msgstr "Časté otázky" #: src/bz-share-list.c:59 msgctxt "Project URL Type" msgid "Help" msgstr "Nápověda" #: src/bz-share-list.c:60 msgctxt "Project URL Type" msgid "Donate" msgstr "Věnovat dar" #: src/bz-share-list.c:61 msgctxt "Project URL Type" msgid "Translate" msgstr "Překlad" #: src/bz-share-list.c:62 msgctxt "Project URL Type" msgid "Contact" msgstr "Kontakt" #: src/bz-share-list.c:63 msgctxt "Project URL Type" msgid "Source Code" msgstr "Zdrojový kód" #: src/bz-share-list.c:64 msgctxt "Project URL Type" msgid "Contribute" msgstr "Přispět" #: src/bz-share-list.c:153 msgid "Copy Link" msgstr "Kopírovat odkaz" #: src/bz-share-list.c:164 msgid "Open Link" msgstr "Otevřít odkaz" #: src/bz-stats-dialog.blp:27 msgid "Timeline" msgstr "Časová osa" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Počet instalací:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Svět" #: src/bz-stats-dialog.blp:69 msgid "Since 4/15/2024" msgstr "Od 15. 4. 2024" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:130 #, c-format msgid "%.2fM Total Installs" msgstr "%.2f mil. celkových instalací" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:133 #, c-format msgid "%.2fK Total Installs" msgstr "%.2f tis. celkových instalací" #: src/bz-stats-dialog.c:135 #, c-format msgid "%'d Total Installs" msgstr "%'d celkových instalací" #: src/bz-tag-list.c:78 msgid "No Results Found" msgstr "Nenalezeny žádné výsledky" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Aplikace se štítkem „%s“" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "Vyhledávání se nezdařilo" #: src/bz-transaction-dialog.c:154 msgid "Keep User Data" msgstr "Ponechat uživatelská data" #: src/bz-transaction-dialog.c:155 msgid "Allow restoring personal settings & content" msgstr "Povolit obnovení uživatelských nastavení a obsahu" #: src/bz-transaction-dialog.c:164 msgid "Delete All Data" msgstr "Odstranit všechna data" #: src/bz-transaction-dialog.c:165 msgid "Permanently erase user data to save space" msgstr "Trvale odstranit uživatelská data, aby se ušetřilo místo" #: src/bz-transaction-dialog.c:190 #, c-format msgid "Install %s?" msgstr "Nainstalovat %s?" #: src/bz-transaction-dialog.c:195 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Vyberte verzi, kterou chcete nainstalovat. Může dojít k instalaci dalších " "sdílených komponent" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "Může nainstalovat dodatečné sdílené komponenty" #: src/bz-transaction-dialog.c:200 src/bz-transaction-dialog.c:229 #: src/bz-transaction-dialog.c:274 src/bz-transaction-dialog.c:576 msgid "_Cancel" msgstr "_Zrušit" #: src/bz-transaction-dialog.c:201 msgid "_Install" msgstr "_Instalovat" #: src/bz-transaction-dialog.c:218 #, c-format msgid "Remove %s?" msgstr "Odebrat %s?" #: src/bz-transaction-dialog.c:221 msgid "Select which version to remove." msgstr "Vyberte, kterou verzi chcete odebrat." #: src/bz-transaction-dialog.c:223 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Po odinstalování nebude možné aplikaci %s používat." #: src/bz-transaction-dialog.c:246 #, c-format msgid "“%s” is High Risk" msgstr "Aplikace „%s“ je vysoce riziková" #: src/bz-transaction-dialog.c:250 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 "" "Tato aplikace má plný přístup k vašemu systému, včetně všech vašich " "souborů, historie prohlížení, uložených hesel a dalších údajů. Má také " "přístup k internetu, což znamená, že může odesílat vaše data externím " "stranám.\n" "\n" "Protože je aplikace uzavřený software, nelze auditovat, co s těmito " "oprávněními dělá." #: src/bz-transaction-dialog.c:259 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 "" "Tato aplikace používá starší okenní systém X11, který jí umožňuje " "zaznamenávat všechny stisky kláves, pořizovat snímky obrazovky a " "monitorovat další aplikace. Má také přístup k internetu, což znamená, že " "může odesílat vaše data externím stranám.\n" "\n" "Protože je aplikace uzavřený software, nelze auditovat, co s těmito " "oprávněními dělá." #: src/bz-transaction-dialog.c:275 msgid "_Install Anyway" msgstr "Přesto na_instalovat" #: src/bz-transaction-dialog.c:330 msgid "Failed to load transaction dialog" msgstr "Nezdařilo se načíst dialogové okno transakce" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "Všechny aplikace jsou již nainstalovány" #: src/bz-transaction-dialog.c:549 msgid "_OK" msgstr "_Budiž" #: src/bz-transaction-dialog.c:565 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "Nainstalovat %u aplikaci?" msgstr[1] "Nainstalovat %u aplikace?" msgstr[2] "Nainstalovat %u aplikací?" #: src/bz-transaction-dialog.c:573 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" "Následující aplikace budou nainstalovány. Mohou být také nainstalovány další " "sdílené komponenty" #: src/bz-transaction-dialog.c:574 #, c-format msgid "%d addons will be installed." msgstr "Bude nainstalováno %d doplňků." #: src/bz-transaction-dialog.c:575 msgid "Additionally, addons will be installed." msgstr "Kromě toho budou nainstalovány doplňky." #: src/bz-transaction-dialog.c:577 msgid "_Install All" msgstr "_Instalovat vše" #: src/bz-transaction-manager.c:795 #, c-format msgid "Finished in %.02f seconds" msgstr "Dokončeno v %.02f sekundách" #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "Doplněk aplikace" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "Prostředí" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "Ve frontě" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "Hotovo" #: src/bz-transaction-tile.blp:230 msgid "Cancelled" msgstr "Zrušeno" #: src/bz-transaction-tile.blp:254 msgid "Error" msgstr "Chyba" #: src/bz-transaction-tile.blp:312 msgid "Cancel Transaction" msgstr "Zrušit transakci" #: src/bz-transaction-tile.blp:436 msgid "Show Error Info" msgstr "Zobrazit informace o chybě" #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "%s uvolněno" #: src/bz-transaction-tile.c:360 src/bz-transaction-tile.c:363 msgid "Transaction Error" msgstr "Chyba transakce" #: src/bz-transaction.c:344 msgid "Pending" msgstr "Čeká" #: src/bz-updates-card.blp:23 msgid "_Update All" msgstr "Akt_ualizovat vše" #: src/bz-updates-card.c:211 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "%u aktualizace prostředí" msgstr[1] "%u aktualizace prostředí" msgstr[2] "%u aktualizací prostředí" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Správa zbylých uživatelských dat" #: src/bz-user-data-page.blp:33 msgid "No User Data Found" msgstr "Nenalezena žádná uživatelská data" #: src/bz-user-data-page.blp:38 msgid "User Data" msgstr "Uživatelská data" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Vymazat uživatelská data" #: src/bz-user-data-tile.c:150 #, c-format msgid "Trashed User Data for %s" msgstr "Uživatelská data aplikace %s byla vymazána" #: src/bz-window.blp:70 msgid "Refreshing" msgstr "Obnovuje se" #: src/bz-window.blp:88 msgid "Curated" msgstr "Vybrané" #: src/bz-window.blp:100 msgid "Explore" msgstr "Procházet" #: src/bz-window.blp:212 msgid "Main Menu" msgstr "Hlavní nabídka" #: src/bz-window.blp:223 msgid "You are running a new version of Bazaar!" msgstr "Používáte novou verzi Bazaaru!" #: src/bz-window.blp:224 msgid "See What's New" msgstr "Podívejte se, co je nového" #: src/bz-window.blp:231 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 verzi Flathubu uloženou v mezipaměti" #: src/bz-window.blp:276 msgid "_Donate to Bazaar" msgstr "Po_dpořit Bazaar" #: src/bz-window.blp:283 msgid "_Refresh" msgstr "_Obnovit" #: src/bz-window.blp:288 msgid "_Preferences" msgstr "_Předvolby" #: src/bz-window.blp:293 msgid "_Login With Flathub" msgstr "Přih_lásit se pomocí Flathubu" #: src/bz-window.blp:299 msgid "_Manage Leftover User Data" msgstr "Sp_ravovat zbylá uživatelská data" #: src/bz-window.blp:304 msgid "_Keyboard Shortcuts" msgstr "_Klávesové zkratky" #: src/bz-window.blp:309 msgid "_About Bazaar" msgstr "O _aplikaci Bazaar" #: src/bz-window.blp:316 msgid "_Quit Bazaar" msgstr "_Ukončit Bazaar" #: src/bz-window.blp:341 msgid "Log Out" msgstr "Odhlásit se" #. Translators: %s is the title of the current page #: src/bz-window.c:376 #, c-format msgid "Bazaar — %s" msgstr "Bazaar – %s" #: src/bz-window.c:596 src/bz-window.c:634 msgid "Failed to launch application" msgstr "Aplikaci se nezdařilo spustit" #: src/bz-window.c:843 msgid "You can't remove Bazaar from Bazaar!" msgstr "Bazaar nelze odstranit z Bazaaru!" #: src/bz-window.c:1127 src/bz-window.c:1161 msgid "Can't do that right now!" msgstr "Toto teď nelze provést!" #. Translators: As in, "1 Install" / "100 Installs" #: src/bz-world-map.c:604 msgid "Install" msgid_plural "Installs" msgstr[0] "instalace" msgstr[1] "instalace" msgstr[2] "instalací" #: src/shortcuts-dialog.blp:5 msgctxt "shortcut window" msgid "Navigation" msgstr "Navigace" #: src/shortcuts-dialog.blp:8 msgctxt "shortcut window" msgid "Open Explore Page" msgstr "Otevřít stránku procházení" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "Otevřít stránku knihovny" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Open Search Page" msgstr "Otevřít stránku vyhledávání" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Remotes" msgstr "Repozitáře" #: src/shortcuts-dialog.blp:27 msgctxt "shortcut window" msgid "Sync Remotes" msgstr "Synchronizovat repozitáře" #: src/shortcuts-dialog.blp:33 msgctxt "shortcut window" msgid "General" msgstr "Obecné" #: src/shortcuts-dialog.blp:36 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Otevřít předvolby" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Zobrazit zkratky" #: src/shortcuts-dialog.blp:46 msgctxt "shortcut window" msgid "Close Window" msgstr "Zavřít okno" #: src/shortcuts-dialog.blp:52 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "Ukončit Bazaar" #~ msgid "Fractal permissions page" #~ msgstr "Stránka oprávnění aplikace Fractal" #~ msgid "Manage Permissions" #~ msgstr "Spravovat oprávnění" #~ msgid "Show Other Options…" #~ msgstr "Zobrazit další možnosti…" #~ msgid "Edit Permissions" #~ msgstr "Upravit oprávnění" #~ msgid "Reset to defaults" #~ msgstr "Vrátit na výchozí" #~ msgid "New Entry" #~ msgstr "Nová položka" #~ msgid "Invalid Format" #~ msgstr "Neplatný formát" #~ msgid "Reset to default" #~ msgstr "Vrátit na výchozí" #~ msgid "Permissions" #~ msgstr "Oprávnění" #~ msgid "" #~ "Modifying permissions may cause apps to break or be less secure. Do not " #~ "make bug reports with them modified!" #~ msgstr "" #~ "Úprava oprávnění může způsobit selhání aplikací nebo snížení jejich " #~ "bezpečnosti. Neohlašujte chyby, pokud jsou oprávnění upravena!" #~ msgid "OK" #~ msgstr "Budiž" #~ msgid "Reset" #~ msgstr "Výchozí" #~ msgid "General" #~ msgstr "Obecné" #~ msgid "Network" #~ msgstr "Síť" #~ msgid "Share the host's network access" #~ msgstr "Sdílení síťového přístupu hostitele" #~ msgid "Audio Server" #~ msgstr "Zvukový server" #~ msgid "" #~ "Play and record sound, enabling this bypasses the individual permissions" #~ msgstr "Přehrávání a nahrávání zvuku, obchází individuální oprávnění" #~ msgid "Bluetooth" #~ msgstr "Bluetooth" #~ msgid "Manage both Bluetooth devices and settings" #~ msgstr "Správa nastavení a zařízení Bluetooth" #~ msgid "Printing" #~ msgstr "Tisk" #~ msgid "Access the system's printing system" #~ msgstr "Přístup k tiskovému systému" #~ msgid "Devices" #~ msgstr "Zařízení" #~ msgid "Smart Cards" #~ msgstr "Čipové karty" #~ msgid "Access smart card readers via PC/SC" #~ msgstr "Přístup ke čtečkám čipových karet přes PC/SC" #~ msgid "All Devices" #~ msgstr "Všechna zařízení" #~ msgid "Access all devices such as webcam, GPU, etc." #~ msgstr "Přístup ke všem zařízením jako jsou webkamera, grafická karta atd." #~ msgid "GPU Acceleration" #~ msgstr "Akcelerace GPU" #~ msgid "Access GPU rendering" #~ msgstr "Přístup k vykreslování na GPU" #~ msgid "USB Devices" #~ msgstr "Zařízení USB" #~ msgid "Manage USB devices directly" #~ msgstr "Přímá správa zařízení USB" #~ msgid "Input Devices" #~ msgstr "Vstupní zařízení" #~ msgid "Access Input devices" #~ msgstr "Přístup ke vstupním zařízením" #~ msgid "KVM Virtualization" #~ msgstr "Virtualizace KVM" #~ msgid "Access KVM for virtual machines" #~ msgstr "Přístup k KVM pro virtuální stroje" #~ msgid "Shared Memory" #~ msgstr "Sdílená paměť" #~ msgid "Create shared memory objects" #~ msgstr "Vytváření objektů sdílené paměti" #~ msgid "Filesystem" #~ msgstr "Souborový systém" #~ msgid "Host Filesystem" #~ msgstr "Souborový systém hostitele" #~ msgid "Full access to the entire filesystem" #~ msgstr "Plný přístup k celému souborovému systému" #~ msgid "Home Folder" #~ msgstr "Domovská složka" #~ msgid "Full access to your home directory" #~ msgstr "Plný přístup k vaší domovské složce" #~ msgid "Access the Downloads folder" #~ msgstr "Přístup ke složce Stažené" #~ msgid "Other Paths" #~ msgstr "Další cesty" #~ msgid "Grant access to additional files and folders" #~ msgstr "Udělit přístup k dalším souborům a složkám" #~ msgid "Advanced System Access" #~ msgstr "Pokročilý přístup k systému" #~ msgid "Inter-process Communication" #~ msgstr "Meziprocesová komunikace" #~ msgid "Share IPC namespace with the host" #~ msgstr "Sdílení jmenného prostoru IPC s hostitelem" #~ msgid "SSH Authentication" #~ msgstr "Ověřování SSH" #~ msgid "Access the SSH authentication agent" #~ msgstr "Přístup k ověřovacímu agentu SSH" #~ msgid "GPG Agent" #~ msgstr "Agent GPG" #~ msgid "" #~ "Access the GPG agent for things like encryption and git commit signing" #~ msgstr "" #~ "Přístup k agentu GPG, například pro šifrování a podepisování commitů gitu" #~ msgid "Session Bus Policy" #~ msgstr "Zásady sběrnice sezení" #~ msgid "Full Access" #~ msgstr "Plný přístup" #~ msgid "Give full access to the D-Bus session bus" #~ msgstr "Umožnit plný přístup ke sběrnici sezení D-Bus" #~ msgid "Talk" #~ msgstr "Komunikace" #~ msgid "Names on the session bus the app is allowed to send messages to" #~ msgstr "Jména na sběrnici sezení, kterým aplikace smí odesílat zprávy" #~ msgid "Own" #~ msgstr "Vlastnění" #~ msgid "Names on the session bus the app is allowed to claim ownership of" #~ msgstr "" #~ "Jména na sběrnici sezení, ke kterým si aplikace smí nárokovat vlastnictví" #~ msgid "System Bus Policy" #~ msgstr "Zásady systémové sběrnice" #~ msgid "Give full access to the D-Bus system bus" #~ msgstr "Umožnit plný přístup k systémové sběrnici D-Bus" #~ msgid "Names on the system bus the app is allowed to send messages to" #~ msgstr "Jména na systémové sběrnici, kterým aplikace smí odesílat zprávy" #~ msgid "Names on the system bus the app is allowed to claim ownership of" #~ msgstr "" #~ "Jména na systémové sběrnici, ke kterým si aplikace smí nárokovat " #~ "vlastnictví" #~ msgid "Developer Options" #~ msgstr "Možnosti pro vývojáře" #~ msgid "Wayland Windowing System" #~ msgstr "Okenní systém Wayland" #~ msgid "Show windows using Wayland" #~ msgstr "Zobrazovat okna pomocí Waylandu" #~ msgid "X11 Windowing System" #~ msgstr "Okenní systém X11" #~ msgid "Show windows using X11" #~ msgstr "Zobrazovat okna pomocí X11" #~ msgid "Fallback X11 Windowing System" #~ msgstr "Záložní okenní systém X11" #~ msgid "Show windows using X11 if Wayland is not available" #~ msgstr "Zobrazovat okna pomocí X11, pokud Wayland není k dispozici" #~ msgid "Development Syscalls" #~ msgstr "Vývojářská systémová volání" #~ msgid "Access development syscalls such as ptrace" #~ msgstr "Přístup k vývojářským systémovým voláním, jako je ptrace" #~ msgid "Multiarch" #~ msgstr "Multiarch" #~ msgid "Run multiarch / multilib binaries" #~ msgstr "Spouštění binárních souborů multiarch / multilib" #~ msgid "CAN Bus" #~ msgstr "Sběrnice CAN" #~ msgid "Access the CAN bus" #~ msgstr "Přístup k sběrnici CAN" #~ msgid "Per-App Shared Memory" #~ msgstr "Sdílená paměť pro jednotlivé aplikace" #~ msgid "Share /dev/shm between app instances & subsandboxes" #~ msgstr "Sdílení /dev/shm mezi instancemi aplikací a subsandboxy" #~ msgid "Variables" #~ msgstr "Proměnné" #~ msgid "Environment variables to set in the application" #~ msgstr "Proměnné prostředí, které se mají nastavit v aplikaci" #~ msgid "Permissions reset!" #~ msgstr "Oprávnění resetována!" #~ msgid "Undo" #~ msgstr "Zpět" #~ msgid "Hide Developer Options" #~ msgstr "Skrýt možnosti pro vývojáře" #~ msgid "Show Developer Options" #~ msgstr "Zobrazit možnosti pro vývojáře" #~ msgid "Background" #~ msgstr "Pozadí" #~ msgid "Speakers" #~ msgstr "Reproduktory" #~ msgid "Camera" #~ msgstr "Kamera" #~ msgid "Location" #~ msgstr "Umístění" #~ msgid "Microphone" #~ msgstr "Mikrofon" bazaar-org-bazaar-43ce9f7/po/de.po000066400000000000000000002313351520414637400170060ustar00rootroot00000000000000# 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 "Apps ausschließen, die nicht von Flathub stammen" #: src/bz-preferences-dialog.blp:44 #, fuzzy msgid "Verified Results Only" msgstr "Nur verifizierte Ergebnisse" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Apps ausschließen, die nicht von Flathub verifiziert wurden" #: 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 "Apps ausschließen, die nicht mehr aktiv weiterentwickelt werden" #: 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 "Ergebnis-Performance durch Debouncing der Suchbegriffe verbessern" #: 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" bazaar-org-bazaar-43ce9f7/po/el.po000066400000000000000000001755671520414637400170340ustar00rootroot00000000000000# 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 "Έξοδος" bazaar-org-bazaar-43ce9f7/po/es.po000066400000000000000000001142541520414637400170250ustar00rootroot00000000000000# 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?" bazaar-org-bazaar-43ce9f7/po/eu.po000066400000000000000000002613011520414637400170230ustar00rootroot00000000000000# Basque 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. # Ibai Oihanguren Sala , 2026. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-05-19 22:56+0200\n" "PO-Revision-Date: 2026-05-19 23:20+0200\n" "Last-Translator: Ibai Oihanguren Sala \n" "Language-Team: Basque\n" "Language: eu\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 50.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:45 #: src/bz-window.blp:199 src/bz-window.c:373 src/bz-window.c:374 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Gehitu, kendu edo eguneratu ordenagailuko flatpak softwarea" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;Sistema;Pakete;Kudeatzailea;Deskubritu;Flatpak;Softwarea;Denda;Biltegia;" #: data/io.github.kolunmi.Bazaar.desktop.in:16 msgid "New Window" msgstr "Leiho berria" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and manage applications" msgstr "Deskubritu eta kudeatu aplikazioak" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "Aplikazio biltegi bizkor eta modernoa Linuxerako, Flatpak aplikazio eta " "gehigarriak (bereziki Flathub-etik) deskubritu eta instalatzera bideratua." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "Gehitu hainbat instalazio ilarara eta jarraitu nabigatzen" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "Ikusi aplikazioen baimenak era errazean" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "Hasi saioa Flathub-en zure gogokoak ikusi eta kudeatzeko" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "Bilatu aplikazioak zuzenean GNOME Shell-etik" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:30 src/bz-application.c:759 msgid "The Bazaar Contributors" msgstr "Bazaarren kolaboratzaileak" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "The home page displaying Flathub apps" msgstr "Flathub aplikazioak erakusten dituen orri nagusia" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:59 msgid "Exhibit app page" msgstr "Aplikazio baten orria" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "Liburutegi orria" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "Bilaketa orria" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "Kategoria orria" #: src/bz-addon-tile.blp:64 src/bz-installed-tile.blp:55 #: src/bz-rich-app-tile.blp:141 msgid "Stopped Receiving Updates" msgstr "Eguneratzeak jasotzeari utzi dio" #: src/bz-addon-tile.c:167 src/bz-favorites-tile.c:155 msgctxt "Install Controls" msgid "Uninstall" msgstr "Desinstalatu" #: src/bz-addon-tile.c:169 src/bz-bundle-install-dialog.blp:126 #: src/bz-favorites-tile.c:157 src/bz-install-controls.wdgt:29 msgctxt "Install Controls" msgid "Install" msgstr "Instalatu" #: src/bz-addons-dialog.blp:14 src/bz-addons-dialog.blp:21 #: src/bz-addons-dialog.blp:70 src/bz-full-view.blp:583 #: src/bz-installed-tile.blp:92 msgid "Manage Add-Ons" msgstr "Kudeatu gehigarriak" #: src/bz-addons-dialog.blp:80 msgid "No Add-Ons Visible" msgstr "Ez dago gehigarririk ikusgai" #: src/bz-addons-dialog.blp:81 msgid "" "Your current filter preferences are hiding all known add-ons. Try adjusting " "them." msgstr "" "Uneko iragazki hobespenek gehigarri erabilgarri guztiak ezkutatu dituzte. " "Doitu hobespenak gehigarriak ikusteko." #: src/bz-addons-dialog.blp:88 msgid "Add-on Page" msgstr "Gehigarriaren orria" #: src/bz-addons-dialog.blp:202 src/bz-full-view.blp:381 msgid "Downloads/Month" msgstr "Deskarga hileko" #: src/bz-addons-dialog.blp:229 src/bz-full-view.blp:417 msgid "Stopped Receiving Core Updates" msgstr "Oinarrizko eguneratzeak jasotzari utzi dio" #: src/bz-addons-dialog.blp:243 msgid "" "This add-on uses a runtime that no longer receives updates or security " "fixes. It may become unsafe to use." msgstr "" "Gehigarri honek eguneratzerik edo segurtasun-konponketarik jasotzen ez duen " "exekuzio-ingurune bat darabil. Baliteke berau erabiltzea ez izatea segurua." #: src/bz-addons-dialog.c:333 #, c-format msgid "Add-on for %s" msgstr "%s(r)entzako gehigarria" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show Less" msgstr "Gutxiago erakutsi" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show More" msgstr "Gehiago erakutsi" #: src/bz-addons-dialog.c:397 msgid "Download Stats" msgstr "Deskargen estatistikak" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:736 src/bz-context-tile-callbacks.c:186 #: src/bz-context-tile-callbacks.c:193 msgid "Age Rating" msgstr "Adin balorazioa" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Marrazki bizidunetako indarkeria" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Ez dago informaziorik marrazki bizidunetako indarkeriari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Fantasiazko indarkeria" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Ez dago informaziorik fantasiazko indarkeriari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Indarkeria errealista" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Ez dago informaziorik indarkeria errealistari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Sarraskia irudikatzen duen indarkeria" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "" "Ez dago informaziorik sarraskia irudikatzen duen indarkeriari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Indarkeria sexuala" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Ez dago informaziorik indarkeria sexualari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Alkohola" #. 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 "Ez dago informaziorik alkohola aipatzeari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "Legez kanpoko drogak" #. 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 "Ez dago informaziorik legez kanpoko drogak aipatzeari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Tabakoa" #. 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 "Ez dago informaziorik tabakoa aipatzeari dagokionean" #. 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 "Biluztasuna" #. 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 "Ez dago informaziorik biluztasunari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Gai sexualak" #. 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 "Ez dago informaziorik gai sexualak aipatzeari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Hizkera zakarra" #. 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 "Ez dago informaziorik edonolako hizkera zakarrari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Umore ezegokia" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Ez dago informaziorik umore ezegokiari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Bereizkeria" #. 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 "Ez dago informaziorik edonolako bereizkeriari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Publizitatea" #. 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 "Ez dago informaziorik edonolako publizitateari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Jokoa (apustuak)" #. 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 "Ez dago informaziorik edonolako apustuei dagokienean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Erosketak" #. 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 "Ez dago informaziorik diruz erosketak egiteko aukerari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Erabiltzaileen arteko txatak" #. 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 "" "Ez dago informaziorik beste erabiltzaileekin berriketan aritzeko bideei " "dagokienean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Erabiltzaileen arteko audio txatak" #. 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 "" "Ez dago informaziorik beste erabiltzaileekin hitz egiteko bideei dagokienean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Harremanetarako xehetasunak" #. 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 "" "Ez dago informaziorik sare sozialetako erabiltzaileak edo email helbideak " "partekatzeari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Identifikatzeko informazioa" #. 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 "" "Ez dago informaziorik erabiltzailearen datuak hirugarren batekin " "partekatzeari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Kokapena partekatzea" #. 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 "" "Ez dago informaziorik beste erabiltzaileekin kokapen fisikoa partekatzeari " "dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Prostituzioa" #. 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 "Ez dago informaziorik prostituzioa aipatzeari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Adulterioa" #. 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 "Ez dago informaziorik adulterioa aipatzeari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Pertsonaia sexualizatuak" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Ez dago informaziorik pertsonaia sexualizatuei dagokienean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "Profanazioa" #. 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 "Ez dago informaziorik profanazioa aipatzeari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Giza hondakinak" #. 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 "Ez dago informaziorik giza hondakinak erakusteari dagokionean" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "Esklabotza" #. 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 "Ez dago informaziorik esklabotza aipatzeari dagokionean" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Ez die drogei aipamenik egiten" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "Ez du biraorik, juramenturik edo bestelako hizkera zakarrik erabiltzen" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Ez du iragarkirik edo diru-trukerik" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Ez du sexu edukirik edo biluztasunik erakusten" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "Ez du kontrolik gabeko txat funtzionalitaterik" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Ez du indarkeriarik erakusten" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Drogak" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Hizkera zakarra" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Dirua" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Soziala" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Indarkeria" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:686 src/bz-context-tile-callbacks.c:176 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "Guztiak" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "%s(e)k adin balorazio ezezaguna dauka" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "%s edonorentzako da egokia" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "%s egokia da haur txikientzako" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "%s egokia da haurrentzako" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "%s egokia da nerabeentzako" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "%s egokia da helduentzako" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "%s egokia da %s urte bitartekoentzako" #: src/bz-age-rating-dialog.c:862 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "%s sistemako karpeta" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Karpeta nagusiko %s azpikarpeta" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Ostalari sistemako karpetak" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Ostalari sistemako konfigurazioa /etc direktoriotik" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Mahaigaineko %s azpikarpeta" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Mahaigaina karpeta" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Dokumentuetako %s azpikarpeta" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Dokumentuak karpeta" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Musikako %s azpikarpeta" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Musika karpeta" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Irudietako %s azpikarpeta" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Irudiak karpeta" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Publikoki partekatutako %s azpikarpeta" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Publikoa karpeta" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Bideoetako %s azpikarpeta" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Bideoak karpeta" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Txantiloietako %s azpikarpeta" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Txantiloiak karpeta" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Erabiltzailearen cacheko %s azpikarpeta" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Erabiltzailearen cache karpeta" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Erabiltzailearen konfigurazioko %s azpikarpeta" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Erabiltzailearen konfigurazio karpeta" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Erabiltzailearen datuetako %s azpikarpeta" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Erabiltzailearen datuen karpeta" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Erabiltzailearen exekuzio-inguruneko %s azpikarpeta" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Erabiltzailearen exekuzio-ingurune karpeta" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Fitxategi-sisteman sarbidea %s karpetara" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Fitxategi-sistemako bide ezezaguna" #: src/bz-app-size-dialog.blp:26 src/bz-app-size-dialog.blp:60 msgid "Download Size" msgstr "Deskargaren tamaina" #: src/bz-app-size-dialog.blp:33 src/bz-app-size-dialog.blp:81 msgid "Installed Size" msgstr "Instalazioaren tamaina" #: src/bz-app-size-dialog.blp:61 msgid "Amount to download from the internet" msgstr "Internetetik deskargatu beharrekoaren tamaina" #: src/bz-app-size-dialog.blp:82 msgid "Size on Disk" msgstr "Diskoan hartzen duen tamaina" #: src/bz-app-size-dialog.blp:133 msgid "Open user data folder" msgstr "Ireki erabiltzaile-datuen karpeta" #: src/bz-app-size-dialog.blp:143 msgid "Your User Data" msgstr "Zure erabiltzaile-datuak" #: src/bz-app-size-dialog.blp:144 msgid "Caches, settings, and other app data" msgstr "Cachea, ezarpenak eta aplikazioaren bestelako datuak" #: src/bz-app-size-dialog.blp:165 msgid "Cache" msgstr "Cachea" #: src/bz-app-size-dialog.blp:166 msgid "Temporary cached data" msgstr "Aldi baterako cacheratutako datuak" #: src/bz-app-size-dialog.blp:176 msgid "Clear Cache" msgstr "Garbitu cachea" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "Instalatutako exekuzio-ingurunearen tamaina" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "Exekuzio-ingurunearen deskarga tamaina" #: src/bz-app-size-dialog.c:220 msgid "App Size" msgstr "Aplikazioaren tamaina" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:105 src/bz-rich-app-tile.c:429 msgid "Verified" msgstr "Egiaztatua" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-context-tile-callbacks.c:135 #: src/bz-releases-list.c:206 msgid "Installed" msgstr "Instalatua" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:762 msgid "translator-credits" msgstr "Ibai Oihanguren Sala" #: src/bz-application.c:772 msgid "Special Thanks" msgstr "Eskerrak" #: src/bz-application.c:830 msgid "Logged Out Successfully!" msgstr "Behar bezala amaitu da saioa!" #: src/bz-application.c:966 msgid "Performing setup…" msgstr "Konfigurazioa osatzen…" #: src/bz-application.c:1052 msgid "Set Up System Flathub?" msgstr "Sistemako Flathub konfiguratu?" #: src/bz-application.c:1055 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Sistemako Flathub urruneko biltegia ez dago konfiguratuta. Bazaar erabilita " "aplikazioak arakatu eta instalatzeko, Flathub konfiguratuta egon behar da " "sistemako Flatpak instalazioan.\n" "\n" "Bestela, Bazaar soilik instalatutako aplikazioak nabigatu eta kentzeko " "erabili ahalko duzu." #: src/bz-application.c:1062 msgid "Set Up Flathub?" msgstr "Flathub konfiguratu?" #: src/bz-application.c:1065 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 ez dago sisteman konfiguratuta. Ezin izango dituzu aplikazioak " "nabigatu eta instalatu Bazaar erabilita.\n" "\n" "Bazaar dagoeneko instalatutako aplikazioak nabigatu eta kentzeko erabili " "ahalko duzu." #: src/bz-application.c:1071 msgid "Later" msgstr "Geroago" #: src/bz-application.c:1072 msgid "Set Up Flathub" msgstr "Konfiguratu Flathub" #: src/bz-application.c:1408 msgid "A backend error occurred" msgstr "Backendeko errorea gertatu da" #: src/bz-application.c:1608 src/bz-application.c:3765 msgid "Refreshing…" msgstr "Berritzen…" #: src/bz-application.c:1772 src/bz-application.c:3763 #, c-format msgid "Loading %d apps…" msgstr "%d aplikazioak kargatzen…" #: src/bz-application.c:1825 msgid "Failed to open file" msgstr "Ezin izan da fitxategia ireki" #: src/bz-application.c:1930 msgid "An initialization error occurred" msgstr "Hasieratze-errore bat gertatu da" #: src/bz-application.c:2296 msgid "Checking for updates…" msgstr "Eguneratzeak bilatzen…" #: src/bz-application.c:2352 msgid "Failed to check for updates" msgstr "Ezin izan dira eguneratzeak bilatu" #: src/bz-application.c:3477 msgid "Malformed Link" msgstr "Gaizki eratutako esteka" #: src/bz-application.c:3478 msgid "" "The link used to open this app has incorrect capitalisation and may stop " "working in the future.\n" "\n" "This is most likely caused by KRunner sending incorrect app IDs" msgstr "" "Aplikazio hau irekitzeko erabilitako estekak maiuskulen okerreko erabilera " "dauka, eta baliteke noizbait funtzionatzeari uztea.\n" "\n" "Seguruenera hau KRunner-ek okerreko aplikazio IDak bidaltzen dituelako " "izango da." #: src/bz-application.c:3485 msgid "Could not find app" msgstr "Ez da aplikazioa aurkitu" #: src/bz-application.c:3516 msgid "Failed to load metainfo" msgstr "Ezin izan da meta informazioa kargatu" #: src/bz-application.c:3767 msgid "Writing to cache…" msgstr "Cachean idazten…" #: src/bz-apps-page.blp:99 msgid "Show All" msgstr "Erakutsi dena" #: src/bz-apps-page.c:237 #, c-format msgid "All \"%s\"" msgstr "\"%s\" aplikazio guztiak" #: src/bz-apps-page.c:487 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "%d aplikazio" #: src/bz-bundle-install-dialog.blp:8 src/bz-bundle-install-dialog.blp:14 msgid "Bundle Installation" msgstr "Sortaren instalazioa" #: src/bz-bundle-install-dialog.blp:147 msgid "Additional dependencies may take extra space" msgstr "Menpekotasun gehigarriek leku gehiago har dezakete" #: src/bz-bundle-install-dialog.blp:181 msgid "" "Installing this app may require adding a new software source. Other apps " "from this source will show up in Bazaar.\n" "\n" "Only add this source if you're sure you trust it." msgstr "" "Baliteke aplikazio hau instalatzeko software-iturri berri bat gehitu behar " "izatea. Iturri honetako beste aplikazioak ere Bazaarren azalduko dira.\n" "\n" "Ez gehitu iturri hau ez bazaude bere fidagarritasunaz ziur." #: src/bz-bundle-install-dialog.blp:357 msgid "Successfully Installed!" msgstr "Behar bezala instalatu da!" #: src/bz-bundle-install-dialog.blp:381 src/bz-bundle-install-dialog.blp:463 #: src/bz-rich-app-tile.blp:198 src/bz-transaction-tile.blp:298 msgid "Open" msgstr "Ireki" #: src/bz-bundle-install-dialog.blp:391 src/bz-bundle-install-dialog.blp:473 msgid "Show App Details" msgstr "Erakutsi aplikazioaren xehetasunak" #: src/bz-bundle-install-dialog.blp:440 msgid "Already Installed" msgstr "Dagoeneko instalatua" #: src/bz-bundle-install-dialog.blp:485 msgid "Installation Failed" msgstr "Instalazioak huts egin du" #: src/bz-bundle-install-dialog.c:169 msgid "Unknown install size" msgstr "Instalazio tamaina ezezaguna" #: src/bz-bundle-install-dialog.c:172 #, c-format msgid "About %s to install" msgstr "%s inguru instalatzeko" #: src/bz-bundle-install-dialog.c:186 src/bz-context-tile-callbacks.c:104 #: src/bz-context-tile-callbacks.c:392 src/bz-context-tile-callbacks.c:409 msgid "N/A" msgstr "E/E" #: src/bz-bundle-install-dialog.c:215 msgid "No special permissions" msgstr "Baimen berezirik ez" #: src/bz-context-tile-callbacks.c:68 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-context-tile-callbacks.c:75 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-context-tile-callbacks.c:82 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-context-tile-callbacks.c:92 #, c-format msgid "%d downloads in the last month" msgstr "%d deskarga azken hilean" #: src/bz-context-tile-callbacks.c:132 #, c-format msgid "+%s runtime" msgstr "+%s exekuzio-ingurunea" #: src/bz-context-tile-callbacks.c:135 msgid "Download" msgstr "Deskargatzeko" #: src/bz-context-tile-callbacks.c:155 msgid "Size information unavailable" msgstr "Ez dago tamainaren informaziorik" #: src/bz-context-tile-callbacks.c:158 #, c-format msgid "Download size of %s" msgstr "%sko deskarga tamaina" #: src/bz-context-tile-callbacks.c:191 msgid "All Ages" msgstr "Adin guztiak" #: src/bz-context-tile-callbacks.c:203 msgid "Age rating information unavailable" msgstr "Ez dago adin balorazioaren informaziorik" #: src/bz-context-tile-callbacks.c:208 msgid "Suitable for all ages" msgstr "Egokia adin guztietakoentzat" #: src/bz-context-tile-callbacks.c:210 #, c-format msgid "Suitable for ages %d and up" msgstr "Egokia %d urtetik gorakoentzat" #: src/bz-context-tile-callbacks.c:243 src/bz-context-tile-callbacks.c:248 #: src/bz-context-tile-callbacks.c:276 src/bz-context-tile-callbacks.c:284 msgid "Unknown" msgstr "Ezezaguna" #: src/bz-context-tile-callbacks.c:253 #, c-format msgid "Free software licensed under %s" msgstr "Software librea %s lizentziapean" #: src/bz-context-tile-callbacks.c:258 msgid "Free software" msgstr "Software librea" #: src/bz-context-tile-callbacks.c:261 msgid "Proprietary Software" msgstr "Software pribatiboa" #: src/bz-context-tile-callbacks.c:264 #, c-format msgid "Special License: %s" msgstr "Lizentzia berezia: %s" #: src/bz-context-tile-callbacks.c:281 msgid "Free" msgstr "Librea" #: src/bz-context-tile-callbacks.c:287 src/bz-license-dialog.c:133 msgid "Proprietary" msgstr "Pribatiboa" #: src/bz-context-tile-callbacks.c:289 src/bz-license-dialog.c:135 msgid "Special License" msgstr "Lizentzia berezia" #: src/bz-context-tile-callbacks.c:309 msgid "Adaptive" msgstr "Moldakorra" #: src/bz-context-tile-callbacks.c:309 msgid "Desktop Only" msgstr "Mahaigainerako soilik" #: src/bz-context-tile-callbacks.c:315 msgid "Works on desktop, tablets, and phones" msgstr "Mahaigainean, tabletetan eta mugikorretan dabil" #: src/bz-context-tile-callbacks.c:316 msgid "May not work on mobile devices" msgstr "Baliteke gailu mugikorretan ez ibiltzea" #: src/bz-context-tile-callbacks.c:399 src/bz-safety-dialog.blp:27 msgid "Safe" msgstr "Segurua" #: src/bz-context-tile-callbacks.c:401 src/bz-context-tile-callbacks.c:403 msgid "Low Risk" msgstr "Arrisku txikia" #: src/bz-context-tile-callbacks.c:405 msgid "Medium Risk" msgstr "Arrisku ertaina" #: src/bz-context-tile-callbacks.c:407 msgid "High Risk" msgstr "Arrisku handia" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:46 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:30 #: src/bz-library-page.blp:67 src/bz-user-data-page.blp:30 msgid "Empty" msgstr "Hutsik" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Aukeraketarik gabe" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Ez dago aukeraketa informaziorik sistema honetan. Halere, Flathub-eko " "aplikazioak araka ditzakezu." #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Arakatu 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 "Lineaz kanpo" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "Nabigatzailea" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "Egiaztatu gabea" #: src/bz-developer-badge.c:213 msgid "Developer information not available." msgstr "Garatzailearen informazioa ez dago eskuragarri." #: src/bz-developer-badge.c:219 src/bz-developer-badge.c:233 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "%s aplikazio IDaren jabetza ez da egiaztatu, eta baliteke komunitateko " "paketea izatea." #: src/bz-developer-badge.c:237 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "%s aplikazio IDaren jabetza eskuz egiaztatu du Flathub-eko lantaldeak." #: src/bz-developer-badge.c:253 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "%1$s aplikazio IDaren jabetza %2$s(e)k egiaztatu du %3$s(e)an." #: src/bz-developer-badge.c:260 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "%1$s aplikazio IDaren jabetza %2$s erabiliz egiaztatu da." #: src/bz-developer-badge.c:264 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "%s aplikazio IDaren jabetza egiaztatua izan da." #: src/bz-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "Bertsio-ohar osoak" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "Bertsio hau zu moduko erabiltzaileei esker sortu da!" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on Ko-Fi." msgstr "" "Maite dut Bazaar garatzea, baina ezin dut lan hau bakarrik egin. Lagundu " "aplikazioaren garapena Ko-Fi erabilita dohaintza bat eginez." #: src/bz-donations-dialog.blp:131 msgid "Donate to Bazaar" msgstr "Lagundu Bazaar diruz" #. Translators: the %s format specifier will be something along the lines of "0.7.6" etc #: src/bz-donations-dialog.c:227 #, c-format msgid "What's New in %s?" msgstr "Zer berri %s bertsioan?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "%Y(e)ko %Bren %-e(e)an argitaratua" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Aukeratu instalazio bat" #: 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 "" "Aplikazio honen hainbat bertsio dituzu instalatuta. Zeinekin egin nahi duzu " "aurrera?" #: src/bz-entry-group-util.c:80 src/bz-rich-app-tile.blp:232 msgid "Cancel" msgstr "Utzi" #: src/bz-entry-selection-row.blp:17 msgid "For This User Only" msgstr "Erabiltzaile honentzat soilik" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "erabiltzaile hau" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "erabiltzaile guztiak" #: src/bz-error-dialog.blp:36 src/bz-error.c:69 src/bz-error.c:88 #: src/bz-safety-dialog.blp:46 msgid "Details" msgstr "Xehetasunak" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "Kopiatu" #: src/bz-error-dialog.c:56 src/bz-share-list.c:94 msgid "Copied!" msgstr "Kopiatuta!" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Gogokoen kopurua" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" msgstr "Huts egin du gogokoa eguneratzeak" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Hasi saioa Flathub-ekin gogokoak kudeatzeko" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Hasi saioa" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:56 #: src/bz-window.blp:334 msgid "Favorites" msgstr "Gogokoak" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "Instalatu dena" #: src/bz-favorites-page.blp:34 src/bz-user-data-page.blp:19 msgid "Loading" msgstr "Kargatzen" #: src/bz-favorites-page.blp:49 msgid "No Favorites" msgstr "Gogokorik ez" #: src/bz-favorites-page.blp:50 msgid "Applications you mark as favorite will appear here" msgstr "Gogoko gisa markatzen dituzun aplikazioak hemen azalduko dira" #: src/bz-favorites-tile.blp:60 src/bz-installed-tile.blp:69 msgid "Support This Application" msgstr "Babestu aplikazio hau" #: src/bz-favorites-tile.blp:109 msgid "Remove From Favorites" msgstr "Kendu gogokoetatik" #: src/bz-favorites-tile.c:353 msgid "Failed to remove favorite" msgstr "Huts egin du gogokoa kentzeak" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Aurrekoa" #: src/bz-featured-carousel.blp:54 msgid "Next" msgstr "Hurrengoa" #: src/bz-flathub-category.c:93 msgid "Editing" msgstr "Edizioa" #: src/bz-flathub-category.c:94 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:95 msgid "Mixer" msgstr "Nahasketa" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:96 src/bz-search-pill-list.c:77 msgid "Music" msgstr "Musika" #: src/bz-flathub-category.c:97 msgid "Player" msgstr "Erreproduzitzailea" #: src/bz-flathub-category.c:98 msgid "Recorder" msgstr "Grabatzailea" #: src/bz-flathub-category.c:99 msgid "Sequencer" msgstr "Sekuentziadorea" #: src/bz-flathub-category.c:100 msgid "Tuner" msgstr "Afinagailua / Sintonizadorea" #: src/bz-flathub-category.c:101 msgid "TV" msgstr "TB" #: src/bz-flathub-category.c:106 msgid "Emulation" msgstr "Emulazioa" #: src/bz-flathub-category.c:107 msgid "Action" msgstr "Akzioa" #: src/bz-flathub-category.c:108 msgid "Adventure" msgstr "Abentura" #: src/bz-flathub-category.c:109 msgid "Arcade" msgstr "Arkade" #: src/bz-flathub-category.c:110 msgid "Blocks" msgstr "Blokeak" #: src/bz-flathub-category.c:111 msgid "Board" msgstr "Mahai-jokoa" #: src/bz-flathub-category.c:112 msgid "Card" msgstr "Kartak" #: src/bz-flathub-category.c:113 msgid "Kids" msgstr "Haurrak" #: src/bz-flathub-category.c:114 msgid "Logic" msgstr "Logika" #: src/bz-flathub-category.c:115 msgid "Role Playing" msgstr "Rol jokoa" #: src/bz-flathub-category.c:116 msgid "Shooter" msgstr "Tiroak" #: src/bz-flathub-category.c:117 msgid "Simulation" msgstr "Simulazioa" #: src/bz-flathub-category.c:118 msgid "Sports" msgstr "Kirolak" #: src/bz-flathub-category.c:119 msgid "Strategy" msgstr "Estrategia" #: src/bz-flathub-category.c:124 msgid "Audio & Video" msgstr "Audioa eta bideoa" #: src/bz-flathub-category.c:124 msgid "Media" msgstr "Multimedia" #: src/bz-flathub-category.c:124 msgid "More Audio & Video" msgstr "Audio / bideo aplikazio gehiago" #: src/bz-flathub-category.c:125 msgid "Developer Tools" msgstr "Garapen tresnak" #: src/bz-flathub-category.c:125 msgid "Develop" msgstr "Garapena" #: src/bz-flathub-category.c:125 msgid "More Developer Tools" msgstr "Garapen tresna gehiago" #: src/bz-flathub-category.c:126 msgid "Education" msgstr "Hezkuntza" #: src/bz-flathub-category.c:126 msgid "Learn" msgstr "Ikasi" #: src/bz-flathub-category.c:126 msgid "More Education" msgstr "Hezkuntza aplikazio gehiago" #: src/bz-flathub-category.c:127 msgid "Gaming" msgstr "Jokoak" #: src/bz-flathub-category.c:127 msgid "Play" msgstr "Jolastu" #: src/bz-flathub-category.c:127 msgid "More Gaming" msgstr "Joko gehiago" #: src/bz-flathub-category.c:128 msgid "Graphics & Photography" msgstr "Grafikoak eta argazkigintza" #: src/bz-flathub-category.c:128 msgid "Create" msgstr "Sortu" #: src/bz-flathub-category.c:128 msgid "More Graphics & Photography" msgstr "Grafiko / argazkigintzako aplikazio gehiago" #: src/bz-flathub-category.c:129 msgid "Networking" msgstr "Sareak" #: src/bz-flathub-category.c:129 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:129 msgid "More Networking" msgstr "Sareko aplikazio gehiago" #: src/bz-flathub-category.c:130 msgid "Productivity" msgstr "Produktibitatea" #: src/bz-flathub-category.c:130 msgid "Work" msgstr "Lana" #: src/bz-flathub-category.c:130 msgid "More Productivity" msgstr "Produktibitate aplikazio gehiago" #: src/bz-flathub-category.c:131 msgid "Science" msgstr "Zientzia" #: src/bz-flathub-category.c:131 msgid "More Science" msgstr "Zientzia aplikazio gehiago" #: src/bz-flathub-category.c:132 msgid "System" msgstr "Sistema" #: src/bz-flathub-category.c:132 msgid "More System" msgstr "Sistema aplikazio gehiago" #: src/bz-flathub-category.c:133 msgid "Utilities" msgstr "Tresnak" #: src/bz-flathub-category.c:133 msgid "Tools" msgstr "Tresnak" #: src/bz-flathub-category.c:133 msgid "More Utilities" msgstr "Tresna gehiago" #: src/bz-flathub-category.c:134 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:148 msgid "Trending" msgstr "Pil-pilean" #: src/bz-flathub-category.c:134 msgid "More Trending" msgstr "Pil-pilean dauden aplikazio gehiago" #: src/bz-flathub-category.c:135 src/bz-flathub-page.blp:122 #: src/bz-flathub-page.blp:178 msgid "Popular" msgstr "Ezagunak" #: src/bz-flathub-category.c:135 msgid "More Popular" msgstr "Aplikazio ezagun gehiago" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:168 msgid "Recently Added" msgstr "Azkena gehituak" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:128 msgid "New" msgstr "Berriak" #: src/bz-flathub-category.c:136 msgid "More New" msgstr "Aplikazio berri gehiago" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:158 msgid "Recently Updated" msgstr "Berriki eguneratuak" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:134 msgid "Updated" msgstr "Eguneratuak" #: src/bz-flathub-category.c:137 msgid "More Updated" msgstr "Eguneratutako aplikazio gehiago" #: src/bz-flathub-category.c:138 msgid "Mobile" msgstr "Mugikorrerako" #: src/bz-flathub-category.c:138 msgid "More Mobile" msgstr "Mugikorrerako aplikazio gehiago" #: src/bz-flathub-category.c:139 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:139 msgid "More Adwaita" msgstr "Adwaita aplikazio gehiago" #: src/bz-flathub-category.c:140 msgid "KDE Apps" msgstr "KDE aplikazioak" #: src/bz-flathub-category.c:140 msgid "More KDE Apps" msgstr "KDE aplikazio gehiago" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Ez da Flathub gehitu" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "Ez da Flathub urrunekorik aurkitu zure Flatpak instalazioetan" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub-ek errorea itzuli du" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Saiatu Flathub-era berriro konektatzen" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub ez dago eskuragarri" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Ezin izan gara Flathub-era konektatu. Halere, aplikazioak kudeatu eta bila " "ditzakezu oraindik." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Bilatu aplikazioak" #: src/bz-flathub-page.blp:205 msgid "App of the Day" msgstr "Eguneko aplikazioa" #: src/bz-flathub-page.blp:268 msgid "On the Go" msgstr "Aldean" #: src/bz-flathub-page.blp:280 msgid "Apps for your Linux phones and tablets" msgstr "Linux mugikor eta tabletentzako aplikazioak" #: src/bz-flathub-page.blp:291 src/bz-flathub-page.blp:326 msgid "More Mobile Apps" msgstr "Aplikazio mugikor gehiago" #: src/bz-flathub-page.blp:382 msgid "We​ ♥​ Games" msgstr "Guk ere ♥​ ditugu jokoak" #: src/bz-flathub-page.blp:395 msgid "Games and apps to run your favorite titles" msgstr "Gogokoen dituzun jokoak eta hauentzako aplikazioak" #: src/bz-flathub-page.blp:429 msgid "More Games" msgstr "Joko gehiago" #: src/bz-full-view.blp:34 src/bz-library-page.blp:78 #: src/bz-library-page.blp:82 msgid "No Results" msgstr "Emaitzarik ez" #: src/bz-full-view.blp:35 msgid "Try a different search query" msgstr "Saiatu beste bilaketa batekin" #: src/bz-full-view.blp:41 msgid "Content" msgstr "Edukia" #: src/bz-full-view.blp:103 msgid "" "This is a local preview, some details may differ from the published listing" msgstr "" "Hau tokiko aurrebista da, baliteke xehetasun batzuk argitaratutako " "zerrendarekin bat ez etortzea" #: src/bz-full-view.blp:106 msgid "Preview Store Appearance" msgstr "Aurreikusi biltegiaren itxura" #: src/bz-full-view.blp:232 msgid "_Support" msgstr "_Babestu" #: src/bz-full-view.blp:431 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Aplikazio honek eguneratzerik edo segurtasun-konponketarik jasotzen ez duen " "exekuzio-ingurune bat darabil. Baliteke berau erabiltzea ez izatea segurua." #: src/bz-full-view.blp:518 msgid "Trash Data" msgstr "Bota datuak zakarrontzira" #: src/bz-full-view.blp:658 msgid "Tags:" msgstr "Etiketak:" #: src/bz-full-view.c:180 msgid "No URL" msgstr "URLrik ez" #: src/bz-full-view.c:198 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Aplikazio honek lizentzia libre eta irekia dauka, eta ondorioz, bere " "iturburu kodea segurtasun ikuspegitik audita daiteke." #: src/bz-full-view.c:199 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Aplikazio honek lizentzia pribatiboa dauka, eta ondorioz, bere iturburu " "kodea pribatuki garatzen da eta ezin du hirugarren independente batek " "auditatu." #: src/bz-full-view.c:206 msgid "More Apps" msgstr "Aplikazio gehiago" #: src/bz-full-view.c:207 #, c-format msgid "More Apps by %s" msgstr "%s(r)en aplikazio gehiago" #: src/bz-full-view.c:214 msgid "Other Apps by this Developer" msgstr "Garatzailearen beste aplikazioak" #: src/bz-full-view.c:216 src/bz-full-view.c:316 #, c-format msgid "Other Apps by %s" msgstr "%s(r)en beste aplikazioak" #: src/bz-full-view.c:225 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" "%s ez dago instalatua, baina oraindik %s daude gordeta datuetan." #: src/bz-full-view.c:318 msgid "Other Apps" msgstr "Bestelako aplikazioak" #: src/bz-full-view.c:320 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "Aplikazio %d" msgstr[1] "%d aplikazio" #: src/bz-full-view.c:536 src/bz-user-data-tile.c:144 msgid "Failed to Remove User Data" msgstr "Huts egin du erabiltzaile-datuak ezabatzeak" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Hardware euskarria" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Teklatu euskarria" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Teklatua behar du" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Teklatua gomendatzen du" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Teklatua onartzen du" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Teklatuentzako euskarria ezezaguna" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Sagu euskarria" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Sagua edo gailu erakuslea behar du" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Sagua edo gailu erakuslea gomendatzen du" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Sagua edo gailu erakuslea onartzen du" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Sagu edo gailu erakusleentzako euskarria ezezaguna" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Ukipen-pantaila euskarria" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Ukipen-pantaila behar du" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Ukipen-pantaila gomendatzen du" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Ukipen-pantaila onartzen du" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Ukipen-pantailentzako euskarria ezezaguna" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Mugikor euskarria" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Gailu mugikorretan funtzionatzen du" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Baliteke gailu mugikorretan behar bezala ez funtzionatzea" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Mahaigain euskarria" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Behar bezala funtzionatzen du pantaila handietan" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s hobeto dabil hardware batzuetan" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s(e)k gailu gehienetan funtzionatzen du" #: src/bz-install-controls.blp:62 msgid "_Open" msgstr "_Ireki" #: src/bz-install-controls.blp:77 src/bz-install-controls.blp:134 msgid "Uninstall Application" msgstr "Desinstalatu aplikazioa" #: src/bz-install-controls.blp:87 src/bz-transaction-dialog.c:230 msgid "_Remove" msgstr "_Kendu" #: src/bz-install-controls.blp:121 src/bz-updates-card.c:164 #: src/bz-updates-card.c:183 msgid "Update" msgstr "Eguneratu" #: src/bz-install-controls.blp:144 src/bz-installed-tile.blp:105 msgid "Remove" msgstr "Kendu" #: src/bz-install-controls.wdgt:32 msgctxt "Install Controls" msgid "Cancel" msgstr "Utzi" #: src/bz-install-controls.wdgt:35 msgctxt "Install Controls" msgid "Cancelling" msgstr "Uzten" #: src/bz-library-page.blp:32 msgid "Search installed apps" msgstr "Bilatu instalatutako aplikazioak" #: src/bz-library-page.blp:50 msgid "Clear search" msgstr "Garbitu bilaketa" #: src/bz-library-page.blp:71 msgid "No Apps Found" msgstr "Ez da aplikaziorik aurkitu" #: src/bz-library-page.blp:90 msgid "Search Store Instead" msgstr "Bilatu biltegian" #. Translators: . #: src/bz-library-page.blp:100 src/bz-window.blp:112 msgid "Library" msgstr "Liburutegia" #: src/bz-library-page.blp:128 msgid "Pending Updates" msgstr "Zain dauden eguneratzeak" #: src/bz-library-page.blp:155 msgid "Downloads" msgstr "Deskargak" #: src/bz-library-page.blp:198 msgid "Recently Uninstalled" msgstr "Berriki desinstalatuak" #: src/bz-library-page.blp:249 msgid "Clear Finished Tasks" msgstr "Garbitu amaitutako atazak" #: src/bz-library-page.blp:334 msgid "Sort By" msgstr "Ordenatu honela" #: src/bz-library-page.blp:348 msgid "Name" msgstr "Izena" #: src/bz-library-page.blp:354 msgid "Size" msgstr "Tamaina" #: src/bz-library-page.c:180 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "" "Ez da \"%s\" bilaketarekin bat datorren emaitzarik aurkitu instalatutako " "aplikazioen zerrendan" #: src/bz-library-page.c:193 src/bz-updates-card.c:433 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "Eguneratze %u erabilgarri" msgstr[1] "%u eguneratze erabilgarri" #: src/bz-library-page.c:203 #, c-format msgid "%u Installed App" msgid_plural "%u Installed Apps" msgstr[0] "Aplikazio %u instalatuta" msgstr[1] "%u aplikazio instalatuta" #: src/bz-license-dialog.blp:94 msgid "Get Involved" msgstr "Hartu parte" #: src/bz-license-dialog.blp:111 msgid "Learn More" msgstr "Informazio gehiago" #: src/bz-license-dialog.c:127 msgid "Unknown License" msgstr "Lizentzia ezezaguna" #: src/bz-license-dialog.c:130 msgid "Community Built" msgstr "Komunitateak eraikia" #: src/bz-license-dialog.c:203 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Aplikazio hau nazioarteko komunitate batek eraiki du modu irekian.\n" "\n" "Parte hartuz hobetzen lagun dezakezu." #: src/bz-license-dialog.c:206 msgid "The license of this app is not known" msgstr "Ez da aplikazio honen lizentzia ezagutzen" #: src/bz-license-dialog.c:212 #, 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 "" "Aplikazio hau nazioarteko komunitate batek eraiki du modu irekian, eta %s " "lizentziapean askatu du.\n" "\n" "Parte hartuz hobetzen lagun dezakezu." #: src/bz-license-dialog.c:220 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 "" "Aplikazio hau ez da modu irekian garatu eta, beraz, bere garatzaileek soilik " "dakite nola funtzionatzen duen. Baliteke segurua ez izatea antzemateko zaila " "den eran, eta inork ikuskatu gabe alda daiteke.\n" "\n" "Ezin dugu ziurtatu aplikazio honen garapenean lagun dezakezunik." #: src/bz-license-dialog.c:226 #, 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 "" "Aplikazio hau %s lizentzia berezipean garatu da.\n" "\n" "Ezin dugu ziurtatu aplikazio honen garapenean lagun dezakezunik." #: src/bz-license-dialog.c:356 src/bz-safety-dialog.blp:49 msgid "License" msgstr "Lizentzia" #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Konektatu Flathub-era" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Zerbaitek ez du funtzionatu" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" "Konektatu zure Flathub kontua Bazaarrera gogoko aplikazioak kudeatzeko." #: src/bz-login-page.blp:110 msgid "Finish" msgstr "Amaitu" #: src/bz-login-page.c:664 #, c-format msgid "Hello, %s!" msgstr "Kaixo, %s!" #: src/bz-metainfo-preview.c:84 msgid "Select Metainfo File" msgstr "Hautatu metainfo fitxategia" #: src/bz-metainfo-preview.c:87 msgid "Metainfo Files" msgstr "Metainfo fitxategiak" #: src/bz-metainfo-preview.c:141 msgid "Select Icon (Optional)" msgstr "Hautatu ikonoa (aukerakoa)" #: src/bz-metainfo-preview.c:144 msgid "Image Files" msgstr "Irudi fitxategiak" #: src/bz-metainfo-preview.c:231 msgid "Preview" msgstr "Aurrebista" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Hobespenak" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data refresh is paused" msgstr "" "Sareko konexioa neurtua da — biltegiko datuen berritze automatikoa pausatu da" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:232 msgid "Refresh Manually" msgstr "Berritu eskuz" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Eduki iragazkiak" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Software librea soilik" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "Ezkutatu aplikazio pribatiboak nabigatzean eta bilatzean" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Flathub-eko emaitzak soilik" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Mugatu bilaketa eta nabigazioko emaitzak Flathub-en erabilgarri dauden " "aplikazioetara" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "Egiaztatutako emaitzak soilik" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Ezkutatu Flathub-ek egiaztatu gabeko emaitzak" #: src/bz-preferences-dialog.blp:49 msgid "Hide End-of-Life Apps" msgstr "Ezkutatu bizirik ez dauden aplikazioak" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "Ezkutatu garatzaileek mantentzen ez dituzten aplikazioak" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:127 msgid "Search" msgstr "Bilaketa" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Atzeratu bilaketen emaitzak" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "" "Hobetu emaitzak erakusteko errendimendua, bilaketako hitzak berehala ez " "prozesatuz" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "Aurrerapen barra" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "Aukeratu aurrerapen barrarako gaia!" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "Marra bertikalak" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from left to right" msgstr "Erakutsi banderen koloreak ezkerretik eskuinerantz" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Kolore orokorra" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Harrotasunaren koloreak" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Harrotasun lesbianaren koloreak" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "Gay harrotasunaren koloreak" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Trans harrotasunaren koloreak" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Ez-bitar harrotasunaren koloreak" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "Harrotasun bisexualaren koloreak" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "Harrotasun asexualaren koloreak" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Harrotasun pansexualaren koloreak" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Harrotasun arromantikoaren koloreak" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Genero fluido harrotasunaren koloreak" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Harrotasun polisexualaren koloreak" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Harrotasun omnisexualaren koloreak" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "Harrotasun arromantiko asexualaren koloreak" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "Genero gabeko harrotasunaren koloreak" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "Kuir harrotasunaren koloreak" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "Intersex harrotasunaren koloreak" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "Demigenero harrotasunaren koloreak" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "Harrotasun birromantikoaren koloreak" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "Ezgaitasun harrotasunaren koloreak" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "Femboy harrotasunaren koloreak" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "Genero neutroko harrotasunaren koloreak" #: src/bz-releases-dialog.blp:5 src/bz-updates-card.c:155 msgid "Version History" msgstr "Bertsioen historia" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "_Bertsioen historia" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "Gaur" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "Atzo" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "Duela egun %d" msgstr[1] "Duela %d egun" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "Duela astebete" msgstr[1] "Duela %d aste" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "Duela hilabete" msgstr[1] "Duela %d hilabete" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "Duela urtebete" msgstr[1] "Duela %d urte" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%Y %b %e" #: src/bz-releases-list.c:196 #, c-format msgid "Version %s" msgstr "%s bertsioa" #: src/bz-releases-list.c:251 msgid "No details for this release" msgstr "Xehetasunik ez argitaratze honentzat" #: src/bz-releases-list.c:263 msgid "Get More Information" msgstr "Eskuratu informazio gehiago" #: src/bz-rich-app-tile.blp:217 msgid "Uninstall" msgstr "Desinstalatu" #. Translators: If you can't find a short enough translation, use "/" to use an icon instead. #: src/bz-rich-app-tile.c:369 msgid "Get" msgstr "Eskuratu" #: src/bz-safety-calculator.c:87 msgid "Unknown Permissions" msgstr "Baimen ezezagunak" #: src/bz-safety-calculator.c:88 msgid "Permissions are missing for this app." msgstr "Aplikazio honen baimenak ezezagunak dira." #: src/bz-safety-calculator.c:101 msgid "No Permissions" msgstr "Baimenik ez" #: src/bz-safety-calculator.c:102 msgid "App is fully sandboxed" msgstr "Aplikazioa guztiz isolatua dago" #: src/bz-safety-calculator.c:108 msgid "Network Access" msgstr "Sarera sarbidea" #: src/bz-safety-calculator.c:109 msgid "Can access the internet" msgstr "Internetera sarbidea dauka" #: src/bz-safety-calculator.c:111 msgid "No Network Access" msgstr "Sarera sarbiderik ez" #: src/bz-safety-calculator.c:112 msgid "Cannot access the internet" msgstr "Ez dauka Internetera sarbiderik" #: src/bz-safety-calculator.c:117 msgid "User Device Access" msgstr "Erabiltzailearen gailuetara sarbidea" #: src/bz-safety-calculator.c:118 msgid "Can access devices such as webcams or gaming controllers" msgstr "Web kamera eta joko-aginteen erako gailuetara sarbidea dauka" #: src/bz-safety-calculator.c:120 msgid "No User Device Access" msgstr "Erabiltzailearen gailuetara sarbiderik ez" #: src/bz-safety-calculator.c:121 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "Ez dauka web kamera eta joko-aginteen erako gailuetara sarbiderik" #: src/bz-safety-calculator.c:126 msgid "Input Device Access" msgstr "Sarrerako gailuetara sarbidea" #: src/bz-safety-calculator.c:127 msgid "Can access input devices" msgstr "Sarrerako gailuetara sarbidea dauka" #: src/bz-safety-calculator.c:133 msgid "Microphone Access and Audio Playback" msgstr "Mikrofonora eta audio erreprodukziora sarbidea" #: src/bz-safety-calculator.c:134 msgid "Can listen using microphones and play audio without asking permission" msgstr "" "Mikrofonotik entzun eta audioa erreproduzitu dezake baimenik eskatu gabe" #: src/bz-safety-calculator.c:140 msgid "System Device Access" msgstr "Sistemako gailuetara sarbidea" #: src/bz-safety-calculator.c:141 msgid "Can access system devices which require elevated permissions" msgstr "Goragoko baimenak behar dituzten sistemako gailuetara sarbidea dauka" #: src/bz-safety-calculator.c:147 msgid "Screen Contents Access" msgstr "Pantailako edukietara sarbidea" #: src/bz-safety-calculator.c:148 msgid "Can access the contents of the screen or other windows" msgstr "Pantailako edo beste leihoetako edukia ikus dezake" #: src/bz-safety-calculator.c:154 msgid "Legacy Windowing System" msgstr "Leiho-sistema legatua" #: src/bz-safety-calculator.c:155 msgid "Always uses a legacy windowing system (X11)" msgstr "Leiho-sistema legatua (X11) darabil beti" #: src/bz-safety-calculator.c:161 msgid "Arbitrary Permissions" msgstr "Baimen arbitrarioak" #: src/bz-safety-calculator.c:162 msgid "Can acquire arbitrary permissions" msgstr "Baimen arbitrarioak eskura ditzake" #: src/bz-safety-calculator.c:168 msgid "User Settings" msgstr "Erabiltza ezarpenak" #: src/bz-safety-calculator.c:169 msgid "Can access and change user settings" msgstr "Erabiltzaile ezarpenak atzitu eta alda ditzake" #: src/bz-safety-calculator.c:175 msgid "Full File System Read/Write Access" msgstr "Fitxategi-sistema osoan irakurri/idazteko sarbidea" #: src/bz-safety-calculator.c:176 msgid "Can read and write all data on the file system" msgstr "Fitxategi-sistemako datu guztiak irakurri eta idatz ditzake" #: src/bz-safety-calculator.c:183 msgid "Home Folder Read/Write Access" msgstr "Karpeta nagusian irakurri/idazteko sarbidea" #: src/bz-safety-calculator.c:184 msgid "Can read and write all data in your home directory" msgstr "Karpeta nagusiko datu guztiak irakurri eta idatz ditzake" #: src/bz-safety-calculator.c:191 msgid "Full File System Read Access" msgstr "Fitxategi-sistema osoa irakurtzeko sarbidea" #: src/bz-safety-calculator.c:192 msgid "Can read all data on the file system" msgstr "Fitxategi-sistemako datu guztiak irakur ditzake" #: src/bz-safety-calculator.c:200 msgid "Home Folder Read Access" msgstr "Karpeta nagusian irakurtzeko sarbidea" #: src/bz-safety-calculator.c:201 msgid "Can read all data in your home directory" msgstr "Karpeta nagusiko datu guztiak irakur ditzake" #: src/bz-safety-calculator.c:209 msgid "Download Folder Read/Write Access" msgstr "Deskarga karpetan irakurri/idazteko sarbidea" #: src/bz-safety-calculator.c:210 msgid "Can read and write all data in your downloads directory" msgstr "Deskarga karpetako datu guztiak irakurri eta idatz ditzake" #: src/bz-safety-calculator.c:220 msgid "Download Folder Read Access" msgstr "Deskarga karpeta irakurtzeko sarbidea" #: src/bz-safety-calculator.c:221 msgid "Can read all data in your downloads directory" msgstr "Deskarga karpetako datu guztiak irakur ditzake" #: src/bz-safety-calculator.c:242 msgid "Can read and write all data in the directory" msgstr "Direktorioko datu guztiak irakurri eta idatz ditzake" #: src/bz-safety-calculator.c:266 msgid "Can read all data in the directory" msgstr "Direktorioko datu guztiak irakur ditzake" #: src/bz-safety-calculator.c:281 msgid "No File System Access" msgstr "Fitxategi-sistemara sarbiderik ez" #: src/bz-safety-calculator.c:282 msgid "Cannot access the file system at all" msgstr "Ezin du fitxategi-sistema inola ere atzitu" #: src/bz-safety-calculator.c:289 msgid "Uses System Services" msgstr "Sistemako zerbitzuak darabiltza" #: src/bz-safety-calculator.c:290 msgid "Can request data from non-portal system services" msgstr "Sistemako zerbitzu zuzenei datuak eska diezazkieke" #: src/bz-safety-calculator.c:296 msgid "Uses Session Services" msgstr "Saioko zerbitzuak darabiltza" #: src/bz-safety-calculator.c:297 msgid "Can request data from non-portal session services" msgstr "Saioko zerbitzu zuzenei datuak eska diezazkieke" #: src/bz-safety-calculator.c:345 msgid "No Service Access" msgstr "Ez du zerbitzuetara sarbiderik" #: src/bz-safety-calculator.c:346 msgid "Cannot access non-portal session or system services at all" msgstr "Ez dauka sistemako edo saioko zerbitzu zuzenetara inolako sarbiderik" #: src/bz-safety-calculator.c:354 msgid "Verified App Developer" msgstr "Aplikazio garatzaile egiaztatua" #: src/bz-safety-calculator.c:355 msgid "The developer of this app has been verified to be who they say they are" msgstr "Aplikazio honen garatzailea berak dioen hura dela egiaztatu da" #: src/bz-safety-calculator.c:364 msgid "Proprietary Code" msgstr "Kode pribatiboa" #: src/bz-safety-calculator.c:365 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "Iturburu kodea ez da publikoa, ezin da era independentean auditatu, eta " "baliteke segurua ez izatea" #: src/bz-safety-calculator.c:375 msgid "Auditable Code" msgstr "Kode auditagarria" #: src/bz-safety-calculator.c:376 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "Iturburu kodea publikoa da, independenteki audita daiteke, eta aplikazioa " "segurua izatea errazten du" #: src/bz-safety-calculator.c:516 #, c-format msgid "Use the %s System Service" msgstr "%s sistemako zerbitzuaren erabilera" #: src/bz-safety-calculator.c:520 #, c-format msgid "Use the %s Session Service" msgstr "%s saioko zerbitzuaren erabilera" #: src/bz-safety-calculator.c:524 #, c-format msgid "Use the %s Service" msgstr "%s zerbitzuaren erabilera" #: src/bz-safety-calculator.c:534 msgid "Can see the non-portal service" msgstr "Zuzeneko zerbitzua ikus dezake" #: src/bz-safety-calculator.c:536 msgid "Can talk to the non-portal service" msgstr "Zuzeneko zerbitzuarekin hitz egin dezake" #: src/bz-safety-calculator.c:538 msgid "Can own the non-portal service" msgstr "Zuzeneko zerbitzua beregana dezake" #: src/bz-safety-calculator.c:553 msgid "Global Menu Integration" msgstr "Menu orokorrarekin integrazioa" #: src/bz-safety-calculator.c:554 msgid "Can display its menus in a global menu bar" msgstr "Bere menuak menu orokorraren barran erakuts ditzake" #: src/bz-safety-calculator.c:559 msgid "KDE Settings Integration" msgstr "KDEren ezarpenekin integrazioa" #: src/bz-safety-calculator.c:560 msgid "Can detect when KDE desktop settings change" msgstr "KDE mahaigaineko ezarpenen aldaketak antzeman ditzake" #: src/bz-safety-calculator.c:565 msgid "KDE Global Settings" msgstr "KDEren ezarpen orokorrak" #: src/bz-safety-calculator.c:566 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "" "KDE mahaigaineko hobespenak irakur ditzake, esaterako letra-tipo eta " "koloreei buruzkoak" #: src/bz-safety-calculator.c:571 msgid "Secret Storage Service" msgstr "Biltegiratze sekretuaren zerbitzua" #: src/bz-safety-calculator.c:572 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "Bere pasahitzak sistemako gako-sorta erabiliz gorde eta eskura ditzake" #: src/bz-safety-calculator.c:577 msgid "Desktop Notifications Service" msgstr "Mahaigaineko jakinarazpenen zerbitzua" #: src/bz-safety-calculator.c:578 msgid "Can send desktop notifications" msgstr "Mahaigaineko jakinarazpenak bidal ditzake" #: src/bz-safety-calculator.c:584 msgid "System Tray Integration" msgstr "Sistemako erretiluarekin integrazioa" #: src/bz-safety-calculator.c:585 msgid "Can display an icon in the system tray" msgstr "Sistemako erretiluan ikono bat erakuts dezake" #: src/bz-safety-calculator.c:590 msgid "KDE Connect Integration" msgstr "KDE Connect-ekin integrazioa" #: src/bz-safety-calculator.c:591 msgid "Can interact with devices paired via KDE Connect" msgstr "KDE Connect bidez parekatutako gailuekin interaktua dezake" #: src/bz-safety-dialog.blp:59 msgid "App ID" msgstr "Aplikazioaren IDa" #: src/bz-safety-dialog.blp:69 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 "" "Aplikazio honek software plataformaren (SDK) bertsio zaharkitua darabil, eta " "baliteke konpondu gabeko akatsak edo segurtasun-zaurgarritasunak izatea." #: src/bz-safety-dialog.c:167 msgid "Safety" msgstr "Segurtasuna" #: src/bz-safety-dialog.c:226 #, c-format msgid "%s is Safe" msgstr "%s segurua da" #: src/bz-safety-dialog.c:231 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s(e)k ez dauka baimen ez segururik" #: src/bz-safety-dialog.c:236 #, c-format msgid "%s is Probably Safe" msgstr "%s segurua da, segur aski" #: src/bz-safety-dialog.c:241 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s beharbada segurua da" #: src/bz-safety-dialog.c:246 #, c-format msgid "%s is Unsafe" msgstr "%s ez da segurua" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Pantaila-argazkiak" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Aurreko pantaila-argazkia" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Hurrengo pantaila-argazkia" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Kopiatu irudia" #: src/bz-screenshot-page.blp:150 msgid "Reset View" msgstr "Berrezarri ikuspegia" #: src/bz-screenshot-page.blp:161 msgid "Zoom Out" msgstr "Urrundu" #: src/bz-screenshot-page.blp:171 msgid "Zoom In" msgstr "Gerturatu" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Pantaila-argazkien aurkezpena" #: src/bz-screenshots-carousel.blp:117 msgid "Open Screenshot Viewer" msgstr "Ireki pantaila-argazki ikustailea" #: src/bz-search-filter-popover.blp:18 src/bz-search-page.blp:83 msgid "Filters" msgstr "Iragazkiak" #: src/bz-search-filter-popover.blp:35 msgid "_Verified" msgstr "_Egiaztatua" #: src/bz-search-filter-popover.blp:42 msgid "_Free/Open" msgstr "_Librea/Irekia" #: src/bz-search-filter-popover.blp:49 msgid "Non-_EOL" msgstr "Bizirik" #: src/bz-search-filter-popover.blp:52 msgid "Filter out End-of-Life apps" msgstr "Ez erakutsi bizirik ez dauden aplikazioak" #: src/bz-search-filter-popover.blp:57 msgid "Categories" msgstr "Kategoriak" #: src/bz-search-page.blp:58 msgid "Search Apps, Games, Software" msgstr "Bilatu aplikazioak, jokoak, softwarea" #: src/bz-search-page.blp:70 msgid "Search Filters" msgstr "Bilaketa iragazkiak" #: src/bz-search-page.blp:100 msgid "Clear Search" msgstr "Garbitu bilaketa" #: src/bz-search-page.blp:192 msgid "Categories Unavailable" msgstr "Kategoriarik erabilgarri ez" #: src/bz-search-page.blp:193 msgid "Search for apps using the search bar above." msgstr "Bilatu aplikazioak goiko bilaketa-barra erabiliz." #: src/bz-search-page.blp:219 msgid "Browse Categories" msgstr "Arakatu kategoriak" #: src/bz-search-page.blp:361 msgid "No Applications Found" msgstr "Ez da aplikaziorik aurkitu" #: src/bz-search-page.c:247 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Ez da emaitzarik aurkitu \"%s\" bilaketarentzat Flathub-en" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "Bideoa" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "Bulegoa" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDFak" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "Egutegia" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "Mezularitza" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Paint" msgstr "Margoketa" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "VPN" msgstr "VPNa" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "Torrent" msgstr "Torrentak" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Emulator" msgstr "Emulatzailea" #: src/bz-share-list.c:55 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub-eko orria" #: src/bz-share-list.c:56 msgctxt "Project URL Type" msgid "Project Website" msgstr "Proiektuaren webgunea" #: src/bz-share-list.c:57 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Akatsen aztarnaria" #: src/bz-share-list.c:58 msgctxt "Project URL Type" msgid "FAQ" msgstr "Ohiko galderak" #: src/bz-share-list.c:59 msgctxt "Project URL Type" msgid "Help" msgstr "Laguntza" #: src/bz-share-list.c:60 msgctxt "Project URL Type" msgid "Donate" msgstr "Eman dirua" #: src/bz-share-list.c:61 msgctxt "Project URL Type" msgid "Translate" msgstr "Itzuli" #: src/bz-share-list.c:62 msgctxt "Project URL Type" msgid "Contact" msgstr "Kontaktua" #: src/bz-share-list.c:63 msgctxt "Project URL Type" msgid "Source Code" msgstr "Iturburu kodea" #: src/bz-share-list.c:64 msgctxt "Project URL Type" msgid "Contribute" msgstr "Lagundu" #: src/bz-share-list.c:153 msgid "Copy Link" msgstr "Kopiatu esteka" #: src/bz-share-list.c:164 msgid "Open Link" msgstr "Ireki esteka" #: src/bz-stats-dialog.blp:27 msgid "Timeline" msgstr "Denbora-lerroa" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Instalazioak:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Mundua" #: src/bz-stats-dialog.blp:69 msgid "Since 4/15/2024" msgstr "2024/04/15etik" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:130 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM instalazio guztira" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:133 #, c-format msgid "%.2fK Total Installs" msgstr "%.2fK instalazio guztira" #: src/bz-stats-dialog.c:135 #, c-format msgid "%'d Total Installs" msgstr "%'d instalazio guztira" #: src/bz-tag-list.c:78 msgid "No Results Found" msgstr "Ez da emaitzarik aurkitu" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "\"%s\" etiketadun aplikazioak" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "Huts egin du bilaketak" #: src/bz-transaction-dialog.c:154 msgid "Keep User Data" msgstr "Mantendu erabiltzaile-datuak" #: src/bz-transaction-dialog.c:155 msgid "Allow restoring personal settings & content" msgstr "Baimendu ezarpen eta eduki pertsonalak berrezartzea" #: src/bz-transaction-dialog.c:164 msgid "Delete All Data" msgstr "Ezabatu datu guztiak" #: src/bz-transaction-dialog.c:165 msgid "Permanently erase user data to save space" msgstr "Ezabatu betiko erabiltzaile-datuak lekua libratzeko" #: src/bz-transaction-dialog.c:190 #, c-format msgid "Install %s?" msgstr "%s instalatu?" #: src/bz-transaction-dialog.c:195 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Hautatu zein bertsio instalatu nahi duzun. Baliteke partekatutako beste " "osagai batzuk ere instalatzea." #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "Baliteke partekatutako osagai gehigarriak instalatzea" #: src/bz-transaction-dialog.c:200 src/bz-transaction-dialog.c:229 #: src/bz-transaction-dialog.c:274 src/bz-transaction-dialog.c:576 msgid "_Cancel" msgstr "_Utzi" #: src/bz-transaction-dialog.c:201 msgid "_Install" msgstr "_Instalatu" #: src/bz-transaction-dialog.c:218 #, c-format msgid "Remove %s?" msgstr "%s kendu?" #: src/bz-transaction-dialog.c:221 msgid "Select which version to remove." msgstr "Hautatu kendu beharreko bertsioa." #: src/bz-transaction-dialog.c:223 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Ezin izango duzu %s erabili desinstalatu ondoren." #: src/bz-transaction-dialog.c:246 #, c-format msgid "“%s” is High Risk" msgstr "\"%s\" arrisku handikoa da" #: src/bz-transaction-dialog.c:250 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 "" "Aplikazio honek sistemara sarbide osoa dauka, zure fitxategi guztiak, " "nabigatze-historia, gordetako pasahitzak eta gehiago atzitzeko baimena " "barne. Internetera sarbidea ere badauka, eta ondorioz, zure datuak kanpoko " "norbaiti bidal diezazkioke.\n" "\n" "Aplikazio hau pribatiboa denez, ezin da auditatu baimen hauekin zer egiten " "duen aztertzeko." #: src/bz-transaction-dialog.c:259 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 "" "Aplikazio honek X11 leiho-sistema legatua darabil, eta honek teklatuko " "sakatze guztiak grabatu, pantaila-argazkiak atera eta beste aplikazioak " "monitorizatzea ahalbidetzen dio. Internetera sarbidea ere badauka, eta " "ondorioz, zure datuak kanpoko norbaiti bidal diezazkioke.\n" "\n" "Aplikazio hau pribatiboa denez, ezin da auditatu baimen hauekin zer egiten " "duen aztertzeko." #: src/bz-transaction-dialog.c:275 msgid "_Install Anyway" msgstr "_Instalatu halere" #: src/bz-transaction-dialog.c:330 msgid "Failed to load transaction dialog" msgstr "Huts egin du transakzioaren leihoa kargatzeak" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "Aplikazio guztiak instalatu dira dagoeneko" #: src/bz-transaction-dialog.c:549 msgid "_OK" msgstr "_Ados" #: src/bz-transaction-dialog.c:565 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "Aplikazioa instalatu?" msgstr[1] "%u aplikazioak instalatu?" #: src/bz-transaction-dialog.c:573 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" "Ondorengoa instalatuko da. Baliteke partekatutako osagai gehigarriak ere " "instalatzea." #: src/bz-transaction-dialog.c:574 #, c-format msgid "%d addons will be installed." msgstr "%d gehigarri instalatuko dira." #: src/bz-transaction-dialog.c:575 msgid "Additionally, addons will be installed." msgstr "Gainera, gehigarriak instalatuko dira." #: src/bz-transaction-dialog.c:577 msgid "_Install All" msgstr "_Instalatu dena" #: src/bz-transaction-manager.c:795 #, c-format msgid "Finished in %.02f seconds" msgstr "%.02f segundoan amaitua" #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "Aplikazioaren gehigarria" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "Exekuzio-ingurunea" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "Ilaran" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "Egina" #: src/bz-transaction-tile.blp:230 msgid "Cancelled" msgstr "Utzita" #: src/bz-transaction-tile.blp:254 msgid "Error" msgstr "Errorea" #: src/bz-transaction-tile.blp:312 msgid "Cancel Transaction" msgstr "Eten transakzioa" #: src/bz-transaction-tile.blp:436 msgid "Show Error Info" msgstr "Erakutsi errore-informazioa" #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "%s libratuta" #: src/bz-transaction-tile.c:360 src/bz-transaction-tile.c:363 msgid "Transaction Error" msgstr "Transakzio-errorea" #: src/bz-transaction.c:344 msgid "Pending" msgstr "Zain" #: src/bz-updates-card.blp:23 msgid "_Update All" msgstr "_Eguneratu dena" #: src/bz-updates-card.c:211 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "Exekuzio-ingurunearen eguneratze %u" msgstr[1] "Exekuzio-ingurunearen %u eguneratze" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Kudeatu soberako erabiltzaile-datuak" #: src/bz-user-data-page.blp:33 msgid "No User Data Found" msgstr "Ez da erabiltzaile-daturik aurkitu" #: src/bz-user-data-page.blp:38 msgid "User Data" msgstr "Erabiltzaile-datuak" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Bota erabiltzaile-datuak zakarrontzira" #: src/bz-user-data-tile.c:150 #, c-format msgid "Trashed User Data for %s" msgstr "%s(r)en erabiltzaile-datuak zakarrontzira bota dira" #: src/bz-window.blp:70 msgid "Refreshing" msgstr "Berritzen" #: src/bz-window.blp:88 msgid "Curated" msgstr "Aukeratua" #: src/bz-window.blp:100 msgid "Explore" msgstr "Arakatu" #: src/bz-window.blp:212 msgid "Main Menu" msgstr "Menu nagusia" #: src/bz-window.blp:223 msgid "You are running a new version of Bazaar!" msgstr "Bazaarren bertsio berria ari zara erabiltzen!" #: src/bz-window.blp:224 msgid "See What's New" msgstr "Ikusi berritasunak" #: src/bz-window.blp:231 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Sareko konexioa daukazu, baina Flathub-en bertsio cacheratua ari zara ikusten" #: src/bz-window.blp:276 msgid "_Donate to Bazaar" msgstr "_Lagundu Bazaar diruz" #: src/bz-window.blp:283 msgid "_Refresh" msgstr "_Berritu" #: src/bz-window.blp:288 msgid "_Preferences" msgstr "_Hobespenak" #: src/bz-window.blp:293 msgid "_Login With Flathub" msgstr "Hasi saioa _Flathub-en" #: src/bz-window.blp:299 msgid "_Manage Leftover User Data" msgstr "_Kudeatu soberako erabiltzaile-datuak" #: src/bz-window.blp:304 msgid "_Keyboard Shortcuts" msgstr "_Teklatuko lasterbideak" #: src/bz-window.blp:309 msgid "_About Bazaar" msgstr "B_azaarri buruz" #: src/bz-window.blp:316 msgid "_Quit Bazaar" msgstr "_Irten" #: src/bz-window.blp:341 msgid "Log Out" msgstr "Amaitu saioa" #. Translators: %s is the title of the current page #: src/bz-window.c:376 #, c-format msgid "Bazaar — %s" msgstr "Bazaar — %s" #: src/bz-window.c:596 src/bz-window.c:634 msgid "Failed to launch application" msgstr "Huts egin du aplikazioa abiarazteak" #: src/bz-window.c:843 msgid "You can't remove Bazaar from Bazaar!" msgstr "Ezin duzu Bazaar kendu Bazaar erabilita!" #: src/bz-window.c:1127 src/bz-window.c:1161 msgid "Can't do that right now!" msgstr "Orain ezin duzu hori egin!" #. Translators: As in, "1 Install" / "100 Installs" #: src/bz-world-map.c:604 msgid "Install" msgid_plural "Installs" msgstr[0] "instalazio" msgstr[1] "instalazio" #: src/shortcuts-dialog.blp:5 msgctxt "shortcut window" msgid "Navigation" msgstr "Nabigazioa" #: src/shortcuts-dialog.blp:8 msgctxt "shortcut window" msgid "Open Explore Page" msgstr "Ireki Arakatu orria" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "Ireki Liburutegia orria" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Open Search Page" msgstr "Ireki Bilaketa orria" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Remotes" msgstr "Urrunekoak" #: src/shortcuts-dialog.blp:27 msgctxt "shortcut window" msgid "Sync Remotes" msgstr "Sinkronizatu urrunekoak" #: src/shortcuts-dialog.blp:33 msgctxt "shortcut window" msgid "General" msgstr "Orokorra" #: src/shortcuts-dialog.blp:36 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Ireki hobespenak" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Erakutsi laster-teklak" #: src/shortcuts-dialog.blp:46 msgctxt "shortcut window" msgid "Close Window" msgstr "Itxi leihoa" #: src/shortcuts-dialog.blp:52 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "Irten" #~ msgid "User Data Size" #~ msgstr "Erabiltzaile-datuen tamaina" #~ msgctxt "About Dialog Developer Credit" #~ msgid "Adam Masciola " #~ msgstr "Adam Masciola " #~ msgctxt "About Dialog Developer Credit" #~ msgid "Alexander Vanhee" #~ msgstr "Alexander Vanhee" #~ msgid "Open App Library" #~ msgstr "Ireki aplikazioen liburutegia" #~ msgid "Installing .flatpak bundles is not yet supported" #~ msgstr "Oraingoz ez dago .flatpak sortak instalatzeko aukerarik" #~ msgid "Steam" #~ msgstr "Steam" #~ msgid "Minecraft" #~ msgstr "Minecraft" #~ msgid "Refresh completed!" #~ msgstr "Berrituta!" #~ msgctxt "As in, \"100 Installs\"" #~ msgid "Installs" #~ msgstr "instalazio" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "Berritu" #~ msgid "Adam Masciola" #~ msgstr "Adam Masciola" #~ msgid "_Donate to Bazaar ❤️" #~ msgstr "_Lagundu diruz Bazaar ❤️" #~ msgid "Flathub" #~ msgstr "Flathub" bazaar-org-bazaar-43ce9f7/po/fa_IR.po000066400000000000000000000411521520414637400173720ustar00rootroot00000000000000# 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 "خروج" bazaar-org-bazaar-43ce9f7/po/fr.po000066400000000000000000002667031520414637400170340ustar00rootroot00000000000000# French translations for Bazaar. # Copyright (C) 2025-2026 The Bazaar Contributors # 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. # SPDX-FileCopyrightText: 2025-2026 Mimolet # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-05-21 06:03+0200\n" "PO-Revision-Date: 2026-05-22 17:20+0200\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: Lokalize 26.04.1\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:45 #: src/bz-window.blp:199 src/bz-window.c:373 src/bz-window.c:374 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Ajoutez, désinstallez ou mettez à jour vos applications flatpak" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "" "GTK;System;Système;PackageManager;Gestionnaire de " "paquets;Discover;Flatpak;Software;Applis;Logiciel;Store;Magasin;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 manage applications" msgstr "Découvrez et gérez des applications" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "Une logithèque rapide et moderne pour Linux, spécialement conçue pour " "découvrir et installer des applications et des extensions Flatpak, notamment " "celles disponibles sur Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "Gérez plusieurs installations en même temps tout en naviguant" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "Consultez facilement les autorisations des applications" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "Connectez-vous à Flathub pour consulter et gérer vos favoris" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "Recherchez des applications directement depuis le Shell GNOME" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:30 src/bz-application.c:759 msgid "The Bazaar Contributors" msgstr "Les Contributeurs de Bazaar" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "The home page displaying Flathub apps" msgstr "Page d’accueil affichant les applis de Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:59 msgid "Exhibit app page" msgstr "Page de l’appli Exhibit" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "Page Bibliothèque" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "Page Recherche" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "Page Catégorie" #: src/bz-addon-tile.blp:64 src/bz-installed-tile.blp:55 #: src/bz-rich-app-tile.blp:141 msgid "Stopped Receiving Updates" msgstr "Utilise un environnement en fin de vie" #: src/bz-addon-tile.c:167 src/bz-favorites-tile.c:155 msgctxt "Install Controls" msgid "Uninstall" msgstr "Désinstaller" #: src/bz-addon-tile.c:169 src/bz-bundle-install-dialog.blp:126 #: src/bz-favorites-tile.c:157 src/bz-install-controls.wdgt:29 msgctxt "Install Controls" msgid "Install" msgstr "Installer" #: src/bz-addons-dialog.blp:14 src/bz-addons-dialog.blp:21 #: src/bz-addons-dialog.blp:70 src/bz-full-view.blp:583 #: src/bz-installed-tile.blp:92 msgid "Manage Add-Ons" msgstr "Gérer les extensions" #: src/bz-addons-dialog.blp:80 msgid "No Add-Ons Visible" msgstr "Aucune extension visible" #: src/bz-addons-dialog.blp:81 msgid "" "Your current filter preferences are hiding all known add-ons. Try adjusting " "them." msgstr "" "Toutes extensions connues de cette appli sont cachés par vos préférences de " "filtrage. Ajustez les pour voir les extensions cachées. " #: src/bz-addons-dialog.blp:88 msgid "Add-on Page" msgstr "Page des extensions" #: src/bz-addons-dialog.blp:202 src/bz-full-view.blp:381 msgid "Downloads/Month" msgstr "Téléchargements/mois" #: src/bz-addons-dialog.blp:229 src/bz-full-view.blp:417 msgid "Stopped Receiving Core Updates" msgstr "L'application utilise un environnement en fin de vie" #: src/bz-addons-dialog.blp:243 msgid "" "This add-on 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 extension ne reçoit plus de " "mises à jour ni de correctifs de sécurité.\n" "Son utilisation pourrait devenir risquée." #: src/bz-addons-dialog.c:333 #, c-format msgid "Add-on for %s" msgstr "Extension pour %s" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show Less" msgstr "Montrer moins" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show More" msgstr "Montrer plus" #: src/bz-addons-dialog.c:397 msgid "Download Stats" msgstr "Statistiques de téléchargement" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:736 src/bz-context-tile-callbacks.c:186 #: src/bz-context-tile-callbacks.c:193 msgid "Age Rating" msgstr "Classification 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:686 src/bz-context-tile-callbacks.c:176 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "Tout" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "%s a une limite d’âge inconnue" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "%s convient à tout le monde" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "%s convient aux jeunes enfants" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "%s convient aux enfants" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "%s convient aux adolescents" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "%s convient aux adultes" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "%s convient aux %s" #: src/bz-age-rating-dialog.c:862 #, c-format msgid "%s • %s" msgstr "%s • %s" #: 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:26 src/bz-app-size-dialog.blp:60 msgid "Download Size" msgstr "Taille du téléchargement" #: src/bz-app-size-dialog.blp:33 src/bz-app-size-dialog.blp:81 msgid "Installed Size" msgstr "Taille après installation" #: src/bz-app-size-dialog.blp:61 msgid "Amount to download from the internet" msgstr "Volume à télécharger depuis Internet" #: src/bz-app-size-dialog.blp:82 msgid "Size on Disk" msgstr "Taille sur le disque" #: src/bz-app-size-dialog.blp:133 msgid "Open user data folder" msgstr "Ouvrir le dossier des données utilisateur" #: src/bz-app-size-dialog.blp:143 msgid "Your User Data" msgstr "Vos données" #: src/bz-app-size-dialog.blp:144 msgid "Caches, settings, and other app data" msgstr "Caches, paramètres et autres données" #: src/bz-app-size-dialog.blp:165 msgid "Cache" msgstr "Cache" #: src/bz-app-size-dialog.blp:166 msgid "Temporary cached data" msgstr "Données mises en cache temporairement" #: src/bz-app-size-dialog.blp:176 msgid "Clear Cache" msgstr "Effacer le cache" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "Taille de l'environnement d’exécution" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "Taille du téléchargement de l'environnement d’exécution" #: src/bz-app-size-dialog.c:220 msgid "App Size" msgstr "Taille de l'appli" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:105 src/bz-rich-app-tile.c:429 msgid "Verified" msgstr "Vérifié" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-context-tile-callbacks.c:135 #: src/bz-releases-list.c:206 msgid "Installed" msgstr "Installée" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:762 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:772 msgid "Special Thanks" msgstr "Remerciements particuliers à" #: src/bz-application.c:830 msgid "Logged Out Successfully!" msgstr "Déconnexion réussie !" #: src/bz-application.c:966 msgid "Performing setup…" msgstr "Configuration en cours…" #: src/bz-application.c:1052 msgid "Set Up System Flathub?" msgstr "Configurer Flathub sur le système ? " #: src/bz-application.c:1055 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Le dépôt d'applications Flathub n’a pas été configuré sur ce système. Bazaar " "a besoin que Flathub soit configuré pour parcourir et installer des " "applications.\n" "\n" "Vous pouvez toujours utiliser Bazaar pour parcourir et désinstaller des " "applis déjà installées." #: src/bz-application.c:1062 msgid "Set Up Flathub?" msgstr "Configurer Flathub ?" #: src/bz-application.c:1065 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:1071 msgid "Later" msgstr "Plus tard" #: src/bz-application.c:1072 msgid "Set Up Flathub" msgstr "Configurer Flathub" #: src/bz-application.c:1408 msgid "A backend error occurred" msgstr "Une erreur de backend est survenue" #: src/bz-application.c:1608 src/bz-application.c:3767 msgid "Refreshing…" msgstr "Actualisation…" #: src/bz-application.c:1772 src/bz-application.c:3765 #, c-format msgid "Loading %d apps…" msgstr "Chargement de %d applis…" #: src/bz-application.c:1825 msgid "Failed to open file" msgstr "Échec de l’ouverture du fichier" #: src/bz-application.c:1930 msgid "An initialization error occurred" msgstr "Une erreur d'initialisation s'est produite" #: src/bz-application.c:2296 msgid "Checking for updates…" msgstr "Recherche de mises à jour…" #: src/bz-application.c:2352 msgid "Failed to check for updates" msgstr "Échec de la vérification des mises à jour" #: src/bz-application.c:3478 msgid "Malformed Link" msgstr "Lien corrigé" #: src/bz-application.c:3479 msgid "" "The link used to open this app has incorrect capitalization and may stop " "working in the future.\n" "\n" "This is most likely caused by KRunner sending incorrect app IDs" msgstr "" "Le lien utilisé pour ouvrir cette application a une majuscule incorrecte et " "a été corrigé par Bazaar.\n" "\n" "Il s'agit très probablement de KRunner qui envoie des identifiants " "d'application incorrects." #: src/bz-application.c:3487 msgid "Could not find app" msgstr "Impossible de trouver l'application" #: src/bz-application.c:3518 msgid "Failed to load metainfo" msgstr "Échec du chargement des métainfos" #: src/bz-application.c:3769 msgid "Writing to cache…" msgstr "Écriture dans le cache…" #: src/bz-apps-page.blp:99 msgid "Show All" msgstr "Tout afficher" #: src/bz-apps-page.c:237 #, c-format msgid "All \"%s\"" msgstr "Toutes les applis « %s »" #: src/bz-apps-page.c:487 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "%d applications" #: src/bz-bundle-install-dialog.blp:8 src/bz-bundle-install-dialog.blp:14 msgid "Bundle Installation" msgstr "Installation de paquet" #: src/bz-bundle-install-dialog.blp:147 msgid "Additional dependencies may take extra space" msgstr "" "Des dépendances additionnelles pourraient nécessiter de l'espace disque " "supplémentaire" #: src/bz-bundle-install-dialog.blp:181 msgid "" "Installing this app may require adding a new software source. Other apps " "from this source will show up in Bazaar.\n" "\n" "Only add this source if you're sure you trust it." msgstr "" "Installer cette application pourrait nécessiter l'ajout d'une nouvelle " "source de logiciels.\n" "D'autres applis de cette source apparaîtront alors dans Bazaar.\n" "\n" "N'ajoutez cette source que si vous lui faites confiance." #: src/bz-bundle-install-dialog.blp:357 msgid "Successfully Installed!" msgstr "Application installée avec succès!" #: src/bz-bundle-install-dialog.blp:381 src/bz-bundle-install-dialog.blp:463 #: src/bz-rich-app-tile.blp:198 src/bz-transaction-tile.blp:298 msgid "Open" msgstr "Ouvrir" #: src/bz-bundle-install-dialog.blp:391 src/bz-bundle-install-dialog.blp:473 msgid "Show App Details" msgstr "Voir les détails" #: src/bz-bundle-install-dialog.blp:440 msgid "Already Installed" msgstr "Déjà installée" #: src/bz-bundle-install-dialog.blp:485 msgid "Installation Failed" msgstr "Échec de l'installation" #: src/bz-bundle-install-dialog.c:169 msgid "Unknown install size" msgstr "Taille d'installation inconnue" #: src/bz-bundle-install-dialog.c:172 #, c-format msgid "About %s to install" msgstr "Environ %s à installer" #: src/bz-bundle-install-dialog.c:186 src/bz-context-tile-callbacks.c:104 #: src/bz-context-tile-callbacks.c:392 src/bz-context-tile-callbacks.c:409 msgid "N/A" msgstr "Inconnu" #: src/bz-bundle-install-dialog.c:215 msgid "No special permissions" msgstr "Aucune autorisation spéciale" #: src/bz-context-tile-callbacks.c:68 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-context-tile-callbacks.c:75 #, c-format msgid "%.*fM" msgstr "%.*f Mio." #. Translators: K is the suffix for thousands #: src/bz-context-tile-callbacks.c:82 #, c-format msgid "%.*fK" msgstr "%.*f mil." #: src/bz-context-tile-callbacks.c:92 #, c-format msgid "%d downloads in the last month" msgstr "%d téléchargements au cours du dernier mois" #: src/bz-context-tile-callbacks.c:132 #, c-format msgid "+%s runtime" msgstr "+%s d'environnement" #: src/bz-context-tile-callbacks.c:135 msgid "Download" msgstr "À télécharger" #: src/bz-context-tile-callbacks.c:155 msgid "Size information unavailable" msgstr "Informations sur la taille non disponibles" #: src/bz-context-tile-callbacks.c:158 #, c-format msgid "Download size of %s" msgstr "Taille du téléchargement de %s" #: src/bz-context-tile-callbacks.c:191 msgid "All Ages" msgstr "Tout public" #: src/bz-context-tile-callbacks.c:203 msgid "Age rating information unavailable" msgstr "Informations sur la classification d’âge non disponibles" #: src/bz-context-tile-callbacks.c:208 msgid "Suitable for all ages" msgstr "Convient à tout public" #: src/bz-context-tile-callbacks.c:210 #, c-format msgid "Suitable for ages %d and up" msgstr "Approprié dès %d ans et plus" #: src/bz-context-tile-callbacks.c:243 src/bz-context-tile-callbacks.c:248 #: src/bz-context-tile-callbacks.c:276 src/bz-context-tile-callbacks.c:284 msgid "Unknown" msgstr "Inconnue" #: src/bz-context-tile-callbacks.c:253 #, c-format msgid "Free software licensed under %s" msgstr "Logiciel libre sous licence %s" #: src/bz-context-tile-callbacks.c:258 msgid "Free software" msgstr "Logiciel libre" #: src/bz-context-tile-callbacks.c:261 msgid "Proprietary Software" msgstr "Logiciel propriétaire" #: src/bz-context-tile-callbacks.c:264 #, c-format msgid "Special License: %s" msgstr "Licence spéciale : %s" #: src/bz-context-tile-callbacks.c:281 msgid "Free" msgstr "Libre" #: src/bz-context-tile-callbacks.c:287 src/bz-license-dialog.c:133 msgid "Proprietary" msgstr "Propriétaire" #: src/bz-context-tile-callbacks.c:289 src/bz-license-dialog.c:135 msgid "Special License" msgstr "Licence spéciale" #: src/bz-context-tile-callbacks.c:309 msgid "Adaptive" msgstr "Adaptatif" #: src/bz-context-tile-callbacks.c:309 msgid "Desktop Only" msgstr "PC uniquement" #: src/bz-context-tile-callbacks.c:315 msgid "Works on desktop, tablets, and phones" msgstr "Fonctionne sur ordinateur, tablette et téléphone" #: src/bz-context-tile-callbacks.c:316 msgid "May not work on mobile devices" msgstr "Peut ne pas fonctionner sur les appareils mobiles" #: src/bz-context-tile-callbacks.c:399 src/bz-safety-dialog.blp:27 msgid "Safe" msgstr "Fiable" #: src/bz-context-tile-callbacks.c:401 src/bz-context-tile-callbacks.c:403 msgid "Low Risk" msgstr "Risque faible" #: src/bz-context-tile-callbacks.c:405 msgid "Medium Risk" msgstr "Risque moyen" #: src/bz-context-tile-callbacks.c:407 msgid "High Risk" msgstr "Risque élevé" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:46 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:30 #: src/bz-library-page.blp:67 src/bz-user-data-page.blp:30 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 possède pas de sélection d'applications. Vous pouvez " "toujours en chercher dans la logithèque" #: 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" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "Navigateur" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "Non-vérifié" #: src/bz-developer-badge.c:213 msgid "Developer information not available." msgstr "Informations sur le développeur non disponibles." #: src/bz-developer-badge.c:219 src/bz-developer-badge.c:233 #, 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 %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:237 #, 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 %s a été vérifiée par l’équipe Flathub." #: src/bz-developer-badge.c:253 #, 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 %1$s a été vérifiée par %2$s sur " "%3$s." #: src/bz-developer-badge.c:260 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "La propriété de l'identifiant %1$s a été vérifiée en utilisant %2$s." #: src/bz-developer-badge.c:264 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "La propriété de l'identifiant %s a été vérifiée." #: src/bz-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "Notes de version complètes" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "Bazaar existe grâce à vous !" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on Ko-Fi." msgstr "" "J'adore travailler sur Bazaar, mais je ne peux pas y arriver seule. Vous " "pouvez m'aider à poursuivre le développement en faisant un don sur Ko-Fi." #: src/bz-donations-dialog.blp:131 msgid "Donate to Bazaar" msgstr "Faire un don à Bazaar" #. Translators: the %s format specifier will be something along the lines of "0.7.6" etc #: src/bz-donations-dialog.c:227 #, c-format msgid "What's New in %s?" msgstr "Quoi de neuf en %s ?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "Publié le %-e %B %Y" #: 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-rich-app-tile.blp:232 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-dialog.blp:36 src/bz-error.c:69 src/bz-error.c:88 #: src/bz-safety-dialog.blp:46 msgid "Details" msgstr "Détails" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "Copier" #: src/bz-error-dialog.c:56 src/bz-share-list.c:94 msgid "Copied!" msgstr "Copié !" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Nombre de favoris" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" msgstr "Échec de la mise à jour des favoris" #: 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-favorites-page.blp:5 src/bz-favorites-page.blp:56 #: src/bz-window.blp:334 msgid "Favorites" msgstr "Favoris" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "Tout installer" #: src/bz-favorites-page.blp:34 src/bz-user-data-page.blp:19 msgid "Loading" msgstr "Chargement" #: src/bz-favorites-page.blp:49 msgid "No Favorites" msgstr "Pas de favoris" #: src/bz-favorites-page.blp:50 msgid "Applications you mark as favorite will appear here" msgstr "Les applications que vous marquerez comme favorites apparaîtront ici" #: src/bz-favorites-tile.blp:60 src/bz-installed-tile.blp:69 msgid "Support This Application" msgstr "Soutenez cette application" #: src/bz-favorites-tile.blp:109 msgid "Remove From Favorites" msgstr "Retirer des favoris" #: src/bz-favorites-tile.c:353 msgid "Failed to remove favorite" msgstr "Échec de la suppression du favori" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Précédent" #: src/bz-featured-carousel.blp:54 msgid "Next" msgstr "Suivant" #: src/bz-flathub-category.c:93 msgid "Editing" msgstr "Édition" #: src/bz-flathub-category.c:94 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:95 msgid "Mixer" msgstr "Mixage" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:96 src/bz-search-pill-list.c:77 msgid "Music" msgstr "Musique" #: src/bz-flathub-category.c:97 msgid "Player" msgstr "Lecteur" #: src/bz-flathub-category.c:98 msgid "Recorder" msgstr "Enregistreur" #: src/bz-flathub-category.c:99 msgid "Sequencer" msgstr "Séquenceur" #: src/bz-flathub-category.c:100 msgid "Tuner" msgstr "Accordeur" #: src/bz-flathub-category.c:101 msgid "TV" msgstr "TV" #: src/bz-flathub-category.c:106 msgid "Emulation" msgstr "Émulateurs" #: src/bz-flathub-category.c:107 msgid "Action" msgstr "Action" #: src/bz-flathub-category.c:108 msgid "Adventure" msgstr "Aventure" #: src/bz-flathub-category.c:109 msgid "Arcade" msgstr "Arcade" #: src/bz-flathub-category.c:110 msgid "Blocks" msgstr "Blocs" #: src/bz-flathub-category.c:111 msgid "Board" msgstr "Plateau" #: src/bz-flathub-category.c:112 msgid "Card" msgstr "Jeux de cartes" #: src/bz-flathub-category.c:113 msgid "Kids" msgstr "Jeux pour enfants" #: src/bz-flathub-category.c:114 msgid "Logic" msgstr "Logique" #: src/bz-flathub-category.c:115 msgid "Role Playing" msgstr "Jeux de rôle" #: src/bz-flathub-category.c:116 msgid "Shooter" msgstr "Jeux de tir" #: src/bz-flathub-category.c:117 msgid "Simulation" msgstr "Simulation" #: src/bz-flathub-category.c:118 msgid "Sports" msgstr "Sports" #: src/bz-flathub-category.c:119 msgid "Strategy" msgstr "Jeux de stratégie" #: src/bz-flathub-category.c:124 msgid "Audio & Video" msgstr "Audio & Vidéo" #: src/bz-flathub-category.c:124 msgid "Media" msgstr "Média" #: src/bz-flathub-category.c:124 msgid "More Audio & Video" msgstr "Plus d’applis audio & vidéo" #: src/bz-flathub-category.c:125 msgid "Developer Tools" msgstr "Outils de Développement" #: src/bz-flathub-category.c:125 msgid "Develop" msgstr "Coder" #: src/bz-flathub-category.c:125 msgid "More Developer Tools" msgstr "Plus d’outils de développement" #: src/bz-flathub-category.c:126 msgid "Education" msgstr "Éducation" #: src/bz-flathub-category.c:126 msgid "Learn" msgstr "Apprendre" #: src/bz-flathub-category.c:126 msgid "More Education" msgstr "Plus d’applis éducatives" #: src/bz-flathub-category.c:127 msgid "Gaming" msgstr "Jeux vidéos" #: src/bz-flathub-category.c:127 msgid "Play" msgstr "Jouer" #: src/bz-flathub-category.c:127 msgid "More Gaming" msgstr "Plus de jeux" #: src/bz-flathub-category.c:128 msgid "Graphics & Photography" msgstr "Graphisme & Photographie" #: src/bz-flathub-category.c:128 msgid "Create" msgstr "Créer" #: src/bz-flathub-category.c:128 msgid "More Graphics & Photography" msgstr "Plus d’applis de graphisme et photographie" #: src/bz-flathub-category.c:129 msgid "Networking" msgstr "Réseau" #: src/bz-flathub-category.c:129 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:129 msgid "More Networking" msgstr "Plus d’applis réseau" #: src/bz-flathub-category.c:130 msgid "Productivity" msgstr "Productivité" #: src/bz-flathub-category.c:130 msgid "Work" msgstr "Travailler" #: src/bz-flathub-category.c:130 msgid "More Productivity" msgstr "Plus d’applis de productivité" #: src/bz-flathub-category.c:131 msgid "Science" msgstr "Sciences" #: src/bz-flathub-category.c:131 msgid "More Science" msgstr "Plus d’applis scientifiques" #: src/bz-flathub-category.c:132 msgid "System" msgstr "Système" #: src/bz-flathub-category.c:132 msgid "More System" msgstr "Plus d’applis système" #: src/bz-flathub-category.c:133 msgid "Utilities" msgstr "Utilitaires" #: src/bz-flathub-category.c:133 msgid "Tools" msgstr "Outils" #: src/bz-flathub-category.c:133 msgid "More Utilities" msgstr "Plus d’utilitaires" #: src/bz-flathub-category.c:134 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:148 msgid "Trending" msgstr "Tendances" #: src/bz-flathub-category.c:134 msgid "More Trending" msgstr "Plus de tendances" #: src/bz-flathub-category.c:135 src/bz-flathub-page.blp:122 #: src/bz-flathub-page.blp:178 msgid "Popular" msgstr "Populaires" #: src/bz-flathub-category.c:135 msgid "More Popular" msgstr "Plus d’applis populaires" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:168 msgid "Recently Added" msgstr "Ajoutées récemment" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:128 msgid "New" msgstr "Nouveautés" #: src/bz-flathub-category.c:136 msgid "More New" msgstr "Plus de nouveautés" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:158 msgid "Recently Updated" msgstr "Mises à jour récemment" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:134 msgid "Updated" msgstr "Mises à jour" #: src/bz-flathub-category.c:137 msgid "More Updated" msgstr "Plus d’applis mises à jour" #: src/bz-flathub-category.c:138 msgid "Mobile" msgstr "Mobile" #: src/bz-flathub-category.c:138 msgid "More Mobile" msgstr "Plus d’applis mobiles" #: src/bz-flathub-category.c:139 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:139 msgid "More Adwaita" msgstr "Plus d’applis Adwaita" #: src/bz-flathub-category.c:140 msgid "KDE Apps" msgstr "KDE" #: src/bz-flathub-category.c:140 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:205 msgid "App of the Day" msgstr "Appli du jour" #: src/bz-flathub-page.blp:268 msgid "On the Go" msgstr "Sur tous vos écrans" #: src/bz-flathub-page.blp:280 msgid "Apps for your Linux phones and tablets" msgstr "Applis pour vos téléphones et tablettes Linux" #: src/bz-flathub-page.blp:291 src/bz-flathub-page.blp:326 msgid "More Mobile Apps" msgstr "Plus d’applis mobiles" #: src/bz-flathub-page.blp:382 msgid "We​ ♥​ Games" msgstr "Nous + jeux = ♥" #: src/bz-flathub-page.blp:395 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:429 msgid "More Games" msgstr "Plus de jeux" #: src/bz-full-view.blp:34 src/bz-library-page.blp:78 #: src/bz-library-page.blp:82 msgid "No Results" msgstr "Aucun résultat" #: src/bz-full-view.blp:35 msgid "Try a different search query" msgstr "Essayez une autre recherche" #: src/bz-full-view.blp:41 msgid "Content" msgstr "Contenu" #: src/bz-full-view.blp:103 msgid "" "This is a local preview, some details may differ from the published listing" msgstr "" "Ceci est une prévisualisation locale, quelques détails pourraient être " "différents du résultat publié" #: src/bz-full-view.blp:106 msgid "Preview Store Appearance" msgstr "Prévisualiser dans la logithèque" #: src/bz-full-view.blp:232 msgid "_Support" msgstr "_Soutenir" #: src/bz-full-view.blp:431 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 application ne reçoit plus de " "mises à jour ni de correctifs de sécurité.\n" "Son utilisation pourrait devenir risquée." #: src/bz-full-view.blp:518 msgid "Trash Data" msgstr "Supprimer les données" #: src/bz-full-view.blp:658 msgid "Tags:" msgstr "Étiquettes :" #: src/bz-full-view.c:180 msgid "No URL" msgstr "Aucune URL" #: src/bz-full-view.c:198 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:199 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:206 msgid "More Apps" msgstr "Plus d’applis" #: src/bz-full-view.c:207 #, c-format msgid "More Apps by %s" msgstr "Plus d’applis par %s" #: src/bz-full-view.c:214 msgid "Other Apps by this Developer" msgstr "D’autres applis de ce développeur" #: src/bz-full-view.c:216 src/bz-full-view.c:316 #, c-format msgid "Other Apps by %s" msgstr "D’autres applis par %s" #: src/bz-full-view.c:225 #, 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:318 msgid "Other Apps" msgstr "D’autres applis" #: src/bz-full-view.c:320 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d application" msgstr[1] "%d applications" #: src/bz-full-view.c:536 src/bz-user-data-tile.c:144 msgid "Failed to Remove User Data" msgstr "Échec de la suppression des données utilisateurs" #: 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 "Peut ne pas fonctionner correctement sur les appareils mobiles" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Prise en charge PC" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Fonctionne bien sur grands écrans" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s fonctionne mieux sur certains appareils" #: 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-install-controls.blp:62 msgid "_Open" msgstr "_Ouvrir" #: src/bz-install-controls.blp:77 src/bz-install-controls.blp:134 msgid "Uninstall Application" msgstr "Désinstaller l’application" #: src/bz-install-controls.blp:87 src/bz-transaction-dialog.c:230 msgid "_Remove" msgstr "_Désinstaller" #: src/bz-install-controls.blp:121 src/bz-updates-card.c:164 #: src/bz-updates-card.c:183 msgid "Update" msgstr "Mettre à jour" #: src/bz-install-controls.blp:144 src/bz-installed-tile.blp:105 msgid "Remove" msgstr "Désinstaller" #: src/bz-install-controls.wdgt:32 msgctxt "Install Controls" msgid "Cancel" msgstr "Annuler" #: src/bz-install-controls.wdgt:35 msgctxt "Install Controls" msgid "Cancelling" msgstr "Annulation" #: src/bz-library-page.blp:32 msgid "Search installed apps" msgstr "Rechercher des applis installées" #: src/bz-library-page.blp:50 msgid "Clear search" msgstr "Effacer la recherche" #: src/bz-library-page.blp:71 msgid "No Apps Found" msgstr "Aucune appli trouvée" #: src/bz-library-page.blp:90 msgid "Search Store Instead" msgstr "Rechercher plutôt dans la logithèque" # "Bibliothèque" est trop long sous un format "mobile" #. Translators: . #: src/bz-library-page.blp:100 src/bz-window.blp:112 msgid "Library" msgstr "Bibliothèque" #: src/bz-library-page.blp:128 msgid "Pending Updates" msgstr "Mises à jour en attente" #: src/bz-library-page.blp:155 msgid "Downloads" msgstr "Téléchargements" #: src/bz-library-page.blp:198 msgid "Recently Uninstalled" msgstr "Désinstallées récemment" #: src/bz-library-page.blp:249 msgid "Clear Finished Tasks" msgstr "Effacer les tâches effectuées" #: src/bz-library-page.blp:334 msgid "Sort By" msgstr "Trier par" #: src/bz-library-page.blp:348 msgid "Name" msgstr "Nom" #: src/bz-library-page.blp:354 msgid "Size" msgstr "Taille" #: src/bz-library-page.c:180 #, 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:193 src/bz-updates-card.c:433 #, 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-library-page.c:203 #, c-format msgid "%u Installed App" msgid_plural "%u Installed Apps" msgstr[0] "%u appli installée" msgstr[1] "%u applis installées" #: src/bz-license-dialog.blp:94 msgid "Get Involved" msgstr "S’impliquer" #: src/bz-license-dialog.blp:111 msgid "Learn More" msgstr "En savoir plus" #: src/bz-license-dialog.c:127 msgid "Unknown License" msgstr "Licence inconnue" #: src/bz-license-dialog.c:130 msgid "Community Built" msgstr "Construite par la communauté" #: src/bz-license-dialog.c:203 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:206 msgid "The license of this app is not known" msgstr "La licence de cette appli est inconnue" #: src/bz-license-dialog.c:212 #, 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:220 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 être modifiée sans aucun " "contrôle préalable.\n" "\n" "Vous ne pourrez peut-être pas contribuer à cette application." #: src/bz-license-dialog.c:226 #, 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-license-dialog.c:356 src/bz-safety-dialog.blp:49 msgid "License" msgstr "Licence" #: 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:110 msgid "Finish" msgstr "Terminer" #: src/bz-login-page.c:664 #, c-format msgid "Hello, %s!" msgstr "Bonjour, %s !" #: src/bz-metainfo-preview.c:84 msgid "Select Metainfo File" msgstr "Sélectionner un fichier métainfo" #: src/bz-metainfo-preview.c:87 msgid "Metainfo Files" msgstr "Fichiers métainfo" #: src/bz-metainfo-preview.c:141 msgid "Select Icon (Optional)" msgstr "Sélectionner une icône (facultatif)" #: src/bz-metainfo-preview.c:144 msgid "Image Files" msgstr "Fichiers image" #: src/bz-metainfo-preview.c:231 msgid "Preview" msgstr "Aperçu" #: 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 refresh 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:232 msgid "Refresh 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 "" "Restreint 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 End-of-Life Apps" msgstr "Masquer les applications 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:127 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-updates-card.c:155 msgid "Version History" msgstr "Historique des versions" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "_Historique des versions" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "Aujourd'hui" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "Hier" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "Il y a %d jour" msgstr[1] "Il y a %d jours" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "Il y a %d semaine" msgstr[1] "Il y a %d semaines" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "Il y a %d mois" msgstr[1] "Il y a %d mois" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "Il y a %d an" msgstr[1] "Il y a %d ans" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%e %B %Y" #: src/bz-releases-list.c:196 #, c-format msgid "Version %s" msgstr "Version %s" #: src/bz-releases-list.c:251 msgid "No details for this release" msgstr "Aucun détail à propos de cette version" #: src/bz-releases-list.c:263 msgid "Get More Information" msgstr "Obtenir plus d’informations" #: src/bz-rich-app-tile.blp:217 msgid "Uninstall" msgstr "Désinstaller" # Dans le contexte d'App Store - "Get" serait plutôt traduit en "Télécharger" ou comme ici en "Installer" #. Translators: If you can't find a short enough translation, use "/" to use an icon instead. #: src/bz-rich-app-tile.c:369 msgid "Get" msgstr "/" #: src/bz-safety-calculator.c:87 msgid "Unknown Permissions" msgstr "Autorisations inconnues" #: src/bz-safety-calculator.c:88 msgid "Permissions are missing for this app." msgstr "Des autorisations sont manquantes pour cette application." #: src/bz-safety-calculator.c:101 msgid "No Permissions" msgstr "Aucune autorisation" #: src/bz-safety-calculator.c:102 msgid "App is fully sandboxed" msgstr "L’application est entièrement sandboxée" #: src/bz-safety-calculator.c:108 msgid "Network Access" msgstr "Accès à Internet" #: src/bz-safety-calculator.c:109 msgid "Can access the internet" msgstr "Peut accéder à Internet" #: src/bz-safety-calculator.c:111 msgid "No Network Access" msgstr "Aucun accès Internet" #: src/bz-safety-calculator.c:112 msgid "Cannot access the internet" msgstr "Ne peut pas accéder à Internet" #: src/bz-safety-calculator.c:117 msgid "User Device Access" msgstr "Accès à l’appareil de l’utilisateur" #: src/bz-safety-calculator.c:118 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:120 msgid "No User Device Access" msgstr "Aucun accès aux périphériques" #: src/bz-safety-calculator.c:121 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:126 msgid "Input Device Access" msgstr "Accès aux périphériques d’entrée" #: src/bz-safety-calculator.c:127 msgid "Can access input devices" msgstr "Peut accéder aux périphériques d’entrée" #: src/bz-safety-calculator.c:133 msgid "Microphone Access and Audio Playback" msgstr "Accès au microphone et à la lecture audio" #: src/bz-safety-calculator.c:134 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:140 msgid "System Device Access" msgstr "Accès aux périphériques du système" #: src/bz-safety-calculator.c:141 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:147 msgid "Screen Contents Access" msgstr "Accès au contenu de l’écran" #: src/bz-safety-calculator.c:148 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:154 msgid "Legacy Windowing System" msgstr "Système de fenêtrage ancien" #: src/bz-safety-calculator.c:155 msgid "Always uses a legacy windowing system (X11)" msgstr "Utilise toujours un ancien système de fenêtrage (X11)" #: src/bz-safety-calculator.c:161 msgid "Arbitrary Permissions" msgstr "Autorisations arbitraires" #: src/bz-safety-calculator.c:162 msgid "Can acquire arbitrary permissions" msgstr "Peut obtenir des autorisations arbitraires" #: src/bz-safety-calculator.c:168 msgid "User Settings" msgstr "Paramètres utilisateur" #: src/bz-safety-calculator.c:169 msgid "Can access and change user settings" msgstr "Peut accéder aux paramètres utilisateur et les modifier" #: src/bz-safety-calculator.c:175 msgid "Full File System Read/Write Access" msgstr "Accès complet en lecture/écriture au système de fichiers" #: src/bz-safety-calculator.c:176 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:183 msgid "Home Folder Read/Write Access" msgstr "Accès en lecture/écriture au dossier personnel" #: src/bz-safety-calculator.c:184 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:191 msgid "Full File System Read Access" msgstr "Accès complet en lecture au système de fichiers" #: src/bz-safety-calculator.c:192 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:200 msgid "Home Folder Read Access" msgstr "Accès en lecture au dossier personnel" #: src/bz-safety-calculator.c:201 msgid "Can read all data in your home directory" msgstr "Peut lire tout le contenu de votre dossier personnel" #: src/bz-safety-calculator.c:209 msgid "Download Folder Read/Write Access" msgstr "Accès en lecture/écriture au dossier Téléchargements" #: src/bz-safety-calculator.c:210 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:220 msgid "Download Folder Read Access" msgstr "Accès en lecture au dossier Téléchargements" #: src/bz-safety-calculator.c:221 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:242 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:266 msgid "Can read all data in the directory" msgstr "Peut lire tout le contenu du répertoire" #: src/bz-safety-calculator.c:281 msgid "No File System Access" msgstr "Aucun accès au système de fichiers" #: src/bz-safety-calculator.c:282 msgid "Cannot access the file system at all" msgstr "Ne peut pas accéder au système de fichiers" #: src/bz-safety-calculator.c:289 msgid "Uses System Services" msgstr "Utilise les services système" #: src/bz-safety-calculator.c:290 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:296 msgid "Uses Session Services" msgstr "Utilise les services de la session utilisateur" #: src/bz-safety-calculator.c:297 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:345 msgid "No Service Access" msgstr "Aucun accès aux services" #: src/bz-safety-calculator.c:346 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:354 msgid "Verified App Developer" msgstr "Développeur vérifié" #: src/bz-safety-calculator.c:355 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:364 msgid "Proprietary Code" msgstr "Code propriétaire" #: src/bz-safety-calculator.c:365 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:375 msgid "Auditable Code" msgstr "Code vérifiable" #: src/bz-safety-calculator.c:376 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:516 #, c-format msgid "Use the %s System Service" msgstr "Utilise le service système %s" #: src/bz-safety-calculator.c:520 #, c-format msgid "Use the %s Session Service" msgstr "Utilise le service de session %s" #: src/bz-safety-calculator.c:524 #, c-format msgid "Use the %s Service" msgstr "Utilise le service %s" #: src/bz-safety-calculator.c:534 msgid "Can see the non-portal service" msgstr "Peut détecter ce service hors portail" #: src/bz-safety-calculator.c:536 msgid "Can talk to the non-portal service" msgstr "Peut communiquer à ce service hors portail" #: src/bz-safety-calculator.c:538 msgid "Can own the non-portal service" msgstr "Peut posséder ce service hors portail" #: src/bz-safety-calculator.c:553 msgid "Global Menu Integration" msgstr "Intégration au menu global" #: src/bz-safety-calculator.c:554 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:559 msgid "KDE Settings Integration" msgstr "Intégration aux paramètres KDE" #: src/bz-safety-calculator.c:560 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:565 msgid "KDE Global Settings" msgstr "Paramètres généraux KDE" #: src/bz-safety-calculator.c:566 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:571 msgid "Secret Storage Service" msgstr "Service de stockage secret" #: src/bz-safety-calculator.c:572 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:577 msgid "Desktop Notifications Service" msgstr "Service de notifications sur le bureau" #: src/bz-safety-calculator.c:578 msgid "Can send desktop notifications" msgstr "Peut envoyer des notifications sur le bureau" #: src/bz-safety-calculator.c:584 msgid "System Tray Integration" msgstr "Intégration dans la barre d’état système" #: src/bz-safety-calculator.c:585 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:590 msgid "KDE Connect Integration" msgstr "Intégration de KDE Connect" #: src/bz-safety-calculator.c:591 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:59 msgid "App ID" msgstr "Identifiant" #: src/bz-safety-dialog.blp:69 msgid "SDK" msgstr "Plateforme logicielle (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 "" "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:167 msgid "Safety" msgstr "Sécurité" #: src/bz-safety-dialog.c:226 #, c-format msgid "%s is Safe" msgstr "%s est fiable" #: src/bz-safety-dialog.c:231 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s n’a pas d’autorisations à risque" #: src/bz-safety-dialog.c:236 #, c-format msgid "%s is Probably Safe" msgstr "%s est probablement fiable" #: src/bz-safety-dialog.c:241 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s n'est peut-être pas fiable" #: src/bz-safety-dialog.c:246 #, c-format msgid "%s is Unsafe" msgstr "%s n’est pas fiable" #: 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:150 msgid "Reset View" msgstr "Réinitialiser l’affichage" #: src/bz-screenshot-page.blp:161 msgid "Zoom Out" msgstr "Zoom arrière" #: src/bz-screenshot-page.blp:171 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:117 msgid "Open Screenshot Viewer" msgstr "Ouvrir la visionneuse de captures d’écran" #: src/bz-search-filter-popover.blp:18 src/bz-search-page.blp:83 msgid "Filters" msgstr "Filtres" #: src/bz-search-filter-popover.blp:35 msgid "_Verified" msgstr "_Vérifiées" #: src/bz-search-filter-popover.blp:42 msgid "_Free/Open" msgstr "_Libres" #: src/bz-search-filter-popover.blp:49 msgid "Non-_EOL" msgstr "À _jour" #: src/bz-search-filter-popover.blp:52 msgid "Filter out End-of-Life apps" msgstr "Affiche/Masque les applications en fin de vie" #: src/bz-search-filter-popover.blp:57 msgid "Categories" msgstr "Catégories" #: src/bz-search-page.blp:58 msgid "Search Apps, Games, Software" msgstr "Rechercher applis, jeux et logiciels" #: src/bz-search-page.blp:70 msgid "Search Filters" msgstr "Filtres de recherche" #: src/bz-search-page.blp:100 msgid "Clear Search" msgstr "Effacer la recherche" #: src/bz-search-page.blp:192 msgid "Categories Unavailable" msgstr "Catégories non disponibles" #: src/bz-search-page.blp:193 msgid "Search for apps using the search bar above." msgstr "Cherchez des applis en utilisant l'onglet « Rechercher »." #: src/bz-search-page.blp:219 msgid "Browse Categories" msgstr "Parcourir les catégories" #: src/bz-search-page.blp:361 msgid "No Applications Found" msgstr "Aucune application trouvée" #: src/bz-search-page.c:247 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Aucun résultat pour « %s » dans la logithèque" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "Vidéo" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "Bureautique" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "Calendrier" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "Messagerie" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Paint" msgstr "Dessin" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "Torrent" msgstr "Torrent" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Emulator" msgstr "Émulateur" #: src/bz-share-list.c:55 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Page Flathub" #: src/bz-share-list.c:56 msgctxt "Project URL Type" msgid "Project Website" msgstr "Site du projet" #: src/bz-share-list.c:57 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Signaler un problème" #: src/bz-share-list.c:58 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-share-list.c:59 msgctxt "Project URL Type" msgid "Help" msgstr "Aide" #: src/bz-share-list.c:60 msgctxt "Project URL Type" msgid "Donate" msgstr "Faire un don" #: src/bz-share-list.c:61 msgctxt "Project URL Type" msgid "Translate" msgstr "Traduire" #: src/bz-share-list.c:62 msgctxt "Project URL Type" msgid "Contact" msgstr "Contact" #: src/bz-share-list.c:63 msgctxt "Project URL Type" msgid "Source Code" msgstr "Code Source" #: src/bz-share-list.c:64 msgctxt "Project URL Type" msgid "Contribute" msgstr "Contribuer" #: src/bz-share-list.c:153 msgid "Copy Link" msgstr "Copier le lien" #: src/bz-share-list.c:164 msgid "Open Link" msgstr "Ouvrir le lien" #: src/bz-stats-dialog.blp:27 msgid "Timeline" msgstr "Chronologie" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Installations :" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Monde" #: src/bz-stats-dialog.blp:69 msgid "Since 4/15/2024" msgstr "Depuis le 15 Avril 2024" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:130 #, c-format msgid "%.2fM Total Installs" msgstr "%.2f Mio installations en tout" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:133 #, c-format msgid "%.2fK Total Installs" msgstr "%.2f mil. installations en tout" #: src/bz-stats-dialog.c:135 #, c-format msgid "%'d Total Installs" msgstr "%'d téléchargements en tout" #: src/bz-tag-list.c:78 msgid "No Results Found" msgstr "Aucun résultat trouvé" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Applis étiquetées « %s »" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "La recherche a échoué" #: src/bz-transaction-dialog.c:154 msgid "Keep User Data" msgstr "Conserver les données utilisateur" #: src/bz-transaction-dialog.c:155 msgid "Allow restoring personal settings & content" msgstr "Permet la restauration des paramètres et du contenu" #: src/bz-transaction-dialog.c:164 msgid "Delete All Data" msgstr "Supprimer les données" #: src/bz-transaction-dialog.c:165 msgid "Permanently erase user 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:190 #, c-format msgid "Install %s?" msgstr "Installer %s?" #: src/bz-transaction-dialog.c:195 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Sélectionnez la version à installer.\n" "Elle pourrait installer des composants partagés supplémentaire" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "Pourrait installer des composants partagés supplémentaires" #: src/bz-transaction-dialog.c:200 src/bz-transaction-dialog.c:229 #: src/bz-transaction-dialog.c:274 src/bz-transaction-dialog.c:576 msgid "_Cancel" msgstr "_Annuler" #: src/bz-transaction-dialog.c:201 msgid "_Install" msgstr "_Installer" #: src/bz-transaction-dialog.c:218 #, c-format msgid "Remove %s?" msgstr "Désinstaller %s ?" #: src/bz-transaction-dialog.c:221 msgid "Select which version to remove." msgstr "Sélectionnez la version à désinstaller." #: src/bz-transaction-dialog.c:223 #, 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:246 #, c-format msgid "“%s” is High Risk" msgstr "« %s » présente un risque élevé" #: src/bz-transaction-dialog.c:250 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:259 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:275 msgid "_Install Anyway" msgstr "_Installer quand même" #: src/bz-transaction-dialog.c:330 msgid "Failed to load transaction dialog" msgstr "Échec du chargement du dialogue de la transaction" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "Toutes les applis sont déjà installées" #: src/bz-transaction-dialog.c:549 msgid "_OK" msgstr "D’_accord" #: src/bz-transaction-dialog.c:565 #, 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:573 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:574 #, c-format msgid "%d addons will be installed." msgstr "%d extensions seront installées." #: src/bz-transaction-dialog.c:575 msgid "Additionally, addons will be installed." msgstr "Des extensions seront aussi installées." #: src/bz-transaction-dialog.c:577 msgid "_Install All" msgstr "_Tout installer" #: src/bz-transaction-manager.c:795 #, c-format msgid "Finished in %.02f seconds" msgstr "Terminé en %.02f secondes" #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "Extension d'application" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "Environnement d’exécution" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "En attente" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "Tâche terminée" #: src/bz-transaction-tile.blp:230 msgid "Cancelled" msgstr "Tâche annulée" #: src/bz-transaction-tile.blp:254 msgid "Error" msgstr "Erreur" #: src/bz-transaction-tile.blp:312 msgid "Cancel Transaction" msgstr "Annuler la tâche" #: src/bz-transaction-tile.blp:436 msgid "Show Error Info" msgstr "Afficher les informations sur l'erreur" # Pluriel car on parle d'octets #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "%s libérés" #: src/bz-transaction-tile.c:360 src/bz-transaction-tile.c:363 msgid "Transaction Error" msgstr "Erreur de transaction" #: src/bz-transaction.c:344 msgid "Pending" msgstr "En attente" #: src/bz-updates-card.blp:23 msgid "_Update All" msgstr "Tout _mettre à jour" #: src/bz-updates-card.c:211 #, 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:33 msgid "No User Data Found" msgstr "Pas de données orphelines trouvées" #: src/bz-user-data-page.blp:38 msgid "User Data" msgstr "Données utilisateur" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Mettre les données utilisateurs à la corbeille" #: src/bz-user-data-tile.c:150 #, c-format msgid "Trashed User Data for %s" msgstr "Les données utilisateur de %s ont été mise à la corbeille" #: src/bz-window.blp:70 msgid "Refreshing" msgstr "Actualisation" #: src/bz-window.blp:88 msgid "Curated" msgstr "Sélection" #: src/bz-window.blp:100 msgid "Explore" msgstr "Explorer" #: src/bz-window.blp:212 msgid "Main Menu" msgstr "Menu principal" #: src/bz-window.blp:223 msgid "You are running a new version of Bazaar!" msgstr "Bazaar a été mis à jour !" #: src/bz-window.blp:224 msgid "See What's New" msgstr "Voir les nouveautés" #: src/bz-window.blp:231 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Votre appareil est connecté à Internet, mais vous consultez une version hors-" "ligne de la logithèque" #: src/bz-window.blp:276 msgid "_Donate to Bazaar" msgstr "Faire un _don à Bazaar" #: src/bz-window.blp:283 msgid "_Refresh" msgstr "_Actualiser" #: src/bz-window.blp:288 msgid "_Preferences" msgstr "_Préférences" #: src/bz-window.blp:293 msgid "_Login With Flathub" msgstr "Se _connecter avec Flathub" #: src/bz-window.blp:299 msgid "_Manage Leftover User Data" msgstr "_Gérer les données utilisateurs orphelines" #: src/bz-window.blp:304 msgid "_Keyboard Shortcuts" msgstr "_Raccourcis clavier" #: src/bz-window.blp:309 msgid "_About Bazaar" msgstr "À propos de _Bazaar" #: src/bz-window.blp:316 msgid "_Quit Bazaar" msgstr "_Quitter Bazaar" #: src/bz-window.blp:341 msgid "Log Out" msgstr "Se déconnecter" #. Translators: %s is the title of the current page #: src/bz-window.c:376 #, c-format msgid "Bazaar — %s" msgstr "Bazaar — %s" #: src/bz-window.c:596 src/bz-window.c:634 msgid "Failed to launch application" msgstr "Échec du lancement de l'application" #: src/bz-window.c:843 msgid "You can't remove Bazaar from Bazaar!" msgstr "Vous ne pouvez supprimer Bazaar depuis Bazaar !" #: src/bz-window.c:1127 src/bz-window.c:1161 msgid "Can't do that right now!" msgstr "Impossible de faire ceci pour le moment !" #. Translators: As in, "1 Install" / "100 Installs" #: src/bz-world-map.c:604 msgid "Install" msgid_plural "Installs" msgstr[0] "Installation" msgstr[1] "Installations" #: src/shortcuts-dialog.blp:5 msgctxt "shortcut window" msgid "Navigation" msgstr "Navigation" #: src/shortcuts-dialog.blp:8 msgctxt "shortcut window" msgid "Open Explore Page" msgstr "Ouvrir la page Explorer" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "Ouvrir la page Bibliothèque" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Open Search Page" msgstr "Ouvrir la page Recherche" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Remotes" msgstr "Sources" #: src/shortcuts-dialog.blp:27 msgctxt "shortcut window" msgid "Sync Remotes" msgstr "Synchroniser les sources" #: src/shortcuts-dialog.blp:33 msgctxt "shortcut window" msgid "General" msgstr "Général" #: src/shortcuts-dialog.blp:36 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Ouvrir les préférences" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Afficher les raccourcis" #: src/shortcuts-dialog.blp:46 msgctxt "shortcut window" msgid "Close Window" msgstr "Fermer la fenêtre" #: src/shortcuts-dialog.blp:52 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "Quitter Bazaar" #~ msgid "Refresh completed!" #~ msgstr "Actualisation terminée !" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "Actualiser" #~ msgid "User Data Size" #~ msgstr "Taille des données utilisateur" #~ msgctxt "About Dialog Developer Credit" #~ msgid "Adam Masciola " #~ msgstr "Adam Masciola " #~ msgctxt "About Dialog Developer Credit" #~ msgid "Alexander Vanhee" #~ msgstr "Alexander Vanhee" #~ msgctxt "As in, \"100 Installs\"" #~ msgid "Installs" #~ msgstr "installations" #~ msgid "Open App Library" #~ msgstr "Ouvrir la bibliothèque" #~ msgid "Installing .flatpak bundles is not yet supported" #~ msgstr "L’installation de lots .flatpak n’est pas encore prise en charge" #~ msgid "Steam" #~ msgstr "Steam" #~ msgid "Minecraft" #~ msgstr "Minecraft" bazaar-org-bazaar-43ce9f7/po/ga.po000066400000000000000000002216421520414637400170050ustar00rootroot00000000000000# 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" bazaar-org-bazaar-43ce9f7/po/hu.po000066400000000000000000001031731520414637400170300ustar00rootroot00000000000000# 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" bazaar-org-bazaar-43ce9f7/po/id.po000066400000000000000000002741701520414637400170160ustar00rootroot00000000000000# 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-03-24 10:16+0700\n" "PO-Revision-Date: 2026-03-30 02:31+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 50.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:46 #: src/bz-window.c:377 src/bz-window.c:378 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 perbarui aplikasi 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:16 msgid "New Window" msgstr "Jendela Baru" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and manage applications" msgstr "Temukan dan pasang aplikasi" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "Toko aplikasi Linux yang cepat dan modern, berfokus pada kemudahan menemukan " "serta memasang aplikasi dan modul tambahan Flatpak, terutama dari Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "Pasang beberapa aplikasi sekaligus dan lanjut menjelajah" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "Dapat melihat izin aplikasi secara mudah" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "Masuk dengan Flathub untuk lihat dan kelola aplikasi favoritmu" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "Cari aplikasi langsung dari bilah pencarian GNOME" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:30 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "The home page displaying Flathub apps" msgstr "Tampilan muka dengan daftar aplikasi dari Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:59 msgid "Exhibit app page" msgstr "Tampilan halaman detail aplikasi" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "Halaman pustaka aplikasi" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "Tampilan pencarian aplikasi" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "Tampilan kategori aplikasi" #: src/bz-addons-dialog.blp:16 src/bz-full-view.blp:627 #: src/bz-installed-tile.blp:101 msgid "Manage Add-Ons" msgstr "Kelola Modul Tambahan" #: src/bz-addons-dialog.c:94 src/bz-install-controls.blp:137 #: src/bz-installed-tile.blp:114 msgid "Remove" msgstr "Hapus" #: src/bz-addons-dialog.c:99 src/bz-favorites-tile.c:159 msgid "Install" msgstr "Pasang" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:736 src/bz-full-view.c:333 src/bz-full-view.c:340 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:686 src/bz-full-view.c:323 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "Semua" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "Peringkat usia untuk %s tidak diketahui" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "%s cocok untuk semua usia" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "%s diperbolehkan untuk usia balita" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "%s diperbolehkan untuk usia anak-anak" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "%s diperbolehkan untuk usia remaja" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "%s diperbolehkan untuk usia dewasa" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "%s diperbolehkan untuk usia %s" #: src/bz-age-rating-dialog.c:862 #, 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:29 #: src/bz-user-data-page.blp:15 src/bz-window.blp:239 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:328 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:335 msgid "_Refresh" msgstr "_Muat Ulang" #: src/bz-all-apps-page.blp:30 src/bz-apps-page.blp:30 #: src/bz-user-data-page.blp:31 src/bz-window.blp:340 msgid "_Preferences" msgstr "_Pengaturan" #: src/bz-all-apps-page.blp:35 src/bz-apps-page.blp:35 #: src/bz-user-data-page.blp:36 src/bz-window.blp:345 msgid "_Login With Flathub" msgstr "_Masuk Dengan Flathub" #: src/bz-all-apps-page.blp:41 src/bz-apps-page.blp:41 #: src/bz-user-data-page.blp:42 src/bz-window.blp:351 msgid "_Manage Leftover User Data" msgstr "_Kelola Sisa Data Pengguna" #: src/bz-all-apps-page.blp:46 src/bz-apps-page.blp:46 #: src/bz-user-data-page.blp:47 src/bz-window.blp:356 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:361 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:368 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:125 msgid "Open user data folder" msgstr "Buka folder data pengguna" #: src/bz-app-size-dialog.blp:135 msgid "User Data Size" msgstr "Ukuran Data Pengguna" #: src/bz-app-size-dialog.blp:136 msgid "Caches, settings, and other app data" msgstr "Cache, konfigurasi, dan data aplikasi lainnya" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "Ukuran Tempokerja Terpasang" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "Ukuran Unduh Tempokerja" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:104 src/bz-rich-app-tile.c:304 msgid "Verified" msgstr "Terverifikasi" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-full-view.c:282 src/bz-releases-list.c:205 msgid "Installed" msgstr "Terpasang" #: src/bz-apps-page.blp:142 msgid "Show All" msgstr "Tunjukkan Semua" #: src/bz-apps-page.c:229 #, c-format msgid "All \"%s\"" msgstr "Semua \"%s\"" #: src/bz-apps-page.c:478 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "%d Aplikasi" #: src/bz-application.c:695 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:696 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #: src/bz-application.c:716 msgid "The Bazaar Contributors" msgstr "Kontributor Bazaar" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:719 msgid "translator-credits" msgstr "KiKaraage , 2025" #: src/bz-application.c:729 msgid "Special Thanks" msgstr "Terima Kasih Khusus" #: src/bz-application.c:787 msgid "Logged Out Successfully!" msgstr "Akun Berhasil Dikeluarkan!" #: src/bz-application.c:910 msgid "Performing setup…" msgstr "Melakukan pengaturan..." #: src/bz-application.c:994 msgid "Set Up System Flathub?" msgstr "Atur Flathub pada Sistem?" #: src/bz-application.c:997 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub belum diatur sebagai sumber Flatpak pada sistem ini. Bazaar " "membutuhkan Flathub terkonfigurasi sebagai sumber Flatpak sistem untuk " "mencari dan memasang aplikasi.\n" "\n" "Anda masih dapat menggunakan Bazaar untuk mencari dan menghapus aplikasi " "terpasang." #: src/bz-application.c:1004 msgid "Set Up Flathub?" msgstr "Atur Flathub?" #: src/bz-application.c:1007 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:1013 msgid "Later" msgstr "Nanti" #: src/bz-application.c:1014 msgid "Set Up Flathub" msgstr "Atur Flathub" #: src/bz-application.c:1303 msgid "A backend error occurred" msgstr "Terjadi kegagalan latar belakang" #: src/bz-application.c:1499 src/bz-application.c:3357 src/bz-window.blp:70 msgid "Refreshing…" msgstr "Memuat ulang..." #: src/bz-application.c:1651 src/bz-application.c:3355 #, c-format msgid "Loading %d apps…" msgstr "%d aplikasi dimuat..." #: src/bz-application.c:1654 msgid "Checking for updates…" msgstr "Memeriksa pembaruan..." #: src/bz-application.c:1717 msgid "Failed to open .flatpakref" msgstr "Gagal membuka .flatpakref" #: src/bz-application.c:1773 msgid "An initialization error occurred" msgstr "Terjadi kegagalan initialisasi" #: src/bz-application.c:2123 msgid "Failed to check for updates" msgstr "Gagal memeriksa pembaruan" #: src/bz-application.c:3128 msgid "Could not find app" msgstr "Tidak dapat mencari aplikasi" #: src/bz-application.c:3359 msgid "Writing to cache…" msgstr "Menulis cache..." #: src/bz-appstream-parser.c:302 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Halaman Flathub" #: src/bz-appstream-parser.c:323 msgctxt "Project URL Type" msgid "Project Website" msgstr "Situs Web Proyek" #: src/bz-appstream-parser.c:327 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Pelacak Masalah" #: src/bz-appstream-parser.c:331 msgctxt "Project URL Type" msgid "FAQ" msgstr "Pertanyaan Jamak" #: src/bz-appstream-parser.c:335 msgctxt "Project URL Type" msgid "Help" msgstr "Bantuan" #: src/bz-appstream-parser.c:339 msgctxt "Project URL Type" msgid "Donate" msgstr "Sumbang" #: src/bz-appstream-parser.c:345 msgctxt "Project URL Type" msgid "Translate" msgstr "Terjemahkan" #: src/bz-appstream-parser.c:349 msgctxt "Project URL Type" msgid "Contact" msgstr "Kontak" #: src/bz-appstream-parser.c:353 msgctxt "Project URL Type" msgid "Source Code" msgstr "Kode Sumber" #: src/bz-appstream-parser.c:359 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:62 #: src/bz-library-page.blp:65 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" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "Peramban" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "Tidak Terverifikasi" #: src/bz-developer-badge.c:145 msgid "Developer information not available." msgstr "Informasi pengembang tidak tersedia." #: src/bz-developer-badge.c:151 src/bz-developer-badge.c:165 #, 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:169 #, 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:175 #, 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:182 #, 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:186 #, 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:74 msgid "Full Release Notes" msgstr "Catatan Rilis Lengkap" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "Versi ini dapat rilis karena dukungan Anda!" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on 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:131 msgid "Donate to Bazaar" msgstr "Donasi ke Bazaar" #. Translators: the %s format specifier will be something along the lines of "0.7.6" etc #: src/bz-donations-dialog.c:227 #, c-format msgid "What's New in %s?" msgstr "Apa Yang Baru di %s?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "Dirilis pada %-e %B %Y" #: 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 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:69 src/bz-error.c:88 src/bz-error-dialog.blp:36 #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Rincian" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "Salin" #: src/bz-error-dialog.c:56 src/bz-share-list.c:64 msgid "Copied!" msgstr "Tersalin!" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" msgstr "Gagal memperbarui daftar favorit" #: 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:157 src/bz-rich-app-tile.blp:172 msgid "Uninstall" msgstr "Bongkar" #: src/bz-favorites-tile.c:357 msgid "Failed to remove favorite" msgstr "Gagal melepas status favorit" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:78 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:386 msgid "Favorites" msgstr "Aplikasi Favorit" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "Pasang Semua" #: src/bz-favorites-page.blp:34 src/bz-full-view.blp:45 src/bz-window.blp:255 msgid "Open App Library" msgstr "Buka Pustaka Aplikasi" #: 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:54 msgid "Next" msgstr "Selanjutnya" #: src/bz-featured-tile.blp:90 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" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:92 src/bz-search-pill-list.c:77 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:182 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:172 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:162 msgid "Recently Updated" msgstr "Baru Dimutakhirkan" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Diperbarui" #: 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:263 msgid "On the Go" msgstr "Di Mana Saja" #: src/bz-flathub-page.blp:275 msgid "Apps for your Linux phones and tablets" msgstr "Aplikasi untuk ponsel dan tablet Linux Anda" #: src/bz-flathub-page.blp:286 src/bz-flathub-page.blp:321 msgid "More Mobile Apps" msgstr "Apl Ponsel Lainnya" #: src/bz-flathub-page.blp:379 msgid "We​ ♥​ Games" msgstr "Kita ♥​ Main" #: src/bz-flathub-page.blp:392 msgid "Games and apps to run your favorite titles" msgstr "Permainan dan aplikasi untuk memainkan judul-judul favoritmu" #: src/bz-flathub-page.blp:426 msgid "More Games" msgstr "Permainan Lainnya" #: src/bz-full-view.blp:66 src/bz-library-page.blp:76 #: src/bz-library-page.blp:80 msgid "No Results" msgstr "Tidak Ada Hasil" #: src/bz-full-view.blp:67 msgid "Try a different search query" msgstr "Coba gunakan kata kunci lainnya" #: src/bz-full-view.blp:73 msgid "Content" msgstr "Konten" #: src/bz-full-view.blp:131 msgid "Installing .flatpak bundles is not yet supported" msgstr "Saat ini pemasangan bundel .flatpak belum didukung" #: src/bz-full-view.blp:257 msgid "_Support" msgstr "_Dukung" #: src/bz-full-view.blp:426 msgid "Downloads/Month" msgstr "Unduhan/Bulan" #: src/bz-full-view.blp:461 msgid "Stopped Receiving Core Updates" msgstr "Berhenti Menerima Pembaruan Utama" #: src/bz-full-view.blp:475 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 " "pembaruan maupun perbaikan keamanan. Aplikasi ini mungkin tidak aman saat " "digunakan." #: src/bz-full-view.blp:562 msgid "Trash Data" msgstr "Buang Data" #: src/bz-full-view.blp:702 msgid "Tags:" msgstr "Label:" #: src/bz-full-view.c:215 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:222 #, c-format msgid "%.*fM" msgstr "%.*fjt" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:229 #, c-format msgid "%.*fK" msgstr "%.*frb" #: src/bz-full-view.c:239 #, c-format msgid "%d downloads in the last month" msgstr "%d unduhan dalam sebulan terakhir" #: src/bz-full-view.c:251 src/bz-full-view.c:592 src/bz-full-view.c:609 msgid "N/A" msgstr "Nihil" #: src/bz-full-view.c:279 #, c-format msgid "+%s runtime" msgstr "+%s Tempokerja (Runtime)" #: src/bz-full-view.c:282 msgid "Download" msgstr "Ukuran Unduh" #: src/bz-full-view.c:302 msgid "Size information unavailable" msgstr "Info ukuran apl tidak tersedia" #: src/bz-full-view.c:305 #, c-format msgid "Download size of %s" msgstr "Ukuran unduhan %s" #: src/bz-full-view.c:338 msgid "All Ages" msgstr "Semua Usia" #: src/bz-full-view.c:350 msgid "Age rating information unavailable" msgstr "Info panduan usia tidak tersedia" #: src/bz-full-view.c:355 msgid "Suitable for all ages" msgstr "Cocok untuk semua usia" #: src/bz-full-view.c:357 #, c-format msgid "Suitable for ages %d and up" msgstr "Cocok untuk usia %d ke atas" #: src/bz-full-view.c:390 src/bz-full-view.c:395 src/bz-full-view.c:423 #: src/bz-full-view.c:431 msgid "Unknown" msgstr "Tidak Diketahui" #: src/bz-full-view.c:400 #, c-format msgid "Free software licensed under %s" msgstr "Aplikasi bebas di bawah lisensi %s" #: src/bz-full-view.c:405 msgid "Free software" msgstr "Aplikasi bebas" #: src/bz-full-view.c:408 msgid "Proprietary Software" msgstr "Aplikasi dengan hak cipta khusus" #: src/bz-full-view.c:411 #, c-format msgid "Special License: %s" msgstr "Lisensi Khusus: %s" #: src/bz-full-view.c:428 msgid "Free" msgstr "Bebas" #: src/bz-full-view.c:434 src/bz-license-dialog.c:132 msgid "Proprietary" msgstr "Proprietari" #: src/bz-full-view.c:436 src/bz-license-dialog.c:134 msgid "Special License" msgstr "Lisensi Khusus" #: src/bz-full-view.c:456 msgid "Adaptive" msgstr "Adaptif" #: src/bz-full-view.c:456 msgid "Desktop Only" msgstr "Hanya Desktop" #: src/bz-full-view.c:462 msgid "Works on desktop, tablets, and phones" msgstr "Bekerja di desktop, tablet dan ponsel" #: src/bz-full-view.c:463 msgid "May not work on mobile devices" msgstr "Mungkin tidak bekerja optimal di ponsel" #: src/bz-full-view.c:474 msgid "No URL" msgstr "Tidak ada URL" #: src/bz-full-view.c:492 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:493 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:500 msgid "More Apps" msgstr "Aplikasi Lainnya" #: src/bz-full-view.c:501 #, c-format msgid "More Apps by %s" msgstr "Aplikasi Lain dari %s" #: src/bz-full-view.c:508 msgid "Other Apps by this Developer" msgstr "Jelajah lebih dari pengembang ini" #: src/bz-full-view.c:510 src/bz-full-view.c:693 #, c-format msgid "Other Apps by %s" msgstr "Jelajah lebih dari %s" #: src/bz-full-view.c:519 #, 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:599 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Aman" #: src/bz-full-view.c:601 src/bz-full-view.c:603 msgid "Low Risk" msgstr "Risiko Rendah" #: src/bz-full-view.c:605 msgid "Medium Risk" msgstr "Risiko Sedang" #: src/bz-full-view.c:607 msgid "High Risk" msgstr "Risiko Tinggi" #: src/bz-full-view.c:695 msgid "Other Apps" msgstr "Aplikasi Lain" #: src/bz-full-view.c:697 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d Aplikasi" #: src/bz-full-view.c:941 msgid "Show Less" msgstr "Sembunyikan" #: src/bz-full-view.c:941 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-install-controls.blp:33 msgid "Download & Install Application" msgstr "Unduh & Pasang Aplikasi" #: src/bz-install-controls.blp:35 src/bz-transaction-dialog.c:202 msgid "_Install" msgstr "_Pasang" #: src/bz-install-controls.blp:61 msgid "_Open" msgstr "_Buka" #: src/bz-install-controls.blp:76 src/bz-install-controls.blp:127 msgid "Uninstall Application" msgstr "Hapus Pemasangan Aplikasi" #: src/bz-install-controls.blp:86 src/bz-transaction-dialog.c:231 msgid "_Remove" msgstr "_Hapus" #: src/bz-install-controls.blp:114 src/bz-updates-card.blp:184 #: src/bz-updates-card.blp:212 msgid "Update" msgstr "Perbarui" #: src/bz-installed-tile.blp:64 src/bz-rich-app-tile.blp:140 msgid "Stopped Receiving Updates" msgstr "Berhenti Menerima Pembaruan" #: src/bz-library-page.blp:31 msgid "Search installed apps" msgstr "Cari aplikasi terpasang" #: src/bz-library-page.blp:48 msgid "Clear search" msgstr "Bersihkan pencarian" #: src/bz-library-page.blp:69 msgid "No Apps Found" msgstr "Tidak Ada Aplikasi Tersedia" #. Translators: . #: src/bz-library-page.blp:98 src/bz-window.blp:112 msgid "Library" msgstr "Pustaka" #: src/bz-library-page.blp:126 msgid "Pending Updates" msgstr "Pembaruan Tertunda" #: src/bz-library-page.blp:153 msgid "Downloads" msgstr "Unduhan" #: src/bz-library-page.blp:196 msgid "Recently Uninstalled" msgstr "Baru Dihapus" #: src/bz-library-page.blp:247 msgid "Clear Finished Tasks" msgstr "Bersihkan Transaksi Lama" #: src/bz-library-page.blp:260 msgid "Installed Apps" msgstr "Aplikasi Terpasang" #: src/bz-library-page.blp:333 msgid "Sort By" msgstr "Urutkan" #: src/bz-library-page.blp:347 msgid "Name" msgstr "Nama" #: src/bz-library-page.blp:353 msgid "Size" msgstr "Ukuran" #: src/bz-library-page.c:180 #, 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:193 src/bz-updates-card.c:257 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u Pembaruan 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:110 msgid "Finish" msgstr "Selesai" #: src/bz-login-page.c:664 #, 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 refresh is paused" msgstr "Koneksi jaringan dibatasi — sinkronisasi data otomatis saat ini dijeda" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:282 msgid "Refresh Manually" msgstr "Segarkan Langsung" #: 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:127 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-updates-card.blp:171 msgid "Version History" msgstr "Riwayat Versi" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "_Riwayat Versi" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "Hari Ini" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "Kemarin" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "%d hari lalu" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "%d minggu lalu" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "%d bulan lalu" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "%d tahun lalu" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%e %B %Y" #: src/bz-releases-list.c:195 #, c-format msgid "Version %s" msgstr "Versi %s" #: src/bz-releases-list.c:250 msgid "No details for this release" msgstr "Tidak ada detail untuk rilisan ini" #: src/bz-releases-list.c:262 msgid "Get More Information" msgstr "Info Lebih Lanjut" #: src/bz-rich-app-tile.blp:157 msgid "Get" msgstr "Pasang" #: src/bz-rich-app-tile.blp:185 src/bz-transaction-tile.blp:272 msgid "Open" msgstr "Buka" #: 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: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:104 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:117 msgid "Open Screenshot Viewer" msgstr "Tampilkan Tangkapan Layar" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "Video" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "Perkantoran" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "Kalender" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "Komunikasi" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Steam" msgstr "Steam" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "Paint" msgstr "Seni Lukis" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Torrent" msgstr "Torrent" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:122 msgid "Minecraft" msgstr "Minecraft" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:127 msgid "Emulator" msgstr "Emulator" #: src/bz-search-page.blp:57 msgid "Search Apps, Games, Software" msgstr "Cari Aplikasi dan Permainan" #: src/bz-search-page.blp:79 msgid "Clear Search" msgstr "Bersihkan Pencarian" #: src/bz-search-page.blp:171 msgid "Categories Unavailable" msgstr "Kategori Tidak Tersedia" #: src/bz-search-page.blp:172 msgid "Search for apps using the search bar above." msgstr "Cari aplikasi menggunakan bilah pencarian di atas. " #: src/bz-search-page.blp:198 msgid "Browse Categories" msgstr "Jelajahi Kategori" #: src/bz-search-page.blp:340 msgid "No Applications Found" msgstr "Tidak Ada Aplikasi Tersedia" #: src/bz-search-page.c:244 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Tidak ada hasil untuk \"%s\" di Flathub" #: 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" #: src/bz-stats-dialog.blp:69 msgid "Since 4/15/2024" msgstr "Sejak 15/4/2024" #. 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:78 msgid "No Results Found" msgstr "Tidak Ada Hasil" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Aplikasi Berlabel \"%s\"" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "Pencarian gagal" #: src/bz-transaction-dialog.c:155 msgid "Keep User Data" msgstr "Simpan Data Pengguna" #: src/bz-transaction-dialog.c:156 msgid "Allow restoring personal settings & content" msgstr "Izinkan pemulihan data & pengaturan personal" #: src/bz-transaction-dialog.c:165 msgid "Delete All Data" msgstr "Hapus Semua Data" #: src/bz-transaction-dialog.c:166 msgid "Permanently erase user data to save space" msgstr "Hapus permanen data aplikasi untuk menghemat ruang" #: src/bz-transaction-dialog.c:191 #, c-format msgid "Install %s?" msgstr "Pasang %s?" #: src/bz-transaction-dialog.c:196 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:198 msgid "May install additional shared components" msgstr "Mungkin membutuhkan pemasangan komponen tambahan" #: 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 "_Batal" #: src/bz-transaction-dialog.c:219 #, c-format msgid "Remove %s?" msgstr "Hapus %s?" #: src/bz-transaction-dialog.c:222 msgid "Select which version to remove." msgstr "Pilih versi aplikasi yang akan dihapus." #: src/bz-transaction-dialog.c:224 #, 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:247 #, c-format msgid "“%s” is High Risk" msgstr "\"%s\" memiliki risiko tinggi" #: 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 "" "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: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 "" "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:276 msgid "_Install Anyway" msgstr "_Tetap Pasang" #: src/bz-transaction-dialog.c:331 msgid "Failed to load transaction dialog" msgstr "Gagal memuat dialog" #: src/bz-transaction-dialog.c:549 msgid "All apps are already installed" msgstr "Semua aplikasi sudah terpasang." #: src/bz-transaction-dialog.c:551 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:567 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "Pasang %u Aplikasi?" #: src/bz-transaction-dialog.c:575 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:576 #, c-format msgid "%d addons will be installed." msgstr "%d komponen tambahan akan dipasang." #: src/bz-transaction-dialog.c:577 msgid "Additionally, addons will be installed." msgstr "Selain itu, komponen tambahan juga akan dipasang." #: src/bz-transaction-dialog.c:579 msgid "_Install All" msgstr "_Pasang Semua" #: src/bz-transaction-manager.c:766 #, c-format msgid "Finished in %.02f seconds" msgstr "Selesai dalam %.02f detik" #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "Modul Aplikasi" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "Tempokerja (Runtime)" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "Dalam Antrian" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "Selesai" #: src/bz-transaction-tile.blp:230 msgid "Error" msgstr "Terjadi Kesalahan" #: src/bz-transaction-tile.blp:286 msgid "Cancel Transaction" msgstr "Batalkan Proses" #: src/bz-transaction-tile.blp:410 msgid "Show Error Info" msgstr "Tampilkan Info Galat" #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "%s Bebas" #: src/bz-transaction-tile.c:362 src/bz-transaction-tile.c:365 msgid "Transaction Error" msgstr "Terjadi Kegagalan" #: src/bz-transaction.c:342 msgid "Pending" msgstr "Ditunda" #: src/bz-updates-card.blp:40 msgid "_Update All" msgstr "_Perbarui Semua" #: 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:88 msgid "Curated" msgstr "Pilihan" #: src/bz-window.blp:100 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:220 msgid "Refresh completed!" msgstr "Penyegaran berhasil!" #: src/bz-window.blp:273 msgid "You are running a new version of Bazaar!" msgstr "Versi terbaru Bazaar telah terpasang!" #: src/bz-window.blp:274 msgid "See What's New" msgstr "Lihat Yang Baru" #: src/bz-window.blp:281 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:393 msgid "Log Out" msgstr "Keluar" #. Translators: %s is the title of the current page #: src/bz-window.c:380 #, c-format msgid "Bazaar — %s" msgstr "Bazaar — %s" #: src/bz-window.c:487 msgid "Failed to load add-ons" msgstr "Gagal memuat modul tambahan" #: src/bz-window.c:601 src/bz-window.c:618 msgid "Failed to launch application" msgstr "Gagal menjalankan aplikasi" #: src/bz-window.c:823 msgid "You can't remove Bazaar from Bazaar!" msgstr "Anda tidak dapat menghapus Bazaar dari dalam Bazaar." #: src/bz-window.c:1108 src/bz-window.c:1142 msgid "Can't do that right now!" msgstr "Tunggu hingga Bazaar selesai memuat" #: src/bz-world-map.c:595 msgctxt "As in, \"100 Downloads\"" msgid "Downloads" msgstr "Unduhan" #: src/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Umum" #: src/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Page" msgstr "Buka Halaman Pencarian" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "Buka Halaman Pustaka" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Refresh" msgstr "Muat ulang" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Buka Pengaturan" #: src/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Tampilkan Pintasan" #: src/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Close Window" msgstr "Tutup Jendela" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "Keluar dari Bazaar" #~ 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. " #~ msgid "_Synchronize Remotes" #~ msgstr "_Sinkronkan Dengan Server" #~ msgid "Synchronizing..." #~ msgstr "Mengsinkronkan..." #, c-format #~ msgid "Receiving %d entries..." #~ msgstr "%d entri tersisa..." #~ msgid "Indexing Data..." #~ msgstr "Mengindeks Data..." #~ msgid "Install Other Version" #~ msgstr "Pasang Versi Lain" #~ msgid "Keep Data" #~ msgstr "Simpan Data" #~ msgid "Open App" #~ msgstr "Buka Aplikasi" #~ msgid "Refreshing Store Content" #~ msgstr "Memuat Ulang Konten Bazaar" #~ msgid "No background tasks!" #~ msgstr "Tidak ada proses latar belakang!" #~ msgctxt "shortcut window" #~ msgid "Synchronize Remotes" #~ msgstr "Sinkronkan Dengan Server" #~ msgctxt "shortcut window" #~ msgid "Quit" #~ msgstr "Keluar" #~ msgid "Nucleus app page" #~ msgstr "Tampilan halaman detail aplikasi" #~ msgid "Close" #~ msgstr "Tutup" #~ msgid "Copy and Close" #~ msgstr "Salin dan Tutup" #~ 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" #, 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 "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" #~ 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 "" #~ "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" #~ 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 "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" bazaar-org-bazaar-43ce9f7/po/it.po000066400000000000000000001317541520414637400170360ustar00rootroot00000000000000# 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" bazaar-org-bazaar-43ce9f7/po/ja.po000066400000000000000000004144131520414637400170100ustar00rootroot00000000000000# 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-04-22 22:40+0900\n" "PO-Revision-Date: 2026-04-22 22:55+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.0.1\n" #: data/io.github.kolunmi.Bazaar.desktop.in:3 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:46 #: src/bz-window.c:377 src/bz-window.c:378 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:17 msgid "New Window" msgstr "新しいウィンドウ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and manage applications" msgstr "アプリケーションを検索したり、管理したりする" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "Linux 用の高速で新しいアプリストアです。Flatpak のアプリケーションやアドオン" "を検索、インストールすることに特化していて、主に Flathub を利用します。" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "ダウンロードタスクをキューに入れて、ブラウジングを続行しよう" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "簡単にアプリの権限を表示して、編集する" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "Flathub にログインしてお気に入りを管理、表示する" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "GNOME シェルから直接検索する" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "The home page displaying Flathub apps" msgstr "Flathub のアプリを表示しているホームページ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:59 msgid "Exhibit app page" msgstr "Exhibit のアプリページ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "ライブラリーページ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "検索ページ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "カテゴリーページ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:79 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:104 #, fuzzy msgid "New Features" msgstr "バグ修正" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:83 msgid "Add support for previewing metainfo files" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:84 msgid "Show total installed apps number in the library view" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:85 msgid "Make exported desktop search provider app icon sizes adjustable" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:87 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:114 #, fuzzy msgid "Fixes" msgstr "バグ修正" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:91 msgid "Fix download timeline graph rerendering too much" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:92 msgid "Fix animated widget ticks not being in sync with fps" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:93 msgid "Fix progress animation for vertical pride flag stripes" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:94 msgid "Many other bug fixes" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:96 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:121 #, fuzzy msgid "Thanks for reading, and have a great day!" msgstr "読んでくれてありがとう! 良い一日を!" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:108 msgid "Rework the add-ons dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:109 msgid "Add a gradient under the download timeline" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:110 msgid "Add a filter button to the search page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:111 msgid "Add a button to show the EULA for some proprietary apps" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:112 msgid "Make the names of verified developers clickable links" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:118 msgid "Fix the colours of the update card" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:119 msgid "Make the update banner follow the accent colour" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:129 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:161 msgid "Changes" msgstr "変更点" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:133 msgid "Update to GNOME 50 Runtime" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:134 msgid "Force Adwaita icon theme to ensure consistency" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:135 msgid "Add support for clickable links in app descriptions" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:136 msgid "" "Add timed lingering cache to async textures, thereby reducing image " "flickering" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:137 msgid "Add ability to sort installed apps by size in library view" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:138 msgid "Add BAZAAR_N_DOWNLOAD_WORKERS envvar support" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:140 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:170 msgid "Bug Fixes" msgstr "バグ修正" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:144 msgid "Fix double shadow around update cards" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:145 msgid "Fix global progress button displaying a focus ring when invisible" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:146 msgid "Fix incorrect total size displayed on update tasks" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:147 msgid "Fix empty UI when Flathub hasn't finished syncing yet" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:149 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:179 msgid "Thanks for reading and have a great day!" msgstr "読んでくれてありがとう! 良い一日を!" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:157 msgid "" "This release contains many technical improvements. This changelog reflects " "roughly 2 weeks of work." msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:165 msgid "Respect system parental controls settings" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:166 msgid "" "Reap download workers when all windows are closed, reducing total memory " "usage" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:167 msgid "Add mnemonics to full app view" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:168 msgid "Many updates to language translations" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:174 msgid "Fix broken library page when backing installed apps model is empty" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:175 msgid "" "Fix int casting bug that was causing RetroDeck to appear to be 18.4 exabytes" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:176 msgid "Make \"all apps\" category pages respect global filters" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:177 msgid "Fix some text wrapping issues" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:187 msgid "This release fixes some bugs and greatly improves search functionality." msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:191 msgid "" "If you missed the previous release, in 0.7.9 we also added the ability to " "cancel transactions in the library view, a brand new screenshots carousel, " "search suggestion buttons, and app runtime size information. You can also " "now skip confirmation dialogs by holding shift as you start a transaction." msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:198 msgid "Thanks for reading!" msgstr "読んでくれてありがとう!" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:206 msgid "**New Features**" msgstr "**新機能**" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:208 msgid "Search suggestion pills" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:209 #, fuzzy msgid "**Cancel installation** transactions" msgstr "現在進行中のダウンロードを停止" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:210 msgid "Skip dialogs by pressing shift" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:211 msgid "Runtime size info for app pages" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:213 msgid "**Updated**" msgstr "**更新点**" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:215 msgid "Redesigned \"What's New\" dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:216 msgid "Improved search results by utilizing Flathub rankings" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:217 #, fuzzy msgid "Improved screenshots carousel" msgstr "スクリーンショット カルーセル" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:224 msgid "" "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." msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:233 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:247 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:269 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:281 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:302 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:321 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:352 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:363 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:381 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:392 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:405 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:415 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:427 msgid "This release comes with the following improvements:" msgstr "このリリースには以下の改善点が含まれています:" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:235 msgid "Merges the task sidebar and install page into the library page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:236 msgid "Add installed version numbers of each app on the library and app pages" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:237 #, fuzzy msgid "Add donations dialog" msgstr "年齢レーティングダイアログ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:238 msgid "Fix broken addon and runtime eol detection" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:239 msgid "Add `enable-bulk-install` key to curated sections" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:240 msgid "Add `override-eol-markings` main config string list" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:249 msgid "Improve context dialogs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:250 msgid "Fix leftover data bar being shown prematurely" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:251 msgid "Have a rotation toggle for flags" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:252 msgid "Add hard check to prevent removing Bazaar flatpak" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:253 #, fuzzy msgid "Improve download statistics tooltips" msgstr "ダウンロードの統計" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:254 msgid "Add read support for flatpak bundles" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:255 msgid "Fix critical output sometimes during transactions" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:256 msgid "Fix error popover refusing to spawn in transaction sidebar" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:263 msgid "Minor bugfix release" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:271 msgid "Fix issue where installed page is empty on opening second window" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:272 msgid "Fix screenshot flickering in search results" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:273 msgid "Fix pride flags sometimes not showing on certain locales" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:274 msgid "Add \"Install all\" to favorites page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:283 msgid "Trash user data instead of deleting" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:284 msgid "Tweaks to permissions dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:285 msgid "Fix broken EOL filtering" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:286 msgid "Add text filter to installed page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:287 msgid "" "Add optional translations mappings for string properties in YAML configs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:288 msgid "Hide EOL apps by default" msgstr "更新終了のアプリをデフォルトで非表示" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:289 msgid "Many other minor bug fixes and improvements" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:296 msgid "" "This small release ensures the new icon is rendered correctly on KDE Plasma." msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:304 msgid "New market stall icon" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:305 msgid "Remove Flathub styling" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:306 msgid "Add horizontal versions of pride flags" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:307 msgid "Text selection in app descriptions can be made across paragraph breaks" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:308 msgid "Support YAML anchors and aliases in config parsing" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:309 msgid "" "Drastically reduce disk cache writes over time by skipping unchanged entries" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:310 msgid "Show background status in popover" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:311 msgid "Add app permission system" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:312 msgid "Add back release URLs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:313 msgid "Fix sync-remotes action in shortcut dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:314 msgid "Fix visual hiccups in comet animations" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:323 msgid "Flathub account support with the ability to manage bookmarks" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:324 msgid "" "Flathub bookmarks replace star count; you can add or remove bookmarks from " "app pages" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:325 msgid "An \"Only Show Verified\" option" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:326 msgid "Exhaustive category pages for most categories" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:327 msgid "An \"Adwaita\" or \"KDE\" category shown based on desktop environment" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:328 msgid "Updated installed indicator for app tiles" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:329 msgid "3 new flag options" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:330 msgid "Fixed GNOME search provider to show the app page instead of search" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:331 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:332 msgid "" "Fixed issue where some proprietary apps were marked as \"Special License\"" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:333 msgid "Fixed issue where graphs did not work with touch" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:340 msgid "" "Another quick release to restore alphabetical sorting on the installed page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:346 msgid "Quick release to allow manual refresh if flathub is being flaky" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:354 msgid "" "Fix frequent disk writes; set refresh frequency to 1 day rather than 1 hour" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:355 msgid "Add \"Delete User Data\" option when uninstalling an application" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:356 msgid "Version cache to prevent incompatibility between Bazaar versions" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:365 msgid "" "Reworked loading to be substantially faster after first start via async " "loading" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:366 msgid "A gaming section on the Flathub page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:367 msgid "Improved UI on mobile, especially on app pages" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:368 msgid "Verified badges next to most places where apps are shown" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:369 msgid "A popover that explains what verification and non-verification mean" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:370 msgid "An \"other apps by\" page for when a developer has more than 6 apps" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:371 msgid "Tags that show other apps with the same tag when pressed" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:372 msgid "An age rating dialog" msgstr "年齢レーティングダイアログ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:373 msgid "Changed search filters into global content filters" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:374 msgid "5 new pride flags" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:383 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:384 msgid "Fix global progress bar theme sometimes not syncing with preferences" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:385 msgid "Show version next to addon name in the addons dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:394 msgid "Add \"On the go\" section and mobile cateogry" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:395 msgid "Greatly decrease reported memory usage" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:396 msgid "Rework search UI" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:397 msgid "Rework page stack navigation" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:398 msgid "Change screenshot dialog to page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:407 msgid "Fix slow/inconsistent image loading" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:408 msgid "Fix context row in full view" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:417 msgid "Rework full view layout" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:418 msgid "Improve progress bar theme selection" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:419 msgid "Reduce quantity and improve quality of search results" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:420 msgid "Allow the application window to fit on mobile screen sizes" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:429 msgid "Add interactive screenshot dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:430 msgid "Fix empty update dialogs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:431 msgid "Greatly improve look of app description rendering" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:432 msgid "Add pending state to the global progress bar" msgstr "全体のプログレスバーに中止の状態を追加しました" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:433 msgid "Add featured apps carousel" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:440 msgid "More improvements:" msgstr "改善点:" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:442 msgid "Improve design of transaction dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:443 msgid "Update remove button pulse effect and comet size curve" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:444 msgid "Reap and reload cached textures after a day" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:445 msgid "Eliminate some crashes caused by race conditions" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:446 msgid "Change preferences group to context bar in full view" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:447 msgid "Switch side panels to sidebars and use flat header bar designs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:448 msgid "Add really useful app size dialog :)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:455 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:467 msgid "Some improvements:" msgstr "改善点:" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:457 msgid "" "Make the global progress bar customizable with pride flags! Check preferences" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:458 msgid "Add a new world map page to the download statistics dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:459 msgid "" "Allow clicking on entries on transaction sidebar to navigate to the original " "store page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:460 msgid "Add Alexander Vanhee to the developer credits" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:469 msgid "Overhaul download history graph; make it interactive" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:470 msgid "Smarter \"back\" functionality" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:471 msgid "Hide bottom bar more often on small window sizes" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:472 msgid "" "Make \"light-banner\" and \"dark-banner\" keys available to curated configs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:479 msgid "This release includes:" msgstr "今回のリリースに含まれる変更:" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:481 msgid "553d041 * chore(po): update Ukrainian translation (#408)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:482 msgid "711732a * Rework Version History (#407)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:483 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:484 msgid "3787e6e * Save window size in gsettings" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:485 msgid "18ba76c * AsyncTexture: increase HTTP timeout to 5 seconds" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:486 msgid "980f752 * SearchWidget: prevent invalid item selection" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:487 msgid "ab95593 * Add installed icons to app tiles (#404)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:488 msgid "203754b * (UI) Improve visiblility of add-on feature (#403)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:489 msgid "069ce61 * fix installed page list outline ring (#402)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:490 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:491 msgid "a6939ba * fix(po): fix Ukrainian translation (#400)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:492 msgid "35c9611 * decrease app-tile description width reqs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:493 msgid "6098be7 * chore(po): update Polish translation (#397)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:494 msgid "2944d1e * change per section limit to 12 from 9 (#396)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:495 msgid "0b04284 * Update Japanese Translation (#394)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:496 msgid "fa60f4f * Move to brand new shiny Adw.ShortcutsDialog (#395)" msgstr "" #: src/bz-addon-tile.blp:49 src/bz-installed-tile.blp:64 #: src/bz-rich-app-tile.blp:140 msgid "Stopped Receiving Updates" msgstr "更新の提供終了" #: src/bz-addon-tile.c:155 src/bz-favorites-tile.c:157 #: src/bz-rich-app-tile.blp:172 msgid "Uninstall" msgstr "アンインストール" #: src/bz-addon-tile.c:157 src/bz-addons-dialog.blp:280 #: src/bz-favorites-tile.c:159 msgid "Install" msgstr "インストール" #: src/bz-addons-dialog.blp:14 src/bz-addons-dialog.blp:21 #: src/bz-addons-dialog.blp:70 src/bz-full-view.blp:627 #: src/bz-installed-tile.blp:101 msgid "Manage Add-Ons" msgstr "アドオンを管理する" #: src/bz-addons-dialog.blp:80 msgid "No Add-Ons Visible" msgstr "表示できるアドオンがありません" #: src/bz-addons-dialog.blp:81 msgid "" "Your current filter preferences are hiding all known add-ons. Try adjusting " "them." msgstr "" "現在のフィルターの設定では、全ての現存するアドオンが非表示になっています。設" "定を変更してもう一度お試しください。" #: src/bz-addons-dialog.blp:88 msgid "Add-on Page" msgstr "アドオン ページ" #: src/bz-addons-dialog.blp:202 src/bz-full-view.blp:426 msgid "Downloads/Month" msgstr "月あたりのダウンロード数" #: src/bz-addons-dialog.blp:229 src/bz-full-view.blp:461 msgid "Stopped Receiving Core Updates" msgstr "コアアップデートの提供終了" #: src/bz-addons-dialog.blp:243 msgid "" "This add-on uses a runtime that no longer receives updates or security " "fixes. It may become unsafe to use." msgstr "" "このアドオンは更新やセキュリティ修正の提供が終了したランタイムを使用していま" "す。 将来的に使用することが安全でなくなる可能性があります。" #: src/bz-addons-dialog.blp:297 src/bz-rich-app-tile.blp:185 #: src/bz-transaction-tile.blp:272 msgid "Open" msgstr "開く" #: src/bz-addons-dialog.blp:304 src/bz-install-controls.blp:141 #: src/bz-installed-tile.blp:114 msgid "Remove" msgstr "削除する" #: src/bz-addons-dialog.c:325 #, c-format msgid "Add-on for %s" msgstr "%s 用のアドオン" #: src/bz-addons-dialog.c:339 src/bz-full-view.c:568 msgid "Show Less" msgstr "折り畳む" #: src/bz-addons-dialog.c:339 src/bz-full-view.c:568 msgid "Show More" msgstr "もっと見る" #: src/bz-addons-dialog.c:389 msgid "Download Stats" msgstr "ダウンロード状態" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:736 src/bz-context-tile-callbacks.c:186 #: src/bz-context-tile-callbacks.c:193 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:686 src/bz-context-tile-callbacks.c:176 #, c-format msgid "%d+" msgstr "" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "全年齢" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "%s の年齢レーティングは不明です" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "%s は全ての年齢のユーザーに適している" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "%s は小さな子供のユーザーに適している" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "%s は子供のユーザーに適している" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "%s はティーンエイジのユーザーに適している" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "%s は大人のユーザーに適している" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "%s は %s のユーザーに適している" #: src/bz-age-rating-dialog.c:862 #, c-format msgid "%s • %s" msgstr "" #: 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:26 src/bz-app-size-dialog.blp:52 msgid "Download Size" msgstr "ダウンロードサイズ" #: src/bz-app-size-dialog.blp:53 msgid "Amount to download from the internet" msgstr "インターネットからダウンロードするデータの量" #: src/bz-app-size-dialog.blp:73 msgid "Installed Size" msgstr "インストール済みのサイズ" #: src/bz-app-size-dialog.blp:74 msgid "Size on Disk" msgstr "ディスク上のサイズ" #: src/bz-app-size-dialog.blp:121 msgid "Open user data folder" msgstr "ユーザーデータのフォルダーを開く" #: src/bz-app-size-dialog.blp:131 msgid "User Data Size" msgstr "ユーザーデータのサイズ" #: src/bz-app-size-dialog.blp:132 msgid "Caches, settings, and other app data" msgstr "キャッシュや設定、その他のアプリデータ" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "インストール済みランタイムのサイズ" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "ランタイムのダウンロードサイズ" #: src/bz-app-size-dialog.c:204 msgid "App Size" msgstr "アプリのサイズ" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:104 src/bz-rich-app-tile.c:304 msgid "Verified" msgstr "認証済み" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-context-tile-callbacks.c:135 #: src/bz-releases-list.c:206 msgid "Installed" msgstr "インストール済み" #: src/bz-apps-page.blp:86 msgid "Show All" msgstr "すべて表示" #: src/bz-apps-page.c:229 #, c-format msgid "All \"%s\"" msgstr "全ての「%s」" #: src/bz-apps-page.c:478 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "アプリケーション総数: %d" #: src/bz-application.c:728 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "" #: src/bz-application.c:729 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "" #: src/bz-application.c:749 msgid "The Bazaar Contributors" msgstr "Bazzar の貢献者たち" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:752 msgid "translator-credits" msgstr "camegone, 2025, 2026" #: src/bz-application.c:762 msgid "Special Thanks" msgstr "スペシャルサンクス" #: src/bz-application.c:820 msgid "Logged Out Successfully!" msgstr "正常にログアウトされました!" #: src/bz-application.c:943 msgid "Performing setup…" msgstr "セットアップの実行中…" #: src/bz-application.c:1027 msgid "Set Up System Flathub?" msgstr "システムに Flathub をセットアップしますか?" #: src/bz-application.c:1030 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub リモートはあなたのシステムでセットアップされていません。Bazaar でアプ" "リを検索したりインストールするためには、システムに Flathub をセットアップする" "必要があります。 \n" "\n" "あなたは引き続き Bazaar でインストール済みのアプリを検索したり削除することが" "できます。" #: src/bz-application.c:1037 msgid "Set Up Flathub?" msgstr "Flathub をセットアップしますか?" #: src/bz-application.c:1040 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 が利用できな" "い場合、アプリを検索したりインストールすることができません。\n" "\n" "あなたは引き続き Bazaar でインストール済みのアプリを検索したり削除することが" "できます。" #: src/bz-application.c:1046 msgid "Later" msgstr "後で" #: src/bz-application.c:1047 msgid "Set Up Flathub" msgstr "Flathub をセットアップする" #: src/bz-application.c:1336 msgid "A backend error occurred" msgstr "バックエンドのエラーが発生しました" #: src/bz-application.c:1532 src/bz-application.c:3483 src/bz-window.blp:70 msgid "Refreshing…" msgstr "再読み込み中…" #: src/bz-application.c:1684 src/bz-application.c:3481 #, c-format msgid "Loading %d apps…" msgstr "%d 個のアプリをロード中…" #: src/bz-application.c:1687 msgid "Checking for updates…" msgstr "更新を確認中…" #: src/bz-application.c:1750 msgid "Failed to open .flatpakref" msgstr ".flatpakref を開けませんでした" #: src/bz-application.c:1806 msgid "An initialization error occurred" msgstr "初期化中にエラーが発生しました" #: src/bz-application.c:2207 msgid "Failed to check for updates" msgstr "更新の確認に失敗しました" #: src/bz-application.c:3215 msgid "Could not find app" msgstr "アプリが見つかりませんでした" #: src/bz-application.c:3248 msgid "Failed to load metainfo" msgstr "メタ情報の読み込みに失敗しました" #: src/bz-application.c:3485 msgid "Writing to cache…" msgstr "キャッシュを書き込み中…" #: src/bz-appstream-parser.c:303 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub ページ" #: src/bz-appstream-parser.c:324 msgctxt "Project URL Type" msgid "Project Website" msgstr "プロジェクトのウェブサイト" #: src/bz-appstream-parser.c:328 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "バグトラッカー" #: src/bz-appstream-parser.c:332 msgctxt "Project URL Type" msgid "FAQ" msgstr "よくある質問" #: src/bz-appstream-parser.c:336 msgctxt "Project URL Type" msgid "Help" msgstr "ヘルプ" #: src/bz-appstream-parser.c:340 msgctxt "Project URL Type" msgid "Donate" msgstr "寄付" #: src/bz-appstream-parser.c:346 msgctxt "Project URL Type" msgid "Translate" msgstr "翝訳" #: src/bz-appstream-parser.c:350 msgctxt "Project URL Type" msgid "Contact" msgstr "連絡先" #: src/bz-appstream-parser.c:354 msgctxt "Project URL Type" msgid "Source Code" msgstr "ソースコード" #: src/bz-appstream-parser.c:360 msgctxt "Project URL Type" msgid "Contribute" msgstr "貢献する" #: src/bz-context-tile-callbacks.c:68 msgid "---" msgstr "" #. Translators: M is the suffix for millions #: src/bz-context-tile-callbacks.c:75 #, c-format msgid "%.*fM" msgstr "" #. Translators: K is the suffix for thousands #: src/bz-context-tile-callbacks.c:82 #, c-format msgid "%.*fK" msgstr "" #: src/bz-context-tile-callbacks.c:92 #, c-format msgid "%d downloads in the last month" msgstr "過去1ヶ月の間に %d ダウンロード" #: src/bz-context-tile-callbacks.c:104 src/bz-context-tile-callbacks.c:389 #: src/bz-context-tile-callbacks.c:406 msgid "N/A" msgstr "利用不能" #: src/bz-context-tile-callbacks.c:132 #, c-format msgid "+%s runtime" msgstr "+%s ランタイム" #: src/bz-context-tile-callbacks.c:135 msgid "Download" msgstr "ダウンロード" #: src/bz-context-tile-callbacks.c:155 msgid "Size information unavailable" msgstr "サイズの情報がありません" #: src/bz-context-tile-callbacks.c:158 #, c-format msgid "Download size of %s" msgstr "ダウンロードサイズ: %s" #: src/bz-context-tile-callbacks.c:191 msgid "All Ages" msgstr "全年齢" #: src/bz-context-tile-callbacks.c:203 msgid "Age rating information unavailable" msgstr "年齢レーティングの情報がありません" #: src/bz-context-tile-callbacks.c:208 msgid "Suitable for all ages" msgstr "全ての年齢のユーザーに適している" #: src/bz-context-tile-callbacks.c:210 #, c-format msgid "Suitable for ages %d and up" msgstr "%d 歳以上のユーザーに適している" #: src/bz-context-tile-callbacks.c:243 src/bz-context-tile-callbacks.c:248 #: src/bz-context-tile-callbacks.c:276 src/bz-context-tile-callbacks.c:284 msgid "Unknown" msgstr "不明" #: src/bz-context-tile-callbacks.c:253 #, c-format msgid "Free software licensed under %s" msgstr "%s ライセンスのもと公開されているフリーソフト" #: src/bz-context-tile-callbacks.c:258 msgid "Free software" msgstr "フリーのソフトウェア" #: src/bz-context-tile-callbacks.c:261 msgid "Proprietary Software" msgstr "プロプライエタリ ソフトウェア" #: src/bz-context-tile-callbacks.c:264 #, c-format msgid "Special License: %s" msgstr "特別なライセンス: %s" #: src/bz-context-tile-callbacks.c:281 msgid "Free" msgstr "フリー" #: src/bz-context-tile-callbacks.c:287 src/bz-license-dialog.c:133 msgid "Proprietary" msgstr "プロプライエタリ" #: src/bz-context-tile-callbacks.c:289 src/bz-license-dialog.c:135 msgid "Special License" msgstr "特別なライセンス" #: src/bz-context-tile-callbacks.c:309 msgid "Adaptive" msgstr "幅広いデバイスに対応" #: src/bz-context-tile-callbacks.c:309 msgid "Desktop Only" msgstr "デスクトップのみ" #: src/bz-context-tile-callbacks.c:315 msgid "Works on desktop, tablets, and phones" msgstr "デスクトップ、タブレット、携帯電話で動きます" #: src/bz-context-tile-callbacks.c:316 msgid "May not work on mobile devices" msgstr "モバイル端末では動かない可能性があります" #: src/bz-context-tile-callbacks.c:396 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "安全" #: src/bz-context-tile-callbacks.c:398 src/bz-context-tile-callbacks.c:400 msgid "Low Risk" msgstr "低いリスク" #: src/bz-context-tile-callbacks.c:402 msgid "Medium Risk" msgstr "中間のリスク" #: src/bz-context-tile-callbacks.c:404 msgid "High Risk" msgstr "高いリスク" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:68 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:53 #: src/bz-library-page.blp:66 src/bz-user-data-page.blp:30 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 "オフライン" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "ブラウザー" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "認証なし" #: src/bz-developer-badge.c:210 msgid "Developer information not available." msgstr "開発者に関する情報がありません。" #: src/bz-developer-badge.c:216 src/bz-developer-badge.c:230 #, 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:234 #, 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:250 #, 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:257 #, 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:261 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "このアプリ ID、%s の所有権は検証済みです。" #: src/bz-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "更新履歴の全文" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "この新バージョンはあなたのようなユーザーのおかげで実現しました!" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on Ko-Fi." msgstr "" "私は Bazaar の開発が好きですが、それは私一人だけではできません。もしあなたが" "将来的な開発の継続を支援したいなら、ko-fi でプロジェクトを支援することを検討" "してください。" #: src/bz-donations-dialog.blp:131 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:227 #, c-format msgid "What's New in %s?" msgstr "バージョン %s での変更点は何?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "リリース日: %Y/%0m/%0d" #: 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 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:69 src/bz-error.c:88 src/bz-error-dialog.blp:36 #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "芳細" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "コピーする" #: src/bz-error-dialog.c:56 src/bz-share-list.c:62 msgid "Copied!" msgstr "コピーしました!" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" 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:357 msgid "Failed to remove favorite" msgstr "お気に入りから削除できませんでした" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:78 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:385 msgid "Favorites" msgstr "お気に入り" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "全てインストール" #: src/bz-favorites-page.blp:34 src/bz-full-view.blp:36 src/bz-window.blp:255 msgid "Open App Library" msgstr "アプリ ライブラリを開く" #: src/bz-favorites-page.blp:56 src/bz-user-data-page.blp:19 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:54 msgid "Next" msgstr "揥へ" #: src/bz-flathub-category.c:93 msgid "Editing" msgstr "編集" #: src/bz-flathub-category.c:94 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:95 msgid "Mixer" msgstr "ミキサー" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:96 src/bz-search-pill-list.c:77 msgid "Music" msgstr "音楽" #: src/bz-flathub-category.c:97 msgid "Player" msgstr "プレーヤー" #: src/bz-flathub-category.c:98 msgid "Recorder" msgstr "レコーダー" #: src/bz-flathub-category.c:99 msgid "Sequencer" msgstr "シーケンサー" #: src/bz-flathub-category.c:100 msgid "Tuner" msgstr "チューナー" #: src/bz-flathub-category.c:101 msgid "TV" msgstr "テレビ" #: src/bz-flathub-category.c:106 msgid "Emulation" msgstr "エミュレーター" #: src/bz-flathub-category.c:107 msgid "Action" msgstr "アクション" #: src/bz-flathub-category.c:108 msgid "Adventure" msgstr "アドベンチャー" #: src/bz-flathub-category.c:109 msgid "Arcade" msgstr "アーケード" #: src/bz-flathub-category.c:110 msgid "Blocks" msgstr "ブロック" #: src/bz-flathub-category.c:111 msgid "Board" msgstr "ボードゲーム" #: src/bz-flathub-category.c:112 msgid "Card" msgstr "カードゲーム" #: src/bz-flathub-category.c:113 msgid "Kids" msgstr "子供向け" #: src/bz-flathub-category.c:114 msgid "Logic" msgstr "論理" #: src/bz-flathub-category.c:115 msgid "Role Playing" msgstr "ロールプレイング" #: src/bz-flathub-category.c:116 msgid "Shooter" msgstr "射撃系" #: src/bz-flathub-category.c:117 msgid "Simulation" msgstr "シミュレーション" #: src/bz-flathub-category.c:118 msgid "Sports" msgstr "スポーツ" #: src/bz-flathub-category.c:119 msgid "Strategy" msgstr "戦略" #: src/bz-flathub-category.c:124 msgid "Audio & Video" msgstr "映像や音楽" #: src/bz-flathub-category.c:124 msgid "Media" msgstr "メディア" #: src/bz-flathub-category.c:124 msgid "More Audio & Video" msgstr "映像や音楽をもっと見る" #: src/bz-flathub-category.c:125 msgid "Developer Tools" msgstr "開発ツール" #: src/bz-flathub-category.c:125 msgid "Develop" msgstr "開発" #: src/bz-flathub-category.c:125 msgid "More Developer Tools" msgstr "開発ツールをもっと見る" #: src/bz-flathub-category.c:126 msgid "Education" msgstr "教育" #: src/bz-flathub-category.c:126 msgid "Learn" msgstr "孌ぜ" #: src/bz-flathub-category.c:126 msgid "More Education" msgstr "教育アプリをもっと見る" #: src/bz-flathub-category.c:127 msgid "Gaming" msgstr "ゲーム" #: src/bz-flathub-category.c:127 msgid "Play" msgstr "遊ぶ" #: src/bz-flathub-category.c:127 msgid "More Gaming" msgstr "ゲームをもっと見る" #: src/bz-flathub-category.c:128 msgid "Graphics & Photography" msgstr "画像や写真" #: src/bz-flathub-category.c:128 msgid "Create" msgstr "創作する" #: src/bz-flathub-category.c:128 msgid "More Graphics & Photography" msgstr "画像や写真関連のアプリをもっと見る" #: src/bz-flathub-category.c:129 msgid "Networking" msgstr "ネットワーク" #: src/bz-flathub-category.c:129 msgid "Internet" msgstr "インターネット" #: src/bz-flathub-category.c:129 msgid "More Networking" msgstr "ネットワーク関連のアプリをもっと見る" #: src/bz-flathub-category.c:130 msgid "Productivity" msgstr "生産性向上" #: src/bz-flathub-category.c:130 msgid "Work" msgstr "働く" #: src/bz-flathub-category.c:130 msgid "More Productivity" msgstr "生産性向上アプリをもっと見る" #: src/bz-flathub-category.c:131 msgid "Science" msgstr "科学" #: src/bz-flathub-category.c:131 msgid "More Science" msgstr "科学アプリをもっと見る" #: src/bz-flathub-category.c:132 msgid "System" msgstr "システム" #: src/bz-flathub-category.c:132 msgid "More System" msgstr "システムアプリをもっと見る" #: src/bz-flathub-category.c:133 msgid "Utilities" msgstr "便利ツール" #: src/bz-flathub-category.c:133 msgid "Tools" msgstr "ツール" #: src/bz-flathub-category.c:133 msgid "More Utilities" msgstr "便利ツールをもっと見る" #: src/bz-flathub-category.c:134 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:148 msgid "Trending" msgstr "話題のアプリ" #: src/bz-flathub-category.c:134 msgid "More Trending" msgstr "話題のアプリをもっと見る" #: src/bz-flathub-category.c:135 src/bz-flathub-page.blp:122 #: src/bz-flathub-page.blp:178 msgid "Popular" msgstr "人気のアプリ" #: src/bz-flathub-category.c:135 msgid "More Popular" msgstr "人気アプリをもっと見る" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:168 msgid "Recently Added" msgstr "最近追加されたアプリ" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:128 msgid "New" msgstr "新しいアプリ" #: src/bz-flathub-category.c:136 msgid "More New" msgstr "新着アプリをもっと見る" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:158 msgid "Recently Updated" msgstr "最近更新されたアプリ" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:134 msgid "Updated" msgstr "更新されたアプリ" #: src/bz-flathub-category.c:137 msgid "More Updated" msgstr "更新されたものをもっと見る" #: src/bz-flathub-category.c:138 msgid "Mobile" msgstr "モバイル" #: src/bz-flathub-category.c:138 msgid "More Mobile" msgstr "モバイル対応アプリをもっと見る" #: src/bz-flathub-category.c:139 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:139 msgid "More Adwaita" msgstr "Adwaita をもっと見る" #: src/bz-flathub-category.c:140 msgid "KDE Apps" msgstr "KDE アプリ" #: src/bz-flathub-category.c:140 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:200 msgid "App of the Day" msgstr "今日のアプリ" #: src/bz-flathub-page.blp:264 msgid "On the Go" msgstr "どこでも一緒" #: src/bz-flathub-page.blp:276 msgid "Apps for your Linux phones and tablets" msgstr "Linux フォンやタブレット向けのアプリ" #: src/bz-flathub-page.blp:287 src/bz-flathub-page.blp:322 msgid "More Mobile Apps" msgstr "モバイル対応アプリをもっと見る" #: src/bz-flathub-page.blp:378 msgid "We​ ♥​ Games" msgstr "" #: src/bz-flathub-page.blp:391 msgid "Games and apps to run your favorite titles" msgstr "ゲームやお気に入りのタイトルを遊ぶためのアプリ" #: src/bz-flathub-page.blp:425 msgid "More Games" msgstr "ゲームをもっと見る" #: src/bz-full-view.blp:57 src/bz-library-page.blp:77 #: src/bz-library-page.blp:81 msgid "No Results" msgstr "結果無し" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "別の語句で検索してみてください" #: src/bz-full-view.blp:64 msgid "Content" msgstr "内容" #: src/bz-full-view.blp:122 msgid "Installing .flatpak bundles is not yet supported" msgstr "" ".flatpak 形式のバンドルをインストールする機能はまだサポートされていません" #: src/bz-full-view.blp:128 msgid "" "This is a local preview, some details may differ from the published listing" msgstr "" "これはローカルのプレビューです。細かな部分は公開のリストのページと異なる可能" "性があります" #: src/bz-full-view.blp:131 msgid "Preview Store Appearance" msgstr "ストアの外観をプレビュー" #: src/bz-full-view.blp:257 msgid "_Support" msgstr "支援する(_S)" #: src/bz-full-view.blp:475 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:562 msgid "Trash Data" msgstr "データをゴミ箱に移動" #: src/bz-full-view.blp:702 msgid "Tags:" msgstr "タグ:" #: src/bz-full-view.c:180 msgid "No URL" msgstr "URL がありません" #: src/bz-full-view.c:198 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "このアプリケーションはフリーのOSSライセンスで公開されており、安全のためにソー" "スコードを確認することができます。" #: src/bz-full-view.c:199 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:206 msgid "More Apps" msgstr "アプリをもっと見る" #: src/bz-full-view.c:207 #, c-format msgid "More Apps by %s" msgstr "%s のアプリをもっと見る" #: src/bz-full-view.c:214 msgid "Other Apps by this Developer" msgstr "この開発者の別のアプリ" #: src/bz-full-view.c:216 src/bz-full-view.c:315 #, c-format msgid "Other Apps by %s" msgstr "%s の別のアプリ" #: src/bz-full-view.c:225 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" "%s はインストールされていませんが、%s のデータは残存しています。" #: src/bz-full-view.c:317 msgid "Other Apps" msgstr "他のアプリ" #: src/bz-full-view.c:319 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "アプリケーション総数: %d" #: 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-install-controls.blp:34 src/bz-transaction-dialog.c:202 msgid "_Install" msgstr "インストール(_I)" #: src/bz-install-controls.blp:60 msgid "_Open" msgstr "開く(_O)" #: src/bz-install-controls.blp:75 src/bz-install-controls.blp:131 msgid "Uninstall Application" msgstr "このアプリケーションをアンインストール" #: src/bz-install-controls.blp:85 src/bz-transaction-dialog.c:231 msgid "_Remove" msgstr "削除する(_R)" #: src/bz-install-controls.blp:118 src/bz-updates-card.c:161 #: src/bz-updates-card.c:180 msgid "Update" msgstr "更新" #: src/bz-library-page.blp:32 msgid "Search installed apps" msgstr "インストール済みのアプリを検索" #: src/bz-library-page.blp:49 msgid "Clear search" msgstr "検索を削除" #: src/bz-library-page.blp:70 msgid "No Apps Found" msgstr "アプリケーションがありません" #: src/bz-library-page.blp:89 msgid "Search Store Instead" msgstr "代わりにストアを検索" #. Translators: . #: src/bz-library-page.blp:99 src/bz-window.blp:112 msgid "Library" msgstr "ライブラリー" #: src/bz-library-page.blp:127 msgid "Pending Updates" msgstr "実行待ちの更新" #: src/bz-library-page.blp:154 msgid "Downloads" msgstr "ダウンロード一覧" #: src/bz-library-page.blp:197 msgid "Recently Uninstalled" msgstr "最近アンインストールされたアプリ" #: src/bz-library-page.blp:248 msgid "Clear Finished Tasks" msgstr "完了したタスクを削除" #: src/bz-library-page.blp:333 msgid "Sort By" msgstr "ソート順" #: src/bz-library-page.blp:347 msgid "Name" msgstr "名前" #: src/bz-library-page.blp:353 msgid "Size" msgstr "サイズ" #: src/bz-library-page.c:180 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "" "インストール済みのアプリ一覧には、「%s」という単語は見つかりませんでした" #: src/bz-library-page.c:193 src/bz-updates-card.c:426 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u 件の利用可能なアップデート" #: src/bz-library-page.c:203 #, c-format msgid "%u Installed App" msgid_plural "%u Installed Apps" msgstr[0] "%u 件のインストール済みのアプリ" #: src/bz-license-dialog.blp:94 msgid "Get Involved" msgstr "参加する" #: src/bz-license-dialog.blp:111 msgid "Learn More" msgstr "詳細を表示" #: src/bz-license-dialog.c:127 msgid "Unknown License" msgstr "不明なライセンス" #: src/bz-license-dialog.c:130 msgid "Community Built" msgstr "コミュニティーによって作られました" #: src/bz-license-dialog.c:203 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:206 msgid "The license of this app is not known" msgstr "このアプリのライセンスは不明です" #: src/bz-license-dialog.c:212 #, 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:220 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:226 #, 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-license-dialog.c:356 src/bz-safety-dialog.blp:53 msgid "License" msgstr "ライセンス" #: 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:110 msgid "Finish" msgstr "完了" #: src/bz-login-page.c:664 #, c-format msgid "Hello, %s!" msgstr "ようこそ、%s!" #: src/bz-metainfo-preview.c:84 msgid "Select Metainfo File" msgstr "メタ情報ファイルを選択" #: src/bz-metainfo-preview.c:87 msgid "Metainfo Files" msgstr "メタ情報ファイル" #: src/bz-metainfo-preview.c:141 msgid "Select Icon (Optional)" msgstr "アイコンを選択(任意)" #: src/bz-metainfo-preview.c:144 msgid "Image Files" msgstr "画像ファイル" #: src/bz-metainfo-preview.c:231 msgid "Preview" msgstr "プレビュー" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "設定" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data refresh is paused" msgstr "" "従量課金のネットワークに接続しています — ストア情報の自動読み込みは一時停止さ" "れています" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:282 msgid "Refresh 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 End-of-Life 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:127 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-updates-card.c:152 msgid "Version History" msgstr "バージョン履歴" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "バージョン履歴(_V)" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "今日" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "昨日" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "%d 日前" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "%d 週間前" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "%d ヶ月前" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "%d 年前" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%Y/%0m/%0d" #: src/bz-releases-list.c:196 #, c-format msgid "Version %s" msgstr "バージョン %s" #: src/bz-releases-list.c:251 msgid "No details for this release" msgstr "このリリースの詳細情報がありません" #: src/bz-releases-list.c:263 msgid "Get More Information" msgstr "詳細情報を確認する" #: src/bz-rich-app-tile.blp:157 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:63 msgid "App ID" msgstr "アプリ ID" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:104 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:150 msgid "Reset View" msgstr "表示をリセット" #: src/bz-screenshot-page.blp:161 msgid "Zoom Out" msgstr "ズームアウト" #: src/bz-screenshot-page.blp:171 msgid "Zoom In" msgstr "ズームイン" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "スクリーンショット カルーセル" #: src/bz-screenshots-carousel.blp:117 msgid "Open Screenshot Viewer" msgstr "スクリーンショットビューアを開く" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "動画" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "オフィス" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "カレンダー" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "メッセージ" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Steam" msgstr "Steam" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "Paint" msgstr "お絵描き" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Torrent" msgstr "Torrent" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:122 msgid "Minecraft" msgstr "Minecraft" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:127 msgid "Emulator" msgstr "エミュレーター" #: src/bz-search-filter-popover.blp:18 src/bz-search-page.blp:83 msgid "Filters" msgstr "フィルター" #: src/bz-search-filter-popover.blp:35 msgid "_Verified" msgstr "認証済み(_V)" #: src/bz-search-filter-popover.blp:42 msgid "_Free/Open" msgstr "フリー/オープン(_F)" #: src/bz-search-filter-popover.blp:49 msgid "Non-_EOL" msgstr "サポート中(_E)" #: src/bz-search-filter-popover.blp:52 msgid "Filter out End-of-Life apps" msgstr "更新終了したアプリを除外する" #: src/bz-search-filter-popover.blp:57 msgid "Categories" msgstr "カテゴリー一覧" #: src/bz-search-page.blp:58 msgid "Search Apps, Games, Software" msgstr "アプリ、ゲーム、ソフトウェアを検索" #: src/bz-search-page.blp:70 msgid "Search Filters" msgstr "検索フィルター" #: src/bz-search-page.blp:100 msgid "Clear Search" msgstr "検索を削除" #: src/bz-search-page.blp:192 msgid "Categories Unavailable" msgstr "カテゴリーが利用不能です" #: src/bz-search-page.blp:193 msgid "Search for apps using the search bar above." msgstr "画面上側にある検索バーを使用してアプリを検索する。" #: src/bz-search-page.blp:219 msgid "Browse Categories" msgstr "カテゴリー一覧" #: src/bz-search-page.blp:361 msgid "No Applications Found" msgstr "アプリケーションがありません" #: src/bz-search-page.c:247 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "「%s」という検索語句に合致するアプリは、Flathub にありませんでした" #: src/bz-share-list.c:123 msgid "Copy Link" msgstr "リンクをコピーする" #: src/bz-share-list.c:134 msgid "Open Link" msgstr "リンクを開く" #: src/bz-stats-dialog.blp:27 msgid "Timeline" msgstr "時系列" #: src/bz-stats-dialog.blp:45 msgid "Installs:" msgstr "インストール数:" #: src/bz-stats-dialog.blp:54 msgid "World" msgstr "地域別" #: src/bz-stats-dialog.blp:68 msgid "Since 4/15/2024" msgstr "2024/04/15 から" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:125 #, c-format msgid "%.2fM Total Installs" msgstr "総ダウンロード回数: %.2fM 回" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:128 #, c-format msgid "%.2fK Total Installs" msgstr "総ダウンロード回数: %.2fK 回" #: src/bz-stats-dialog.c:130 #, c-format msgid "%'d Total Installs" msgstr "総ダウンロード回数: %'d 回" #: src/bz-tag-list.c:78 msgid "No Results Found" msgstr "検索結果無し" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "\"%s\" タグのついたアプリ" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "検索に失敗しました" #: src/bz-transaction-dialog.c:155 msgid "Keep User Data" msgstr "ユーザーデータを保持" #: src/bz-transaction-dialog.c:156 msgid "Allow restoring personal settings & content" msgstr "設定やコンテンツをまた使うことのできるように保持する" #: src/bz-transaction-dialog.c:165 msgid "Delete All Data" msgstr "全てのデータを削除" #: src/bz-transaction-dialog.c:166 msgid "Permanently erase user 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:201 src/bz-transaction-dialog.c:230 #: src/bz-transaction-dialog.c:275 src/bz-transaction-dialog.c:578 msgid "_Cancel" msgstr "キャンセル(_C)" #: 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 "それでもインストールする(_I)" #: src/bz-transaction-dialog.c:331 msgid "Failed to load transaction dialog" msgstr "ファイル操作のダイアログを読み込むことができませんでした" #: src/bz-transaction-dialog.c:549 msgid "All apps are already installed" msgstr "全てのアプリがすでにインストール済みです" #: src/bz-transaction-dialog.c:551 msgid "_OK" msgstr "OK(_O)" #: 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-dialog.c:579 msgid "_Install All" msgstr "全てインストール(_I)" #: src/bz-transaction-manager.c:766 #, c-format msgid "Finished in %.02f seconds" msgstr "%.02f 秒で完了しました" #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "アプリ アドオン" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "ランタイム" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "順番待ち" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "完了" #: src/bz-transaction-tile.blp:230 msgid "Error" msgstr "エラー" #: src/bz-transaction-tile.blp:286 msgid "Cancel Transaction" msgstr "ファイル操作をキャンセル" #: src/bz-transaction-tile.blp:410 msgid "Show Error Info" msgstr "エラーの詳細を表示" #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "%s を解放しました" #: src/bz-transaction-tile.c:362 src/bz-transaction-tile.c:365 msgid "Transaction Error" msgstr "ファイル操作のエラー" #: src/bz-transaction.c:342 msgid "Pending" msgstr "一時停止中" #: src/bz-updates-card.blp:22 msgid "_Update All" msgstr "全て更新(_U)" #: src/bz-updates-card.c:208 #, 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:33 msgid "No User Data Found" msgstr "ユーザーデータが見つかりませんでした" #: src/bz-user-data-page.blp:38 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:88 msgid "Curated" msgstr "特選アプリ" #: src/bz-window.blp:100 msgid "Explore" msgstr "探索" #: src/bz-window.blp:220 msgid "Refresh completed!" msgstr "再読み込み完了!" #: src/bz-window.blp:239 msgid "Main Menu" msgstr "メインメニュー" #: src/bz-window.blp:273 msgid "You are running a new version of Bazaar!" msgstr "Bazaar のバージョンが新しくなりました!" #: src/bz-window.blp:274 msgid "See What's New" msgstr "変更点を見る" #: src/bz-window.blp:281 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "ネットワークに接続されていますが、キャッシュされた Flathub を表示しています" #: src/bz-window.blp:327 msgid "_Donate to Bazaar" msgstr "Bazaar に寄付する(_D)" #: src/bz-window.blp:334 msgid "_Refresh" msgstr "再読み込み(_R)" #: src/bz-window.blp:339 msgid "_Preferences" msgstr "設定(_P)" #: src/bz-window.blp:344 msgid "_Login With Flathub" msgstr "Flathub にログイン(_L)" #: src/bz-window.blp:350 msgid "_Manage Leftover User Data" msgstr "残存しているユーザーデータを管理(_M)" #: src/bz-window.blp:355 msgid "_Keyboard Shortcuts" msgstr "キーボードショートカット(_K)" #: src/bz-window.blp:360 msgid "_About Bazaar" msgstr "Bazaar について(_A)" #: src/bz-window.blp:367 msgid "_Quit Bazaar" msgstr "Bazaar を終了(_Q)" #: src/bz-window.blp:392 msgid "Log Out" msgstr "ログアウト" #. Translators: %s is the title of the current page #: src/bz-window.c:380 #, c-format msgid "Bazaar — %s" msgstr "Bazaar — %s" #: src/bz-window.c:544 src/bz-window.c:561 msgid "Failed to launch application" msgstr "アプリケーションの起動失敗" #: src/bz-window.c:766 msgid "You can't remove Bazaar from Bazaar!" msgstr "Bazaar を使って Bazaar を削除することはできません!" #: src/bz-window.c:1051 src/bz-window.c:1085 msgid "Can't do that right now!" msgstr "今すぐにはできません!" #: src/bz-world-map.c:603 msgctxt "As in, \"100 Installs\"" msgid "Installs" msgstr "インストール" #: src/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "一般" #: src/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Page" msgstr "検索ページを表示" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "ライブラリ ページを開く" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Refresh" msgstr "再読み込み" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Open Preferences" msgstr "設定を開く" #: src/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "ショートカットを表示" #: src/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Close Window" msgstr "ウィンドウを閉じる" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "Bazaar を終了" #~ msgid "_Donate to Bazaar ❤️" #~ msgstr "Bazaar に寄付する❤️(_D)" #~ msgid "Flathub" #~ msgstr "Flathub" #~ msgctxt "As in, \"100 Downloads\"" #~ msgid "Downloads" #~ msgstr "ダウンロード" #~ msgid "Download & Install Application" #~ msgstr "アプリケーションをダウンロードしてインストールする" #~ 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 ではディストリビューターが管理できる「特選アプリ」タブによってユー" #~ "ザーの体験を最適化することを可能にします。" #~ msgid "Install Other Version" #~ msgstr "ほかのバージョンをインストール" #~ msgid "%e %B" #~ msgstr "%0m/%0d" #~ msgid "Keep Data" #~ msgstr "データを保持" #~ msgid "Open App" #~ msgstr "アプリを開く" #~ msgid "Support this application" #~ msgstr "このアプリケーションを支援する" #~ msgid "Manage Add-ons" #~ msgstr "アドオンを管理する" #~ msgid "_Login with Flathub" #~ msgstr "Flathub にログイン(_L)" #~ msgid "_Synchronize Remotes" #~ msgstr "リモートと同期(_S)" #~ msgid "Synchronizing..." #~ msgstr "同期中..." #, c-format #~ msgid "Receiving %d entries..." #~ msgstr "%d 件のエントリを受信中..." #~ msgid "Indexing Data..." #~ msgstr "データをインデックス中..." #~ msgid "View the Release Page" #~ msgstr "リリースページを表示" #~ msgid "Close" #~ msgstr "閉じる" #~ msgid "Copy and Close" #~ msgstr "コピーして閉じる" #~ msgid "Refreshing Store Content" #~ msgstr "ストアの内容を再読み込み中" #~ msgid "No background tasks!" #~ msgstr "バックグラウンドタスクがありません!" #~ msgctxt "shortcut window" #~ msgid "Synchronize Remotes" #~ msgstr "リモートと同期" #~ msgctxt "shortcut window" #~ msgid "Quit" #~ msgstr "アプリを閉じる" #~ msgid "Nucleus app page" #~ msgstr "Nucleus アプリページ" #, fuzzy #~ msgid "Better track installed versions of apps" #~ 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 "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 "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 "No Flatpaks Installed" #~ msgstr "Flatpak がインストールされていません" #~ msgid "Inspect UI Entry" #~ msgstr "UI エントリを検査" #~ msgid "All Debug Actions" #~ msgstr "すべてのデバッグオプション" #~ msgid "Open Bazaar Inspector" #~ msgstr "Bazaar インスペクターを開く" #~ 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 "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 "グラフィック" #~ msgctxt "Project URL Type" #~ msgid "Homepage" #~ 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" #~ msgstr "%0m/%0d" #~ 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 "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 "今週のアプリ" #~ 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 "このリンクを外部で開く" bazaar-org-bazaar-43ce9f7/po/kw.po000066400000000000000000002744701520414637400170460ustar00rootroot00000000000000# 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-05-22 17:01+0100\n" "PO-Revision-Date: 2026-05-22 20:15+0100\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 50.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:45 #: src/bz-window.blp:199 src/bz-window.c:373 src/bz-window.c:374 msgid "Bazaar" msgstr "Basar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Keworra, dilea, po nowedhi medhelweyth flatpak war'n 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:16 msgid "New Window" msgstr "Fenester Nowydh" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and manage applications" msgstr "Trovya ha dyghtya appys" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "Gwerthji appys snell hag arnowydh rag Linux gans fog war ow trovya hag ow " "lea appys hag ystynansow Flatpak, dres oll dhyworth Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "Lostya meur a leyansow ha pesya ow peuri" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "Gweles kummyasow app yn es" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "Omgelmi dhe Flathub rag gweles ha dyghtya agas appys drudh" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "Hwilas appys dhyworth GNOME Shell didro" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:30 src/bz-application.c:759 msgid "The Bazaar Contributors" msgstr "An Kevriysi Vasar" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "The home page displaying Flathub apps" msgstr "An folen dre ow tispletya appys Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:59 msgid "Exhibit app page" msgstr "Folen app diskwedhyn" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "Folen lyverva" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "Folen hwithrans" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "Folen glass" #: src/bz-addon-tile.blp:64 src/bz-installed-tile.blp:55 #: src/bz-rich-app-tile.blp:141 msgid "Stopped Receiving Updates" msgstr "Nowedhys Namoy" #: src/bz-addon-tile.c:167 src/bz-favorites-tile.c:155 msgctxt "Install Controls" msgid "Uninstall" msgstr "Dilea" #: src/bz-addon-tile.c:169 src/bz-bundle-install-dialog.blp:126 #: src/bz-favorites-tile.c:157 src/bz-install-controls.wdgt:29 msgctxt "Install Controls" msgid "Install" msgstr "Lea" #: src/bz-addons-dialog.blp:14 src/bz-addons-dialog.blp:21 #: src/bz-addons-dialog.blp:70 src/bz-full-view.blp:583 #: src/bz-installed-tile.blp:92 msgid "Manage Add-Ons" msgstr "Dyghtya Ystynansow" #: src/bz-addons-dialog.blp:80 msgid "No Add-Ons Visible" msgstr "Nyns eus Ystynansow Weladow" #: src/bz-addons-dialog.blp:81 msgid "" "Your current filter preferences are hiding all known add-ons. Try adjusting " "them." msgstr "" "Agas dewisyow sidhlans a-lemmyn yw ow kudha oll ystynansow aswonys. " "Assayewgh ow chanjya dhedha." #: src/bz-addons-dialog.blp:88 msgid "Add-on Page" msgstr "Folen Ystynnans" #: src/bz-addons-dialog.blp:202 src/bz-full-view.blp:381 msgid "Downloads/Month" msgstr "Iskargow/Mis" #: src/bz-addons-dialog.blp:229 src/bz-full-view.blp:417 msgid "Stopped Receiving Core Updates" msgstr "Ow Receva Nowedhyansow Kolonnen Na Fella" #: src/bz-addons-dialog.blp:243 msgid "" "This add-on uses a runtime that no longer receives updates or security " "fixes. It may become unsafe to use." msgstr "" "An app ma a dhevnydh kerghynnedh nag ow receva nowedhyansow po ewnheansow " "sawder na fella. Yth a yll bydh diantel dhe dhevnydhya." #: src/bz-addons-dialog.c:333 #, c-format msgid "Add-on for %s" msgstr "Ystynnans rag %s" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show Less" msgstr "Diskwedhes Le" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show More" msgstr "Diskwedhes Moy" #: src/bz-addons-dialog.c:397 msgid "Download Stats" msgstr "Statystygyon Iskargow" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:736 src/bz-context-tile-callbacks.c:186 #: src/bz-context-tile-callbacks.c:193 msgid "Age Rating" msgstr "Gwiwder Bloodh" #. 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow 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 "Nyns eus 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow yn-kever kampollans dhe wara 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow yn-kever kampollans dhe bo portrayansow a nas 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 "Nyns eus kedhlow yn-kever kossyans" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Hwarthuster Anwiw" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Nyns eus kedhlow yn-kever hwarthuster anwiw" #. 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 "Nyns eus kedhlow yn-kever keskows disfaveryans a neb eghen" #. 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow yn-kever kevrans a henwyn devnydhyer 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 "" "Nyns eus kedhlow yn-kever kevrans a gedhlow privedh gans partiow-tressa" #. 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow 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 "Nyns eus kedhlow yn-kever kampollans dhe dhefolyans" #. 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 "Nyns eus kedhlow yn-kever korf marow gweladow" #. 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 "Nyns eus kedhlow yn-kever kampollans dhe gethneth" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Nyns eus kampollans dhe dhroggys ynno" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "Nyns eus kossya ynno" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Nyns eus argemynnow po treuswriansow monesek ynno" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Nyns eus kyjyans po nothedh ynno" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "Nyns eus keskows heb musur ynno" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Nyns eus garowder ynno" #: 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:686 src/bz-context-tile-callbacks.c:176 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "Oll" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "Yma gwiwder bloodh ankoth dhe %s" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "%s yw gwiw rag oll" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "%s yw gwiw rag fleghes yowynk" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "%s yw gwiw rag fleghes" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "%s yw gwiw rag degowogyon" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "%s yw gwiw rag tevesigesow" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "%s yw gwiw rag %s" #: src/bz-age-rating-dialog.c:862 #, c-format msgid "%s • %s" msgstr "%s • %s" #: 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 "Isrestrenva dre %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 "Selyans system ost dhyworth /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Isrestrenva dhesktop %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Restrenva dhesktop" #: 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 ilow %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Restrenva ilow" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Isrestrenva skeusennow %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Restrenva skeusennow" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Isrestrenva Gevren Poblek %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Restrenva Gevren Poblek" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Isrestrenva wydhyowyow %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Restrenva wydhyowyow" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Isrestrenva ensamplys %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Restrenva ensamplys" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Isrestrenva sorn devnydhyer %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Restrenva sorn devnydhyer" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Isrestrenva selyans devnydhyer %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Restrenva selyans devnydhyer" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Isrestrenva dhata devnydhyer %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Restrenva Dhata Devnydhyer" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Isrestrenva gerghynnedh devnydhyer %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Restrenva gerghynnedh devnydhyer" #: 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:26 src/bz-app-size-dialog.blp:60 msgid "Download Size" msgstr "Braster a'n Iskarg" #: src/bz-app-size-dialog.blp:33 src/bz-app-size-dialog.blp:81 msgid "Installed Size" msgstr "Braster pan Leys" #: src/bz-app-size-dialog.blp:61 msgid "Amount to download from the internet" msgstr "Myns dhe iskarga dhyworth an kesrosweyth" #: src/bz-app-size-dialog.blp:82 msgid "Size on Disk" msgstr "Braster war Blasen" #: src/bz-app-size-dialog.blp:133 msgid "Open user data folder" msgstr "Ygeri restrenva dhata devnydhyer" #: src/bz-app-size-dialog.blp:143 msgid "Your User Data" msgstr "Agas Data Devnydhyer" #: src/bz-app-size-dialog.blp:144 msgid "Caches, settings, and other app data" msgstr "Sornow, settyansow, ha data app erel" #: src/bz-app-size-dialog.blp:165 msgid "Cache" msgstr "Sorn" #: src/bz-app-size-dialog.blp:166 msgid "Temporary cached data" msgstr "Data yn sorn yn servadow" #: src/bz-app-size-dialog.blp:176 msgid "Clear Cache" msgstr "Dilea Sorn" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "Braster Leys Kerghynnedh" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "Braster Iskarg Kerghynnedh" #: src/bz-app-size-dialog.c:220 msgid "App Size" msgstr "Braster App" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:105 src/bz-rich-app-tile.c:429 msgid "Verified" msgstr "Gwirhes" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-context-tile-callbacks.c:135 #: src/bz-releases-list.c:206 msgid "Installed" msgstr "Leys" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:762 msgid "translator-credits" msgstr "Flynn " #: src/bz-application.c:772 msgid "Special Thanks" msgstr "Grassow Arbennik" #: src/bz-application.c:830 msgid "Logged Out Successfully!" msgstr "Omdhigelmys yn Sewen!" #: src/bz-application.c:966 msgid "Performing setup…" msgstr "Ow kwruthyl selyans…" #: src/bz-application.c:1052 msgid "Set Up System Flathub?" msgstr "Selya Flathub System?" #: src/bz-application.c:1055 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "An withva system Flathub nag yw selys na hwath. Res yw dhe Vasar rag Flathub " "bos selys war'n leyans Flatpak system dhe peuri ha lea appys.\n" "\n" "Hwi a yll devnydhya Basar hwath rag peuri ha remova appys leys seulabrys." #: src/bz-application.c:1062 msgid "Set Up Flathub?" msgstr "Selya Flathub?" #: src/bz-application.c:1065 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 nag yw selys war'n system ma. Ny yllowgh peuri ha lea appys yn Basar " "mars ankavadow yw.\n" "\n" "Hwi a yll devnydhya Basar hwath rag peuri ha remova appys leys seulabrys." #: src/bz-application.c:1071 msgid "Later" msgstr "Wosa Henna" #: src/bz-application.c:1072 msgid "Set Up Flathub" msgstr "Selya Flathub" #: src/bz-application.c:1411 msgid "A backend error occurred" msgstr "Yth esa error a-bervedh" #: src/bz-application.c:1611 src/bz-application.c:3770 msgid "Refreshing…" msgstr "Ow Tisegha…" #: src/bz-application.c:1775 src/bz-application.c:3768 #, c-format msgid "Loading %d apps…" msgstr "Ow karga %d appys…" #: src/bz-application.c:1828 msgid "Failed to open file" msgstr "Ny yllir ygeri restren" #: src/bz-application.c:1933 msgid "An initialization error occurred" msgstr "Yth esa error dalleth" #: src/bz-application.c:2299 msgid "Checking for updates…" msgstr "Ow checkya rag nowedhyansow…" #: src/bz-application.c:2355 msgid "Failed to check for updates" msgstr "Ny yllir checkya rag nowedhyansow" #: src/bz-application.c:3481 msgid "Malformed Link" msgstr "Gorgrevren Gamm" #: src/bz-application.c:3482 msgid "" "The link used to open this app has incorrect capitalization and may stop " "working in the future.\n" "\n" "This is most likely caused by KRunner sending incorrect app IDs" msgstr "" "Yma lytherennans anewn y'n worgevren devnydhys rag ygeri an app ma hag yth a " "yll astel owth oberi yn termyn a dheu.\n" "\n" "Dell yw gwirhaval, hemm yw drefen KRunner ow tanvon IDys app anewn" #: src/bz-application.c:3490 msgid "Could not find app" msgstr "Ny yllir kavos app" #: src/bz-application.c:3521 msgid "Failed to load metainfo" msgstr "Ny yllir karga metakedhlow" #: src/bz-application.c:3772 msgid "Writing to cache…" msgstr "Ow skrifa dhe sorn…" #: src/bz-apps-page.blp:99 msgid "Show All" msgstr "Diskwedhes Oll" #: src/bz-apps-page.c:237 #, c-format msgid "All \"%s\"" msgstr "Oll \"%s\"" #: src/bz-apps-page.c:487 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "%d Appys" #: src/bz-bundle-install-dialog.blp:8 src/bz-bundle-install-dialog.blp:14 msgid "Bundle Installation" msgstr "Leyans Fardel" #: src/bz-bundle-install-dialog.blp:147 msgid "Additional dependencies may take extra space" msgstr "Medhelweyth serghek keworransel a yll kemeres moy spas" #: src/bz-bundle-install-dialog.blp:181 msgid "" "Installing this app may require adding a new software source. Other apps " "from this source will show up in Bazaar.\n" "\n" "Only add this source if you're sure you trust it." msgstr "" "Ow lea an app ma a yll rekwirya ow keworra devedhyans medhelweyth nowydh. " "Appys erel dhyworth an devedhyans ma a wra diskwedhes yn Basar.\n" "\n" "Keworra an devedhyans ma hepken mar sur owgh hwi a'n fydhya." #: src/bz-bundle-install-dialog.blp:357 msgid "Successfully Installed!" msgstr "Leys yn Sewen!" #: src/bz-bundle-install-dialog.blp:381 src/bz-bundle-install-dialog.blp:463 #: src/bz-rich-app-tile.blp:198 src/bz-transaction-tile.blp:298 msgid "Open" msgstr "Ygeri" #: src/bz-bundle-install-dialog.blp:391 src/bz-bundle-install-dialog.blp:473 msgid "Show App Details" msgstr "Diskwedhes Manylyon App" #: src/bz-bundle-install-dialog.blp:440 msgid "Already Installed" msgstr "Leys Seulabrys" #: src/bz-bundle-install-dialog.blp:485 msgid "Installation Failed" msgstr "Leyans re Fyllis" #: src/bz-bundle-install-dialog.c:169 msgid "Unknown install size" msgstr "Braster leyans ankoth" #: src/bz-bundle-install-dialog.c:172 #, c-format msgid "About %s to install" msgstr "A-dro dhe %s rag lea" #: src/bz-bundle-install-dialog.c:186 src/bz-context-tile-callbacks.c:104 #: src/bz-context-tile-callbacks.c:392 src/bz-context-tile-callbacks.c:409 msgid "N/A" msgstr "Ankavadow" #: src/bz-bundle-install-dialog.c:215 msgid "No special permissions" msgstr "Nyn eus kummyasow arbennik" #: src/bz-context-tile-callbacks.c:68 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-context-tile-callbacks.c:75 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-context-tile-callbacks.c:82 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-context-tile-callbacks.c:92 #, c-format msgid "%d downloads in the last month" msgstr "%d iskargow y'n mis yw passys" #: src/bz-context-tile-callbacks.c:132 #, c-format msgid "+%s runtime" msgstr "+%s kerghynnedh rag app" #: src/bz-context-tile-callbacks.c:135 msgid "Download" msgstr "Iskarg" #: src/bz-context-tile-callbacks.c:155 msgid "Size information unavailable" msgstr "Kedhlow braster ankavadow" #: src/bz-context-tile-callbacks.c:158 #, c-format msgid "Download size of %s" msgstr "Braster iskarg a %s" #: src/bz-context-tile-callbacks.c:191 msgid "All Ages" msgstr "Oll Bloodh" #: src/bz-context-tile-callbacks.c:203 msgid "Age rating information unavailable" msgstr "Kedhlow gwiwder bloodh ankavadow" #: src/bz-context-tile-callbacks.c:208 msgid "Suitable for all ages" msgstr "Gwiw rag oll bloodh" #: src/bz-context-tile-callbacks.c:210 #, c-format msgid "Suitable for ages %d and up" msgstr "Gwiw rag %d bloodh hag a-ugh" #: src/bz-context-tile-callbacks.c:243 src/bz-context-tile-callbacks.c:248 #: src/bz-context-tile-callbacks.c:276 src/bz-context-tile-callbacks.c:284 msgid "Unknown" msgstr "Ankoth" #: src/bz-context-tile-callbacks.c:253 #, c-format msgid "Free software licensed under %s" msgstr "Medhelweyth rydh a-woles dhe'n leshyans %s" #: src/bz-context-tile-callbacks.c:258 msgid "Free software" msgstr "Medhelweyth rydh" #: src/bz-context-tile-callbacks.c:261 msgid "Proprietary Software" msgstr "Medhelweyth Perghenogel" #: src/bz-context-tile-callbacks.c:264 #, c-format msgid "Special License: %s" msgstr "Leshyans Arbennik: %s" #: src/bz-context-tile-callbacks.c:281 msgid "Free" msgstr "Rydh" #: src/bz-context-tile-callbacks.c:287 src/bz-license-dialog.c:133 msgid "Proprietary" msgstr "Perghenogel" #: src/bz-context-tile-callbacks.c:289 src/bz-license-dialog.c:135 msgid "Special License" msgstr "Leshyans Arbennik" #: src/bz-context-tile-callbacks.c:309 msgid "Adaptive" msgstr "Desedhadow" #: src/bz-context-tile-callbacks.c:309 msgid "Desktop Only" msgstr "Amontyell yn Unnik" #: src/bz-context-tile-callbacks.c:315 msgid "Works on desktop, tablets, and phones" msgstr "Gweythresek war amontyellow, leghennow, ha klapkodhow" #: src/bz-context-tile-callbacks.c:316 msgid "May not work on mobile devices" msgstr "Martesen angweythresek war dhevisyow wayadow" #: src/bz-context-tile-callbacks.c:399 src/bz-safety-dialog.blp:27 msgid "Safe" msgstr "Saw" #: src/bz-context-tile-callbacks.c:401 src/bz-context-tile-callbacks.c:403 msgid "Low Risk" msgstr "Peryl Isel" #: src/bz-context-tile-callbacks.c:405 msgid "Medium Risk" msgstr "Peryl Kresek" #: src/bz-context-tile-callbacks.c:407 msgid "High Risk" msgstr "Peryl Ughel" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:46 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:30 #: src/bz-library-page.blp:67 src/bz-user-data-page.blp:30 msgid "Empty" msgstr "Gwag" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Nyns eus Dyghtyans" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Nyns eus kedhlow dyghtyans provys war'n system ma. Hwi a yll peuri appys war " "Flathub hwath" #: 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" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "Peurell" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "Na Wirhys" #: src/bz-developer-badge.c:213 msgid "Developer information not available." msgstr "Kedhlow awtour nag yw kavadow." #: src/bz-developer-badge.c:219 src/bz-developer-badge.c:233 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "An berghenogeth a'n %s ID app nag yw gwirys ha martesen fardel gemeneth yw." #: src/bz-developer-badge.c:237 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "An berghenogeth a'n %s ID app re beu gwirys dre dhorn gans an bagas Flathub." #: src/bz-developer-badge.c:253 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "An berghenogeth a'n %1$s ID app re beu gwirys gans %2$s war %3$s." #: src/bz-developer-badge.c:260 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "An berghenogeth a'n %1$s ID app re beu gwirys ow tevnydhya %2$s." #: src/bz-developer-badge.c:264 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "An berghenogeth a'n %s ID app re beu gwirys." #: src/bz-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "Notennow Dyllans Leun" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "An dyllans ma o gwrys possybyl gans devnydhyoryon avel hwi!" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on Ko-Fi." msgstr "" "My a gar ow kwruthyl Basar, mes ny allav vy gul henna yn unsel. Gweresewgh " "skoodhya displegyans pella gans owth argevri war Ko-Fi." #: src/bz-donations-dialog.blp:131 msgid "Donate to Bazaar" msgstr "Argevri dhe Vasar" #. Translators: the %s format specifier will be something along the lines of "0.7.6" etc #: src/bz-donations-dialog.c:227 #, c-format msgid "What's New in %s?" msgstr "Pyth yw Nowydh yn %s?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "Dyllys %-e ves %B, %Y" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Dewis Leyans" #: 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 "" "Yma dhywgh versyons liesek a'n app ma leys. Pyneyl a vynnowgh procedya gans?" #: src/bz-entry-group-util.c:80 src/bz-rich-app-tile.blp:232 msgid "Cancel" msgstr "Hedhi" #: src/bz-entry-selection-row.blp:17 msgid "For This User Only" msgstr "Rag An Devnydhyer Ma Hepken" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "an devnydhyer" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "oll devnydhyoryon" #: src/bz-error-dialog.blp:36 src/bz-error.c:69 src/bz-error.c:88 #: src/bz-safety-dialog.blp:46 msgid "Details" msgstr "Manylyon" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "Kopia" #: src/bz-error-dialog.c:56 src/bz-share-list.c:94 msgid "Copied!" msgstr "Kopys!" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Somm Drudhyow" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" msgstr "Ny yllir nowedhi drudh" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Omgelmi gans Flathub rag dyghtya drudhyow" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Omgelmi" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:56 #: src/bz-window.blp:334 msgid "Favorites" msgstr "Drudhyow" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "Lea Oll" #: src/bz-favorites-page.blp:34 src/bz-user-data-page.blp:19 msgid "Loading" msgstr "Ow karga" #: src/bz-favorites-page.blp:49 msgid "No Favorites" msgstr "Drudhyow Vyth" #: src/bz-favorites-page.blp:50 msgid "Applications you mark as favorite will appear here" msgstr "Appys hwi a verkya avel drudh a wra diskwedhes omma" #: src/bz-favorites-tile.blp:60 src/bz-installed-tile.blp:69 msgid "Support This Application" msgstr "Skoodhya An App Ma" #: src/bz-favorites-tile.blp:109 msgid "Remove From Favorites" msgstr "Dilea Dhyworth Drudhyow" #: src/bz-favorites-tile.c:353 msgid "Failed to remove favorite" msgstr "Ny yllir remova drudh" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Kyns" #: src/bz-featured-carousel.blp:54 msgid "Next" msgstr "Nessa" #: src/bz-flathub-category.c:93 msgid "Editing" msgstr "Ow Pennskrifa" #: src/bz-flathub-category.c:94 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:95 msgid "Mixer" msgstr "Kemyskell" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:96 src/bz-search-pill-list.c:77 msgid "Music" msgstr "Ilow" #: src/bz-flathub-category.c:97 msgid "Player" msgstr "Gwarier" #: src/bz-flathub-category.c:98 msgid "Recorder" msgstr "Rekordyer" #: src/bz-flathub-category.c:99 msgid "Sequencer" msgstr "Kevreser" #: src/bz-flathub-category.c:100 msgid "Tuner" msgstr "Tonyer" #: src/bz-flathub-category.c:101 msgid "TV" msgstr "Pellwolok" #: src/bz-flathub-category.c:106 msgid "Emulation" msgstr "Omhevelians" #: src/bz-flathub-category.c:107 msgid "Action" msgstr "Gwrians" #: src/bz-flathub-category.c:108 msgid "Adventure" msgstr "Aventur" #: src/bz-flathub-category.c:109 msgid "Arcade" msgstr "Arkade" #: src/bz-flathub-category.c:110 msgid "Blocks" msgstr "Stockow" #: src/bz-flathub-category.c:111 msgid "Board" msgstr "Bordh" #: src/bz-flathub-category.c:112 msgid "Card" msgstr "Karten" #: src/bz-flathub-category.c:113 msgid "Kids" msgstr "Fleghes" #: src/bz-flathub-category.c:114 msgid "Logic" msgstr "Lojyk" #: src/bz-flathub-category.c:115 msgid "Role Playing" msgstr "Gwari Rann" #: src/bz-flathub-category.c:116 msgid "Shooter" msgstr "Sether" #: src/bz-flathub-category.c:117 msgid "Simulation" msgstr "Hevelebyans" #: src/bz-flathub-category.c:118 msgid "Sports" msgstr "Sportys" #: src/bz-flathub-category.c:119 msgid "Strategy" msgstr "Strateji" #: src/bz-flathub-category.c:124 msgid "Audio & Video" msgstr "Son & Gwydhyow" #: src/bz-flathub-category.c:124 msgid "Media" msgstr "Media" #: src/bz-flathub-category.c:124 msgid "More Audio & Video" msgstr "Moy Son & Gwydhyow" #: src/bz-flathub-category.c:125 msgid "Developer Tools" msgstr "Toulys Amontydh" #: src/bz-flathub-category.c:125 msgid "Develop" msgstr "Displegya" #: src/bz-flathub-category.c:125 msgid "More Developer Tools" msgstr "Moy Toulys Amontydh" #: src/bz-flathub-category.c:126 msgid "Education" msgstr "Adhyskans" #: src/bz-flathub-category.c:126 msgid "Learn" msgstr "Dyski" #: src/bz-flathub-category.c:126 msgid "More Education" msgstr "Moy Adhyskans" #: src/bz-flathub-category.c:127 msgid "Gaming" msgstr "Gwariow" #: src/bz-flathub-category.c:127 msgid "Play" msgstr "Gwari" #: src/bz-flathub-category.c:127 msgid "More Gaming" msgstr "Moy Gwariow" #: src/bz-flathub-category.c:128 msgid "Graphics & Photography" msgstr "Grafek & Skeusenieth" #: src/bz-flathub-category.c:128 msgid "Create" msgstr "Gwruthyl" #: src/bz-flathub-category.c:128 msgid "More Graphics & Photography" msgstr "Moy Grafek & Skeusenieth" #: src/bz-flathub-category.c:129 msgid "Networking" msgstr "Rosweythyans" #: src/bz-flathub-category.c:129 msgid "Internet" msgstr "Kesrosweyth" #: src/bz-flathub-category.c:129 msgid "More Networking" msgstr "Moy Rosweythyans" #: src/bz-flathub-category.c:130 msgid "Productivity" msgstr "Askorruster" #: src/bz-flathub-category.c:130 msgid "Work" msgstr "Ober" #: src/bz-flathub-category.c:130 msgid "More Productivity" msgstr "Moy Askorruster" #: src/bz-flathub-category.c:131 msgid "Science" msgstr "Godhonieth" #: src/bz-flathub-category.c:131 msgid "More Science" msgstr "Moy Godhonieth" #: src/bz-flathub-category.c:132 msgid "System" msgstr "Kevreyth" #: src/bz-flathub-category.c:132 msgid "More System" msgstr "Moy Kevreyth" #: src/bz-flathub-category.c:133 msgid "Utilities" msgstr "Lesow" #: src/bz-flathub-category.c:133 msgid "Tools" msgstr "Toulys" #: src/bz-flathub-category.c:133 msgid "More Utilities" msgstr "Moy Lesow" #: src/bz-flathub-category.c:134 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:148 msgid "Trending" msgstr "Gerys-da Lemmyn" #: src/bz-flathub-category.c:134 msgid "More Trending" msgstr "Moy Gerys-da Lemmyn" #: src/bz-flathub-category.c:135 src/bz-flathub-page.blp:122 #: src/bz-flathub-page.blp:178 msgid "Popular" msgstr "Gerys-da" #: src/bz-flathub-category.c:135 msgid "More Popular" msgstr "Moy Gerys-da" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:168 msgid "Recently Added" msgstr "Keworrys A-dhiwedhes" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:128 msgid "New" msgstr "Nowydh" #: src/bz-flathub-category.c:136 msgid "More New" msgstr "Moy Nowydh" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:158 msgid "Recently Updated" msgstr "Nowedhys A-dhiwedhes" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:134 msgid "Updated" msgstr "Nowedhys" #: src/bz-flathub-category.c:137 msgid "More Updated" msgstr "Moy Nowedhys" #: src/bz-flathub-category.c:138 msgid "Mobile" msgstr "Gwayadow" #: src/bz-flathub-category.c:138 msgid "More Mobile" msgstr "Moy Gwayadow" #: src/bz-flathub-category.c:139 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:139 msgid "More Adwaita" msgstr "Moy Adwaita" #: src/bz-flathub-category.c:140 msgid "KDE Apps" msgstr "Appys KDE" #: src/bz-flathub-category.c:140 msgid "More KDE Apps" msgstr "Moy Appys KDE" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub nag yw Keworrys" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "An gwerthji Flathub nag o kevys war neb a'gas leyansow Flatpak" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub ros tre error" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Assaya Junyans Flathub Arta" #: 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 "Ny yllsyn junya dhe Flathub. Hwi a yll dyghtya ha hwilas appys hwath." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Hwilas Appys" #: src/bz-flathub-page.blp:205 msgid "App of the Day" msgstr "App a'n Jydh" #: src/bz-flathub-page.blp:268 msgid "On the Go" msgstr "Gwayadow" #: src/bz-flathub-page.blp:280 msgid "Apps for your Linux phones and tablets" msgstr "Appys rag agas klapkodhow ha leghennow Linux" #: src/bz-flathub-page.blp:291 src/bz-flathub-page.blp:326 msgid "More Mobile Apps" msgstr "Moy Appys Gwayadow" #: src/bz-flathub-page.blp:382 msgid "We​ ♥​ Games" msgstr "Ni ♥ Gwariow​" #: src/bz-flathub-page.blp:395 msgid "Games and apps to run your favorite titles" msgstr "Gwariow hag appys rag eksekutya agas titlys dhrudh" #: src/bz-flathub-page.blp:429 msgid "More Games" msgstr "Moy Gwariow" #: src/bz-full-view.blp:34 src/bz-library-page.blp:78 #: src/bz-library-page.blp:82 msgid "No Results" msgstr "Sewyansow Vyth" #: src/bz-full-view.blp:35 msgid "Try a different search query" msgstr "Assayewgh hwithrans aral" #: src/bz-full-view.blp:41 msgid "Content" msgstr "Synsas" #: src/bz-full-view.blp:103 msgid "" "This is a local preview, some details may differ from the published listing" msgstr "" "Hemm yw ragwolok leel, nebes manylyon a yll bos dihaval dhe'n rolyans dyllys" #: src/bz-full-view.blp:106 msgid "Preview Store Appearance" msgstr "Gis Gwerthji Ragwolok" #: src/bz-full-view.blp:232 msgid "_Support" msgstr "_Skoodhya" #: src/bz-full-view.blp:431 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "An app ma a dhevnydh kerghynnedh na fella ow receva nowedhyansow po " "ewnheansow sawder. Yth a yll bydh rag devnydh." #: src/bz-full-view.blp:518 msgid "Trash Data" msgstr "Data Atal" #: src/bz-full-view.blp:658 msgid "Tags:" msgstr "Taggys:" #: src/bz-full-view.c:180 msgid "No URL" msgstr "Gorgevren Vyth" #: src/bz-full-view.c:198 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Yma leshyans rydh dhe'n app ma, ytho an kod a yll bos arhwilys rag salowder." #: src/bz-full-view.c:199 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Yma leshyans perghenogel dhe'n app ma, ytho an kod yw displegys privedh ha " "ny yllir bos arhwilys gans parti tressa anserghek." #: src/bz-full-view.c:206 msgid "More Apps" msgstr "Moy Appys" #: src/bz-full-view.c:207 #, c-format msgid "More Apps by %s" msgstr "Moy Appys gans %s" #: src/bz-full-view.c:214 msgid "Other Apps by this Developer" msgstr "Appys Erel gans an Awtour ma" #: src/bz-full-view.c:216 src/bz-full-view.c:316 #, c-format msgid "Other Apps by %s" msgstr "Appys Erel gans %s" #: src/bz-full-view.c:225 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s nag yw leys, mes yma %s a dhata remenant hwath." #: src/bz-full-view.c:318 msgid "Other Apps" msgstr "Appys Erel" #: src/bz-full-view.c:320 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d App" msgstr[1] "%d Appys" #: src/bz-full-view.c:536 src/bz-user-data-tile.c:144 msgid "Failed to Remove User Data" msgstr "Ny yllir remova data devnydhyer" #: 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 "Bysowegi a res" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Bysowegi komendys" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Bysowegi skoodhys" #: 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 "Logosen po devisyow boyntya a res" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Logosen po devisyow boyntya komendys" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Logosen po devisyow boyntya skoodhys" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Skoodhyans ankoth rag logosen po devisyow boyntya" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Skoodhyans tochskrin" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Tochskrinyow a res" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Tochskrinyow gomendys" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Tochskrinyow skoodhys" #: 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 klapkodh" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Gweythresek war dhevisyow wayadow" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Martesen angweythresek war dhevisyow wayadow" #: 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 vras" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s gweythresek gwella war galesweyth komparek" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s yw gweythresek war an rann vrassa a dhevisyow" #: src/bz-install-controls.blp:62 msgid "_Open" msgstr "_Ygeri" #: src/bz-install-controls.blp:77 src/bz-install-controls.blp:134 msgid "Uninstall Application" msgstr "Dilea App" #: src/bz-install-controls.blp:87 src/bz-transaction-dialog.c:230 msgid "_Remove" msgstr "_Remova" #: src/bz-install-controls.blp:121 src/bz-updates-card.c:164 #: src/bz-updates-card.c:183 msgid "Update" msgstr "Nowedhyans" #: src/bz-install-controls.blp:144 src/bz-installed-tile.blp:105 msgid "Remove" msgstr "Remova" #: src/bz-install-controls.wdgt:32 msgctxt "Install Controls" msgid "Cancel" msgstr "Hedhi" #: src/bz-install-controls.wdgt:35 msgctxt "Install Controls" msgid "Cancelling" msgstr "Ow Hedhi" #: src/bz-library-page.blp:32 msgid "Search installed apps" msgstr "Hwilas appys leys" #: src/bz-library-page.blp:50 msgid "Clear search" msgstr "Dilea hwithrans" #: src/bz-library-page.blp:71 msgid "No Apps Found" msgstr "Nyns eus Appys Kevys" #: src/bz-library-page.blp:90 msgid "Search Store Instead" msgstr "Hwilas Gwerthji Yn Le" #. Translators: . #: src/bz-library-page.blp:100 src/bz-window.blp:112 msgid "Library" msgstr "Lyverva" #: src/bz-library-page.blp:128 msgid "Pending Updates" msgstr "Nowedhyansow Ow Gortos" #: src/bz-library-page.blp:155 msgid "Downloads" msgstr "Iskargow" #: src/bz-library-page.blp:198 msgid "Recently Uninstalled" msgstr "Dileys A-Dhiwedhes" #: src/bz-library-page.blp:249 msgid "Clear Finished Tasks" msgstr "Dilea Oberennow Deu" #: src/bz-library-page.blp:334 msgid "Sort By" msgstr "Sortya Orth" #: src/bz-library-page.blp:348 msgid "Name" msgstr "Hanow" #: src/bz-library-page.blp:354 msgid "Size" msgstr "Braster" #: src/bz-library-page.c:180 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "Nyns eus parow rag \"%s\" y'n rol appys leys" #: src/bz-library-page.c:193 src/bz-updates-card.c:433 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u Nowedhyans Kavadow" msgstr[1] "%u Nowedhyansow Gavadow" #: src/bz-library-page.c:203 #, c-format msgid "%u Installed App" msgid_plural "%u Installed Apps" msgstr[0] "%u App Leys" msgstr[1] "%u Appys Leys" #: src/bz-license-dialog.blp:94 msgid "Get Involved" msgstr "Bos Omvyskys" #: src/bz-license-dialog.blp:111 msgid "Learn More" msgstr "Dyski Moy" #: src/bz-license-dialog.c:127 msgid "Unknown License" msgstr "Leshyans Ankoth" #: src/bz-license-dialog.c:130 msgid "Community Built" msgstr "Byldys gans an Gemeneth" #: src/bz-license-dialog.c:203 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 yw gwrys y'n poblek gans kemeneth geswlasek.\n" "\n" "Hwi a yll kemeres rann ha gweres dhe wellhe." #: src/bz-license-dialog.c:206 msgid "The license of this app is not known" msgstr "An leshyans rag an app ma yw ankoth" #: src/bz-license-dialog.c:212 #, 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 yw gwrys y'n poblek gans kemeneth geswlasek, ha dyllys a-woles " "dhe'n leshyans %s.\n" "\n" "Hwi a yll kemeres rann ha gweres ow kwellhe." #: src/bz-license-dialog.c:220 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 nag yw gwyrs y'n poblek, ytho an awtours hepken a aswon fatel yth " "a ober. Martesen, yth yw andhiogel yn agwedhow kales dhe helergi, hag yth a " "yll chanja heb ankov.\n" "\n" "Ny wodhon mar hwi a yll kevri dhe'n app ma." #: src/bz-license-dialog.c:226 #, 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 yw gwyrs a-woles dhe'n leshyans arbennik %s.\n" "\n" "Ny wodhon mar hwi a yll kevri dhe'n app ma." #: src/bz-license-dialog.c:356 src/bz-safety-dialog.blp:49 msgid "License" msgstr "Leshyans" #: 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 "Yth esa Hager Vargen" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "Junya agas akont Flathub dhe Vasar rag dyghtya agas appys dhrudh." #: src/bz-login-page.blp:110 msgid "Finish" msgstr "Finsya" #: src/bz-login-page.c:664 #, c-format msgid "Hello, %s!" msgstr "Dydh dha, %s!" #: src/bz-metainfo-preview.c:84 msgid "Select Metainfo File" msgstr "Dewis Restren Vetakedhlow" #: src/bz-metainfo-preview.c:87 msgid "Metainfo Files" msgstr "Restrennow Metakedhlow" #: src/bz-metainfo-preview.c:141 msgid "Select Icon (Optional)" msgstr "Dewis Arwodhik (Dre Dhewis)" #: src/bz-metainfo-preview.c:144 msgid "Image Files" msgstr "Restrennow Skeusen" #: src/bz-metainfo-preview.c:231 msgid "Preview" msgstr "Ragwolok" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Dewisyow" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data refresh is paused" msgstr "" "Junyans kesrosweyth yw strothys — diseghans awtomatek synsas gwerthji yw " "powesys" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:232 msgid "Refresh Manually" msgstr "Disegha dre Dhorn" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Sidhlow Synsas" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Medhelweyth Rydh Hepken" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "Kudha appys berghenogel dres ow peuri hag ow hwilas" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Sewyansow Flathub Hepken" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Finwetha sewyansow hwithrans ha peuryans dhe appys gavadow war Flathub hepken" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "Sewyansow Wirhes Hepken" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Kudha sewyansow nag yw gwirhes war Flathub" #: src/bz-preferences-dialog.blp:49 msgid "Hide End-of-Life 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 skoodhys na fella gans aga awtours" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:127 msgid "Search" msgstr "Hwithrans" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Delatya Sewyansow 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 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 liwyow vaner a-gledh dhe a-dhyghow" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Liw Devnydhyer" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Liwyow Wooth" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Liwyow Wooth Lesbian" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "Liwyow Wooth Gourkethreydhel" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Liwyow Wooth Treusreydhek" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Liwyow Wooth Andhewek" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "Liwyow Wooth Dewreydhel" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "Liwyow Wooth Anreydhel" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Liwyow Wooth Pubreydhel" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Liwyow Wooth Anromansek" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Liwyow Wooth Reydh Linyel" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Liwyow Wooth Liesreydhel" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Liwyow Wooth Ollreydhel" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "Liwyow Wooth Anromansek hag Anreydhel" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "Liwyow Wooth Anreydh" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "Liwyow Gooth Reydhkwir" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "Liwyow Wooth Kesreydh" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "Liwyow Wooth Hanterreydh" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "Liwyow Wooth Dewromansek" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "Liwyow Wooth Evredhyon" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "Liwyow Wooth Maw-Gwregel" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "Liwyow Wooth Newtroys" #: src/bz-releases-dialog.blp:5 src/bz-updates-card.c:155 msgid "Version History" msgstr "Istori Dyllansow" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "Istori _Dyllansow" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "Hedhyw" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "De" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "Nans yw %d dydh" msgstr[1] "Nans yw %d dedhyow" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "Nans yw %d seythen" msgstr[1] "Nans yw %d seythennyow" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "Nans yw %d mis" msgstr[1] "Nans yw %d misyow" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "Nans yw %d bledhen" msgstr[1] "Nans yw %d bledhynnyow" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%e %B %Y" #: src/bz-releases-list.c:196 #, c-format msgid "Version %s" msgstr "Dyllans %s" #: src/bz-releases-list.c:251 msgid "No details for this release" msgstr "Nyns eus manylyon rag an dyllans ma" #: src/bz-releases-list.c:263 msgid "Get More Information" msgstr "Kerghes Moy Kedhlow" #: src/bz-rich-app-tile.blp:217 msgid "Uninstall" msgstr "Dilea" #. Translators: If you can't find a short enough translation, use "/" to use an icon instead. #: src/bz-rich-app-tile.c:369 msgid "Get" msgstr "Kerghes" #: src/bz-safety-calculator.c:87 msgid "Unknown Permissions" msgstr "Kummyasow Ankoth" #: src/bz-safety-calculator.c:88 msgid "Permissions are missing for this app." msgstr "Kummyasow yw fyllis rag an app ma." #: src/bz-safety-calculator.c:101 msgid "No Permissions" msgstr "Kummyasow Vyth" #: src/bz-safety-calculator.c:102 msgid "App is fully sandboxed" msgstr "App yw kontaynys yn leun" #: src/bz-safety-calculator.c:108 msgid "Network Access" msgstr "Hedhas Kesrosweyth" #: src/bz-safety-calculator.c:109 msgid "Can access the internet" msgstr "A yll drehedhes an kesrosweyth" #: src/bz-safety-calculator.c:111 msgid "No Network Access" msgstr "Hedhas Kesrosweyth Vyth" #: src/bz-safety-calculator.c:112 msgid "Cannot access the internet" msgstr "Ny yllir drehedhes an kesrosweyth" #: src/bz-safety-calculator.c:117 msgid "User Device Access" msgstr "Hedhas Devis Devnydhyer" #: src/bz-safety-calculator.c:118 msgid "Can access devices such as webcams or gaming controllers" msgstr "A yll drehedhes devisyow kepar ha kameras po konsolen wariow gwydhyow" #: src/bz-safety-calculator.c:120 msgid "No User Device Access" msgstr "Hedhas Devis Devnydhyer Vyth" #: src/bz-safety-calculator.c:121 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "" "Ny yllir drehedhes devisyow kepar ha kameras po konsolen wariow gwydhyow" #: src/bz-safety-calculator.c:126 msgid "Input Device Access" msgstr "Hedhas Devis Ynworrans" #: src/bz-safety-calculator.c:127 msgid "Can access input devices" msgstr "A yll drehedhes devisyow ynworrans" #: src/bz-safety-calculator.c:133 msgid "Microphone Access and Audio Playback" msgstr "Hedhas Korrgewsell ha Seni Son" #: src/bz-safety-calculator.c:134 msgid "Can listen using microphones and play audio without asking permission" msgstr "A yll goslowes ow tevnydhya korrgewsellow ha seni son heb ow peji" #: src/bz-safety-calculator.c:140 msgid "System Device Access" msgstr "Hedhas Devis System" #: src/bz-safety-calculator.c:141 msgid "Can access system devices which require elevated permissions" msgstr "A yll drehedhes devisyow system may a rekwir kummyasow ughelhys" #: src/bz-safety-calculator.c:147 msgid "Screen Contents Access" msgstr "Hedhas Synsas Skrin" #: src/bz-safety-calculator.c:148 msgid "Can access the contents of the screen or other windows" msgstr "A yll drehedhes an synsas a'n skrin po fenestri erel" #: src/bz-safety-calculator.c:154 msgid "Legacy Windowing System" msgstr "System Fenester Anterrus" #: src/bz-safety-calculator.c:155 msgid "Always uses a legacy windowing system (X11)" msgstr "A dhevnydh prest system fenester anterrus (X11)" #: src/bz-safety-calculator.c:161 msgid "Arbitrary Permissions" msgstr "Kummyas Siansek" #: src/bz-safety-calculator.c:162 msgid "Can acquire arbitrary permissions" msgstr "A yll kavos kummyasow siansek" #: src/bz-safety-calculator.c:168 msgid "User Settings" msgstr "Settyansow Dhevnydhyer" #: src/bz-safety-calculator.c:169 msgid "Can access and change user settings" msgstr "A yll drehedhes ha chanjya settyansow dhevnydhyer" #: src/bz-safety-calculator.c:175 msgid "Full File System Read/Write Access" msgstr "Hedhas rag Redya/Skrifa System Restrenva Leun" #: src/bz-safety-calculator.c:176 msgid "Can read and write all data on the file system" msgstr "A yll redya ha skrifa oll data war'n system restrenva" #: src/bz-safety-calculator.c:183 msgid "Home Folder Read/Write Access" msgstr "Hedhas rag Redya/Skrifa Restrenva Dre" #: src/bz-safety-calculator.c:184 msgid "Can read and write all data in your home directory" msgstr "A yll redya ha skrifa oll data y'gas restrenva dre" #: src/bz-safety-calculator.c:191 msgid "Full File System Read Access" msgstr "Hedhas rag Redya System Restrenva Leun" #: src/bz-safety-calculator.c:192 msgid "Can read all data on the file system" msgstr "A yll redya oll data y'n system restrenva" #: src/bz-safety-calculator.c:200 msgid "Home Folder Read Access" msgstr "Hedhas rag Redya Restrenva Dre" #: src/bz-safety-calculator.c:201 msgid "Can read all data in your home directory" msgstr "A yll redya oll data y'gas restrenva dre" #: src/bz-safety-calculator.c:209 msgid "Download Folder Read/Write Access" msgstr "Hedhas rag Redya/Skrifa yn Restrenva Iskargow" #: src/bz-safety-calculator.c:210 msgid "Can read and write all data in your downloads directory" msgstr "A yll redya ha skrifa oll data y'gas restrenva iskargow" #: src/bz-safety-calculator.c:220 msgid "Download Folder Read Access" msgstr "Hedhas rag Redya yn Restrenva Iskargow" #: src/bz-safety-calculator.c:221 msgid "Can read all data in your downloads directory" msgstr "A yll redya oll data y'gas restrenva iskargow" #: src/bz-safety-calculator.c:242 msgid "Can read and write all data in the directory" msgstr "A yll redya ha skrifa oll data y'n restrenva" #: src/bz-safety-calculator.c:266 msgid "Can read all data in the directory" msgstr "A yll redya oll data y'n restrenva" #: src/bz-safety-calculator.c:281 msgid "No File System Access" msgstr "Hedhas System Restrenva Vyth" #: src/bz-safety-calculator.c:282 msgid "Cannot access the file system at all" msgstr "Ny yllir drehedhes an system restrenva banna" #: src/bz-safety-calculator.c:289 msgid "Uses System Services" msgstr "A dhevnydh Gonisyow System" #: src/bz-safety-calculator.c:290 msgid "Can request data from non-portal system services" msgstr "A yll govyn data dhyworth gonisyow anportal system" #: src/bz-safety-calculator.c:296 msgid "Uses Session Services" msgstr "A dhevnydh Gonisyow Esedhek" #: src/bz-safety-calculator.c:297 msgid "Can request data from non-portal session services" msgstr "A yll govyn data dhyworth gonisyow anportal esedhek" #: src/bz-safety-calculator.c:345 msgid "No Service Access" msgstr "Hedhas Gonis Vyth" #: src/bz-safety-calculator.c:346 msgid "Cannot access non-portal session or system services at all" msgstr "Ny yllir drehedhes gonisyow anportal system po esedhek banna" #: src/bz-safety-calculator.c:354 msgid "Verified App Developer" msgstr "Awtour App Gwirhes" #: src/bz-safety-calculator.c:355 msgid "The developer of this app has been verified to be who they say they are" msgstr "An awtour a'n app ma yw gwirhes rag bos piw i onwul" #: src/bz-safety-calculator.c:364 msgid "Proprietary Code" msgstr "Kod Perghenogel" #: src/bz-safety-calculator.c:365 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "An kod nag yw poblek, ytho ny allas bos arhwilys yn anserghek ha martesen " "diantel yw" #: src/bz-safety-calculator.c:375 msgid "Auditable Code" msgstr "Kod Arhwiladow" #: src/bz-safety-calculator.c:376 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 hag a yll bos arhwilys yn anserghek, ytho an app ma yw saw " "moy gwirhaval" #: src/bz-safety-calculator.c:516 #, c-format msgid "Use the %s System Service" msgstr "Devnydhya an Gonis System %s" #: src/bz-safety-calculator.c:520 #, c-format msgid "Use the %s Session Service" msgstr "Devnydhya an Gonis Esedhek %s" #: src/bz-safety-calculator.c:524 #, c-format msgid "Use the %s Service" msgstr "Devnydhya an Gonis %s" #: src/bz-safety-calculator.c:534 msgid "Can see the non-portal service" msgstr "A yll gweles an gonis anportal" #: src/bz-safety-calculator.c:536 msgid "Can talk to the non-portal service" msgstr "A yll kewsel dhe'n gonis anportal" #: src/bz-safety-calculator.c:538 msgid "Can own the non-portal service" msgstr "A yll perghenna an gonis anportal" #: src/bz-safety-calculator.c:553 msgid "Global Menu Integration" msgstr "Oberyans Rol Olldalghus" #: src/bz-safety-calculator.c:554 msgid "Can display its menus in a global menu bar" msgstr "A yll diskwedhes rolyow yn barr rol olldalghus" #: src/bz-safety-calculator.c:559 msgid "KDE Settings Integration" msgstr "Oberyans Settyansow KDE" #: src/bz-safety-calculator.c:560 msgid "Can detect when KDE desktop settings change" msgstr "A yll helerghi pan settyansow KDE chanjya" #: src/bz-safety-calculator.c:565 msgid "KDE Global Settings" msgstr "Settyansow Olldalghus KDE" #: src/bz-safety-calculator.c:566 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "A yll redya settyansow desktop KDE kepar ha fontow ha liwyow" #: src/bz-safety-calculator.c:571 msgid "Secret Storage Service" msgstr "Gonis Gwithyans Kevrinyow" #: src/bz-safety-calculator.c:572 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "" "A yll gwitha ha kerghes an eryow-tremena y honan ow tevnydhya an alhwedhow-" "kylgh system" #: src/bz-safety-calculator.c:577 msgid "Desktop Notifications Service" msgstr "Gonis Gwarnyansow Dhesktop" #: src/bz-safety-calculator.c:578 msgid "Can send desktop notifications" msgstr "A yll danvon gwarnyansow dhesktop" #: src/bz-safety-calculator.c:584 msgid "System Tray Integration" msgstr "Oberyans Tallyour System" #: src/bz-safety-calculator.c:585 msgid "Can display an icon in the system tray" msgstr "A yll diskwedhes arwodhik y'n tallyour system" #: src/bz-safety-calculator.c:590 msgid "KDE Connect Integration" msgstr "Oberyans KDE Connect" #: src/bz-safety-calculator.c:591 msgid "Can interact with devices paired via KDE Connect" msgstr "A yll keskomunya gans devisyow junys dre KDE Connect" #: src/bz-safety-dialog.blp:59 msgid "App ID" msgstr "ID App" #: src/bz-safety-dialog.blp:69 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 "" "An app ma a dhevnydh dyllans anterrus a'n kerghynnedh medhelweyth (SDK) hag " "a yll synsi kudynnow po goliadewderow sawder may na vydh ewnhys." #: src/bz-safety-dialog.c:167 msgid "Safety" msgstr "Sawder" #: src/bz-safety-dialog.c:226 #, c-format msgid "%s is Safe" msgstr "%s yw Saw" #: src/bz-safety-dialog.c:231 #, c-format msgid "%s has no Unsafe Permissions" msgstr "Nyns eus Kummyasow Dhiantel dhe %s" #: src/bz-safety-dialog.c:236 #, c-format msgid "%s is Probably Safe" msgstr "%s yw Saw Dell Hevel" #: src/bz-safety-dialog.c:241 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s yw Saw Martesen" #: src/bz-safety-dialog.c:246 #, c-format msgid "%s is Unsafe" msgstr "%s yw Diantel" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Skrinskeusennow" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Skeusen Gyns" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Skeusen Nessa" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Kopia Skeusen" #: src/bz-screenshot-page.blp:150 msgid "Reset View" msgstr "Dasgorra Gwel" #: src/bz-screenshot-page.blp:161 msgid "Zoom Out" msgstr "Lehe" #: src/bz-screenshot-page.blp:171 msgid "Zoom In" msgstr "Moghhe" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Res A-dro Skeusennow" #: src/bz-screenshots-carousel.blp:117 msgid "Open Screenshot Viewer" msgstr "Ygeri Gwelell Skeusennow" #: src/bz-search-filter-popover.blp:18 src/bz-search-page.blp:83 msgid "Filters" msgstr "Sidhlow" #: src/bz-search-filter-popover.blp:35 msgid "_Verified" msgstr "_Gwirhes" #: src/bz-search-filter-popover.blp:42 msgid "_Free/Open" msgstr "_Rydh/Ygor" #: src/bz-search-filter-popover.blp:49 msgid "Non-_EOL" msgstr "_Anmarow" #: src/bz-search-filter-popover.blp:52 msgid "Filter out End-of-Life apps" msgstr "Sidhla rag appys Varow" #: src/bz-search-filter-popover.blp:57 msgid "Categories" msgstr "Klassys" #: src/bz-search-page.blp:58 msgid "Search Apps, Games, Software" msgstr "Hwilas Appys, Gwariow, Medhelweyth" #: src/bz-search-page.blp:70 msgid "Search Filters" msgstr "Sidhlow Hwithrans" #: src/bz-search-page.blp:100 msgid "Clear Search" msgstr "Dilea Hwithrans" #: src/bz-search-page.blp:192 msgid "Categories Unavailable" msgstr "Klassys Ankavadow" #: src/bz-search-page.blp:193 msgid "Search for apps using the search bar above." msgstr "Hwilas rag appys gans an barr hwithrans a-ugh." #: src/bz-search-page.blp:219 msgid "Browse Categories" msgstr "Peuri Klassys" #: src/bz-search-page.blp:361 msgid "No Applications Found" msgstr "Appys Kevys Vyth" #: src/bz-search-page.c:247 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Sewyansow kevys vyth rag \"%s\" yn Flathub" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "Gwydhyow" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "Buro" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "Kalender" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "Messajys" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Paint" msgstr "Liwa" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "Torrent" msgstr "Keynres" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Emulator" msgstr "Omhevelians" #: src/bz-share-list.c:55 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Folen Flathub" #: src/bz-share-list.c:56 msgctxt "Project URL Type" msgid "Project Website" msgstr "Gwiasva Ragdres" #: src/bz-share-list.c:57 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Rol Gudynnow" #: src/bz-share-list.c:58 msgctxt "Project URL Type" msgid "FAQ" msgstr "Govynnow Gemmyn" #: src/bz-share-list.c:59 msgctxt "Project URL Type" msgid "Help" msgstr "Gweres" #: src/bz-share-list.c:60 msgctxt "Project URL Type" msgid "Donate" msgstr "Argevri" #: src/bz-share-list.c:61 msgctxt "Project URL Type" msgid "Translate" msgstr "Treylya" #: src/bz-share-list.c:62 msgctxt "Project URL Type" msgid "Contact" msgstr "Kestava" #: src/bz-share-list.c:63 msgctxt "Project URL Type" msgid "Source Code" msgstr "Pennfenten God" #: src/bz-share-list.c:64 msgctxt "Project URL Type" msgid "Contribute" msgstr "Kevri" #: src/bz-share-list.c:153 msgid "Copy Link" msgstr "Kopia Gorgevren" #: src/bz-share-list.c:164 msgid "Open Link" msgstr "Ygeri Gorgevren" #: src/bz-stats-dialog.blp:27 msgid "Timeline" msgstr "Linen Dermyn" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Leyansow:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Bys" #: src/bz-stats-dialog.blp:69 msgid "Since 4/15/2024" msgstr "A-dhia 15/4/2024" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:130 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM Somm Leyansow" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:133 #, c-format msgid "%.2fK Total Installs" msgstr "%.2fk Somm Leyansow" #: src/bz-stats-dialog.c:135 #, c-format msgid "%'d Total Installs" msgstr "%'d Somm Leyansow" #: src/bz-tag-list.c:78 msgid "No Results Found" msgstr "Sewyansow Kevys Vyth" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Appys Taggys avel \"%s\"" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "Hwithrans re fyllis" #: src/bz-transaction-dialog.c:154 msgid "Keep User Data" msgstr "Gwitha Data Devnydhyer" #: src/bz-transaction-dialog.c:155 msgid "Allow restoring personal settings & content" msgstr "Alowa ow taskor settyansow & synsas personel" #: src/bz-transaction-dialog.c:164 msgid "Delete All Data" msgstr "Dilea Oll Data" #: src/bz-transaction-dialog.c:165 msgid "Permanently erase user data to save space" msgstr "Dilea yn fast data devnydhyer rag erbysi dalghuster" #: src/bz-transaction-dialog.c:190 #, c-format msgid "Install %s?" msgstr "Lea %s?" #: src/bz-transaction-dialog.c:195 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Dewis py dyllans dhe lea. Martesen a wra lea darnow gevrennys keworransel" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "Martesen a wra lea darnow geworransel poblek" #: src/bz-transaction-dialog.c:200 src/bz-transaction-dialog.c:229 #: src/bz-transaction-dialog.c:274 src/bz-transaction-dialog.c:576 msgid "_Cancel" msgstr "_Hedhi" #: src/bz-transaction-dialog.c:201 msgid "_Install" msgstr "_Lea" #: src/bz-transaction-dialog.c:218 #, c-format msgid "Remove %s?" msgstr "Remova %s?" #: src/bz-transaction-dialog.c:221 msgid "Select which version to remove." msgstr "Dewis py dyllans dhe remova." #: src/bz-transaction-dialog.c:223 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Ny vydh galladow dhe dhevnydhya %s wosa dileys yw." #: src/bz-transaction-dialog.c:246 #, c-format msgid "“%s” is High Risk" msgstr "\"%s\" yw Peryl Ughel" #: src/bz-transaction-dialog.c:250 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 "" "Yma hedhas leun dh'gas system dhe'n app ma, ow synsi oll a'gas " "restrennow, istori peurell, geryow-tremena sawys ha moy. Ynwedh, yma " "hedhas dhe'n kesrosweyth, ytho yth a yll danvon agas data dhe bartiow " "tressa.\n" "\n" "Drefen perghenogel yw an app, ny allas bos arwhilys rag an pyth yth a wul " "gans an gummyasow ma." #: src/bz-transaction-dialog.c:259 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 a dhevnydh an system fenestri anterrus X11, ytho yth a yll " "rekordya oll jynnskrifow, kemeres skrinskeusennow, ha helerghi appys " "erel. Ynwedh, yth a yll drehedhes an kesrosweyth, ytho yth a yll danvon " "agas data dhe bartiow tressa.\n" "\n" "Drefen perghenogel yw an app, ny allas bos arwhilys rag an pyth yth a wul " "gans an gummyasow ma." #: src/bz-transaction-dialog.c:275 msgid "_Install Anyway" msgstr "_Lea yn neb Kas" #: src/bz-transaction-dialog.c:330 msgid "Failed to load transaction dialog" msgstr "Ny yllir karga fenester negys" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "Oll appys yw leys seulabrys" #: src/bz-transaction-dialog.c:549 msgid "_OK" msgstr "_Da Lowr" #: src/bz-transaction-dialog.c:565 #, 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:573 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" "An pyth a sew a vydh leys. Ynwedh, darnow gevrennys keworransel a vydh leys " "martesen" #: src/bz-transaction-dialog.c:574 #, c-format msgid "%d addons will be installed." msgstr "%d ystynansow a vydh leys." #: src/bz-transaction-dialog.c:575 msgid "Additionally, addons will be installed." msgstr "Ynwedh, ystyanansow a vydh leys." #: src/bz-transaction-dialog.c:577 msgid "_Install All" msgstr "_Lea Oll" #: src/bz-transaction-manager.c:795 #, c-format msgid "Finished in %.02f seconds" msgstr "Deu yn %.02f eylennow" #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "Ystynnans rag App" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "Kerghynnedh rag App" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "Yn Lost" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "Deu" #: src/bz-transaction-tile.blp:230 msgid "Cancelled" msgstr "Hedhys" #: src/bz-transaction-tile.blp:254 msgid "Error" msgstr "Error" #: src/bz-transaction-tile.blp:312 msgid "Cancel Transaction" msgstr "Hedhi Negys" #: src/bz-transaction-tile.blp:436 msgid "Show Error Info" msgstr "Diskwedhes Kedhlow Error" #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "%s Rythhes" #: src/bz-transaction-tile.c:360 src/bz-transaction-tile.c:363 msgid "Transaction Error" msgstr "Error Negys" #: src/bz-transaction.c:344 msgid "Pending" msgstr "Ow Gortos" #: src/bz-updates-card.blp:23 msgid "_Update All" msgstr "_Nowedhi Oll" #: src/bz-updates-card.c:211 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "%u Nowedhyans Kerghynnedh" msgstr[1] "%u Nowedhyansow Gerghynnedh" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Dyghtya Data Devnydhyer Remenant" #: src/bz-user-data-page.blp:33 msgid "No User Data Found" msgstr "Data Devnydhyer Kevys Vyth" #: src/bz-user-data-page.blp:38 msgid "User Data" msgstr "Data Devnydhyer" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Remova Data Devnydhyer" #: src/bz-user-data-tile.c:150 #, c-format msgid "Trashed User Data for %s" msgstr "Data Devnydhhyer Removys rag %s" #: src/bz-window.blp:70 msgid "Refreshing" msgstr "Ow Tisegha" #: src/bz-window.blp:88 msgid "Curated" msgstr "Dyghtys" #: src/bz-window.blp:100 msgid "Explore" msgstr "Trovya" #: src/bz-window.blp:212 msgid "Main Menu" msgstr "Pennrol" #: src/bz-window.blp:223 msgid "You are running a new version of Bazaar!" msgstr "Owth eksekutya owgh hwi dyllans nowydh a Vasar!" #: src/bz-window.blp:224 msgid "See What's New" msgstr "Pyth yw Nowydh" #: src/bz-window.blp:231 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Yma dhywgh junyans kewrosweyth mes ow kweles owgh hwi dyllans koth a Flathub" #: src/bz-window.blp:276 msgid "_Donate to Bazaar" msgstr "_Argevri dhe Vasar" #: src/bz-window.blp:283 msgid "_Refresh" msgstr "_Disegha" #: src/bz-window.blp:288 msgid "_Preferences" msgstr "_Dewisyow" #: src/bz-window.blp:293 msgid "_Login With Flathub" msgstr "_Omgelmi gans Flathub" #: src/bz-window.blp:299 msgid "_Manage Leftover User Data" msgstr "_Dyghtya Data Devnydhyer Remenant" #: src/bz-window.blp:304 msgid "_Keyboard Shortcuts" msgstr "_Kesunyansow Vysowek" #: src/bz-window.blp:309 msgid "_About Bazaar" msgstr "_A-dro dhe Vasar" #: src/bz-window.blp:316 msgid "_Quit Bazaar" msgstr "_Kwytya Basar" #: src/bz-window.blp:341 msgid "Log Out" msgstr "Omdhigelmi" #. Translators: %s is the title of the current page #: src/bz-window.c:376 #, c-format msgid "Bazaar — %s" msgstr "Basar — %s" #: src/bz-window.c:596 src/bz-window.c:634 msgid "Failed to launch application" msgstr "Ny yllir lonchya app" #: src/bz-window.c:843 msgid "You can't remove Bazaar from Bazaar!" msgstr "Ny yllowgh remova Basar dhyworth Basar!" #: src/bz-window.c:1127 src/bz-window.c:1161 msgid "Can't do that right now!" msgstr "Ny yllir gul an re na y'n eur ma" #. Translators: As in, "1 Install" / "100 Installs" #: src/bz-world-map.c:604 msgid "Install" msgid_plural "Installs" msgstr[0] "Leyans" msgstr[1] "Leyansow" #: src/shortcuts-dialog.blp:5 msgctxt "shortcut window" msgid "Navigation" msgstr "Navigacyon" #: src/shortcuts-dialog.blp:8 msgctxt "shortcut window" msgid "Open Explore Page" msgstr "Ygeri Folen Drovya" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "Ygeri Folen Lyverva" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Open Search Page" msgstr "Ygeri Folen Hwithrans" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Remotes" msgstr "Pellwithvaow" #: src/shortcuts-dialog.blp:27 msgctxt "shortcut window" msgid "Sync Remotes" msgstr "Kettermynyegi Gwerthjiow" #: src/shortcuts-dialog.blp:33 msgctxt "shortcut window" msgid "General" msgstr "Ollgemmyn" #: src/shortcuts-dialog.blp:36 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Ygeri Dewisyow" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Diskwedhes Kesunyansow Vysowek" #: src/shortcuts-dialog.blp:46 msgctxt "shortcut window" msgid "Close Window" msgstr "Degea Fenester" #: src/shortcuts-dialog.blp:52 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "Kwytya Basar" #~ msgid "User Data Size" #~ msgstr "Braster Data Devnydhyer" #~ msgctxt "About Dialog Developer Credit" #~ msgid "Adam Masciola " #~ msgstr "Adam Masciola " #~ msgctxt "About Dialog Developer Credit" #~ msgid "Alexander Vanhee" #~ msgstr "Alexander Vanhee" #~ msgid "Installing" #~ msgstr "Ow Lea" #~ msgid "Refresh completed!" #~ msgstr "Diseghans deu!" #~ msgctxt "As in, \"100 Installs\"" #~ msgid "Installs" #~ msgstr "Leyansow" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "Disegha" #~ msgid "Adam Masciola" #~ msgstr "Adam Masciola" #~ msgid "_Donate to Bazaar ❤️" #~ msgstr "_Argevri dhe Vasar ❤️" #~ msgid "Open App Library" #~ msgstr "Ygeri Lyverva Appys" #~ msgid "Installing .flatpak bundles is not yet supported" #~ msgstr "Ow lea fardellow .flatpak yw anskoodhys hwath" #~ msgid "Download & Install Application" #~ msgstr "Iskarga & Lea App" #~ msgid "Steam" #~ msgstr "Steam" #~ msgid "Minecraft" #~ msgstr "Minecraft" #~ msgid "Flathub" #~ msgstr "Flathub" #~ msgctxt "As in, \"100 Downloads\"" #~ msgid "Downloads" #~ msgstr "Iskargow" #~ 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 "" #~ "Yth posleva ow skoodhya an awtours neb a gul an ekokevreyth Linux. Basar " #~ "omdhiskwedhes an tabb \"dyghtys\" dre konfigurys gans lesrenyadesow dhe " #~ "alowa rag eksperyans leel." #~ msgid "%e %B" #~ msgstr "%e %B" #~ msgid "Install Other Version" #~ msgstr "Lea Versyon Aral" #~ msgid "Support this application" #~ msgstr "Skoodhya an app ma" #~ msgid "Manage Add-ons" #~ msgstr "Dyghtya Ystynansow" #~ msgid "Keep Data" #~ msgstr "Gwitha Data" #~ msgid "Open App" #~ msgstr "Ygeri App" #~ msgid "_Login with Flathub" #~ msgstr "_Omgelmi gans Flathub" #~ msgid "Nucleus app page" #~ msgstr "Folen app Nuklesen" #~ msgid "_Synchronize Remotes" #~ msgstr "_Kerghes Gwerthjiow" #~ msgid "Synchronizing..." #~ msgstr "Ow Kettermynyegi..." #, c-format #~ msgid "Receiving %d entries..." #~ msgstr "Ow receva %d enworrans manylyon..." #~ msgid "Indexing Data..." #~ msgstr "Ow Kevernya Data..." #~ msgid "Bazaar is a Passion Project" #~ msgstr "Basar yw Ragdres Passyon" #~ msgid "Support the Future of Linux App Distribution" #~ msgstr "Skoodhya an Termyn a Dheu a Lesrannans Appys Linux" #~ msgid "Disable the donations banner on startup" #~ msgstr "Ungallosegi an baner argevrohow dres dalleth" #~ msgid "Close" #~ msgstr "Kwytya" #~ msgid "Copy and Close" #~ msgstr "Dasskrifa ha Kwytya" #~ msgid "Refreshing Store Content" #~ msgstr "Ow Diseghow Dalgh Gwerthji" #~ msgid "No background tasks!" #~ msgstr "Oberennow vyth yn kilva!" #~ msgid "See More" #~ msgstr "Gweles Moy" #~ msgctxt "shortcut window" #~ msgid "Toggle Transaction Manager" #~ msgstr "Dewis Dyghtyer Treuswrians" #~ msgctxt "shortcut window" #~ msgid "Quit" #~ msgstr "Kwytya" #~ 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 "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 "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" #, 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" bazaar-org-bazaar-43ce9f7/po/meson.build000066400000000000000000000000471520414637400202120ustar00rootroot00000000000000i18n.gettext('bazaar', preset: 'glib') bazaar-org-bazaar-43ce9f7/po/nl.po000066400000000000000000002110501520414637400170170ustar00rootroot00000000000000# 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" bazaar-org-bazaar-43ce9f7/po/pl.po000066400000000000000000003400611520414637400170260ustar00rootroot00000000000000# 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-05-22 18:01+0200\n" "PO-Revision-Date: 2026-05-22 20:15+0200\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 26.04.1\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:45 #: src/bz-window.blp:199 src/bz-window.c:373 src/bz-window.c:374 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;Marketplace;Zarządza" "nieOprogramowaniem;Odkryj;Odkrywaj;Odkrywca;Oprogramowanie;Sklep;Bazar;Sklepza" "plikacjami;AppStore;Play;Aplikacja;Aplikacje;Rynek;Targ;Bazar;Giełda;Apki;Apka" ";Program;Pobieranie;Pobierz;Instalowanie;Instaluj;Instalacja;Flathub;" #: data/io.github.kolunmi.Bazaar.desktop.in:16 msgid "New Window" msgstr "Nowe okno" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and manage applications" msgstr "Odkrywaj i zarządzaj aplikacjami" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "Nowoczesny, szybki sklep z aplikacjami na Linuxa z naciskiem na odkrywanie " "oraz instalowanie aplikacji i dodatkĂłw z repozytoriĂłw flatpak, głównie z " "Flathuba" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "Ustawiaj w kolejce kilka instalacji i nadal przeglądaj" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "Łatwo przeglądaj uprawnienia aplikacji" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "Zaloguj się do konta Flathub, aby zarządzać ulubionymi" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "Wyszukuj aplikacje prościutko z GNOME Shell" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:30 src/bz-application.c:759 msgid "The Bazaar Contributors" msgstr "Kontrybutorzy Bazaaru" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "The home page displaying Flathub apps" msgstr "Widok domowy pokazujący aplikacje z Flathuba" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:59 msgid "Exhibit app page" msgstr "Strona aplikacji Exhibit" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "Strona biblioteki" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "Strona wyszukiwania" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "Strona kategorii" #: src/bz-addon-tile.blp:64 src/bz-installed-tile.blp:55 #: src/bz-rich-app-tile.blp:141 msgid "Stopped Receiving Updates" msgstr "Zatrzymano otrzymywanie wystąpień" #: src/bz-addon-tile.c:167 src/bz-favorites-tile.c:155 msgctxt "Install Controls" msgid "Uninstall" msgstr "Odinstaluj" #: src/bz-addon-tile.c:169 src/bz-bundle-install-dialog.blp:126 #: src/bz-favorites-tile.c:157 src/bz-install-controls.wdgt:29 msgctxt "Install Controls" msgid "Install" msgstr "Zainstaluj" #: src/bz-addons-dialog.blp:14 src/bz-addons-dialog.blp:21 #: src/bz-addons-dialog.blp:70 src/bz-full-view.blp:583 #: src/bz-installed-tile.blp:92 msgid "Manage Add-Ons" msgstr "Zarządzaj dodatkami" #: src/bz-addons-dialog.blp:80 msgid "No Add-Ons Visible" msgstr "Brak widocznych dodatkĂłw" #: src/bz-addons-dialog.blp:81 msgid "" "Your current filter preferences are hiding all known add-ons. Try adjusting " "them." msgstr "" "Twoje aktualne preferencje filtrowania ukrywają wszystkie znane dodatki. " "SprĂłbuj dostosować je." #: src/bz-addons-dialog.blp:88 msgid "Add-on Page" msgstr "Strona dodatkĂłw" #: src/bz-addons-dialog.blp:202 src/bz-full-view.blp:381 msgid "Downloads/Month" msgstr "Pobrań/m-c" #: src/bz-addons-dialog.blp:229 src/bz-full-view.blp:417 msgid "Stopped Receiving Core Updates" msgstr "Nie otrzymuje podstawowych aktualizacji" #: src/bz-addons-dialog.blp:243 msgid "" "This add-on uses a runtime that no longer receives updates or security " "fixes. It may become unsafe to use." msgstr "" "Ten dodatek wykorzystuje bibliotekę, ktĂłra juĹź nie otrzymuje aktualizacji " "lub poprawek zabezpieczeń. MoĹźe się stać niebezpieczny." #: src/bz-addons-dialog.c:333 #, c-format msgid "Add-on for %s" msgstr "Dodatki dla aplikacji %s" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show Less" msgstr "PokaĹź mniej" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show More" msgstr "PokaĹź więcej" #: src/bz-addons-dialog.c:397 msgid "Download Stats" msgstr "Statystyki pobrań" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:736 src/bz-context-tile-callbacks.c:186 #: src/bz-context-tile-callbacks.c:193 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:686 src/bz-context-tile-callbacks.c:176 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "3+" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "Aplikacja %s nie posiada progu wiekowego" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "Aplikacja %s jest odpowiednia dla wszystkich" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "Aplikacja %s jest odpowiednia dla młodszych dzieci" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "Aplikacja %s jest odpowiednia dla dzieci" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "Aplikacja %s jest odpowiednia dla nastolatkĂłw" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "Aplikacja %s jest odpowiednia dla dorosłych" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "Aplikacja %s jest odpowiednia dla %s" #: src/bz-age-rating-dialog.c:862 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Folder systemowy %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:26 src/bz-app-size-dialog.blp:60 msgid "Download Size" msgstr "Rozmiar do pobrania" #: src/bz-app-size-dialog.blp:33 src/bz-app-size-dialog.blp:81 msgid "Installed Size" msgstr "Rozmiar po instalacji" #: src/bz-app-size-dialog.blp:61 msgid "Amount to download from the internet" msgstr "Ilość do pobrania z internetu" #: src/bz-app-size-dialog.blp:82 msgid "Size on Disk" msgstr "Rozmiar na dysku" #: src/bz-app-size-dialog.blp:133 msgid "Open user data folder" msgstr "OtwĂłrz folder danych uĹźytkownika" #: src/bz-app-size-dialog.blp:143 msgid "Your User Data" msgstr "Twoje dane uĹźytkownika" #: src/bz-app-size-dialog.blp:144 msgid "Caches, settings, and other app data" msgstr "Pamięć podręczna, ustawienia i inne dane aplikacji" #: src/bz-app-size-dialog.blp:165 msgid "Cache" msgstr "Pamięć podręczna" #: src/bz-app-size-dialog.blp:166 msgid "Temporary cached data" msgstr "Tymczasowo przechowywane dane w pamięci podręcznej" #: src/bz-app-size-dialog.blp:176 msgid "Clear Cache" msgstr "Wyczyść pamięć podręczną" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "Rozmiar bibliotek po instalacji" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "Rozmiar bibliotek do pobrania" #: src/bz-app-size-dialog.c:220 msgid "App Size" msgstr "Rozmiar aplikacji" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:105 src/bz-rich-app-tile.c:429 msgid "Verified" msgstr "Zweryfikowane" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-context-tile-callbacks.c:135 #: src/bz-releases-list.c:206 msgid "Installed" msgstr "Zainstalowane" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:762 msgid "translator-credits" msgstr "Marcel MrĂłwka (Microwave) , 2025, 2026" #: src/bz-application.c:772 msgid "Special Thanks" msgstr "Specjalne podziękowania" #: src/bz-application.c:830 msgid "Logged Out Successfully!" msgstr "Wylogowano pomyślnie!" #: src/bz-application.c:966 msgid "Performing setup…" msgstr "Konfigurowanie…" #: src/bz-application.c:1052 msgid "Set Up System Flathub?" msgstr "Skonfigurować Flathub systemowo?" #: src/bz-application.c:1055 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Repozytorium Flathuba na poziomie systemu nie jest skonfigurowane. Bazaar " "wymaga Flathuba skonfigurowanego na systemowej instalacji Flatpaka, aby mĂłc " "przeglądać oraz instalować aplikacje.\n" "\n" "Nadal moĹźesz uĹźywać Bazaaru do przeglądania i usuwania juĹź zainstalowanych " "aplikacji." #: src/bz-application.c:1062 msgid "Set Up Flathub?" msgstr "Skonfigurować Flathub?" #: src/bz-application.c:1065 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 usuwania juĹź zainstalowanych " "aplikacji." #: src/bz-application.c:1071 msgid "Later" msgstr "Później" #: src/bz-application.c:1072 msgid "Set Up Flathub" msgstr "Skonfiguruj Flathub" #: src/bz-application.c:1411 msgid "A backend error occurred" msgstr "Wystąpił błąd w backendzie" #: src/bz-application.c:1611 src/bz-application.c:3770 msgid "Refreshing…" msgstr "OdświeĹźanie…" #: src/bz-application.c:1775 src/bz-application.c:3768 #, c-format msgid "Loading %d apps…" msgstr "Ładowanie %d aplikacji…" #: src/bz-application.c:1828 msgid "Failed to open file" msgstr "Otwieranie pliku nie powiodło się" #: src/bz-application.c:1933 msgid "An initialization error occurred" msgstr "Wystąpił błąd inicjalizacji" #: src/bz-application.c:2299 msgid "Checking for updates…" msgstr "Sprawdzanie dostępności aktualizacji…" #: src/bz-application.c:2355 msgid "Failed to check for updates" msgstr "Sprawdzanie dostępności aktualizacji nie powiodło się" #: src/bz-application.c:3481 msgid "Malformed Link" msgstr "Zniekształcone złącze" #: src/bz-application.c:3482 msgid "" "The link used to open this app has incorrect capitalization and may stop " "working in the future.\n" "\n" "This is most likely caused by KRunner sending incorrect app IDs" msgstr "" "Łącze uĹźyte do otwarcia ma niepoprawną kapitalizację i moĹźe przestać " "działać w przyszłości.\n" "\n" "Jest to prawdopodobnie spowodowane KRunnerem nie dającym poprawnych identyfika" "torĂłw" #: src/bz-application.c:3490 msgid "Could not find app" msgstr "Nie moĹźna znaleźć aplikacji" #: src/bz-application.c:3521 msgid "Failed to load metainfo" msgstr "Ładowanie metainfo nie powiodło się" #: src/bz-application.c:3772 msgid "Writing to cache…" msgstr "Zapisywanie do pamięci podręcznej…" #: src/bz-apps-page.blp:99 msgid "Show All" msgstr "PokaĹź wszystkie" #: src/bz-apps-page.c:237 #, c-format msgid "All \"%s\"" msgstr "Wszystkie aplikacje dot. \"%s\"" #: src/bz-apps-page.c:487 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "%d aplikacji" #: src/bz-bundle-install-dialog.blp:8 src/bz-bundle-install-dialog.blp:14 msgid "Bundle Installation" msgstr "Instalacja pakietu" #: src/bz-bundle-install-dialog.blp:147 msgid "Additional dependencies may take extra space" msgstr "Dodatkowe zaleĹźności mogą zająć dodatkowe miejsce" #: src/bz-bundle-install-dialog.blp:181 msgid "" "Installing this app may require adding a new software source. Other apps " "from this source will show up in Bazaar.\n" "\n" "Only add this source if you're sure you trust it." msgstr "" "Instalacja tej aplikacji moĹźe wymagać dodania nowego ĹşrĂłdła oprogramowania. " "Inne aplikacje z tego ĹşrĂłdła będą pojawiać się w Bazaarze.\n" "\n" "Tylko dodaj to ĹşrĂłdło, jeśli pewny, Ĺźe moĹźna mu zaufać." #: src/bz-bundle-install-dialog.blp:357 msgid "Successfully Installed!" msgstr "Pomyślnie zainstalowano!" #: src/bz-bundle-install-dialog.blp:381 src/bz-bundle-install-dialog.blp:463 #: src/bz-rich-app-tile.blp:198 src/bz-transaction-tile.blp:298 msgid "Open" msgstr "OtwĂłrz" #: src/bz-bundle-install-dialog.blp:391 src/bz-bundle-install-dialog.blp:473 msgid "Show App Details" msgstr "PokaĹź szczegóły aplikacji" #: src/bz-bundle-install-dialog.blp:440 msgid "Already Installed" msgstr "JuĹź zainstalowano" #: src/bz-bundle-install-dialog.blp:485 msgid "Installation Failed" msgstr "Instalacja nie powiodła się" #: src/bz-bundle-install-dialog.c:169 msgid "Unknown install size" msgstr "Nieznany rozmiar instalacji" #: src/bz-bundle-install-dialog.c:172 #, c-format msgid "About %s to install" msgstr "Około %s do zainstalowania" #: src/bz-bundle-install-dialog.c:186 src/bz-context-tile-callbacks.c:104 #: src/bz-context-tile-callbacks.c:392 src/bz-context-tile-callbacks.c:409 msgid "N/A" msgstr "Niedostępne" #: src/bz-bundle-install-dialog.c:215 msgid "No special permissions" msgstr "Brak specjalnych uprawnień" #: src/bz-context-tile-callbacks.c:68 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-context-tile-callbacks.c:75 #, c-format msgid "%.*fM" msgstr "%.*f mln" #. Translators: K is the suffix for thousands #: src/bz-context-tile-callbacks.c:82 #, c-format msgid "%.*fK" msgstr "%.*f tys." #: src/bz-context-tile-callbacks.c:92 #, c-format msgid "%d downloads in the last month" msgstr "%'d pobrań w ciągu zeszłego miesiąca" #: src/bz-context-tile-callbacks.c:132 #, c-format msgid "+%s runtime" msgstr "+%s bibliotek" #: src/bz-context-tile-callbacks.c:135 msgid "Download" msgstr "Rozmiar do pobrania" #: src/bz-context-tile-callbacks.c:155 msgid "Size information unavailable" msgstr "Informacja o rozmiarze jest nie dostępna" #: src/bz-context-tile-callbacks.c:158 #, c-format msgid "Download size of %s" msgstr "Rozmiar do pobrania %s" #: src/bz-context-tile-callbacks.c:191 msgid "All Ages" msgstr "PrĂłg wiekowy" #: src/bz-context-tile-callbacks.c:203 msgid "Age rating information unavailable" msgstr "Informacja o progu wiekowym jest nie dostępna" #: src/bz-context-tile-callbacks.c:208 msgid "Suitable for all ages" msgstr "Odpowiednie od 3 lat" #: src/bz-context-tile-callbacks.c:210 #, c-format msgid "Suitable for ages %d and up" msgstr "Odpowiednie od %d lat" #: src/bz-context-tile-callbacks.c:243 src/bz-context-tile-callbacks.c:248 #: src/bz-context-tile-callbacks.c:276 src/bz-context-tile-callbacks.c:284 msgid "Unknown" msgstr "Nieznane" #: src/bz-context-tile-callbacks.c:253 #, c-format msgid "Free software licensed under %s" msgstr "Wolne oprogramowanie pod licencją %s" #: src/bz-context-tile-callbacks.c:258 msgid "Free software" msgstr "Wolne oprogramowanie" #: src/bz-context-tile-callbacks.c:261 msgid "Proprietary Software" msgstr "Oprogramowanie własnościowe" #: src/bz-context-tile-callbacks.c:264 #, c-format msgid "Special License: %s" msgstr "Licencja specjalna: %s" #: src/bz-context-tile-callbacks.c:281 msgid "Free" msgstr "Wolne" #: src/bz-context-tile-callbacks.c:287 src/bz-license-dialog.c:133 msgid "Proprietary" msgstr "Własnościowe" #: src/bz-context-tile-callbacks.c:289 src/bz-license-dialog.c:135 msgid "Special License" msgstr "Licencja specjalna" #: src/bz-context-tile-callbacks.c:309 msgid "Adaptive" msgstr "" "Na róşne\n" "urządzenia" #: src/bz-context-tile-callbacks.c:309 msgid "Desktop Only" msgstr "" "Tylko na\n" "komputery" #: src/bz-context-tile-callbacks.c:315 msgid "Works on desktop, tablets, and phones" msgstr "Działa na komputerach, tabletach i telefonach" #: src/bz-context-tile-callbacks.c:316 msgid "May not work on mobile devices" msgstr "MoĹźe nie działać na urządzeniach mobilnych" #: src/bz-context-tile-callbacks.c:399 src/bz-safety-dialog.blp:27 msgid "Safe" msgstr "Bezpieczna" #: src/bz-context-tile-callbacks.c:401 src/bz-context-tile-callbacks.c:403 msgid "Low Risk" msgstr "Niskie ryzyko" #: src/bz-context-tile-callbacks.c:405 msgid "Medium Risk" msgstr "Średnie ryzyko" #: src/bz-context-tile-callbacks.c:407 msgid "High Risk" msgstr "Wysokie ryzyko" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:46 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:30 #: src/bz-library-page.blp:67 src/bz-user-data-page.blp:30 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" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "Przeglądarka" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "Nie zweryfikowane" #: src/bz-developer-badge.c:213 msgid "Developer information not available." msgstr "Informacja o twĂłrcy jest nie dostępna" #: src/bz-developer-badge.c:219 src/bz-developer-badge.c:233 #, 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:237 #, 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:253 #, 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:260 #, 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:264 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Własność identyfikatora aplikacji %s została zweryfikowana." #: src/bz-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "Pełne notatki o wydaniu" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "To wydanie było moĹźliwe dzięki uĹźytkownikom takim jak ty!" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on Ko-Fi." msgstr "" "Kocham tworzyć Bazaar, lecz nie mogę robić tego bez niczyjej pomocy. Wspomóş " "dalszy rozwĂłj aplikacji, przekazując darowiznę na Ko-Fi." #: src/bz-donations-dialog.blp:131 msgid "Donate to Bazaar" msgstr "Wesprzyj Bazaar" #. Translators: the %s format specifier will be something along the lines of "0.7.6" etc #: src/bz-donations-dialog.c:227 #, c-format msgid "What's New in %s?" msgstr "Co nowego w wersji %s?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "Wydano %-e %B, %Y" #: 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-rich-app-tile.blp:232 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-dialog.blp:36 src/bz-error.c:69 src/bz-error.c:88 #: src/bz-safety-dialog.blp:46 msgid "Details" msgstr "Szczegóły" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "Kopiuj" #: src/bz-error-dialog.c:56 src/bz-share-list.c:94 msgid "Copied!" msgstr "Skopiowano!" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Liczba polubień" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" msgstr "Aktualizacja polubienia nie powiodła się" #: 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-favorites-page.blp:5 src/bz-favorites-page.blp:56 #: src/bz-window.blp:334 msgid "Favorites" msgstr "Ulubione" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "Zainstaluj wszystkie" #: src/bz-favorites-page.blp:34 src/bz-user-data-page.blp:19 msgid "Loading" msgstr "Ładowanie" #: src/bz-favorites-page.blp:49 msgid "No Favorites" msgstr "Brak ulubionych" #: src/bz-favorites-page.blp:50 msgid "Applications you mark as favorite will appear here" msgstr "Aplikacje, ktĂłre oznaczysz jako ulubione będą się tutaj ukazywać" #: src/bz-favorites-tile.blp:60 src/bz-installed-tile.blp:69 msgid "Support This Application" msgstr "Wesprzyj tą aplikację" #: src/bz-favorites-tile.blp:109 msgid "Remove From Favorites" msgstr "Usuń z ulubionych" #: src/bz-favorites-tile.c:353 msgid "Failed to remove favorite" msgstr "Usunięcie z ulubionych nie powiodło się" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Wstecz" #: src/bz-featured-carousel.blp:54 msgid "Next" msgstr "Dalej" #: src/bz-flathub-category.c:93 msgid "Editing" msgstr "Edytowanie" #: src/bz-flathub-category.c:94 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:95 msgid "Mixer" msgstr "Mikser" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:96 src/bz-search-pill-list.c:77 msgid "Music" msgstr "Muzyka" #: src/bz-flathub-category.c:97 msgid "Player" msgstr "Gracz" #: src/bz-flathub-category.c:98 msgid "Recorder" msgstr "Nagrywarka" #: src/bz-flathub-category.c:99 msgid "Sequencer" msgstr "Sekwencer" #: src/bz-flathub-category.c:100 msgid "Tuner" msgstr "Tuner" #: src/bz-flathub-category.c:101 msgid "TV" msgstr "Telewizja" #: src/bz-flathub-category.c:106 msgid "Emulation" msgstr "Emulacja" #: src/bz-flathub-category.c:107 msgid "Action" msgstr "Akcja" #: src/bz-flathub-category.c:108 msgid "Adventure" msgstr "Przygoda" #: src/bz-flathub-category.c:109 msgid "Arcade" msgstr "Automatowe" #: src/bz-flathub-category.c:110 msgid "Blocks" msgstr "Klocki" #: src/bz-flathub-category.c:111 msgid "Board" msgstr "PlanszĂłwki" #: src/bz-flathub-category.c:112 msgid "Card" msgstr "Karciane" #: src/bz-flathub-category.c:113 msgid "Kids" msgstr "Dla dzieci" #: src/bz-flathub-category.c:114 msgid "Logic" msgstr "Logiczne" #: src/bz-flathub-category.c:115 msgid "Role Playing" msgstr "RPG" #: src/bz-flathub-category.c:116 msgid "Shooter" msgstr "Strzelanki" #: src/bz-flathub-category.c:117 msgid "Simulation" msgstr "Symulacja" #: src/bz-flathub-category.c:118 msgid "Sports" msgstr "Sporty" #: src/bz-flathub-category.c:119 msgid "Strategy" msgstr "Strategiczne" #: src/bz-flathub-category.c:124 msgid "Audio & Video" msgstr "Audio i wideo" #: src/bz-flathub-category.c:124 msgid "Media" msgstr "Multimedia" #: src/bz-flathub-category.c:124 msgid "More Audio & Video" msgstr "Więcej aplikacji multimedialnych" #: src/bz-flathub-category.c:125 msgid "Developer Tools" msgstr "Narzędzia programistyczne" #: src/bz-flathub-category.c:125 msgid "Develop" msgstr "Programowanie" #: src/bz-flathub-category.c:125 msgid "More Developer Tools" msgstr "Więcej narzędzi programistycznych" #: src/bz-flathub-category.c:126 msgid "Education" msgstr "Edukacja" #: src/bz-flathub-category.c:126 msgid "Learn" msgstr "Ucz się" #: src/bz-flathub-category.c:126 msgid "More Education" msgstr "Więcej aplikacji dot. edukacji" #: src/bz-flathub-category.c:127 msgid "Gaming" msgstr "Gry" #: src/bz-flathub-category.c:127 msgid "Play" msgstr "Graj" #: src/bz-flathub-category.c:127 msgid "More Gaming" msgstr "Więcej gier" #: src/bz-flathub-category.c:128 msgid "Graphics & Photography" msgstr "Grafika i fotografia" #: src/bz-flathub-category.c:128 msgid "Create" msgstr "TwĂłrz" #: src/bz-flathub-category.c:128 msgid "More Graphics & Photography" msgstr "Więcej aplikacji dot. grafiki i fotografii" #: src/bz-flathub-category.c:129 msgid "Networking" msgstr "Narzędzia sieciowe" #: src/bz-flathub-category.c:129 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:129 msgid "More Networking" msgstr "Więcej narzędzi sieciowych" #: src/bz-flathub-category.c:130 msgid "Productivity" msgstr "Produktywność" #: src/bz-flathub-category.c:130 msgid "Work" msgstr "Pracuj" #: src/bz-flathub-category.c:130 msgid "More Productivity" msgstr "Więcej aplikacji dot. produktywności" #: src/bz-flathub-category.c:131 msgid "Science" msgstr "Nauka" #: src/bz-flathub-category.c:131 msgid "More Science" msgstr "Więcej aplikacji dot. nauki" #: src/bz-flathub-category.c:132 msgid "System" msgstr "System" #: src/bz-flathub-category.c:132 msgid "More System" msgstr "Więcej aplikacji dot. systemu" #: src/bz-flathub-category.c:133 msgid "Utilities" msgstr "Narzędzia" #: src/bz-flathub-category.c:133 msgid "Tools" msgstr "Narzędzia" #: src/bz-flathub-category.c:133 msgid "More Utilities" msgstr "Więcej narzędzi" #: src/bz-flathub-category.c:134 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:148 msgid "Trending" msgstr "Trendujące" #: src/bz-flathub-category.c:134 msgid "More Trending" msgstr "Więcej trendujących" #: src/bz-flathub-category.c:135 src/bz-flathub-page.blp:122 #: src/bz-flathub-page.blp:178 msgid "Popular" msgstr "Popularne" #: src/bz-flathub-category.c:135 msgid "More Popular" msgstr "Więcej popularnych" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:168 msgid "Recently Added" msgstr "Niedawno dodane" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:128 msgid "New" msgstr "Nowe" #: src/bz-flathub-category.c:136 msgid "More New" msgstr "Więcej nowych" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:158 msgid "Recently Updated" msgstr "Niedawno zaktualizowane" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:134 msgid "Updated" msgstr "Zaktualizowane" #: src/bz-flathub-category.c:137 msgid "More Updated" msgstr "Więcej zaktualizowanych" #: src/bz-flathub-category.c:138 msgid "Mobile" msgstr "Mobilne" #: src/bz-flathub-category.c:138 msgid "More Mobile" msgstr "Więcej mobilnych" #: src/bz-flathub-category.c:139 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:139 msgid "More Adwaita" msgstr "Więcej aplikacji Adwaita" #: src/bz-flathub-category.c:140 msgid "KDE Apps" msgstr "Od KDE" #: src/bz-flathub-category.c:140 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:205 msgid "App of the Day" msgstr "Aplikacja dnia" #: src/bz-flathub-page.blp:268 msgid "On the Go" msgstr "W biegu" #: src/bz-flathub-page.blp:280 msgid "Apps for your Linux phones and tablets" msgstr "Aplikacje na twoje urządzenia mobilne z Linuxem" #: src/bz-flathub-page.blp:291 src/bz-flathub-page.blp:326 msgid "More Mobile Apps" msgstr "Więcej aplikacji mobilnych" #: src/bz-flathub-page.blp:382 msgid "We​ ♥​ Games" msgstr "My ♥ gry" #: src/bz-flathub-page.blp:395 msgid "Games and apps to run your favorite titles" msgstr "Gry i aplikacje do uruchamiania twoich ulubionych pozycji" #: src/bz-flathub-page.blp:429 msgid "More Games" msgstr "Więcej gier" #: src/bz-full-view.blp:34 src/bz-library-page.blp:78 #: src/bz-library-page.blp:82 msgid "No Results" msgstr "Brak wynikĂłw" #: src/bz-full-view.blp:35 msgid "Try a different search query" msgstr "SprĂłbuj wyszukać coś innego" #: src/bz-full-view.blp:41 msgid "Content" msgstr "Zawartość" #: src/bz-full-view.blp:103 msgid "" "This is a local preview, some details may differ from the published listing" msgstr "" "To jest lokalny podgląd, niektĂłre szczegóły mogą się róşnić od opublikowanej " "pozycji" #: src/bz-full-view.blp:106 msgid "Preview Store Appearance" msgstr "Wygląd podglądu sklepu" #: src/bz-full-view.blp:232 msgid "_Support" msgstr "We_sprzyj" #: src/bz-full-view.blp:431 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:518 msgid "Trash Data" msgstr "Przenieś dane do kosza" #: src/bz-full-view.blp:658 msgid "Tags:" msgstr "Identyfikatory:" #: src/bz-full-view.c:180 msgid "No URL" msgstr "Brak adresu URL" #: src/bz-full-view.c:198 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:199 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:206 msgid "More Apps" msgstr "Więcej aplikacji" #: src/bz-full-view.c:207 #, c-format msgid "More Apps by %s" msgstr "Więcej aplikacji od %s" #: src/bz-full-view.c:214 msgid "Other Apps by this Developer" msgstr "Inne aplikacje od tego twĂłrcy" #: src/bz-full-view.c:216 src/bz-full-view.c:316 #, c-format msgid "Other Apps by %s" msgstr "Inne aplikacje od %s" #: src/bz-full-view.c:225 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" "Aplikacja %s nie jest zainstalowana, lecz nadal ma %s obecnych danych." #: src/bz-full-view.c:318 msgid "Other Apps" msgstr "Inne aplikacje" #: src/bz-full-view.c:320 #, 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:536 src/bz-user-data-tile.c:144 msgid "Failed to Remove User Data" msgstr "Usunięcie danych uĹźytkownika nie powiodło się" #: 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 "Wsparcie komputerĂłw" #: 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 "Aplikacja %s działa najlepiej na konkretnym sprzęcie" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "Aplikacja %s działa na większości urządzeń" #: src/bz-install-controls.blp:62 msgid "_Open" msgstr "_OtwĂłrz" #: src/bz-install-controls.blp:77 src/bz-install-controls.blp:134 msgid "Uninstall Application" msgstr "Odinstaluj aplikację" #: src/bz-install-controls.blp:87 src/bz-transaction-dialog.c:230 msgid "_Remove" msgstr "_Usuń" #: src/bz-install-controls.blp:121 src/bz-updates-card.c:164 #: src/bz-updates-card.c:183 msgid "Update" msgstr "Aktualizuj" #: src/bz-install-controls.blp:144 src/bz-installed-tile.blp:105 msgid "Remove" msgstr "Usuń" #: src/bz-install-controls.wdgt:32 msgctxt "Install Controls" msgid "Cancel" msgstr "Anuluj" #: src/bz-install-controls.wdgt:35 msgctxt "Install Controls" msgid "Cancelling" msgstr "Anulowanie" #: src/bz-library-page.blp:32 msgid "Search installed apps" msgstr "Wyszukuj zainstalowanych aplikacji" #: src/bz-library-page.blp:50 msgid "Clear search" msgstr "Wyczyść wyszukiwanie" #: src/bz-library-page.blp:71 msgid "No Apps Found" msgstr "Nie znaleziono aplikacji" #: src/bz-library-page.blp:90 msgid "Search Store Instead" msgstr "W zamian przeszukaj sklep" #. Translators: . #: src/bz-library-page.blp:100 src/bz-window.blp:112 msgid "Library" msgstr "Biblioteka" #: src/bz-library-page.blp:128 msgid "Pending Updates" msgstr "Aktualizacje w toku" #: src/bz-library-page.blp:155 msgid "Downloads" msgstr "Pobrania" #: src/bz-library-page.blp:198 msgid "Recently Uninstalled" msgstr "Niedawno odinstalowane" #: src/bz-library-page.blp:249 msgid "Clear Finished Tasks" msgstr "Wyczyść zakończone zadania" #: src/bz-library-page.blp:334 msgid "Sort By" msgstr "Sortuj wg" #: src/bz-library-page.blp:348 msgid "Name" msgstr "Nazwa" #: src/bz-library-page.blp:354 msgid "Size" msgstr "Rozmiar" #: src/bz-library-page.c:180 #, 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-library-page.c:193 src/bz-updates-card.c:433 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u aktualizacja dostępna" msgstr[1] "%u aktualizacje dostępne" msgstr[2] "%u aktualizacji dostępnych" #: src/bz-library-page.c:203 #, c-format msgid "%u Installed App" msgid_plural "%u Installed Apps" msgstr[0] "%u zainstalowana aplikacja" msgstr[1] "%u zainstalowane aplikacje" msgstr[2] "%u zainstalowanych aplikacji" #: src/bz-license-dialog.blp:94 msgid "Get Involved" msgstr "Miej wkład" #: src/bz-license-dialog.blp:111 msgid "Learn More" msgstr "Dowiedz się więcej" #: src/bz-license-dialog.c:127 msgid "Unknown License" msgstr "Nieznana licencja" #: src/bz-license-dialog.c:130 msgid "Community Built" msgstr "Stworzone przez społeczność" #: src/bz-license-dialog.c:203 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:206 msgid "The license of this app is not known" msgstr "Licencja tej aplikacji jest nieznana." #: src/bz-license-dialog.c:212 #, 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:220 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:226 #, 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-license-dialog.c:356 src/bz-safety-dialog.blp:49 msgid "License" msgstr "Licencja" #: 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:110 msgid "Finish" msgstr "Zakończ" #: src/bz-login-page.c:664 #, c-format msgid "Hello, %s!" msgstr "Cześć, %s!" #: src/bz-metainfo-preview.c:84 msgid "Select Metainfo File" msgstr "Wybierz plik Metainfo" #: src/bz-metainfo-preview.c:87 msgid "Metainfo Files" msgstr "Pliki Metainfo" #: src/bz-metainfo-preview.c:141 msgid "Select Icon (Optional)" msgstr "Wybierz ikonę (opcjonalnie)" #: src/bz-metainfo-preview.c:144 msgid "Image Files" msgstr "Pliki obrazĂłw" #: src/bz-metainfo-preview.c:231 msgid "Preview" msgstr "Podgląd" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Preferencje" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data refresh is paused" msgstr "" "Wykryto taryfowe połączenie internetowe - zatrzymano automatyczną " "synchronizację danych sklepowych" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:232 msgid "Refresh Manually" msgstr "OdświeĹź 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 End-of-Life 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:127 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 left to right" msgstr "Wyświetlaj kolory flag od lewej do prawej" #: 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-updates-card.c:155 msgid "Version History" msgstr "Historia wersji" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "Historia _wersji" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "Dzisiaj" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "Wczoraj" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "%d dzień temu" msgstr[1] "%d dni temu" msgstr[2] "%d dni temu" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "%d tydzień temu" msgstr[1] "%d tygodnie temu" msgstr[2] "%d tygodni temu" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "%d miesiąc temu" msgstr[1] "%d miesiące temu" msgstr[2] "%d miesięcy temu" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "%d rok temu" msgstr[1] "%d lata temu" msgstr[2] "%d lat temu" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%e %B %Y" #: src/bz-releases-list.c:196 #, c-format msgid "Version %s" msgstr "Wersja %s" #: src/bz-releases-list.c:251 msgid "No details for this release" msgstr "Brak szczegółów dla tego wydania" #: src/bz-releases-list.c:263 msgid "Get More Information" msgstr "Dowiedz się więcej" #: src/bz-rich-app-tile.blp:217 msgid "Uninstall" msgstr "Odinstaluj" #. Translators: If you can't find a short enough translation, use "/" to use an icon instead. #: src/bz-rich-app-tile.c:369 msgid "Get" msgstr "Pobierz" #: src/bz-safety-calculator.c:87 msgid "Unknown Permissions" msgstr "Nieznane uprawnienia" #: src/bz-safety-calculator.c:88 msgid "Permissions are missing for this app." msgstr "Brakuje uprawnień tej aplikacji." #: src/bz-safety-calculator.c:101 msgid "No Permissions" msgstr "Brak uprawnień" #: src/bz-safety-calculator.c:102 msgid "App is fully sandboxed" msgstr "Aplikacja jest w pełni uruchamiana w środowisku piaskownicy" #: src/bz-safety-calculator.c:108 msgid "Network Access" msgstr "Dostęp do sieci" #: src/bz-safety-calculator.c:109 msgid "Can access the internet" msgstr "Ma dostęp do internetu" #: src/bz-safety-calculator.c:111 msgid "No Network Access" msgstr "Nie potrzebuje internetu" #: src/bz-safety-calculator.c:112 msgid "Cannot access the internet" msgstr "Nie ma dostępu do internetu" #: src/bz-safety-calculator.c:117 msgid "User Device Access" msgstr "Dostęp do urządzeń uĹźytkownika" #: src/bz-safety-calculator.c:118 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:120 msgid "No User Device Access" msgstr "Brak dostępu do urządzeń uĹźytkownika" #: src/bz-safety-calculator.c:121 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:126 msgid "Input Device Access" msgstr "Dostęp do urządzeń wprowadzania" #: src/bz-safety-calculator.c:127 msgid "Can access input devices" msgstr "Ma dostęp do urządzeń wprowadzania" #: src/bz-safety-calculator.c:133 msgid "Microphone Access and Audio Playback" msgstr "Dostęp do mikrofonu i odtwarzania dĹşwięku" #: src/bz-safety-calculator.c:134 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:140 msgid "System Device Access" msgstr "Dostęp do urządzeń systemowych" #: src/bz-safety-calculator.c:141 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:147 msgid "Screen Contents Access" msgstr "Dostęp do zawartości ekranu" #: src/bz-safety-calculator.c:148 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:154 msgid "Legacy Windowing System" msgstr "Przestarzały system okien" #: src/bz-safety-calculator.c:155 msgid "Always uses a legacy windowing system (X11)" msgstr "Zawsze wykorzystuje przestarzały system okien (X11)" #: src/bz-safety-calculator.c:161 msgid "Arbitrary Permissions" msgstr "Samowolne uprawnienia" #: src/bz-safety-calculator.c:162 msgid "Can acquire arbitrary permissions" msgstr "MoĹźe uzyskać samowolne uprawnienia" #: src/bz-safety-calculator.c:168 msgid "User Settings" msgstr "Ustawienia uĹźytkownika" #: src/bz-safety-calculator.c:169 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:175 msgid "Full File System Read/Write Access" msgstr "Pełny dostęp do systemu plikĂłw" #: src/bz-safety-calculator.c:176 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:183 msgid "Home Folder Read/Write Access" msgstr "Dostęp do katalogu domowego" #: src/bz-safety-calculator.c:184 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:191 msgid "Full File System Read Access" msgstr "Pełny dostęp do odczytu systemu plikĂłw" #: src/bz-safety-calculator.c:192 msgid "Can read all data on the file system" msgstr "MoĹźe odczytywać wszystkie dane na systemie plikĂłw" #: src/bz-safety-calculator.c:200 msgid "Home Folder Read Access" msgstr "Dostęp do odczytu katalogu domowego" #: src/bz-safety-calculator.c:201 msgid "Can read all data in your home directory" msgstr "MoĹźe odczytywać dane w twoim katalogu domowym" #: src/bz-safety-calculator.c:209 msgid "Download Folder Read/Write Access" msgstr "Dostęp do folderu pobranych" #: src/bz-safety-calculator.c:210 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:220 msgid "Download Folder Read Access" msgstr "Dostęp do odczytu folderu pobranych" #: src/bz-safety-calculator.c:221 msgid "Can read all data in your downloads directory" msgstr "MoĹźe odczytywać dane w twoim folderze pobranych" #: src/bz-safety-calculator.c:242 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:266 msgid "Can read all data in the directory" msgstr "MoĹźe odczytywać wszystkie dane w katalogu" #: src/bz-safety-calculator.c:281 msgid "No File System Access" msgstr "Brak dostępu do systemu plikĂłw" #: src/bz-safety-calculator.c:282 msgid "Cannot access the file system at all" msgstr "Absolutnie nie ma dostępu do systemu plikĂłw" #: src/bz-safety-calculator.c:289 msgid "Uses System Services" msgstr "Wykorzystuje usługi systemowe" #: src/bz-safety-calculator.c:290 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:296 msgid "Uses Session Services" msgstr "Usługi sesji uĹźytkownika" #: src/bz-safety-calculator.c:297 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:345 msgid "No Service Access" msgstr "Brak dostępu do usług" #: src/bz-safety-calculator.c:346 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:354 msgid "Verified App Developer" msgstr "Zweryfikowany twĂłrca aplikacji" #: src/bz-safety-calculator.c:355 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:364 msgid "Proprietary Code" msgstr "Własnościowy kod" #: src/bz-safety-calculator.c:365 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:375 msgid "Auditable Code" msgstr "Audytowalny" #: src/bz-safety-calculator.c:376 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:516 #, c-format msgid "Use the %s System Service" msgstr "Korzysta z usługi systemowej %s" #: src/bz-safety-calculator.c:520 #, c-format msgid "Use the %s Session Service" msgstr "Korzysta z usługi sesji %s" #: src/bz-safety-calculator.c:524 #, c-format msgid "Use the %s Service" msgstr "Korzysta z usługi %s" #: src/bz-safety-calculator.c:534 msgid "Can see the non-portal service" msgstr "MoĹźe widzieć poza-portalowe usługi" #: src/bz-safety-calculator.c:536 msgid "Can talk to the non-portal service" msgstr "MoĹźe rozmawiać z poza-portalowymi usługami" #: src/bz-safety-calculator.c:538 msgid "Can own the non-portal service" msgstr "MoĹźe posiadać poza-portalowe usługi" #: src/bz-safety-calculator.c:553 msgid "Global Menu Integration" msgstr "Integracja z globalnym menu" #: src/bz-safety-calculator.c:554 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:559 msgid "KDE Settings Integration" msgstr "Integracja z ustawieniami KDE" #: src/bz-safety-calculator.c:560 msgid "Can detect when KDE desktop settings change" msgstr "MoĹźe wykryć kiedy ustawienia pulpitu KDE się zmieniają" #: src/bz-safety-calculator.c:565 msgid "KDE Global Settings" msgstr "Globalne ustawienia KDE" #: src/bz-safety-calculator.c:566 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:571 msgid "Secret Storage Service" msgstr "Usługa tajemnej pamięci" #: src/bz-safety-calculator.c:572 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 " "kluczy" #: src/bz-safety-calculator.c:577 msgid "Desktop Notifications Service" msgstr "Usługa powiadomień pulpitowych" #: src/bz-safety-calculator.c:578 msgid "Can send desktop notifications" msgstr "MoĹźe wysyłać powiadomienia pulpitowe" #: src/bz-safety-calculator.c:584 msgid "System Tray Integration" msgstr "Integracja z zasobnikiem systemowym" #: src/bz-safety-calculator.c:585 msgid "Can display an icon in the system tray" msgstr "MoĹźe wyświetlać ikonę w zasobniku systemowym" #: src/bz-safety-calculator.c:590 msgid "KDE Connect Integration" msgstr "Integracja z KDE Connect" #: src/bz-safety-calculator.c:591 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:59 msgid "App ID" msgstr "Identyfikator aplikacji" #: src/bz-safety-dialog.blp:69 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:167 msgid "Safety" msgstr "Bezpieczeństwo" #: src/bz-safety-dialog.c:226 #, c-format msgid "%s is Safe" msgstr "Aplikacja %s jest bezpieczna" #: src/bz-safety-dialog.c:231 #, c-format msgid "%s has no Unsafe Permissions" msgstr "Aplikacja %s nie posiada niebezpiecznych uprawnień" #: src/bz-safety-dialog.c:236 #, c-format msgid "%s is Probably Safe" msgstr "Aplikacja %s jest prawdopodobnie bezpieczna" #: src/bz-safety-dialog.c:241 #, c-format msgid "%s is Possibly Unsafe" msgstr "Aplikacja %s jest prawdopodobnie niebezpieczna" #: src/bz-safety-dialog.c:246 #, 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:150 msgid "Reset View" msgstr "Zresetuj widok" #: src/bz-screenshot-page.blp:161 msgid "Zoom Out" msgstr "Oddal" #: src/bz-screenshot-page.blp:171 msgid "Zoom In" msgstr "PrzybliĹź" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Karuzela zrzutĂłw ekranu" #: src/bz-screenshots-carousel.blp:117 msgid "Open Screenshot Viewer" msgstr "OtwĂłrz przeglądarkę zrzutĂłw ekranu" #: src/bz-search-filter-popover.blp:18 src/bz-search-page.blp:83 msgid "Filters" msgstr "Filtry" #: src/bz-search-filter-popover.blp:35 msgid "_Verified" msgstr "Z_weryfikowane" #: src/bz-search-filter-popover.blp:42 msgid "_Free/Open" msgstr "W_olne" #: src/bz-search-filter-popover.blp:49 msgid "Non-_EOL" msgstr "Wspi_erane" #: src/bz-search-filter-popover.blp:52 msgid "Filter out End-of-Life apps" msgstr "Odfiltruj aplikacje z brakiem wsparcia" #: src/bz-search-filter-popover.blp:57 msgid "Categories" msgstr "Kategorie" #: src/bz-search-page.blp:58 msgid "Search Apps, Games, Software" msgstr "Wyszukuj aplikacje, gry i oprogramowanie" #: src/bz-search-page.blp:70 msgid "Search Filters" msgstr "Filtry wyszukiwania" #: src/bz-search-page.blp:100 msgid "Clear Search" msgstr "Wyczyść wyszukiwanie" #: src/bz-search-page.blp:192 msgid "Categories Unavailable" msgstr "Kategorie są niedostępne" #: src/bz-search-page.blp:193 msgid "Search for apps using the search bar above." msgstr "Wyszukuj aplikacje korzystając z powyĹźszego paska wyszukiwania" #: src/bz-search-page.blp:219 msgid "Browse Categories" msgstr "Przeglądaj kategorie" #: src/bz-search-page.blp:361 msgid "No Applications Found" msgstr "Nie znaleziono aplikacji" #: src/bz-search-page.c:247 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Brak wynikĂłw dotyczących \"%s\" na Flathubie" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "Filmy" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "Biuro" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "Kalendarz" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "Komunikatory" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Paint" msgstr "Rysowanie" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "Torrent" msgstr "Torrent" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Emulator" msgstr "Emulator" #: src/bz-share-list.c:55 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Strona Flathub" #: src/bz-share-list.c:56 msgctxt "Project URL Type" msgid "Project Website" msgstr "Strona projektu" #: src/bz-share-list.c:57 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Issue Tracker" #: src/bz-share-list.c:58 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-share-list.c:59 msgctxt "Project URL Type" msgid "Help" msgstr "Pomoc" #: src/bz-share-list.c:60 msgctxt "Project URL Type" msgid "Donate" msgstr "PrzekaĹź darowiznę" #: src/bz-share-list.c:61 msgctxt "Project URL Type" msgid "Translate" msgstr "Tłumacz" #: src/bz-share-list.c:62 msgctxt "Project URL Type" msgid "Contact" msgstr "Skontaktuj się" #: src/bz-share-list.c:63 msgctxt "Project URL Type" msgid "Source Code" msgstr "Kod ĹşrĂłdłowy" #: src/bz-share-list.c:64 msgctxt "Project URL Type" msgid "Contribute" msgstr "Miej wkład" #: src/bz-share-list.c:153 msgid "Copy Link" msgstr "Kopiuj łącze" #: src/bz-share-list.c:164 msgid "Open Link" msgstr "OtwĂłrz łącze" #: src/bz-stats-dialog.blp:27 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" #: src/bz-stats-dialog.blp:69 msgid "Since 4/15/2024" msgstr "Od 15.04.2024" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:130 #, c-format msgid "%.2fM Total Installs" msgstr "Suma instalacji: %.2f mln" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:133 #, c-format msgid "%.2fK Total Installs" msgstr "Suma instalacji: %.2f tys." #: src/bz-stats-dialog.c:135 #, c-format msgid "%'d Total Installs" msgstr "Suma instalacji: %'d" #: src/bz-tag-list.c:78 msgid "No Results Found" msgstr "Brak wynikĂłw" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Aplikacje z identyfikatorem \"%s\"" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "Wyszukiwanie nie powiodło się" #: src/bz-transaction-dialog.c:154 msgid "Keep User Data" msgstr "Usuń dane uĹźytkownika" #: src/bz-transaction-dialog.c:155 msgid "Allow restoring personal settings & content" msgstr "PozwĂłl na przywracanie ustawień i zawartości" #: src/bz-transaction-dialog.c:164 msgid "Delete All Data" msgstr "Usuń wszystkie dane" #: src/bz-transaction-dialog.c:165 msgid "Permanently erase user data to save space" msgstr "Usuń dane aplikacji na zawsze, aby zaoszczędzić miejsce" #: src/bz-transaction-dialog.c:190 #, c-format msgid "Install %s?" msgstr "Zainstalować aplikację %s?" #: src/bz-transaction-dialog.c:195 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Wybierz wersję do zainstalowania. MoĹźe zainstalować dodatkowe współdzielone " "komponenty" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "MoĹźe zainstalować dodatkowe współdzielone komponenty" #: src/bz-transaction-dialog.c:200 src/bz-transaction-dialog.c:229 #: src/bz-transaction-dialog.c:274 src/bz-transaction-dialog.c:576 msgid "_Cancel" msgstr "_Anuluj" #: src/bz-transaction-dialog.c:201 msgid "_Install" msgstr "Za_instaluj" #: src/bz-transaction-dialog.c:218 #, c-format msgid "Remove %s?" msgstr "Usunąć aplikację %s?" #: src/bz-transaction-dialog.c:221 msgid "Select which version to remove." msgstr "Wybierz wersję do usunięcia." #: src/bz-transaction-dialog.c:223 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Nie będzie moĹźna korzystać z aplikacji %s po odinstalowaniu jej." #: src/bz-transaction-dialog.c:246 #, c-format msgid "“%s” is High Risk" msgstr "Aplikacja %s jest wysokim zagroĹźeniem" #: src/bz-transaction-dialog.c:250 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:259 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:275 msgid "_Install Anyway" msgstr "Za_instaluj mimo to" #: src/bz-transaction-dialog.c:330 msgid "Failed to load transaction dialog" msgstr "Ładowanie okna transakcji nie powiodło się" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "Wszystkie aplikacje są juĹź zainstalowane" #: 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] "Zainstalować %u aplikację?" msgstr[1] "Zainstalować %u aplikacje?" msgstr[2] "Zainstalować %u aplikacji?" #: src/bz-transaction-dialog.c:573 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:574 #, c-format msgid "%d addons will be installed." msgstr "Dodatki do zainstalowania: %d" #: src/bz-transaction-dialog.c:575 msgid "Additionally, addons will be installed." msgstr "Dodatkowo, następująca liczba dodatkĂłw zostanie zainstalowana: %d." #: src/bz-transaction-dialog.c:577 msgid "_Install All" msgstr "Za_instaluj wszystkie" #: src/bz-transaction-manager.c:795 #, c-format msgid "Finished in %.02f seconds" msgstr "Ukończono w %.02f sek." #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "Dodatek aplikacji" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "Biblioteka" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "W kolejce" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "Gotowe" #: src/bz-transaction-tile.blp:230 msgid "Cancelled" msgstr "Anulowane" #: src/bz-transaction-tile.blp:254 msgid "Error" msgstr "Bład" #: src/bz-transaction-tile.blp:312 msgid "Cancel Transaction" msgstr "Anuluj transakcję" #: src/bz-transaction-tile.blp:436 msgid "Show Error Info" msgstr "PokaĹź szczegóły błędu" #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "Zwolniono %s" #: src/bz-transaction-tile.c:360 src/bz-transaction-tile.c:363 msgid "Transaction Error" msgstr "Błąd transakcji" #: src/bz-transaction.c:344 msgid "Pending" msgstr "Oczekujące" #: src/bz-updates-card.blp:23 msgid "_Update All" msgstr "Akt_ualizuj wszystkie" #: src/bz-updates-card.c:211 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "%u aktualizacja biblioteki" msgstr[1] "%u aktualizacje bibliotek" msgstr[2] "%u aktualizacji bibliotek" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Zarządzaj pozostałymi danymi" #: src/bz-user-data-page.blp:33 msgid "No User Data Found" msgstr "Nie znaleziono pozostałych danych" #: src/bz-user-data-page.blp:38 msgid "User Data" msgstr "Dane uĹźytkownika" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Przenieś do kosza dane uĹźytkownika" #: src/bz-user-data-tile.c:150 #, c-format msgid "Trashed User Data for %s" msgstr "Przeniesiono do kosza dane uĹźytkownika aplikacji %s" #: src/bz-window.blp:70 msgid "Refreshing" msgstr "OdświeĹźanie" #: src/bz-window.blp:88 msgid "Curated" msgstr "Polecane" #: src/bz-window.blp:100 msgid "Explore" msgstr "Odkrywaj" #: src/bz-window.blp:212 msgid "Main Menu" msgstr "Menu główne" #: src/bz-window.blp:223 msgid "You are running a new version of Bazaar!" msgstr "Odpaliłeś nowiutką wersję Bazaaru!" #: src/bz-window.blp:224 msgid "See What's New" msgstr "Zobacz co nowego" #: src/bz-window.blp:231 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:276 msgid "_Donate to Bazaar" msgstr "_Wesprzyj Bazaar" #: src/bz-window.blp:283 msgid "_Refresh" msgstr "_OdświeĹź" #: src/bz-window.blp:288 msgid "_Preferences" msgstr "_Preferencje" #: src/bz-window.blp:293 msgid "_Login With Flathub" msgstr "Za_loguj się do Flathub" #: src/bz-window.blp:299 msgid "_Manage Leftover User Data" msgstr "Zarządzaj pozostały_mi danymi" #: src/bz-window.blp:304 msgid "_Keyboard Shortcuts" msgstr "SkrĂłty _klawiszowe" #: src/bz-window.blp:309 msgid "_About Bazaar" msgstr "O _aplikacji Bazaar" #: src/bz-window.blp:316 msgid "_Quit Bazaar" msgstr "_Zamknij Bazaar" #: src/bz-window.blp:341 msgid "Log Out" msgstr "Wyloguj się" #. Translators: %s is the title of the current page #: src/bz-window.c:376 #, c-format msgid "Bazaar — %s" msgstr "Bazaar — %s" #: src/bz-window.c:596 src/bz-window.c:634 msgid "Failed to launch application" msgstr "Uruchomienie aplikacji nie powiodło się" #: src/bz-window.c:843 msgid "You can't remove Bazaar from Bazaar!" msgstr "Nie moĹźesz usunąć Bazaaru z poziomu Bazaaru!" #: src/bz-window.c:1127 src/bz-window.c:1161 msgid "Can't do that right now!" msgstr "Nie moĹźesz tego teraz zrobić!" #. Translators: As in, "1 Install" / "100 Installs" #: src/bz-world-map.c:604 msgid "Install" msgid_plural "Installs" msgstr[0] "instalacja" msgstr[1] "instalacje" msgstr[2] "instalacji" #: src/shortcuts-dialog.blp:5 msgctxt "shortcut window" msgid "Navigation" msgstr "Nawigacja" #: src/shortcuts-dialog.blp:8 msgctxt "shortcut window" msgid "Open Explore Page" msgstr "OtwĂłrz stronę \"Odkrywaj\"" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "OtwĂłrz stronę biblioteki" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Open Search Page" msgstr "OtwĂłrz stronę wyszukiwania" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Remotes" msgstr "Repozytoria" #: src/shortcuts-dialog.blp:27 msgctxt "shortcut window" msgid "Sync Remotes" msgstr "Zsynchronizuj repozytoria" #: src/shortcuts-dialog.blp:33 msgctxt "shortcut window" msgid "General" msgstr "OgĂłlne" #: src/shortcuts-dialog.blp:36 msgctxt "shortcut window" msgid "Open Preferences" msgstr "OtwĂłrz preferencje" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "PokaĹź skrĂłty" #: src/shortcuts-dialog.blp:46 msgctxt "shortcut window" msgid "Close Window" msgstr "Zamknij okno" #: src/shortcuts-dialog.blp:52 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "Zamknij Bazaar" #~ msgid "User Data Size" #~ msgstr "Rozmiar danych uĹźytkownika" #~ msgctxt "About Dialog Developer Credit" #~ msgid "Adam Masciola " #~ msgstr "Adam Masciola " #~ msgctxt "About Dialog Developer Credit" #~ msgid "Alexander Vanhee" #~ msgstr "Alexander Vanhee" #~ msgid "Open App Library" #~ msgstr "OtwĂłrz bibliotekę aplikacji" #~ msgid "Installing .flatpak bundles is not yet supported" #~ msgstr "Instalowanie pakietĂłw .flatpak nie jest jeszcze wspierane" #~ msgid "Steam" #~ msgstr "Steam" #~ msgid "Minecraft" #~ msgstr "Minecraft" #~ msgid "Refresh completed!" #~ msgstr "Ukończono odświeĹźanie!" #~ msgctxt "As in, \"100 Installs\"" #~ msgid "Installs" #~ msgstr "zainstalowań" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "OdświeĹź" #~ msgid "Adam Masciola" #~ msgstr "Adam Masciola" #~ msgid "_Donate to Bazaar ❤️" #~ msgstr "PrzekaĹź _darowiznę ❤️" #~ msgid "Hide EOL Apps" #~ msgstr "Ukrywaj aplikacje z brakiem wsparcia" #~ msgid "Flathub" #~ msgstr "Flathub" #~ msgid "Download & Install Application" #~ msgstr "Pobierz i zainstaluj aplikację" #~ msgctxt "As in, \"100 Downloads\"" #~ msgid "Downloads" #~ msgstr "Pobrań" #~ msgid "%e %B" #~ msgstr "%e %B" #~ 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." #~ msgid "Install Other Version" #~ msgstr "Zainstaluj inną wersję" #~ msgid "Keep Data" #~ msgstr "Zachowaj dane" #~ msgid "Open App" #~ msgstr "OtwĂłrz aplikację" #~ msgid "_Synchronize Remotes" #~ msgstr "Z_synchronizuj repozytoria" #~ msgid "Synchronizing..." #~ msgstr "Synchronizowanie..." #, c-format #~ msgid "Receiving %d entries..." #~ msgstr "Otrzymywanie %d wystąpień..." #~ msgid "Indexing Data..." #~ msgstr "Indeksowanie danych..." #~ msgid "Refreshing Store Content" #~ msgstr "OdświeĹźanie zawartości" #~ msgid "No background tasks!" #~ msgstr "Brak zadań w tle!" #~ msgctxt "shortcut window" #~ msgid "Quit" #~ msgstr "WyjdĹş" #~ msgid "View the Release Page" #~ msgstr "PokaĹź stronę wydania" #~ msgid "Close" #~ msgstr "Zamknij" #~ msgid "Copy and Close" #~ msgstr "Kopiuj i zamknij" #~ msgid "Nucleus app page" #~ msgstr "Strona aplikacji Nucleus" #~ msgid "Toggle transaction sidebar" #~ msgstr "Włącz pasek boczny transakcji" #~ msgctxt "Project URL Type" #~ msgid "Manifest" #~ msgstr "Manifest" #~ msgid "Ongoing" #~ msgstr "Trwające" #~ msgid "Finished" #~ msgstr "Zakończone" #, c-format #~ msgid "Transferred %s so far" #~ msgstr "Do tej pory przeniesiono %s" #~ msgid "Tasks" #~ msgstr "Zadania" #~ msgid "Stop Active Tasks" #~ msgstr "Zatrzymaj aktywne zadania" #~ msgid "No Tasks Yet" #~ msgstr "Brak zadań" #, 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" #~ msgid "Updates Are Available" #~ msgstr "Dostępne są aktualizacje" #~ 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ć?" #, 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ć?" #, 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." #~ msgid "Update Now" #~ msgstr "Aktualizuj teraz" #~ 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" #~ msgid "Resume Current Tasks" #~ msgstr "Kontynuuj wykonywanie zadań" #~ msgid "Pause Current Tasks" #~ msgstr "Zapauzuj wykonywanie zadań" #~ msgctxt "shortcut window" #~ msgid "Toggle Transaction Manager" #~ msgstr "Włącz menedĹźera transakcji" #~ 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 "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 "--- 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 "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 " #~ 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 "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 "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 "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 "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 "Show Downloads Over Time" #~ msgstr "PokaĹź pobrania na przestrzeni czasu" #~ msgid "Remote repo name" #~ msgstr "Nazwa repozytorium" #~ 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 "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" #~ 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" bazaar-org-bazaar-43ce9f7/po/pt_BR.po000066400000000000000000003213561520414637400174270ustar00rootroot00000000000000# 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-2026. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-05-06 02:13-0400\n" "PO-Revision-Date: 2026-05-10 12:23-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 50.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:45 #: src/bz-window.c:374 src/bz-window.c:375 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;" #: data/io.github.kolunmi.Bazaar.desktop.in:16 msgid "New Window" msgstr "Nova Janela" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and manage applications" msgstr "Descobrir e gerenciar aplicativos" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "Uma nova loja de aplicativos rĂĄpida e moderna para Linux, focada em " "descobrir e instalar aplicativos e extensĂľes Flatpak, particularmente do " "Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "Enfileire mĂşltiplas instalaçþes e continuar navegando" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "Veja permissĂľes de apps facilmente" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "Faça login com o Flathub para ver e gerenciar seus favoritos" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "Pesquise apps diretamente do GNOME Shell" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "The home page displaying Flathub apps" msgstr "A pĂĄgina inicial exibindo apps do Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:59 msgid "Exhibit app page" msgstr "Exibir pĂĄgina do app" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "PĂĄgina da Biblioteca" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "PĂĄgina de Pesquisa" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "PĂĄgina de Catergorias" #: src/bz-addon-tile.blp:49 src/bz-installed-tile.blp:64 #: src/bz-rich-app-tile.blp:140 msgid "Stopped Receiving Updates" msgstr "Parou de Receber Atualizaçþes" #: src/bz-addon-tile.c:155 src/bz-favorites-tile.c:157 #: src/bz-rich-app-tile.blp:172 msgid "Uninstall" msgstr "Desinstalar" #: src/bz-addon-tile.c:157 src/bz-favorites-tile.c:159 msgid "Install" msgstr "Instalar" #: src/bz-addons-dialog.blp:14 src/bz-addons-dialog.blp:21 #: src/bz-addons-dialog.blp:70 src/bz-full-view.blp:606 #: src/bz-installed-tile.blp:101 msgid "Manage Add-Ons" msgstr "Gerenciar ExtensĂľes" #: src/bz-addons-dialog.blp:80 msgid "No Add-Ons Visible" msgstr "Sem ExtensĂľes VisĂ­veis" #: src/bz-addons-dialog.blp:81 msgid "" "Your current filter preferences are hiding all known add-ons. Try adjusting " "them." msgstr "" "As suas preferĂŞncias de filtro atuais estĂŁo escondendo todos as extensĂľes " "conhecidas. Tente ajustĂĄ-las" #: src/bz-addons-dialog.blp:88 msgid "Add-on Page" msgstr "PĂĄgina de ExtensĂľes" #: src/bz-addons-dialog.blp:202 src/bz-full-view.blp:404 msgid "Downloads/Month" msgstr "Downloads/MĂŞs" #: src/bz-addons-dialog.blp:229 src/bz-full-view.blp:440 msgid "Stopped Receiving Core Updates" msgstr "Parou de receber atualizaçþes crĂ­ticas" #: src/bz-addons-dialog.blp:243 msgid "" "This add-on uses a runtime that no longer receives updates or security " "fixes. It may become unsafe to use." msgstr "" "Esta extensĂŁo utiliza um runtime que nĂŁo recebe mais atualizaçþes ou " "atualizaçþes de segurança. Talvez se torne insegura para uso." #: src/bz-addons-dialog.c:330 #, c-format msgid "Add-on for %s" msgstr "ExtensĂŁo para %s" #: src/bz-addons-dialog.c:344 src/bz-full-view.c:568 msgid "Show Less" msgstr "Mostrar Menos" #: src/bz-addons-dialog.c:344 src/bz-full-view.c:568 msgid "Show More" msgstr "Mostrar Mais" #: src/bz-addons-dialog.c:394 msgid "Download Stats" msgstr "EstatĂ­sticas de Download" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:736 src/bz-context-tile-callbacks.c:186 #: src/bz-context-tile-callbacks.c:193 msgid "Age Rating" msgstr "Classificação Indicativa" # https://pt.wikipedia.org/wiki/Sistema_de_Classifica%C3%A7%C3%A3o_Indicativa_Brasileiro #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "ViolĂŞncia Caricata" # https://pt.wikipedia.org/wiki/Sistema_de_Classifica%C3%A7%C3%A3o_Indicativa_Brasileiro #. 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çþes acerca de violĂŞncia caricata" # https://pt.wikipedia.org/wiki/Sistema_de_Classifica%C3%A7%C3%A3o_Indicativa_Brasileiro #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "ViolĂŞncia Fantasiosa" # https://pt.wikipedia.org/wiki/Sistema_de_Classifica%C3%A7%C3%A3o_Indicativa_Brasileiro #. 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çþes acerca de violĂŞncia fantasiosa" #. 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çþes acerca de 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 com Presença de 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çþes acerca de violĂŞncia com presença de 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çþes acerca de 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çþes acerca de referĂŞncias Ă  ĂĄlcool" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "NarcĂłticos" #. 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çþes acerca de referĂŞncias a drogas ilĂ­citas" #. 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çþes acerca de 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çþes acerca de nenhum tipo de nudez" #. 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çþes acerca de referĂŞncias ou retrataçþes a nenhum tipo de " "natureza sexual" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Profanidade" #. 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çþes acerca de nenhum tipo de profanidade" #. 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çþes acerca 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çþes acerca de nenhum tipo de linguagem discriminatĂłria" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Propaganda" #. 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çþes acerca de nenhum tipo de propaganda" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Apostas ou 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çþes acerca de nenhum tipo de apostas ou jogos de azar" #. 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çþes acerca de possibilidades 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 "Mensagens Entre UsuĂĄrios" #. 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çþes acerca de formas de se comunicar com outros usuĂĄrios" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Comunicaçþes de Áudio Entre UsuĂĄrios" #. 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çþes acerca de formas de se comunicar por ĂĄudio com outros " "usuĂĄrios" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Detalhes de Contato" #. 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çþes acerca de compartilhamento de nomes de usuĂĄrio de redes " "sociais ou endereços de e-mail" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Informaçþes de Identidade" #. 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çþes acerca de compartilhamento de informaçþes de usuĂĄrio com " "terceiros" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Compartilhamento 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çþes acerca de compartilhamento de localização com outros usuĂĄrios" #. 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çþes acerca de 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çþes acerca de 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 "Personagens 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çþes acerca de personagens sexualizados" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 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çþes acerca de 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 "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çþes acerca de restos humanos mortos 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çþes acerca de 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 drogas" #: src/bz-age-rating-dialog.c:426 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:428 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:430 msgid "Does not include sex or nudity" msgstr "NĂŁo inclui sexo ou nudez" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "NĂŁo inclui funcionalidade nĂŁo controlada de comunicação" #: 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 ImprĂłpria" #: 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 msgid "Violence" msgstr "ViolĂŞncia" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:686 src/bz-context-tile-callbacks.c:176 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "Livre" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "%s possui classificação indicativa desconhecida" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "%s ĂŠ adequado para todos" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "%s ĂŠ adequado para crianças pequenas" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "%s ĂŠ adequado para crianças" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "%s ĂŠ adequado para adolecentes" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "%s ĂŠ adequado para adultos" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "%s ĂŠ adequado para %s" #: src/bz-age-rating-dialog.c:862 #, c-format msgid "%s • %s" msgstr "%s • %s" #: 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 da Pasta pessoal %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Pastas host do sistema" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Configuraçþes host do sistema de /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Subpasta do Desktop %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Pasta do Desktop" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Subpasta de Documentos %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Pasta de Documentos" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Subpasta de MĂşsicas %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Pasta de MĂşsicas" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Subpasta de images %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Pasta de imagens" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Subpasta de Compartilhamento PĂşblico %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Pasta de Compartilhamento PĂşblico" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Subpasta de VĂ­deos %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Pasta de VĂ­deos" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Subpasta de Modelos %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Pasta de Modelos" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Subpasta de cache de usuĂĄrio %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Pasta de cache de usuĂĄrio" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Subpasta de configuração de usuĂĄrio %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Pasta de configuração de usuĂĄrio" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Subpasta de dados de usuĂĄrio %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Pasta de dados de usuĂĄrio" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Subpasta de runtime de usuĂĄrio %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Pasta de runtime de usuĂĄrio" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Acesso ao sistema de arquivos para %s" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "DiretĂłrio do sistema de arquivos desconhecido" #: src/bz-app-size-dialog.blp:26 src/bz-app-size-dialog.blp:52 msgid "Download Size" msgstr "Tamanho do Download" #: src/bz-app-size-dialog.blp:53 msgid "Amount to download from the internet" msgstr "Quantidade a ser baixada da internet" #: src/bz-app-size-dialog.blp:73 msgid "Installed Size" msgstr "Tamanho Instalado" #: src/bz-app-size-dialog.blp:74 msgid "Size on Disk" msgstr "Tamanho no Disco" #: src/bz-app-size-dialog.blp:121 msgid "Open user data folder" msgstr "Abrir pasta de dados de usuĂĄrio" #: src/bz-app-size-dialog.blp:131 msgid "User Data Size" msgstr "Tamanho dos Dados de UsuĂĄrio" #: src/bz-app-size-dialog.blp:132 msgid "Caches, settings, and other app data" msgstr "Caches, configuraçþes e outros dados do app" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "Tamanho do Runtime Instalado" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "Tamanho de Download do Runtime" #: src/bz-app-size-dialog.c:204 msgid "App Size" msgstr "Tamanho do App" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:104 src/bz-rich-app-tile.c:304 msgid "Verified" msgstr "Verificado" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-context-tile-callbacks.c:135 #: src/bz-releases-list.c:206 msgid "Installed" msgstr "Instalado" #: src/bz-application.c:737 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:738 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #: src/bz-application.c:758 msgid "The Bazaar Contributors" msgstr "Contribuidores do Bazaar" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:761 msgid "translator-credits" msgstr "" "JoĂŁo Victor , 2025\n" "Rin Koito , 2025" #: src/bz-application.c:771 msgid "Special Thanks" msgstr "Agradecimentos Especiais" #: src/bz-application.c:829 msgid "Logged Out Successfully!" msgstr "Desconectado com Sucesso!" #: src/bz-application.c:968 msgid "Performing setup…" msgstr "Realizando configuração..." #: src/bz-application.c:1054 msgid "Set Up System Flathub?" msgstr "Configurar Flathub do Sistema?" #: src/bz-application.c:1057 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "O repositĂłrio Flathub do sistema nĂŁo estĂĄ configurado. O Bazaar precisa que " "o Flahub esteja configurado na instalação Flatpak do sistema para navegar e " "instalar aplicaçþes.\n" "\n" "VocĂŞ ainda pode utilizar o Bazaar para navegar e remover apps jĂĄ instalados." #: src/bz-application.c:1064 msgid "Set Up Flathub?" msgstr "Configurar Flathub?" #: src/bz-application.c:1067 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:1073 msgid "Later" msgstr "Depois" #: src/bz-application.c:1074 msgid "Set Up Flathub" msgstr "Configurando Flathub" #: src/bz-application.c:1291 src/bz-application.c:1778 msgid "Checking for updates…" msgstr "Procurando por atualizaçþes..." #: src/bz-application.c:1411 msgid "A backend error occurred" msgstr "Ocorreu um erro no backend" #: src/bz-application.c:1611 src/bz-application.c:3655 src/bz-window.blp:69 msgid "Refreshing…" msgstr "Atualizando..." #: src/bz-application.c:1775 src/bz-application.c:3653 #, c-format msgid "Loading %d apps…" msgstr "Carregando %d apps..." #: src/bz-application.c:1833 msgid "Failed to open file" msgstr "Falha ao abrir arquivo" #: src/bz-application.c:1918 msgid "An initialization error occurred" msgstr "Ocorreu Um Erro de Iniciazalição" #: src/bz-application.c:2339 msgid "Failed to check for updates" msgstr "Falha ao procurar por atualizaçþes" #: src/bz-application.c:3373 msgid "Could not find app" msgstr "NĂŁo foi possĂ­vel encontrar o app" #: src/bz-application.c:3406 msgid "Failed to load metainfo" msgstr "Falha ao carregar metainfo" #: src/bz-application.c:3657 msgid "Writing to cache…" msgstr "Escrevendo no cache" #: src/bz-apps-page.blp:86 msgid "Show All" msgstr "Mostrar Tudo" #: src/bz-apps-page.c:229 #, c-format msgid "All \"%s\"" msgstr "Todos \"%s\"" #: src/bz-apps-page.c:478 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "%d Aplicativos" #: src/bz-appstream-parser.c:303 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "PĂĄgina do Flathub" #: src/bz-appstream-parser.c:324 msgctxt "Project URL Type" msgid "Project Website" msgstr "Site do Projeto" #: src/bz-appstream-parser.c:328 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Rastreador de problemas" #: src/bz-appstream-parser.c:332 msgctxt "Project URL Type" msgid "FAQ" msgstr "Perguntas Mais Frequentes" #: src/bz-appstream-parser.c:336 msgctxt "Project URL Type" msgid "Help" msgstr "Ajuda" #: src/bz-appstream-parser.c:340 msgctxt "Project URL Type" msgid "Donate" msgstr "Doar" #: src/bz-appstream-parser.c:346 msgctxt "Project URL Type" msgid "Translate" msgstr "Traduzir" #: src/bz-appstream-parser.c:350 msgctxt "Project URL Type" msgid "Contact" msgstr "Contatar" #: src/bz-appstream-parser.c:354 msgctxt "Project URL Type" msgid "Source Code" msgstr "CĂłdigo Fonte" #: src/bz-appstream-parser.c:360 msgctxt "Project URL Type" msgid "Contribute" msgstr "Contribuir" #: src/bz-bundle-install-dialog.c:240 msgid "Installing" msgstr "Instalando" #: src/bz-bundle-install-dialog.c:254 msgid "Installed!" msgstr "Instalado!" #: src/bz-context-tile-callbacks.c:68 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-context-tile-callbacks.c:75 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-context-tile-callbacks.c:82 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-context-tile-callbacks.c:92 #, c-format msgid "%d downloads in the last month" msgstr "%d downloads no Ăşltimo mĂŞs" #: src/bz-context-tile-callbacks.c:104 src/bz-context-tile-callbacks.c:389 #: src/bz-context-tile-callbacks.c:406 msgid "N/A" msgstr "N/A" #: src/bz-context-tile-callbacks.c:132 #, c-format msgid "+%s runtime" msgstr "+%s runtime" #: src/bz-context-tile-callbacks.c:135 msgid "Download" msgstr "Download" #: src/bz-context-tile-callbacks.c:155 msgid "Size information unavailable" msgstr "Informação sobre o tamanho nĂŁo disponĂ­vel" #: src/bz-context-tile-callbacks.c:158 #, c-format msgid "Download size of %s" msgstr "Tamanho do download de %s" #: src/bz-context-tile-callbacks.c:191 msgid "All Ages" msgstr "Todas as idades" #: src/bz-context-tile-callbacks.c:203 msgid "Age rating information unavailable" msgstr "Classificação indicativa indisponĂ­vel" #: src/bz-context-tile-callbacks.c:208 msgid "Suitable for all ages" msgstr "Adequado para todas as idades" #: src/bz-context-tile-callbacks.c:210 #, c-format msgid "Suitable for ages %d and up" msgstr "Adequado para idades de %d anos ou mais" #: src/bz-context-tile-callbacks.c:243 src/bz-context-tile-callbacks.c:248 #: src/bz-context-tile-callbacks.c:276 src/bz-context-tile-callbacks.c:284 msgid "Unknown" msgstr "Desconhecido" #: src/bz-context-tile-callbacks.c:253 #, c-format msgid "Free software licensed under %s" msgstr "Software livre sob a licença %s" #: src/bz-context-tile-callbacks.c:258 msgid "Free software" msgstr "Software Livre" #: src/bz-context-tile-callbacks.c:261 msgid "Proprietary Software" msgstr "Software ProprietĂĄrio" #: src/bz-context-tile-callbacks.c:264 #, c-format msgid "Special License: %s" msgstr "Licença Especial: %s" #: src/bz-context-tile-callbacks.c:281 msgid "Free" msgstr "Livre" #: src/bz-context-tile-callbacks.c:287 src/bz-license-dialog.c:133 msgid "Proprietary" msgstr "ProprietĂĄrio" #: src/bz-context-tile-callbacks.c:289 src/bz-license-dialog.c:135 msgid "Special License" msgstr "Licença Especial" #: src/bz-context-tile-callbacks.c:309 msgid "Adaptive" msgstr "Adaptativo" #: src/bz-context-tile-callbacks.c:309 msgid "Desktop Only" msgstr "Somente Desktop" #: src/bz-context-tile-callbacks.c:315 msgid "Works on desktop, tablets, and phones" msgstr "Funciona em desktops, tablets e celulares" #: src/bz-context-tile-callbacks.c:316 msgid "May not work on mobile devices" msgstr "Talvez nĂŁo funcione em dispositivos mĂłveis" #: src/bz-context-tile-callbacks.c:396 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Seguro" #: src/bz-context-tile-callbacks.c:398 src/bz-context-tile-callbacks.c:400 msgid "Low Risk" msgstr "Baixo Risco" #: src/bz-context-tile-callbacks.c:402 msgid "Medium Risk" msgstr "MĂŠdio Risco" #: src/bz-context-tile-callbacks.c:404 msgid "High Risk" msgstr "Alto Risco" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:46 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:30 #: src/bz-library-page.blp:67 src/bz-user-data-page.blp:30 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 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" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "Navegador" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "NĂŁo Verificado" #: src/bz-developer-badge.c:210 msgid "Developer information not available." msgstr "Informaçþes sobre desenvolveres nĂŁo estĂĄ disponĂ­vel" #: src/bz-developer-badge.c:216 src/bz-developer-badge.c:230 #, 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:234 #, 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:250 #, 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 do aplicativo %1$s foi verificada por %2$s em " "%3$s." #: src/bz-developer-badge.c:257 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "A propriedade do ID do aplicativo %1$s foi verificada utilizando %2$s." #: src/bz-developer-badge.c:261 #, 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-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "Notas de Lançamento Completas" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "Esta versĂŁo do Bazaar foi possĂ­vel graças a usuĂĄrios como vocĂŞ!" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on Ko-Fi." msgstr "" "Eu amo fazer o Bazaar, mas eu nĂŁo consigo fazĂŞ-lo sem ajuda. Ajude o " "desenvolvimento doando para o projeto no Ko-Fi:" #: src/bz-donations-dialog.blp:131 msgid "Donate to Bazaar" msgstr "Doar para o Bazaar" #. Translators: the %s format specifier will be something along the lines of "0.7.6" etc #: src/bz-donations-dialog.c:227 #, c-format msgid "What's New in %s?" msgstr "O Que Tem de Novo na %s?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "Lançado em %B %-e, %Y" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Escolha uma Instalação" #: 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 "" "VocĂŞ tem vĂĄrias versĂľes deste aplicativo instaladas. Com qual vocĂŞ gostaria " "de prosseguir?" #: src/bz-entry-group-util.c:80 msgid "Cancel" msgstr "Cancelar" #: src/bz-entry-selection-row.blp:17 msgid "For This User Only" msgstr "Somente Para Este UsuĂĄrio" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "este usuĂĄrio" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "todos os usuĂĄrios" #: src/bz-error-dialog.blp:36 src/bz-error.c:69 src/bz-error.c:88 #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Detalhes" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "Copiar" #: src/bz-error-dialog.c:56 src/bz-share-list.c:62 msgid "Copied!" msgstr "Copiado!" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Contagem de Favoritos" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" msgstr "Falha ao atualizar favorito" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Faça login com o Flathub para gerenciar seus favoritos" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Entrar" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:56 #: src/bz-window.blp:360 msgid "Favorites" msgstr "Favoritos" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "Instalar Todos" #: src/bz-favorites-page.blp:34 src/bz-user-data-page.blp:19 msgid "Loading" msgstr "Carregando" #: src/bz-favorites-page.blp:49 msgid "No Favorites" msgstr "Sem Favoritos" #: src/bz-favorites-page.blp:50 msgid "Applications you mark as favorite will appear here" msgstr "Aplicativos que vocĂŞ marcar como favoritos aparecerĂŁo aqui" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:78 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-tile.c:357 msgid "Failed to remove favorite" msgstr "Falha ao remover favorito" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Anterior" #: src/bz-featured-carousel.blp:54 msgid "Next" msgstr "PrĂłximo" #: src/bz-flathub-category.c:93 msgid "Editing" msgstr "Editação" #: src/bz-flathub-category.c:94 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:95 msgid "Mixer" msgstr "Mixagem" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:96 src/bz-search-pill-list.c:77 msgid "Music" msgstr "MĂşsica" #: src/bz-flathub-category.c:97 msgid "Player" msgstr "Reprodutor de MĂ­dia" #: src/bz-flathub-category.c:98 msgid "Recorder" msgstr "Gravador" #: src/bz-flathub-category.c:99 msgid "Sequencer" msgstr "Sequenciador" #: src/bz-flathub-category.c:100 msgid "Tuner" msgstr "Sintonizador" #: src/bz-flathub-category.c:101 msgid "TV" msgstr "TV" #: src/bz-flathub-category.c:106 msgid "Emulation" msgstr "Emulação" #: src/bz-flathub-category.c:107 msgid "Action" msgstr "Ação" #: src/bz-flathub-category.c:108 msgid "Adventure" msgstr "Aventura" #: src/bz-flathub-category.c:109 msgid "Arcade" msgstr "Arcade" #: src/bz-flathub-category.c:110 msgid "Blocks" msgstr "Blocos" #: src/bz-flathub-category.c:111 msgid "Board" msgstr "Tabuleiro" #: src/bz-flathub-category.c:112 msgid "Card" msgstr "Carta" #: src/bz-flathub-category.c:113 msgid "Kids" msgstr "Crianças" #: src/bz-flathub-category.c:114 msgid "Logic" msgstr "LĂłgica" #: src/bz-flathub-category.c:115 msgid "Role Playing" msgstr "Role Playing" #: src/bz-flathub-category.c:116 msgid "Shooter" msgstr "Tiro" #: src/bz-flathub-category.c:117 msgid "Simulation" msgstr "Simulação" #: src/bz-flathub-category.c:118 msgid "Sports" msgstr "Estportes" #: src/bz-flathub-category.c:119 msgid "Strategy" msgstr "EstratĂŠgia" #: src/bz-flathub-category.c:124 msgid "Audio & Video" msgstr "Áudio & VĂ­deo" #: src/bz-flathub-category.c:124 msgid "Media" msgstr "MĂ­dia" #: src/bz-flathub-category.c:124 msgid "More Audio & Video" msgstr "Mais Áudio e VĂ­deo" #: src/bz-flathub-category.c:125 msgid "Developer Tools" msgstr "Ferramentas de desenvolvedores" #: src/bz-flathub-category.c:125 msgid "Develop" msgstr "Desenvolver" #: src/bz-flathub-category.c:125 msgid "More Developer Tools" msgstr "Mais Ferramentas de desenvolvedores" #: src/bz-flathub-category.c:126 msgid "Education" msgstr "Educação" #: src/bz-flathub-category.c:126 msgid "Learn" msgstr "Aprender" #: src/bz-flathub-category.c:126 msgid "More Education" msgstr "Mais Educação" #: src/bz-flathub-category.c:127 msgid "Gaming" msgstr "Jogos" #: src/bz-flathub-category.c:127 msgid "Play" msgstr "Jogar" #: src/bz-flathub-category.c:127 msgid "More Gaming" msgstr "Mais Jogos" #: src/bz-flathub-category.c:128 msgid "Graphics & Photography" msgstr "GrĂĄficos e Fotografia" #: src/bz-flathub-category.c:128 msgid "Create" msgstr "Criar" #: src/bz-flathub-category.c:128 msgid "More Graphics & Photography" msgstr "Mais GrĂĄficos e Fotografia" #: src/bz-flathub-category.c:129 msgid "Networking" msgstr "Conectividade" #: src/bz-flathub-category.c:129 msgid "Internet" msgstr "Comunicação" #: src/bz-flathub-category.c:129 msgid "More Networking" msgstr "Mais Comunicação" #: src/bz-flathub-category.c:130 msgid "Productivity" msgstr "Produtividade" #: src/bz-flathub-category.c:130 msgid "Work" msgstr "Trabalho" #: src/bz-flathub-category.c:130 msgid "More Productivity" msgstr "Mais Produtividade" #: src/bz-flathub-category.c:131 msgid "Science" msgstr "CiĂŞncia" #: src/bz-flathub-category.c:131 msgid "More Science" msgstr "Mais CiĂŞncia" #: src/bz-flathub-category.c:132 msgid "System" msgstr "Sistema" #: src/bz-flathub-category.c:132 msgid "More System" msgstr "Mais Sistema" #: src/bz-flathub-category.c:133 msgid "Utilities" msgstr "UtilitĂĄrios" #: src/bz-flathub-category.c:133 msgid "Tools" msgstr "Ferramentas" #: src/bz-flathub-category.c:133 msgid "More Utilities" msgstr "Mais UtilitĂĄrios" #: src/bz-flathub-category.c:134 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:148 msgid "Trending" msgstr "Em Alta" #: src/bz-flathub-category.c:134 msgid "More Trending" msgstr "Mais Em Alta" #: src/bz-flathub-category.c:135 src/bz-flathub-page.blp:122 #: src/bz-flathub-page.blp:178 msgid "Popular" msgstr "Populares" #: src/bz-flathub-category.c:135 msgid "More Popular" msgstr "Mais Populares" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:168 msgid "Recently Added" msgstr "Recentemente Adicionados" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:128 msgid "New" msgstr "Novos" #: src/bz-flathub-category.c:136 msgid "More New" msgstr "Mais Novos" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:158 msgid "Recently Updated" msgstr "Recentemente Atualizados" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:134 msgid "Updated" msgstr "Atualizados" #: src/bz-flathub-category.c:137 msgid "More Updated" msgstr "Mais Atualizados" #: src/bz-flathub-category.c:138 msgid "Mobile" msgstr "Aplicativos MĂłveis" #: src/bz-flathub-category.c:138 msgid "More Mobile" msgstr "Mais Aplicativos MĂłveis" #: src/bz-flathub-category.c:139 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:139 msgid "More Adwaita" msgstr "Mais Adwaita" #: src/bz-flathub-category.c:140 msgid "KDE Apps" msgstr "Apps KDE" #: src/bz-flathub-category.c:140 msgid "More KDE Apps" msgstr "Mais Apps KDE" #: 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:200 msgid "App of the Day" msgstr "Aplicativo do Dia" #: src/bz-flathub-page.blp:264 msgid "On the Go" msgstr "Em movimento" #: src/bz-flathub-page.blp:276 msgid "Apps for your Linux phones and tablets" msgstr "Aplicativos para seus telefones e tablets Linux" #: src/bz-flathub-page.blp:287 src/bz-flathub-page.blp:322 msgid "More Mobile Apps" msgstr "Mais Aplicativos MĂłveis" #: src/bz-flathub-page.blp:378 msgid "We​ ♥​ Games" msgstr "NĂłs♥Jogos" #: src/bz-flathub-page.blp:391 msgid "Games and apps to run your favorite titles" msgstr "Jogos e aplicativos para rodar seus tĂ­tulos favoritos" #: src/bz-flathub-page.blp:425 msgid "More Games" msgstr "Mais Jogos" #: src/bz-full-view.blp:34 src/bz-library-page.blp:78 #: src/bz-library-page.blp:82 msgid "No Results" msgstr "Sem Resultados" #: src/bz-full-view.blp:35 msgid "Try a different search query" msgstr "Tente outro termo de pesquisa" #: src/bz-full-view.blp:41 msgid "Content" msgstr "ConteĂşdo" #: src/bz-full-view.blp:105 msgid "" "This is a local preview, some details may differ from the published listing" msgstr "" "Esta ĂŠ uma prĂŠ-visualização local, alguns detalhes podem estar diferentes da " "listagem publicada" #: src/bz-full-view.blp:108 msgid "Preview Store Appearance" msgstr "Pre-visualizar AparĂŞncia da Loja" #: src/bz-full-view.blp:234 msgid "_Support" msgstr "_Apoiar" #: src/bz-full-view.blp:454 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:541 msgid "Trash Data" msgstr "Deletar dados" #: src/bz-full-view.blp:681 msgid "Tags:" msgstr "Etiquetas:" #: src/bz-full-view.c:180 msgid "No URL" msgstr "Sem URL" #: src/bz-full-view.c:198 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:199 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:206 msgid "More Apps" msgstr "Mais Aplicativos" #: src/bz-full-view.c:207 #, c-format msgid "More Apps by %s" msgstr "Mais Aplicativos de %s" #: src/bz-full-view.c:214 msgid "Other Apps by this Developer" msgstr "Outros Aplicativos Deste Desenvolvedor" #: src/bz-full-view.c:216 src/bz-full-view.c:315 #, c-format msgid "Other Apps by %s" msgstr "Outros Aplicativos de %s" #: src/bz-full-view.c:225 #, 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:317 msgid "Other Apps" msgstr "Outros Aplicativos" #: src/bz-full-view.c:319 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d Aplicativo" msgstr[1] "%d Aplicativos" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Suporte a Hardware" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Suporte a Teclado" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Precisa de teclado" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Teclado recomendado" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Suporta teclados" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Suporte a teclado desconhecido" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Suporte a mouse" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Precisa de mouse ou dispositivo de indicação" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Recomenda mouse ou dispositivo de indicação" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Suporta mouse ou dispositivo de indicação" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Suporte para mouses ou dispositivos de indicação desconhecido" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Suporte a tela sensĂ­vel ao toque" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Precisa de tela sensĂ­vel ao toque" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Recomenda tela sensĂ­vel ao toque" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Suporta tela sensĂ­vel ao toque" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Suporte a telas sensĂ­veis ao toque 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 dispositivos mĂłveis" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Talvez nĂŁo funcione bem em dispositivos mĂłveis" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Suporte a Desktop" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Funciona bem em telas grandes" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s funciona melhor em hardwares especĂ­ficos" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s funciona na maioria dos dispositivos" #: src/bz-install-controls.blp:62 msgid "_Open" msgstr "_Abrir" #: src/bz-install-controls.blp:77 src/bz-install-controls.blp:134 msgid "Uninstall Application" msgstr "Desinstalar Aplicativo" #: src/bz-install-controls.blp:87 src/bz-transaction-dialog.c:230 msgid "_Remove" msgstr "_Remover" #: src/bz-install-controls.blp:121 src/bz-updates-card.c:161 #: src/bz-updates-card.c:180 msgid "Update" msgstr "Atualizar" #: src/bz-install-controls.blp:144 src/bz-installed-tile.blp:114 msgid "Remove" msgstr "Remover" #: src/bz-library-page.blp:32 msgid "Search installed apps" msgstr "Pesquisar apps instalados" #: src/bz-library-page.blp:50 msgid "Clear search" msgstr "Limpar pesquisa" #: src/bz-library-page.blp:71 msgid "No Apps Found" msgstr "Nenhum App Encontrado" #: src/bz-library-page.blp:90 msgid "Search Store Instead" msgstr "Tentar Pesquisar na Loja" #. Translators: . #: src/bz-library-page.blp:100 src/bz-window.blp:111 msgid "Library" msgstr "Biblioteca" #: src/bz-library-page.blp:128 msgid "Pending Updates" msgstr "Atualizaçþes pendentes" #: src/bz-library-page.blp:155 msgid "Downloads" msgstr "Downloads" #: src/bz-library-page.blp:198 msgid "Recently Uninstalled" msgstr "Recentemente Desinstalado" #: src/bz-library-page.blp:249 msgid "Clear Finished Tasks" msgstr "Limpar Tarefas Finalizadas" #: src/bz-library-page.blp:334 msgid "Sort By" msgstr "Ordenar Por" #: src/bz-library-page.blp:348 msgid "Name" msgstr "Nome" #: src/bz-library-page.blp:354 msgid "Size" msgstr "Tamanho" #: src/bz-library-page.c:180 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "Nenhum resultado encontrado para \"%s\" na lista de apps instalados" #: src/bz-library-page.c:193 src/bz-updates-card.c:426 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u Atualização DisponĂ­vel" msgstr[1] "%u Atualizaçþes DisponĂ­veis" #: src/bz-library-page.c:203 #, c-format msgid "%u Installed App" msgid_plural "%u Installed Apps" msgstr[0] "%u Apps Instalados" msgstr[1] "%u Apps Instalados" #: src/bz-license-dialog.blp:94 msgid "Get Involved" msgstr "Envolva-se" #: src/bz-license-dialog.blp:111 msgid "Learn More" msgstr "Aprender Mais" #: src/bz-license-dialog.c:127 msgid "Unknown License" msgstr "Licença Desconhecida" #: src/bz-license-dialog.c:130 msgid "Community Built" msgstr "Feito pela Comunidade" #: src/bz-license-dialog.c:203 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 app ĂŠ desenvolvido em aberto por uma comunidade internacional.\n" "\n" "VocĂŞ pode participar e ajudar a tornĂĄ-lo ainda melhor." #: src/bz-license-dialog.c:206 msgid "The license of this app is not known" msgstr "A licença deste app ĂŠ desconhecida" #: src/bz-license-dialog.c:212 #, 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 app ĂŠ 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:220 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 app 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 app." #: src/bz-license-dialog.c:226 #, 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 app ĂŠ desenvolvido sob a licença especial %s.\n" "\n" "VocĂŞ talvez nĂŁo possa contribuir para este aplicativo." #: src/bz-license-dialog.c:356 src/bz-safety-dialog.blp:53 msgid "License" msgstr "Licença" #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Conectar-se ao Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Algo Deu Errado" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" "Connect sua conta do Flathub ao Bazaar para gerenciar seus apps favoritos." #: src/bz-login-page.blp:110 msgid "Finish" msgstr "Finalizar" #: src/bz-login-page.c:664 #, c-format msgid "Hello, %s!" msgstr "OlĂĄ, %s!" #: src/bz-metainfo-preview.c:84 msgid "Select Metainfo File" msgstr "Selecionar Arquivo de Metainfo" #: src/bz-metainfo-preview.c:87 msgid "Metainfo Files" msgstr "Arquivos de Metainfo" #: src/bz-metainfo-preview.c:141 msgid "Select Icon (Optional)" msgstr "Selecionar Ícone (Opcional)" #: src/bz-metainfo-preview.c:144 msgid "Image Files" msgstr "Arquivos de Imagem" #: src/bz-metainfo-preview.c:231 msgid "Preview" msgstr "PrĂŠ-visualizar" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "PreferĂŞncias" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data refresh is paused" msgstr "" "Sua conexĂŁo ĂŠ limitada — atualização automĂĄtica de dados da loja pausada" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:258 msgid "Refresh Manually" msgstr "Atualizar Manualmente" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Filtros de ConteĂşdo" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Somente Software Livre" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "" "Ocultar aplicaçþes proprietĂĄrias dos resultados de navegação e pesquisa" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Somente Resultados do Flathub" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Limitar resultados de navegação e pesquisa Ă s aplicaçþes disponĂ­veis no " "Flathub" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "Somente Resultados Verificados" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Ocultar resultados que nĂŁo sĂŁo verificados no Flathub" #: src/bz-preferences-dialog.blp:49 msgid "Hide End-of-Life Apps" msgstr "Ocultar Aplicativos 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 nĂŁo sĂŁo mais suportados por seus desenvolvedores" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:126 msgid "Search" msgstr "Pesquisa" #: 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 resultados de performance utilizando debouncing nos termos " "pesquisados" #: 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 "Listras 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 "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 "Male Homosexual Pride Colors" msgstr "Cores do Orgulho Homossexual Masculino" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Cores do Orgulho TransgĂŞnero" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Cores do Orgulho NĂŁo BinĂĄrio" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "Cores do Orgulho Bisexual" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "Cores do Orgulho Asexual" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Cores do Orgulho Pansexual" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Cores do Orgulho Arromântico" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Cores do Orgulho GĂŞnero FluĂ­do" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Cores do Orgulho Polissexual" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Cores do Orgulho Omnissexual" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "Cores do Orgulho Aroace" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "Cores do Orgulho AgĂŞnero" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "Cores do Orgulho Genderqueer" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "Cores do Orgulho Intersexo" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "Cores do Orgulho DemigĂŞnero" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "Cores do Orgulho Birromântico" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "Cores do Orgulho da DeficiĂŞncia" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "Cores do Orgulho Femboy" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "Cores do Orgulho Neutrois" #: src/bz-releases-dialog.blp:5 src/bz-updates-card.c:152 msgid "Version History" msgstr "HistĂłrico de VersĂŁo" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "_HistĂłrico de VersĂŁo" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "Hoje" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "Ontem" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "HĂĄ %d dia" msgstr[1] "HĂĄ %d dias" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "HĂĄ %d semana" msgstr[1] "HĂĄ %d semanas" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "HĂĄ %d mĂŞs" msgstr[1] "HĂĄ %d meses" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "HĂĄ %d ano" msgstr[1] "HĂĄ %d anos" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%e %B %Y" #: src/bz-releases-list.c:196 #, c-format msgid "Version %s" msgstr "VersĂŁo %s" #: src/bz-releases-list.c:251 msgid "No details for this release" msgstr "NĂŁo hĂĄ detalhes para este lançamento" #: src/bz-releases-list.c:263 msgid "Get More Information" msgstr "Obter mais informaçþes" #: src/bz-rich-app-tile.blp:157 msgid "Get" msgstr "Obter" #: src/bz-rich-app-tile.blp:185 src/bz-transaction-tile.blp:296 msgid "Open" msgstr "Abrir" #: src/bz-safety-calculator.c:82 msgid "Unknown Permissions" msgstr "PermissĂľes Desconhecidas" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "EstĂŁo faltando permissĂľes para este app." #: src/bz-safety-calculator.c:96 msgid "No Permissions" msgstr "Sem PermissĂľes" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "O app ĂŠ completamente isolado" #: 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 acessar a internet" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "Sem Acesso Ă  Rede" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "NĂŁo pode acessar a internet" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "Acesso a Dispositivos de UsuĂĄrio" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "Pode acessar dispositivos como webcams ou controles de jogos" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "Sem Acesso a Dispositivos de UsuĂĄrio" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "NĂŁo pode acessar dispositivos como webcams ou controles de jogos" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "Acesso a Dispositivos de Entrada" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "Pode acessar dispositivos de entrada" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "Acesso a Microfone e Tocar Áudio" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "Pode ouvir usando microfones e tocar ĂĄudio sem pedir permissĂŁo" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "Acesso a Dispositivo do Sistema" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "Pode acessar dispositivos do sistema que requerem permissĂľes elevadas" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "Acesso a ConteĂşdos da Tela" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "Pode acessar os conteĂşdos da tela e de outras janelas" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "Sistema de Janelas Legado" #: src/bz-safety-calculator.c:150 msgid "Always uses a legacy windowing system (X11)" msgstr "Sempre usa um sistema de janelas legado (X11)" #: src/bz-safety-calculator.c:156 msgid "Arbitrary Permissions" msgstr "PermissĂľes ArbitrĂĄrias" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "Pode adquirir permissĂľes arbitrĂĄrias" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "Configuraçþes de UsuĂĄrio" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "Pode acessar e mudar configuraçþes de usuĂĄrio" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "Acesso Total de Leitura/Escrita ao Sistema de Arquivos" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "Pode ler e escrever todos os dados no sistema de arquivos" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "Acesso de Leitura/Escrita Ă  Pasta Pessoal" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "Pode ler e escrever todos os dados na sua pasta pessoal" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "Acesso Total de Leitura ao Sistema de Arquivos" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "Pode ler todos os dados no sistema de arquivos" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "Acesso de Leitura Ă  Pasta Pessoal" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "Pode ler todos os dados na sua pasta pessoal" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "Acesso de Leitura/Escrita Ă  Pasta de Download" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "Pode ler e escrever todos os dados na sua pasta de downloads" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "Acesso de Leitura Ă  Pasta de Downloads" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "Pode ler todos os dados na sua pasta de downloads" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "Pode ler e escrever todos os dados na sua pasta de downloads" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "Pode ler todos os dados no diretĂłrio" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "Sem Acesso ao Sistema de Arquivos" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "NĂŁo pode acessar o sistema de arquivos de maneira alguma" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "Usa Serviços do Sistema" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "Pode solicitar dados de serviços do sistema que nĂŁo utilizam portais" #: 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 solicitar dados de serviços de sessĂŁo que nĂŁo utilizam portais" #: 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 acessar serviçþes de sessĂŁo ou do sistema de maneira alguma" #: src/bz-safety-calculator.c:331 msgid "Verified App Developer" msgstr "Desenvolvedor do App Verificado" #: 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 deste app foi verificado e ĂŠ quem diz ser" #: src/bz-safety-calculator.c:341 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, entĂŁo nĂŁo pode ser auditado independentemente " "e pode ser inseguro" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "CĂłdigo 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 "" "O cĂłdigo fonte ĂŠ pĂşblico e pode ser auditado independentemente, o que torna " "o app potencialmente seguro" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "Usa o Serviço do Sistema %s" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "Usa a 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 serviços que nĂŁo usam portais" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "Pode se comunicar com serviços que nĂŁo utilizam portais" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "Pode ter um serviço que nĂŁo utiliza portais" #: src/bz-safety-calculator.c:530 msgid "Global Menu Integration" msgstr "Integração de Menu Global" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "Pode mostrar seus menus em uma menu de barra global" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "Integração de Configuraçþes do KDE" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "Pode detectar quando configuraçþes do desktop KDE mudam" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "Configuraçþes Globais do KDE" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "Pode ler preferĂŞncia do desktop KDE como fontes e cores" #: src/bz-safety-calculator.c:548 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 recuperar suas prĂłprias senhas usando o keyring do sistema" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "Serviço de Notificaçþes do Desktop" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "Pode mandar notificaçþes de desktop" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "Integração com a Bandeja do Sistema" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "Pode mostrar um Ă­cone na bandeja do sistema" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "Integração com KDE Connect" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "Pode interagir com dispositivos pareados via KDE Connect" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "Segurança" #: src/bz-safety-dialog.blp:63 msgid "App ID" msgstr "ID do App" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:104 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 "" "Este app utiliza uma versĂŁo desatualizada da plataforma de software (SDK) e " "pode conter bugs ou vunerabilidades de segurança que talvez nĂŁo estejam " "consertadas." #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "%s ĂŠ Seguro" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s nĂŁo possui PermissĂľes Inseguras" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "%s ĂŠ Provavelmente Seguro" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s ĂŠ Possivelmente Inseguro" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "%s ĂŠ Inseguro" #: 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:150 msgid "Reset View" msgstr "Redefinir Visualização" #: src/bz-screenshot-page.blp:161 msgid "Zoom Out" msgstr "Diminuir Zoom" #: src/bz-screenshot-page.blp:171 msgid "Zoom In" msgstr "Aumentar Zoom" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Carrossel de Capturas de Tela" #: src/bz-screenshots-carousel.blp:117 msgid "Open Screenshot Viewer" msgstr "Abrir Visualizador de Imagens" #: src/bz-search-filter-popover.blp:18 src/bz-search-page.blp:83 msgid "Filters" msgstr "Filtros" #: src/bz-search-filter-popover.blp:35 msgid "_Verified" msgstr "_Verificado" #: src/bz-search-filter-popover.blp:42 msgid "_Free/Open" msgstr "_Livre/Aberto" #: src/bz-search-filter-popover.blp:49 msgid "Non-_EOL" msgstr "NĂŁo-_EOL" #: src/bz-search-filter-popover.blp:52 msgid "Filter out End-of-Life apps" msgstr "Filtrar apps em fim-de-vida (EOL)" #: src/bz-search-filter-popover.blp:57 msgid "Categories" msgstr "Catergorias" #: src/bz-search-page.blp:58 msgid "Search Apps, Games, Software" msgstr "Pesquisar Apps, Jogos e Softwares" #: src/bz-search-page.blp:70 msgid "Search Filters" msgstr "Filtros de Pesquisa" #: src/bz-search-page.blp:100 msgid "Clear Search" msgstr "Limpar Pesquisa" #: src/bz-search-page.blp:192 msgid "Categories Unavailable" msgstr "Atualizaçþes IndisponĂ­veis" #: src/bz-search-page.blp:193 msgid "Search for apps using the search bar above." msgstr "Pesquise apps utilizando a barra de pesquisa acima." #: src/bz-search-page.blp:219 msgid "Browse Categories" msgstr "Navegar por Categorias" #: src/bz-search-page.blp:361 msgid "No Applications Found" msgstr "Nenhuma Aplicação Encontrada" #: src/bz-search-page.c:247 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Sem resultados para \"%s\" no Flathub" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "VĂ­deo" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "Produtividade" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "CalendĂĄrio" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "Mensagens" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Paint" msgstr "Pintura" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "Torrent" msgstr "Torrent" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Emulator" msgstr "Emuladores" #: src/bz-share-list.c:123 msgid "Copy Link" msgstr "Copiar Link" #: src/bz-share-list.c:134 msgid "Open Link" msgstr "Abrir Link" #: src/bz-stats-dialog.blp:27 msgid "Timeline" msgstr "Linha do tempo" #: src/bz-stats-dialog.blp:45 msgid "Installs:" msgstr "Instalaçþes:" #: src/bz-stats-dialog.blp:54 msgid "World" msgstr "Mundo" #: src/bz-stats-dialog.blp:68 msgid "Since 4/15/2024" msgstr "Desde 15/04/2024" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:125 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM de Instalaçþes Totais" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:128 #, c-format msgid "%.2fK Total Installs" msgstr "%.2fK de Instalaçþes Totais" #: src/bz-stats-dialog.c:130 #, c-format msgid "%'d Total Installs" msgstr "%'d de Instalaçþes Totais" #: src/bz-tag-list.c:78 msgid "No Results Found" msgstr "Nenhum Resultado Encontrado" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Aplicativos com a etiqueta \"%s\"" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "A pesquisa falhou" #: src/bz-transaction-dialog.c:154 msgid "Keep User Data" msgstr "Manter Dados de UsuĂĄrio" #: src/bz-transaction-dialog.c:155 msgid "Allow restoring personal settings & content" msgstr "Habilitar restauração de configuraçþes pessoais & conteĂşdos" #: src/bz-transaction-dialog.c:164 msgid "Delete All Data" msgstr "Excluir Todos os Dados" #: src/bz-transaction-dialog.c:165 msgid "Permanently erase user data to save space" msgstr "Remover permanentemente dados de usuĂĄrio para liberar espaço" #: src/bz-transaction-dialog.c:190 #, c-format msgid "Install %s?" msgstr "Instalar %s?" #: src/bz-transaction-dialog.c:195 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Selecione qual versĂŁo para instalar. Talvez haja a instalação de componente " "compartilhados adicionais" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "Pode instalar componentes compartilhados adicionais" #: src/bz-transaction-dialog.c:200 src/bz-transaction-dialog.c:229 #: src/bz-transaction-dialog.c:274 src/bz-transaction-dialog.c:576 msgid "_Cancel" msgstr "_Cancelar" #: src/bz-transaction-dialog.c:201 msgid "_Install" msgstr "_Instalar" #: src/bz-transaction-dialog.c:218 #, c-format msgid "Remove %s?" msgstr "Remover %s?" #: src/bz-transaction-dialog.c:221 msgid "Select which version to remove." msgstr "Selecione qual versĂŁo para remover." #: src/bz-transaction-dialog.c:223 #, 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-transaction-dialog.c:246 #, c-format msgid "“%s” is High Risk" msgstr "\"%s\" ĂŠ de Alto Risco" #: src/bz-transaction-dialog.c:250 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 "" "Este app possui acesso total ao seu sistema, incluindo todos os seus " "arquivos, histĂłrico de navegação, senhas salvas e mais. TambĂŠm possui " "acesso Ă  internet, o que significa que tambĂŠm pode enviar seus dados para " "terceiros.\n" "\n" "Por este app ser proprietĂĄrio, nĂŁo ĂŠ possĂ­vel auditar o que faz com estas " "permissĂľes." #: src/bz-transaction-dialog.c:259 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 "" "Este app utiliza o sistema de janelas legado X11, o qual permite gravar " "todas as teclas pressionadas, capturar tela e monitorar outros " "aplicativos. TambĂŠm possui acesso Ă  internet, o que significa que tambĂŠm " "pode enviar os seus dados para terceiros.\n" "\n" "Por este app ser proprietĂĄrio, nĂŁo ĂŠ possĂ­vel auditar o que faz com estas " "permissĂľes." #: src/bz-transaction-dialog.c:275 msgid "_Install Anyway" msgstr "_Instalar de Qualquer Maneira" #: src/bz-transaction-dialog.c:330 msgid "Failed to load transaction dialog" msgstr "Falha ao carregar o diĂĄlogo de transação" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "Todos os apps jĂĄ estĂŁo instalados" #: 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] "Instalar Aplicativo %u?" msgstr[1] "Instalar Aplicativos %u?" #: src/bz-transaction-dialog.c:573 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" "Os seguintes aplicativos serĂŁo instalados. Componentes compartilhados " "adicionais tambĂŠm podem ser instalados" #: src/bz-transaction-dialog.c:574 #, c-format msgid "%d addons will be installed." msgstr "%d addons serĂŁo instalados." #: src/bz-transaction-dialog.c:575 msgid "Additionally, addons will be installed." msgstr "Adicionalmente, %d addons serĂŁo instalados." #: src/bz-transaction-dialog.c:577 msgid "_Install All" msgstr "_Instalar Todos" #: src/bz-transaction-manager.c:784 #, c-format msgid "Finished in %.02f seconds" msgstr "ConcluĂ­do em %.02f segundos" #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "ExtensĂľes do App" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "Runtime" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "Em Fila" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "ConcluĂ­do" #: src/bz-transaction-tile.blp:230 msgid "Cancelled" msgstr "Cancelado" #: src/bz-transaction-tile.blp:254 msgid "Error" msgstr "Erro" #: src/bz-transaction-tile.blp:310 msgid "Cancel Transaction" msgstr "Cancelar Transação" #: src/bz-transaction-tile.blp:434 msgid "Show Error Info" msgstr "Mostrar Informaçþes do Erro" #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "%s Liberados" #: src/bz-transaction-tile.c:360 src/bz-transaction-tile.c:363 msgid "Transaction Error" msgstr "Erro de Transação" #: src/bz-transaction.c:344 msgid "Pending" msgstr "Pendente" #: src/bz-updates-card.blp:22 msgid "_Update All" msgstr "_Atualizar Todos" #: src/bz-updates-card.c:208 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "%u Atualização de Runtime" msgstr[1] "%u Atualizaçþes de Runtime" #: 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:33 msgid "No User Data Found" msgstr "Nenhum Dado de UsuĂĄrio Encontrado" #: src/bz-user-data-page.blp:38 msgid "User Data" msgstr "Dados de UsuĂĄrio" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Apagar Dados de UsuĂĄrio" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "Apagar Dados de UsuĂĄrio de %s" #: src/bz-window.blp:87 msgid "Curated" msgstr "Recomendados" #: src/bz-window.blp:99 msgid "Explore" msgstr "Exporar" #: src/bz-window.blp:219 msgid "Refresh completed!" msgstr "Atualização completa!" #: src/bz-window.blp:238 msgid "Main Menu" msgstr "Menu Principal" #: src/bz-window.blp:249 msgid "You are running a new version of Bazaar!" msgstr "VocĂŞ estĂĄ utilizando a nova versĂŁo do Bazaar!" #: src/bz-window.blp:250 msgid "See What's New" msgstr "Veja O Que HĂĄ de Novo" #: src/bz-window.blp:257 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:302 msgid "_Donate to Bazaar" msgstr "_Doar para o Bazaar" #: src/bz-window.blp:309 msgid "_Refresh" msgstr "_Atualizar" #: src/bz-window.blp:314 msgid "_Preferences" msgstr "_PreferĂŞncias" #: src/bz-window.blp:319 msgid "_Login With Flathub" msgstr "_Entrar com Flathub" #: src/bz-window.blp:325 msgid "_Manage Leftover User Data" msgstr "_Gerenciar Dados de UsuĂĄrio Restantes" #: src/bz-window.blp:330 msgid "_Keyboard Shortcuts" msgstr "_Atalhos de Teclado" #: src/bz-window.blp:335 msgid "_About Bazaar" msgstr "_Sobre o Bazaar" #: src/bz-window.blp:342 msgid "_Quit Bazaar" msgstr "_Sair do Bazaar" #: src/bz-window.blp:367 msgid "Log Out" msgstr "Desconectar" #. Translators: %s is the title of the current page #: src/bz-window.c:377 #, c-format msgid "Bazaar — %s" msgstr "Bazaar — %s" #: src/bz-window.c:586 src/bz-window.c:624 msgid "Failed to launch application" msgstr "Falha ao iniciar a aplicação" #: src/bz-window.c:825 msgid "You can't remove Bazaar from Bazaar!" msgstr "VocĂŞ nĂŁo pode remover o Bazaar pelo Bazaar!" #: src/bz-window.c:1110 src/bz-window.c:1144 msgid "Can't do that right now!" msgstr "NĂŁo ĂŠ possĂ­vel fazer isso agora!" #: src/bz-world-map.c:603 msgctxt "As in, \"100 Installs\"" msgid "Installs" msgstr "Instalaçþes" #: src/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Geral" #: src/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Page" msgstr "Abrir PĂĄgina de Pesquisa" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "Abrir PĂĄgina da Biblioteca" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Refresh" msgstr "Atualizar" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Abrir PreferĂŞncias" #: src/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Mostrar Atalhos" #: src/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Close Window" msgstr "Fechar Janela" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "Sair do Bazaar" #~ msgid "_Donate to Bazaar ❤️" #~ msgstr "_Doar para o Bazaar ❤️" #~ msgid "Open App Library" #~ msgstr "Abrir Biblioteca de Apps" #~ msgid "Installing .flatpak bundles is not yet supported" #~ msgstr "Instalar bundles .flatpak ainda nĂŁo ĂŠ suportado" #~ msgid "Steam" #~ msgstr "Steam" #~ msgid "Minecraft" #~ msgstr "Minecraft" #~ msgid "Flathub" #~ msgstr "Flathub" #~ 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." #~ msgid "_Synchronize Remotes" #~ msgstr "_Sincronizar RepositĂłrios" #~ msgid "Adam Masciola" #~ msgstr "Adam Masciola" #~ msgid "Synchronizing..." #~ msgstr "Sincronizando..." #, c-format #~ msgid "Receiving %d entries..." #~ msgstr "Obtendo %d entradas" #~ msgid "Indexing Data..." #~ msgstr "Indexando Dados..." #~ msgid "View the Release Page" #~ msgstr "Visualizar PĂĄgina de Lançamento" #~ msgid "Close" #~ msgstr "Fechar" #~ msgid "Copy and Close" #~ msgstr "Copiar e Fechar" #~ msgid "Download & Install Application" #~ msgstr "Baixar & Instalar Aplicativo" #~ msgid "Install Other Version" #~ msgstr "Instalar Outra VersĂŁo" #~ msgid "Keep Data" #~ msgstr "Manter Dados" #~ msgid "Open App" #~ msgstr "Abrir App" #~ msgid "Refreshing Store Content" #~ msgstr "Recarregando o ConteĂşdo da Loja" #~ msgid "No background tasks!" #~ msgstr "Sem atividades em segundo plano!" #~ msgctxt "As in, \"100 Downloads\"" #~ msgid "Downloads" #~ msgstr "Downloads" #~ msgctxt "shortcut window" #~ msgid "Synchronize Remotes" #~ msgstr "Sincronizar RepositĂłrios" #~ msgctxt "shortcut window" #~ msgid "Quit" #~ msgstr "Sair" #~ msgid "Nucleus app page" #~ msgstr "PĂĄgina do aplicativo Nucleus" #~ msgid "Toggle transaction sidebar" #~ msgstr "Alternar barra lateral de transaçþes" #~ msgid "Install Size" #~ msgstr "Tamanho da Instalação" #, fuzzy #~ msgid "Finished" #~ msgstr "Tarefas finalizadas" #, c-format #~ msgid "Transferred %s so far" #~ msgstr "%s transferidos atĂŠ agora" #, 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" #~ msgid "Updates Are Available" #~ msgstr "Atualizaçþes EstĂŁo DisponĂ­veis" #~ 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?" #, 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?" #, c-format #~ msgid "Additionally, %d runtimes and/or addons will be updated." #~ msgstr "Adicionalmente, %d runtimes e/ou extensĂľes serĂŁo atualizados." #~ msgid "Update Now" #~ msgstr "Atualizar Agora" #~ msgctxt "shortcut window" #~ msgid "Toggle Transaction Manager" #~ msgstr "Alternar Gerenciador de Transaçþes" # https://pt.wikipedia.org/wiki/Fim_de_vida_(produto) #~ msgid "Hide EOL Entries" #~ msgstr "Esconder entradas em fim de vida (EOL)" # https://pt.wikipedia.org/wiki/Fim_de_vida_(produto) #~ msgid "Hide EOL entries and entries depending on them" #~ msgstr "Esconder entradas em fim de vida (EOL) e entradas dependentes delas" #~ msgid "Show Git Forge Star Counts" #~ msgstr "Exibir a contagem de estrelas de plataformas Git" #~ 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" #~ msgid "Only Show Free Software" #~ msgstr "Mostrar apenas softwares livres" #~ msgid "Hide proprietary software" #~ msgstr "Ocultar softwares proprietĂĄrios" #~ msgid "Show Only Flathub Content" #~ msgstr "Mostrar Apenas ConteĂşdos do Flathub" #~ msgid "Debounce Search Inputs" #~ msgstr "Entrada de Pesquisa com Atraso" #~ 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" #~ msgid "Global Progress Bar Theme" #~ msgstr "Tema da Barra de Progresso Global" #~ msgid "Describes the look of the global progress bar" #~ msgstr "Descreve a aparĂŞncia da barra de progresso global" #~ msgid "Saved Window Dimensions" #~ msgstr "DimensĂľes da Janela Salvas" #~ 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" #~ msgid "?" #~ msgstr "?" #, c-format #~ msgid "%s is suitable for toddlers" #~ msgstr "%s ĂŠ adequado para crianças de um a trĂŞs anos" #~ msgid "--- MB" #~ msgstr "--- MB" #~ msgid "Of the size of human DNA" #~ msgstr "Do tamanho do DNA humano" #~ msgid "3 billion base pairs" #~ msgstr "3 bilhĂľes de pares de bases" #~ msgid "Of the Linux Kernel" #~ msgstr "Do Kernel Linux" #~ msgid "linux-6.17.tar.xz" #~ msgstr "linux-6.17.tar.xz" #~ msgid "Of the Apollo 11 guidance computer" #~ msgstr "Do computador de orientação da Apollo 11" #~ msgid "Total ROM and RAM" #~ msgstr "Total de ROM e RAM" #~ msgid "Of the original Super Mario Bros" #~ msgstr "Do Super Mario Bros original" #~ msgid "On the NES" #~ msgstr "No NES" #~ msgid "Of the size of Wikipedia" #~ msgstr "Do tamanho da Wikipedia" #~ msgid "Without any media" #~ msgstr "Sem nenhuma mĂ­dia" #~ 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." #~ msgid "Entry Inspector" #~ msgstr "Inspetor de entrada" #~ msgid "Serialize" #~ msgstr "Serializar" #~ msgid "Convert to JSON" #~ msgstr "Converter para JSON" #~ msgid "More Mobile apps" #~ msgstr "Mais Aplicativos MĂłveis" #~ msgid "Repository Star Count" #~ msgstr "Contagem de Estrelas do RepositĂłrio" #~ msgid "Bazaar Inspector" #~ msgstr "Inspetor do Bazaar" #~ msgid "Enable Global Debug Mode" #~ msgstr "Habilitar Modo de Depuração Global" #~ msgid "Active Blocklists" #~ msgstr "Listas de Bloqueio Ativas" #~ msgid "Active Curated-Configs" #~ msgstr "Configuraçþes de Listas Recomendadas Ativas" #~ msgid "All Entry Groups" #~ msgstr "Todos os Grupos de Entradas" #~ msgid "Decache and Inspect" #~ msgstr "Limpar Cache e Inspecionar" #~ msgid "No Flatpaks Installed" #~ msgstr "Sem Flatpaks Instalados" #~ msgid "Application Details" #~ msgstr "Detalhes do Aplicativo" #~ msgid "Display Star Count" #~ msgstr "Mostrar Contagem de Estrelas" #~ 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" #~ 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." #~ msgid "Inspect UI Entry" #~ msgstr "Inspecionar Entrada de UI" #~ msgid "All Debug Actions" #~ msgstr "Depurar todas as açþes" #~ msgid "Tasks" #~ msgstr "Tarefas" #~ msgid "Stop Active Tasks" #~ msgstr "Parar Tarefas Ativas" #~ msgid "No Tasks Yet" #~ msgstr "Nenhuma Tarefa Ainda" #~ msgid "Open Bazaar Inspector" #~ msgstr "Abrir Inspetor 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 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." #~ msgid "Resume Current Tasks" #~ msgstr "Retomar Tarefas Atuais" #~ msgid "Pause Current Tasks" #~ msgstr "Pausar Tarefas Atuais" #, c-format #~ msgid "%s: %'u downloads" #~ msgstr "%s: %'u downloads" #~ 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" #~ 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 "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" #~ msgstr "%-d de %B" #~ msgid "Run this application" #~ msgstr "Executar este aplicativo" #~ msgid "Run" #~ msgstr "Executar" #~ 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 "Browse" #~ msgstr "Navegar" #~ 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 "_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 "Show Downloads Over Time" #~ msgstr "Mostrar downloads ao longo do tempo" #~ msgid "Remote repo name" #~ msgstr "Nome do repositĂłrio remoto" #~ 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 "Halt the execution of transactions" #~ msgstr "Interromper a execução das transaçþes" #~ 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" #, 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" #, 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 "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" bazaar-org-bazaar-43ce9f7/po/pt_PT.po000066400000000000000000002564241520414637400174520ustar00rootroot00000000000000# 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" bazaar-org-bazaar-43ce9f7/po/ru.po000066400000000000000000003226461520414637400170520ustar00rootroot00000000000000# 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-05-21 11:03+0700\n" "PO-Revision-Date: 2026-05-22 22:57+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 50.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:45 #: src/bz-window.blp:199 src/bz-window.c:373 src/bz-window.c:374 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:16 msgid "New Window" msgstr "Новое ОкнО" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and manage applications" msgstr "Поиск и управление приложениями" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "Быстрый и современный ПагаСин приложений для Linux с фокусом на пОиско, " "установке приложений и дОпОНнониК иС Flatpak репозиторий, в частности с " "Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "" "Добавьте несколько установок в очередь и продолжайте просматривать страницы" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "Просто просматривайте разрешения приложений" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "" "Войдите в Flathub для просмотра и управления вашиПи избранными приложениями" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "Поиск приложения напрямую с GNOME Shell" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:30 src/bz-application.c:759 msgid "The Bazaar Contributors" msgstr "Разработчики Bazaar" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "The home page displaying Flathub apps" msgstr "Главная страница, отображающая приложения Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:59 msgid "Exhibit app page" msgstr "Страница приложения Exhibit" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "Страница библиотеки" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "Страница пОиска" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "Страница категорий" #: src/bz-addon-tile.blp:64 src/bz-installed-tile.blp:55 #: src/bz-rich-app-tile.blp:141 msgid "Stopped Receiving Updates" msgstr "Прекращено получение ОйнОвНониК" #: src/bz-addon-tile.c:167 src/bz-favorites-tile.c:155 msgctxt "Install Controls" msgid "Uninstall" msgstr "Удалить" #: src/bz-addon-tile.c:169 src/bz-bundle-install-dialog.blp:126 #: src/bz-favorites-tile.c:157 src/bz-install-controls.wdgt:29 msgctxt "Install Controls" msgid "Install" msgstr "Установить" #: src/bz-addons-dialog.blp:14 src/bz-addons-dialog.blp:21 #: src/bz-addons-dialog.blp:70 src/bz-full-view.blp:583 #: src/bz-installed-tile.blp:92 msgid "Manage Add-Ons" msgstr "Управление дополнениями" #: src/bz-addons-dialog.blp:80 msgid "No Add-Ons Visible" msgstr "Нет видимых дОпОНнониК" #: src/bz-addons-dialog.blp:81 msgid "" "Your current filter preferences are hiding all known add-ons. Try adjusting " "them." msgstr "" "Ваши параметры фильтра скрывают всо известные дополнения. Попробуйте " "изменить их." #: src/bz-addons-dialog.blp:88 msgid "Add-on Page" msgstr "Страница дОпОНнониК" #: src/bz-addons-dialog.blp:202 src/bz-full-view.blp:381 msgid "Downloads/Month" msgstr "Загрузок в месяц" #: src/bz-addons-dialog.blp:229 src/bz-full-view.blp:417 msgid "Stopped Receiving Core Updates" msgstr "Прекращено получение основных ОйнОвНониК" #: src/bz-addons-dialog.blp:243 msgid "" "This add-on uses a runtime that no longer receives updates or security " "fixes. It may become unsafe to use." msgstr "" "Это дОпОНнонио использует среду выполнения, которая больше но получает " "обновления иНи исправления ОшийОк безопасности. Оно может стать небезопасным " "для использования." #: src/bz-addons-dialog.c:333 #, c-format msgid "Add-on for %s" msgstr "Дополнение Đş %s" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show Less" msgstr "Показать меньше" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:600 msgid "Show More" msgstr "Показать больше" #: src/bz-addons-dialog.c:397 msgid "Download Stats" msgstr "Статистика загрузок" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:736 src/bz-context-tile-callbacks.c:186 #: src/bz-context-tile-callbacks.c:193 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:686 src/bz-context-tile-callbacks.c:176 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "Все" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "%s имеет неизвестное возрастное ограничение" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "%s предназначено для всех возрастов" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "%s предназначено для маленьких детей" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "%s предназначено для детей" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "%s предназначено для подростков" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "%s предназначено для взрослых" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "%s предназначено для %s" #: src/bz-age-rating-dialog.c:862 #, c-format msgid "%s • %s" msgstr "%s • %s" #: 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:26 src/bz-app-size-dialog.blp:60 msgid "Download Size" msgstr "Размер скачивания" #: src/bz-app-size-dialog.blp:33 src/bz-app-size-dialog.blp:81 msgid "Installed Size" msgstr "Размер установки" #: src/bz-app-size-dialog.blp:61 msgid "Amount to download from the internet" msgstr "Размер скачивания иС интернета" #: src/bz-app-size-dialog.blp:82 msgid "Size on Disk" msgstr "Размер на диско" #: src/bz-app-size-dialog.blp:133 msgid "Open user data folder" msgstr "Открыть папку пользовательских данных" #: src/bz-app-size-dialog.blp:143 msgid "Your User Data" msgstr "Ваши пользовательские данные" #: src/bz-app-size-dialog.blp:144 msgid "Caches, settings, and other app data" msgstr "Кэши, настройки и другие пользовательские данные" #: src/bz-app-size-dialog.blp:165 msgid "Cache" msgstr "Кэш" #: src/bz-app-size-dialog.blp:166 msgid "Temporary cached data" msgstr "Временно кэшированные данные" #: src/bz-app-size-dialog.blp:176 msgid "Clear Cache" msgstr "Очистить кэш" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "Размер установленной среды выполнения" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "Размер скачивания среды выполнения" #: src/bz-app-size-dialog.c:220 msgid "App Size" msgstr "Размер приложения" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:105 src/bz-rich-app-tile.c:429 msgid "Verified" msgstr "Подтверждено" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-context-tile-callbacks.c:135 #: src/bz-releases-list.c:206 msgid "Installed" msgstr "Установлено" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:762 msgid "translator-credits" msgstr "Джилл Фиори , 2025, 2026" #: src/bz-application.c:772 msgid "Special Thanks" msgstr "Особая благодарность" #: src/bz-application.c:830 msgid "Logged Out Successfully!" msgstr "Выход иС аккаунта выполнен успошнО!" #: src/bz-application.c:966 msgid "Performing setup…" msgstr "Выполняется настройка…" #: src/bz-application.c:1052 msgid "Set Up System Flathub?" msgstr "Добавить системный Flathub?" #: src/bz-application.c:1055 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Системный Flathub но был дОйавНон. Bazaar требует наличия Flathub в " "системной установке Flatpak для пОиска и установки приложений.\n" "\n" "Вы пО-прежнему можете использовать Bazaar для обзора и удаления уМо " "установленных приложений." #: src/bz-application.c:1062 msgid "Set Up Flathub?" msgstr "Добавить Flathub?" #: src/bz-application.c:1065 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:1071 msgid "Later" msgstr "Позже" #: src/bz-application.c:1072 msgid "Set Up Flathub" msgstr "Добавить Flathub" #: src/bz-application.c:1408 msgid "A backend error occurred" msgstr "Произошла Ошийка бэкэнда" #: src/bz-application.c:1608 src/bz-application.c:3767 msgid "Refreshing…" msgstr "Обновление…" #: src/bz-application.c:1772 src/bz-application.c:3765 #, c-format msgid "Loading %d apps…" msgstr "Загрузка %d приложений…" #: src/bz-application.c:1825 msgid "Failed to open file" msgstr "Невозможно открыть файл" #: src/bz-application.c:1930 msgid "An initialization error occurred" msgstr "Произошла Ошийка инициализации" #: src/bz-application.c:2296 msgid "Checking for updates…" msgstr "Проверка на наличие обновлений…" #: src/bz-application.c:2352 msgid "Failed to check for updates" msgstr "Невозможно проверить на наличие ОйнОвНониК" #: src/bz-application.c:3478 msgid "Malformed Link" msgstr "Неверный формат ссылки" #: src/bz-application.c:3479 msgid "" "The link used to open this app has incorrect capitalization and may stop " "working in the future.\n" "\n" "This is most likely caused by KRunner sending incorrect app IDs" msgstr "" "В ссылке, используемой для Сапуска даннОгО приложения, допущена Ошийка в " "написании заглавных йукв, и в будущем Она может перестать работать.\n" "\n" "Скорее всогО это связано с тем, что KRunner отправляет неверные ID приложений" #: src/bz-application.c:3487 msgid "Could not find app" msgstr "Не удалось найти приложение" #: src/bz-application.c:3518 msgid "Failed to load metainfo" msgstr "Не удалось загрузить метаданные" #: src/bz-application.c:3769 msgid "Writing to cache…" msgstr "Запись в кэш…" #: src/bz-apps-page.blp:99 msgid "Show All" msgstr "Показать всо" #: src/bz-apps-page.c:237 #, c-format msgid "All \"%s\"" msgstr "Все \"%s\"" #: src/bz-apps-page.c:487 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "%d приложений" #: src/bz-bundle-install-dialog.blp:8 src/bz-bundle-install-dialog.blp:14 msgid "Bundle Installation" msgstr "Установка пакета" #: src/bz-bundle-install-dialog.blp:147 msgid "Additional dependencies may take extra space" msgstr "Дополнительные зависимости могут занять дополнительное место" #: src/bz-bundle-install-dialog.blp:181 msgid "" "Installing this app may require adding a new software source. Other apps " "from this source will show up in Bazaar.\n" "\n" "Only add this source if you're sure you trust it." msgstr "" "Установка даннОгО приложения может потребовать добавления нОвОгО " "репозитория. Другие приложения иС этого источника будут отображаться в " "Bazaar.\n" "\n" "Добавляйте данный репозиторий только в том случае, осНи доверяете оПу." #: src/bz-bundle-install-dialog.blp:357 msgid "Successfully Installed!" msgstr "УспошнО установлено!" #: src/bz-bundle-install-dialog.blp:381 src/bz-bundle-install-dialog.blp:463 #: src/bz-rich-app-tile.blp:198 src/bz-transaction-tile.blp:298 msgid "Open" msgstr "Открыть" #: src/bz-bundle-install-dialog.blp:391 src/bz-bundle-install-dialog.blp:473 msgid "Show App Details" msgstr "Показать детали приложения" #: src/bz-bundle-install-dialog.blp:440 msgid "Already Installed" msgstr "УМо установлено" #: src/bz-bundle-install-dialog.blp:485 msgid "Installation Failed" msgstr "Ошибка установки" #: src/bz-bundle-install-dialog.c:169 msgid "Unknown install size" msgstr "Неизвестный размер установки" #: src/bz-bundle-install-dialog.c:172 #, c-format msgid "About %s to install" msgstr "Примерно %s Đş установке" #: src/bz-bundle-install-dialog.c:186 src/bz-context-tile-callbacks.c:104 #: src/bz-context-tile-callbacks.c:392 src/bz-context-tile-callbacks.c:409 msgid "N/A" msgstr "Н/Д" #: src/bz-bundle-install-dialog.c:215 msgid "No special permissions" msgstr "Нет специальных разрешений" #: src/bz-context-tile-callbacks.c:68 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-context-tile-callbacks.c:75 #, c-format msgid "%.*fM" msgstr "%.*f ПиН." #. Translators: K is the suffix for thousands #: src/bz-context-tile-callbacks.c:82 #, c-format msgid "%.*fK" msgstr "%.*f тыс." #: src/bz-context-tile-callbacks.c:92 #, c-format msgid "%d downloads in the last month" msgstr "%d загрузок Са пОсНодниК месяц" #: src/bz-context-tile-callbacks.c:132 #, c-format msgid "+%s runtime" msgstr "+%s среды выполнения" #: src/bz-context-tile-callbacks.c:135 msgid "Download" msgstr "Скачивание" #: src/bz-context-tile-callbacks.c:155 msgid "Size information unavailable" msgstr "Информация Đž размере недоступна" #: src/bz-context-tile-callbacks.c:158 #, c-format msgid "Download size of %s" msgstr "Размер скачивания %s" #: src/bz-context-tile-callbacks.c:191 msgid "All Ages" msgstr "Для всех" #: src/bz-context-tile-callbacks.c:203 msgid "Age rating information unavailable" msgstr "Информация Đž возрастном ограничении недоступна" #: src/bz-context-tile-callbacks.c:208 msgid "Suitable for all ages" msgstr "Предназначено для всех возрастов" #: src/bz-context-tile-callbacks.c:210 #, c-format msgid "Suitable for ages %d and up" msgstr "Предназначено для лиц старше %d лет" #: src/bz-context-tile-callbacks.c:243 src/bz-context-tile-callbacks.c:248 #: src/bz-context-tile-callbacks.c:276 src/bz-context-tile-callbacks.c:284 msgid "Unknown" msgstr "Неизвестно" #: src/bz-context-tile-callbacks.c:253 #, c-format msgid "Free software licensed under %s" msgstr "ХвОйОднОо программное обеспечение, лицензированное пОд %s" #: src/bz-context-tile-callbacks.c:258 msgid "Free software" msgstr "CвОйОднОо программное обеспечение" #: src/bz-context-tile-callbacks.c:261 msgid "Proprietary Software" msgstr "Проприетарное программное обеспечение" #: src/bz-context-tile-callbacks.c:264 #, c-format msgid "Special License: %s" msgstr "Специальная лицензия: %s" #: src/bz-context-tile-callbacks.c:281 msgid "Free" msgstr "ХвОйОднОо" #: src/bz-context-tile-callbacks.c:287 src/bz-license-dialog.c:133 msgid "Proprietary" msgstr "Проприетарное" #: src/bz-context-tile-callbacks.c:289 src/bz-license-dialog.c:135 msgid "Special License" msgstr "Специальная лицензия" #: src/bz-context-tile-callbacks.c:309 msgid "Adaptive" msgstr "Адаптивное" #: src/bz-context-tile-callbacks.c:309 msgid "Desktop Only" msgstr "Только для ПК" #: src/bz-context-tile-callbacks.c:315 msgid "Works on desktop, tablets, and phones" msgstr "Работает на настольных компьютерах, планшетах и телефонах" #: src/bz-context-tile-callbacks.c:316 msgid "May not work on mobile devices" msgstr "Может но работать на мобильных устройствах" #: src/bz-context-tile-callbacks.c:399 src/bz-safety-dialog.blp:27 msgid "Safe" msgstr "Безопасно" #: src/bz-context-tile-callbacks.c:401 src/bz-context-tile-callbacks.c:403 msgid "Low Risk" msgstr "Низкий риск" #: src/bz-context-tile-callbacks.c:405 msgid "Medium Risk" msgstr "Средний риск" #: src/bz-context-tile-callbacks.c:407 msgid "High Risk" msgstr "Высокий риск" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:46 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:30 #: src/bz-library-page.blp:67 src/bz-user-data-page.blp:30 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 "Нет интернета" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "Браузеры" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "Не подтверждено" #: src/bz-developer-badge.c:213 msgid "Developer information not available." msgstr "Информация Đž разработчике недоступна." #: src/bz-developer-badge.c:219 src/bz-developer-badge.c:233 #, 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:237 #, 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:253 #, 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:260 #, 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:264 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Право собственности на ID приложения %s было подтверждено." #: src/bz-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "Полные изменения выпуска" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "Этот выпуск был сдоНан благодаря таким пользователям, как Вы!" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on Ko-Fi." msgstr "" "Мне нравится делать Bazaar, нО я но ПОгу это делать в одиночку. Поддержите " "дальнейшую разработку пожертвовав средства в моём Ko-Fi." #: src/bz-donations-dialog.blp:131 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:227 #, c-format msgid "What's New in %s?" msgstr "Что нОвОгО в %s?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "Выпущено %-e %B, %Y" #: 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-rich-app-tile.blp:232 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-dialog.blp:36 src/bz-error.c:69 src/bz-error.c:88 #: src/bz-safety-dialog.blp:46 msgid "Details" msgstr "Детали" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "Скопировать" #: src/bz-error-dialog.c:56 src/bz-share-list.c:94 msgid "Copied!" msgstr "Скопировано!" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "ЧисНО избранных" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" 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-favorites-page.blp:5 src/bz-favorites-page.blp:56 #: src/bz-window.blp:334 msgid "Favorites" msgstr "Избранные" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "Установить всо" #: src/bz-favorites-page.blp:34 src/bz-user-data-page.blp:19 msgid "Loading" msgstr "Загрузка" #: src/bz-favorites-page.blp:49 msgid "No Favorites" msgstr "Нет избранных" #: src/bz-favorites-page.blp:50 msgid "Applications you mark as favorite will appear here" msgstr "Приложения помеченные как избранные будут показаны здесь" #: src/bz-favorites-tile.blp:60 src/bz-installed-tile.blp:69 msgid "Support This Application" msgstr "Поддержать это приложение" #: src/bz-favorites-tile.blp:109 msgid "Remove From Favorites" msgstr "Удалить иС избранных" #: src/bz-favorites-tile.c:353 msgid "Failed to remove favorite" msgstr "Не удалось удалить иС избранных" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Предыдущий" #: src/bz-featured-carousel.blp:54 msgid "Next" msgstr "Следующий" #: src/bz-flathub-category.c:93 msgid "Editing" msgstr "Монтаж" #: src/bz-flathub-category.c:94 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:95 msgid "Mixer" msgstr "Микшеры" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:96 src/bz-search-pill-list.c:77 msgid "Music" msgstr "Музыка" #: src/bz-flathub-category.c:97 msgid "Player" msgstr "Проигрыватели" #: src/bz-flathub-category.c:98 msgid "Recorder" msgstr "Звукозапись" #: src/bz-flathub-category.c:99 msgid "Sequencer" msgstr "Секвенсоры" #: src/bz-flathub-category.c:100 msgid "Tuner" msgstr "Тюнеры" #: src/bz-flathub-category.c:101 msgid "TV" msgstr "ТВ" #: src/bz-flathub-category.c:106 msgid "Emulation" msgstr "Эмуляторы" #: src/bz-flathub-category.c:107 msgid "Action" msgstr "Экшон" #: src/bz-flathub-category.c:108 msgid "Adventure" msgstr "Приключения" #: src/bz-flathub-category.c:109 msgid "Arcade" msgstr "Аркады" #: src/bz-flathub-category.c:110 msgid "Blocks" msgstr "Блоки" #: src/bz-flathub-category.c:111 msgid "Board" msgstr "Настольные" #: src/bz-flathub-category.c:112 msgid "Card" msgstr "Карточные" #: src/bz-flathub-category.c:113 msgid "Kids" msgstr "Для детей" #: src/bz-flathub-category.c:114 msgid "Logic" msgstr "Логические" #: src/bz-flathub-category.c:115 msgid "Role Playing" msgstr "Ролевые" #: src/bz-flathub-category.c:116 msgid "Shooter" msgstr "Шутеры" #: src/bz-flathub-category.c:117 msgid "Simulation" msgstr "Симуляторы" #: src/bz-flathub-category.c:118 msgid "Sports" msgstr "Спортивные" #: src/bz-flathub-category.c:119 msgid "Strategy" msgstr "Стратегии" #: src/bz-flathub-category.c:124 msgid "Audio & Video" msgstr "АудиО и видоО" #: src/bz-flathub-category.c:124 msgid "Media" msgstr "Медиа" #: src/bz-flathub-category.c:124 msgid "More Audio & Video" msgstr "Больше приложений для аудиО и видоО" #: src/bz-flathub-category.c:125 msgid "Developer Tools" msgstr "Инструменты разработчика" #: src/bz-flathub-category.c:125 msgid "Develop" msgstr "Разработчикам" #: src/bz-flathub-category.c:125 msgid "More Developer Tools" msgstr "Больше приложений для разработки" #: src/bz-flathub-category.c:126 msgid "Education" msgstr "Образование" #: src/bz-flathub-category.c:126 msgid "Learn" msgstr "Обучение" #: src/bz-flathub-category.c:126 msgid "More Education" msgstr "Больше образовательных приложений" #: src/bz-flathub-category.c:127 msgid "Gaming" msgstr "Игры" #: src/bz-flathub-category.c:127 msgid "Play" msgstr "Игры" #: src/bz-flathub-category.c:127 msgid "More Gaming" msgstr "Больше игр" #: src/bz-flathub-category.c:128 msgid "Graphics & Photography" msgstr "Графика и фотография" #: src/bz-flathub-category.c:128 msgid "Create" msgstr "Творение" #: src/bz-flathub-category.c:128 msgid "More Graphics & Photography" msgstr "Больше приложений для графики" #: src/bz-flathub-category.c:129 msgid "Networking" msgstr "Сеть" #: src/bz-flathub-category.c:129 msgid "Internet" msgstr "Сеть" #: src/bz-flathub-category.c:129 msgid "More Networking" msgstr "Больше сетевых приложений" #: src/bz-flathub-category.c:130 msgid "Productivity" msgstr "Продуктивность" #: src/bz-flathub-category.c:130 msgid "Work" msgstr "Работа" #: src/bz-flathub-category.c:130 msgid "More Productivity" msgstr "Больше приложений для продуктивности" #: src/bz-flathub-category.c:131 msgid "Science" msgstr "Наука" #: src/bz-flathub-category.c:131 msgid "More Science" msgstr "Больше научных приложений" #: src/bz-flathub-category.c:132 msgid "System" msgstr "Система" #: src/bz-flathub-category.c:132 msgid "More System" msgstr "Больше системных приложений" #: src/bz-flathub-category.c:133 msgid "Utilities" msgstr "Утилиты" #: src/bz-flathub-category.c:133 msgid "Tools" msgstr "Утилиты" #: src/bz-flathub-category.c:133 msgid "More Utilities" msgstr "Больше утилит" #: src/bz-flathub-category.c:134 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:148 msgid "Trending" msgstr "В тренде" #: src/bz-flathub-category.c:134 msgid "More Trending" msgstr "Больше трендовых" #: src/bz-flathub-category.c:135 src/bz-flathub-page.blp:122 #: src/bz-flathub-page.blp:178 msgid "Popular" msgstr "Популярное" #: src/bz-flathub-category.c:135 msgid "More Popular" msgstr "Больше популярных" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:168 msgid "Recently Added" msgstr "Недавно добавленные" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:128 msgid "New" msgstr "Новое" #: src/bz-flathub-category.c:136 msgid "More New" msgstr "Больше нОвинОк" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:158 msgid "Recently Updated" msgstr "Недавно обновленные" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:134 msgid "Updated" msgstr "Обновлённые" #: src/bz-flathub-category.c:137 msgid "More Updated" msgstr "Больше обновленных" #: src/bz-flathub-category.c:138 msgid "Mobile" msgstr "Мобильные" #: src/bz-flathub-category.c:138 msgid "More Mobile" msgstr "Больше мобильных приложений" #: src/bz-flathub-category.c:139 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:139 msgid "More Adwaita" msgstr "Больше Adwaita" #: src/bz-flathub-category.c:140 msgid "KDE Apps" msgstr "KDE приложения" #: src/bz-flathub-category.c:140 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:205 msgid "App of the Day" msgstr "Приложение дня" #: src/bz-flathub-page.blp:268 msgid "On the Go" msgstr "Всегда пОд рукой" #: src/bz-flathub-page.blp:280 msgid "Apps for your Linux phones and tablets" msgstr "Приложения для ваших телефонов и планшетов на Linux" #: src/bz-flathub-page.blp:291 src/bz-flathub-page.blp:326 msgid "More Mobile Apps" msgstr "Больше мобильных приложений" #: src/bz-flathub-page.blp:382 msgid "We​ ♥​ Games" msgstr "Мы ♥ Игры" #: src/bz-flathub-page.blp:395 msgid "Games and apps to run your favorite titles" msgstr "Игры и приложения для Сапуска ваших любимых тайтлов" #: src/bz-flathub-page.blp:429 msgid "More Games" msgstr "Больше игр" #: src/bz-full-view.blp:34 src/bz-library-page.blp:78 #: src/bz-library-page.blp:82 msgid "No Results" msgstr "Нет результатов" #: src/bz-full-view.blp:35 msgid "Try a different search query" msgstr "Попробуйте выполнить другой поисковый запрос" #: src/bz-full-view.blp:41 msgid "Content" msgstr "Содержимое" #: src/bz-full-view.blp:103 msgid "" "This is a local preview, some details may differ from the published listing" msgstr "" "Это локальный предварительный просмотр, некоторые детали могут отличаться от " "ОпуйНикОваннОК страницы" #: src/bz-full-view.blp:106 msgid "Preview Store Appearance" msgstr "Предварительный просмотр элемента ПагаСина" #: src/bz-full-view.blp:232 msgid "_Support" msgstr "_Поддержать" #: src/bz-full-view.blp:431 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:518 msgid "Trash Data" msgstr "Отправить в корзину" #: src/bz-full-view.blp:658 msgid "Tags:" msgstr "Метки:" #: src/bz-full-view.c:180 msgid "No URL" msgstr "Нет URL" #: src/bz-full-view.c:198 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Это приложение имеет лицензию FLOSS, что значит исходный кОд может быть " "проверен на безопасность." #: src/bz-full-view.c:199 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:206 msgid "More Apps" msgstr "Больше приложений" #: src/bz-full-view.c:207 #, c-format msgid "More Apps by %s" msgstr "Больше приложений от %s" #: src/bz-full-view.c:214 msgid "Other Apps by this Developer" msgstr "Другие приложения от этого разработчика" #: src/bz-full-view.c:216 src/bz-full-view.c:316 #, c-format msgid "Other Apps by %s" msgstr "Другие приложения от %s" #: src/bz-full-view.c:225 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" "%s но установлено, нО пользовательские данные в размере %s ещё " "присутствуют." #: src/bz-full-view.c:318 msgid "Other Apps" msgstr "Другие приложения" #: src/bz-full-view.c:320 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d приложение" msgstr[1] "%d приложения" msgstr[2] "%d приложений" #: src/bz-full-view.c:536 src/bz-user-data-tile.c:144 msgid "Failed to Remove User Data" 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-install-controls.blp:62 msgid "_Open" msgstr "_Открыть" #: src/bz-install-controls.blp:77 src/bz-install-controls.blp:134 msgid "Uninstall Application" msgstr "Удалить приложение" #: src/bz-install-controls.blp:87 src/bz-transaction-dialog.c:230 msgid "_Remove" msgstr "_Удалить" #: src/bz-install-controls.blp:121 src/bz-updates-card.c:164 #: src/bz-updates-card.c:183 msgid "Update" msgstr "Обновить" #: src/bz-install-controls.blp:144 src/bz-installed-tile.blp:105 msgid "Remove" msgstr "Удалить" #: src/bz-install-controls.wdgt:32 msgctxt "Install Controls" msgid "Cancel" msgstr "Отмена" #: src/bz-install-controls.wdgt:35 msgctxt "Install Controls" msgid "Cancelling" msgstr "Отменяется" #: src/bz-library-page.blp:32 msgid "Search installed apps" msgstr "Поиск установленных приложений" #: src/bz-library-page.blp:50 msgid "Clear search" msgstr "Очистить пОиск" #: src/bz-library-page.blp:71 msgid "No Apps Found" msgstr "Приложение но наКдонО" #: src/bz-library-page.blp:90 msgid "Search Store Instead" msgstr "Искать в ПагаСино" #. Translators: . #: src/bz-library-page.blp:100 src/bz-window.blp:112 msgid "Library" msgstr "Библиотека" #: src/bz-library-page.blp:128 msgid "Pending Updates" msgstr "Ожидают обновления" #: src/bz-library-page.blp:155 msgid "Downloads" msgstr "Загрузки" #: src/bz-library-page.blp:198 msgid "Recently Uninstalled" msgstr "Недавно удалённые" #: src/bz-library-page.blp:249 msgid "Clear Finished Tasks" msgstr "Очистить выполненные задачи" #: src/bz-library-page.blp:334 msgid "Sort By" msgstr "Сортировка" #: src/bz-library-page.blp:348 msgid "Name" msgstr "Название" #: src/bz-library-page.blp:354 msgid "Size" msgstr "Размер" #: src/bz-library-page.c:180 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "Нет результатов пО запросу \"%s\" в списко установленных приложений" #: src/bz-library-page.c:193 src/bz-updates-card.c:433 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "Доступно %u ОйнОвНонио" msgstr[1] "Доступно %u обновления" msgstr[2] "Доступно %u ОйнОвНониК" #: src/bz-library-page.c:203 #, c-format msgid "%u Installed App" msgid_plural "%u Installed Apps" msgstr[0] "%u установленное приложение" msgstr[1] "%u установленных приложения" msgstr[2] "%u установленных приложений" #: src/bz-license-dialog.blp:94 msgid "Get Involved" msgstr "Внести вкНад" #: src/bz-license-dialog.blp:111 msgid "Learn More" msgstr "Узнать больше" #: src/bz-license-dialog.c:127 msgid "Unknown License" msgstr "Неизвестная лицензия" #: src/bz-license-dialog.c:130 msgid "Community Built" msgstr "ХдоНанО сообществом" #: src/bz-license-dialog.c:203 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:206 msgid "The license of this app is not known" msgstr "Лицензия этого приложения неизвестна" #: src/bz-license-dialog.c:212 #, 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:220 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:226 #, 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-license-dialog.c:356 src/bz-safety-dialog.blp:49 msgid "License" msgstr "Лицензия" #: 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:110 msgid "Finish" msgstr "Завершить" #: src/bz-login-page.c:664 #, c-format msgid "Hello, %s!" msgstr "Приветствуем, %s!" #: src/bz-metainfo-preview.c:84 msgid "Select Metainfo File" msgstr "Выбрать файл метаданных" #: src/bz-metainfo-preview.c:87 msgid "Metainfo Files" msgstr "Файлы метаданных" #: src/bz-metainfo-preview.c:141 msgid "Select Icon (Optional)" msgstr "Выбрать икОнку (необязательно)" #: src/bz-metainfo-preview.c:144 msgid "Image Files" msgstr "Файлы изображений" #: src/bz-metainfo-preview.c:231 msgid "Preview" msgstr "Предварительный просмотр" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Параметры" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data refresh is paused" msgstr "" "Сетевое сОодинонио ограничено — автоматическое ОйнОвНонио данных ПагаСина " "приостановлена" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:232 msgid "Refresh 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 End-of-Life 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:127 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-updates-card.c:155 msgid "Version History" msgstr "История версий" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "_История версий" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "Сегодня" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "Вчера" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "%d день наСад" msgstr[1] "%d дня наСад" msgstr[2] "%d дноК наСад" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "%d неделю наСад" msgstr[1] "%d нодоНи наСад" msgstr[2] "%d недель наСад" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "%d месяц наСад" msgstr[1] "%d месяца наСад" msgstr[2] "%d месяцев наСад" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "%d гОд наСад" msgstr[1] "%d гОда наСад" msgstr[2] "%d лет наСад" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%e %B %Y" #: src/bz-releases-list.c:196 #, c-format msgid "Version %s" msgstr "Версия %s" #: src/bz-releases-list.c:251 msgid "No details for this release" msgstr "Нет подробностей" #: src/bz-releases-list.c:263 msgid "Get More Information" msgstr "Получить дополнительную информацию" #: src/bz-rich-app-tile.blp:217 msgid "Uninstall" msgstr "Удалить" #. Translators: If you can't find a short enough translation, use "/" to use an icon instead. #: src/bz-rich-app-tile.c:369 msgid "Get" msgstr "Скачать" #: src/bz-safety-calculator.c:87 msgid "Unknown Permissions" msgstr "Неизвестные разрешения" #: src/bz-safety-calculator.c:88 msgid "Permissions are missing for this app." msgstr "Разрешения для этого приложения отсутствуют." #: src/bz-safety-calculator.c:101 msgid "No Permissions" msgstr "Нет разрешений" #: src/bz-safety-calculator.c:102 msgid "App is fully sandboxed" msgstr "Приложение полностью изолировано" #: src/bz-safety-calculator.c:108 msgid "Network Access" msgstr "Доступ Đş сети" #: src/bz-safety-calculator.c:109 msgid "Can access the internet" msgstr "Может получить доступ Đş интернету" #: src/bz-safety-calculator.c:111 msgid "No Network Access" msgstr "Нет доступа Đş сети" #: src/bz-safety-calculator.c:112 msgid "Cannot access the internet" msgstr "Не может получить доступ Đş интернету" #: src/bz-safety-calculator.c:117 msgid "User Device Access" msgstr "Доступ Đş устройствам пользователя" #: src/bz-safety-calculator.c:118 msgid "Can access devices such as webcams or gaming controllers" msgstr "" "Может получить доступ Đş таким устройствам, как вой-камеры иНи игровые " "контроллеры" #: src/bz-safety-calculator.c:120 msgid "No User Device Access" msgstr "Нет доступа Đş устройствам пользователя" #: src/bz-safety-calculator.c:121 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "" "Не может получить доступ Đş таким устройствам, как вой-камеры иНи игровые " "контроллеры" #: src/bz-safety-calculator.c:126 msgid "Input Device Access" msgstr "Доступ Đş устройствам ввОда" #: src/bz-safety-calculator.c:127 msgid "Can access input devices" msgstr "Может получить доступ Đş устройствам ввОда" #: src/bz-safety-calculator.c:133 msgid "Microphone Access and Audio Playback" msgstr "Доступ Đş микрофону и воспроизведение Свука" #: src/bz-safety-calculator.c:134 msgid "Can listen using microphones and play audio without asking permission" msgstr "Может слышать с помощью микрофона и воспроизводить Свук йоС разрешения" #: src/bz-safety-calculator.c:140 msgid "System Device Access" msgstr "Доступ Đş системным устройствам" #: src/bz-safety-calculator.c:141 msgid "Can access system devices which require elevated permissions" msgstr "" "Может получить доступ Đş системным устройствам, требующие повышенные " "разрешения" #: src/bz-safety-calculator.c:147 msgid "Screen Contents Access" msgstr "Доступ Đş содержимому экрана" #: src/bz-safety-calculator.c:148 msgid "Can access the contents of the screen or other windows" msgstr "Может получить доступ Đş содержимому экрана иНи других ОкОн" #: src/bz-safety-calculator.c:154 msgid "Legacy Windowing System" msgstr "Устаревшая оконная система" #: src/bz-safety-calculator.c:155 msgid "Always uses a legacy windowing system (X11)" msgstr "Использует устаревшую оконную систему постоянно (X11)" #: src/bz-safety-calculator.c:161 msgid "Arbitrary Permissions" msgstr "Произвольные разрешения" #: src/bz-safety-calculator.c:162 msgid "Can acquire arbitrary permissions" msgstr "Может получить произвольные разрешения" #: src/bz-safety-calculator.c:168 msgid "User Settings" msgstr "Пользовательские настройки" #: src/bz-safety-calculator.c:169 msgid "Can access and change user settings" msgstr "Может получить и изменить пользовательские настройки" #: src/bz-safety-calculator.c:175 msgid "Full File System Read/Write Access" msgstr "Полный доступ Đş файловой системе на чтение/запись" #: src/bz-safety-calculator.c:176 msgid "Can read and write all data on the file system" msgstr "Может читать и записывать всо данные в файловой системе" #: src/bz-safety-calculator.c:183 msgid "Home Folder Read/Write Access" msgstr "Доступ Đş дОПашноК папко для чтения/Саписи" #: src/bz-safety-calculator.c:184 msgid "Can read and write all data in your home directory" msgstr "Может читать и записывать всо данные в вашоК дОПашноК папко" #: src/bz-safety-calculator.c:191 msgid "Full File System Read Access" msgstr "Полный доступ Đş файловой системе на чтение" #: src/bz-safety-calculator.c:192 msgid "Can read all data on the file system" msgstr "Может читать всо данные в файловой системе" #: src/bz-safety-calculator.c:200 msgid "Home Folder Read Access" msgstr "Доступ на чтение дОПашноК папки" #: src/bz-safety-calculator.c:201 msgid "Can read all data in your home directory" msgstr "Может читать всо данные в вашоК дОПашноК папко" #: src/bz-safety-calculator.c:209 msgid "Download Folder Read/Write Access" msgstr "Доступ для чтения/Саписи в папку загрузки" #: src/bz-safety-calculator.c:210 msgid "Can read and write all data in your downloads directory" msgstr "Может читать и записывать всо данные в вашоК папко загрузки" #: src/bz-safety-calculator.c:220 msgid "Download Folder Read Access" msgstr "Доступ на чтение папки загрузки" #: src/bz-safety-calculator.c:221 msgid "Can read all data in your downloads directory" msgstr "Может читать всо данные в вашоК папко загрузки" #: src/bz-safety-calculator.c:242 msgid "Can read and write all data in the directory" msgstr "Может читать и записывать всо данные в папко" #: src/bz-safety-calculator.c:266 msgid "Can read all data in the directory" msgstr "Может читать всо данные в папко" #: src/bz-safety-calculator.c:281 msgid "No File System Access" msgstr "Нет доступа Đş файловой системе" #: src/bz-safety-calculator.c:282 msgid "Cannot access the file system at all" msgstr "Не может получить доступ Đş файловой системе" #: src/bz-safety-calculator.c:289 msgid "Uses System Services" msgstr "Использует системные службы" #: src/bz-safety-calculator.c:290 msgid "Can request data from non-portal system services" msgstr "Может запрашивать данные у системных сНуМй, но относящихся Đş порталу" #: src/bz-safety-calculator.c:296 msgid "Uses Session Services" msgstr "Использует службы соанса" #: src/bz-safety-calculator.c:297 msgid "Can request data from non-portal session services" msgstr "Может запрашивать данные у сНуМй соанса, но относящихся Đş порталу" #: src/bz-safety-calculator.c:345 msgid "No Service Access" msgstr "Нет доступа Đş сНуМйо" #: src/bz-safety-calculator.c:346 msgid "Cannot access non-portal session or system services at all" msgstr "" "Не может получить доступ Đş сНуМйаП соанса иНи системным, но относящимся Đş " "порталу" #: src/bz-safety-calculator.c:354 msgid "Verified App Developer" msgstr "Подтверждённый разработчик приложения" #: src/bz-safety-calculator.c:355 msgid "The developer of this app has been verified to be who they say they are" msgstr "" "Разработчик этого приложения подтвердил, что является тем, Са кОгО себя " "выдает" #: src/bz-safety-calculator.c:364 msgid "Proprietary Code" msgstr "Проприетарный кОд" #: src/bz-safety-calculator.c:365 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "Исходный кОд но является открытым, поэтому но может быть подвергнут " "ноСависиПОПу аудиту и может быть небезопасным" #: src/bz-safety-calculator.c:375 msgid "Auditable Code" msgstr "Проверяемый кОд" #: src/bz-safety-calculator.c:376 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:516 #, c-format msgid "Use the %s System Service" msgstr "Использует системную сНуМйу %s" #: src/bz-safety-calculator.c:520 #, c-format msgid "Use the %s Session Service" msgstr "Использует сНуМйу соанса %s" #: src/bz-safety-calculator.c:524 #, c-format msgid "Use the %s Service" msgstr "Использует сНуМйу %s" #: src/bz-safety-calculator.c:534 msgid "Can see the non-portal service" msgstr "Может просматривать сНуМйу, но относящуюся Đş порталу" #: src/bz-safety-calculator.c:536 msgid "Can talk to the non-portal service" msgstr "Может связаться сО сНуМйОК, но относящейся Đş порталу" #: src/bz-safety-calculator.c:538 msgid "Can own the non-portal service" msgstr "Может быть владельцем службы, но относящейся Đş порталу" #: src/bz-safety-calculator.c:553 msgid "Global Menu Integration" msgstr "Интеграция с глобальным меню" #: src/bz-safety-calculator.c:554 msgid "Can display its menus in a global menu bar" msgstr "Может показывать своё меню в глобальной пОНОсо меню" #: src/bz-safety-calculator.c:559 msgid "KDE Settings Integration" msgstr "Интеграция с настройками KDE" #: src/bz-safety-calculator.c:560 msgid "Can detect when KDE desktop settings change" msgstr "Может определять иСПононио в настройках рабочего стола KDE" #: src/bz-safety-calculator.c:565 msgid "KDE Global Settings" msgstr "Глобальные параметры KDE" #: src/bz-safety-calculator.c:566 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "Может читать параметры рабочего стола KDE как шрифты и цвета" #: src/bz-safety-calculator.c:571 msgid "Secret Storage Service" msgstr "ХНуМйа хранения секретов" #: src/bz-safety-calculator.c:572 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "Может хранить и извлекать свОи пароли используя системные ключи" #: src/bz-safety-calculator.c:577 msgid "Desktop Notifications Service" msgstr "ХНуМйа уводОПНониК рабочего стола" #: src/bz-safety-calculator.c:578 msgid "Can send desktop notifications" msgstr "Может отправлять уведомления на рабочий стол" #: src/bz-safety-calculator.c:584 msgid "System Tray Integration" msgstr "Интеграция с системным треем" #: src/bz-safety-calculator.c:585 msgid "Can display an icon in the system tray" msgstr "Может отображать икОнку в системном треем" #: src/bz-safety-calculator.c:590 msgid "KDE Connect Integration" msgstr "Интеграция с KDE Connect" #: src/bz-safety-calculator.c:591 msgid "Can interact with devices paired via KDE Connect" msgstr "Может взаимодействовать с устройстами привязанным Đş KDE Connect" #: src/bz-safety-dialog.blp:59 msgid "App ID" msgstr "ID приложения" #: src/bz-safety-dialog.blp:69 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 "" "Это приложение использует устаревшую версию платформа для разработки (SDK) и " "может иметь йаги иНи уязвимости безопасности которые но были исправлены." #: src/bz-safety-dialog.c:167 msgid "Safety" msgstr "Безопасность" #: src/bz-safety-dialog.c:226 #, c-format msgid "%s is Safe" msgstr "%s йоСОпаснОо" #: src/bz-safety-dialog.c:231 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s имеет небезопасные разрешения" #: src/bz-safety-dialog.c:236 #, c-format msgid "%s is Probably Safe" msgstr "%s вероятно йоСОпаснОо" #: src/bz-safety-dialog.c:241 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s вероятно нойоСОпаснОо" #: src/bz-safety-dialog.c:246 #, 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:150 msgid "Reset View" msgstr "Возобновить вид" #: src/bz-screenshot-page.blp:161 msgid "Zoom Out" msgstr "Отдалить" #: src/bz-screenshot-page.blp:171 msgid "Zoom In" msgstr "Приблизить" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Карусель скриншотов" #: src/bz-screenshots-carousel.blp:117 msgid "Open Screenshot Viewer" msgstr "Открыть просмотрщик скриншотов" #: src/bz-search-filter-popover.blp:18 src/bz-search-page.blp:83 msgid "Filters" msgstr "Фильтры" #: src/bz-search-filter-popover.blp:35 msgid "_Verified" msgstr "_Подтвержденные" #: src/bz-search-filter-popover.blp:42 msgid "_Free/Open" msgstr "_Свободные" #: src/bz-search-filter-popover.blp:49 msgid "Non-_EOL" msgstr "П_оддерживаемые" #: src/bz-search-filter-popover.blp:52 msgid "Filter out End-of-Life apps" msgstr "Отфильтровать неподдерживаемые приложения" #: src/bz-search-filter-popover.blp:57 msgid "Categories" msgstr "Категории" #: src/bz-search-page.blp:58 msgid "Search Apps, Games, Software" msgstr "Поиск приложений, игр, ПО" #: src/bz-search-page.blp:70 msgid "Search Filters" msgstr "Фильтры пОиска" #: src/bz-search-page.blp:100 msgid "Clear Search" msgstr "Очистить пОиск" #: src/bz-search-page.blp:192 msgid "Categories Unavailable" msgstr "Категории недоступны" #: src/bz-search-page.blp:193 msgid "Search for apps using the search bar above." msgstr "Попробуйте поискать приложения используя пОНо ввОда запроса выше." #: src/bz-search-page.blp:219 msgid "Browse Categories" msgstr "Обзор категорий" #: src/bz-search-page.blp:361 msgid "No Applications Found" msgstr "Приложение но наКдонО" #: src/bz-search-page.c:247 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Нет результатов пО запросу \"%s\" в Flathub" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "Видео" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "Офис" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "Календарь" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "Общение" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Paint" msgstr "РисОванио" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "Torrent" msgstr "Торрент" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Emulator" msgstr "Эмуляторы" #: src/bz-share-list.c:55 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Страница Flathub" #: src/bz-share-list.c:56 msgctxt "Project URL Type" msgid "Project Website" msgstr "Веб-сайт проекта" #: src/bz-share-list.c:57 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Отслеживание ОшийОк" #: src/bz-share-list.c:58 msgctxt "Project URL Type" msgid "FAQ" msgstr "Часто задаваемые вопросы" #: src/bz-share-list.c:59 msgctxt "Project URL Type" msgid "Help" msgstr "Помощь" #: src/bz-share-list.c:60 msgctxt "Project URL Type" msgid "Donate" msgstr "Пожертвовать" #: src/bz-share-list.c:61 msgctxt "Project URL Type" msgid "Translate" msgstr "Перевод" #: src/bz-share-list.c:62 msgctxt "Project URL Type" msgid "Contact" msgstr "Связаться" #: src/bz-share-list.c:63 msgctxt "Project URL Type" msgid "Source Code" msgstr "Исходный кОд" #: src/bz-share-list.c:64 msgctxt "Project URL Type" msgid "Contribute" msgstr "Внести вкНад" #: src/bz-share-list.c:153 msgid "Copy Link" msgstr "Скопировать ссылку" #: src/bz-share-list.c:164 msgid "Open Link" msgstr "Открыть ссылку" #: src/bz-stats-dialog.blp:27 msgid "Timeline" msgstr "Временная шкаНа" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Установок:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Карта мира" #: src/bz-stats-dialog.blp:69 msgid "Since 4/15/2024" msgstr "ĐĄ 15 апреля 2024" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:130 #, c-format msgid "%.2fM Total Installs" msgstr "%.2f ПиННиОнОв общих установок" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:133 #, c-format msgid "%.2fK Total Installs" msgstr "%.2f тысяч общих установок" #: src/bz-stats-dialog.c:135 #, c-format msgid "%'d Total Installs" msgstr "%'d общих установок" #: src/bz-tag-list.c:78 msgid "No Results Found" msgstr "Нет результатов" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Приложения с меткой \"%s\"" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "Ошибка пОиска" #: src/bz-transaction-dialog.c:154 msgid "Keep User Data" msgstr "Оставить пользовательские данные" #: src/bz-transaction-dialog.c:155 msgid "Allow restoring personal settings & content" msgstr "Возможно восстановление настроек и содержимого" #: src/bz-transaction-dialog.c:164 msgid "Delete All Data" msgstr "Удалить всо данные" #: src/bz-transaction-dialog.c:165 msgid "Permanently erase user data to save space" msgstr "Навсегда удалить данные приложения для сохранения места" #: src/bz-transaction-dialog.c:190 #, c-format msgid "Install %s?" msgstr "Установить %s?" #: src/bz-transaction-dialog.c:195 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Выберите какую версию установить. Может установить дополнительные общие " "компоненты" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "Может установить дополнительные общие компоненты" #: src/bz-transaction-dialog.c:200 src/bz-transaction-dialog.c:229 #: src/bz-transaction-dialog.c:274 src/bz-transaction-dialog.c:576 msgid "_Cancel" msgstr "_Отмена" #: src/bz-transaction-dialog.c:201 msgid "_Install" msgstr "_Установить" #: src/bz-transaction-dialog.c:218 #, c-format msgid "Remove %s?" msgstr "Удалить %s?" #: src/bz-transaction-dialog.c:221 msgid "Select which version to remove." msgstr "Выберите какую версию удалить." #: src/bz-transaction-dialog.c:223 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Станет невозможным использовать %s пОсНо огО удаления." #: src/bz-transaction-dialog.c:246 #, c-format msgid "“%s” is High Risk" msgstr "“%s” пОд высоким риском" #: src/bz-transaction-dialog.c:250 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:259 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:275 msgid "_Install Anyway" msgstr "_Всё равно установить" #: src/bz-transaction-dialog.c:330 msgid "Failed to load transaction dialog" msgstr "Не удалось загрузить диаНОг транзакции" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "Все приложения уМо были установлены" #: src/bz-transaction-dialog.c:549 msgid "_OK" msgstr "_ОК" #: src/bz-transaction-dialog.c:565 #, 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: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-dialog.c:577 msgid "_Install All" msgstr "_Установить всо" #: src/bz-transaction-manager.c:795 #, c-format msgid "Finished in %.02f seconds" msgstr "Закончено Са %.02f сокунд" #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "Дополнение приложения" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "Среда выполнения" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "В очереди" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "Готово" #: src/bz-transaction-tile.blp:230 msgid "Cancelled" msgstr "Отменено" #: src/bz-transaction-tile.blp:254 msgid "Error" msgstr "Ошибка" #: src/bz-transaction-tile.blp:312 msgid "Cancel Transaction" msgstr "Отменить транзакцию" #: src/bz-transaction-tile.blp:436 msgid "Show Error Info" msgstr "Показать информацию Ой Ошийко" #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "%s очищено" #: src/bz-transaction-tile.c:360 src/bz-transaction-tile.c:363 msgid "Transaction Error" msgstr "Ошибка транзакции" #: src/bz-transaction.c:344 msgid "Pending" msgstr "В ОМидании" #: src/bz-updates-card.blp:23 msgid "_Update All" msgstr "_Обновить всо" #: src/bz-updates-card.c:211 #, 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:33 msgid "No User Data Found" msgstr "Пользовательские данные но найдены" #: src/bz-user-data-page.blp:38 msgid "User Data" msgstr "Пользовательские данные" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Отправить в корзину" #: src/bz-user-data-tile.c:150 #, c-format msgid "Trashed User Data for %s" msgstr "Пользовательские данные Đş %s отправлены в корзину" #: src/bz-window.blp:70 msgid "Refreshing" msgstr "Обновление" #: src/bz-window.blp:88 msgid "Curated" msgstr "Курируемое" #: src/bz-window.blp:100 msgid "Explore" msgstr "Обзор" #: src/bz-window.blp:212 msgid "Main Menu" msgstr "Главное меню" #: src/bz-window.blp:223 msgid "You are running a new version of Bazaar!" msgstr "Вы используете новую версию Bazaar!" #: src/bz-window.blp:224 msgid "See What's New" msgstr "Посмотреть что нОвОгО" #: src/bz-window.blp:231 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Вы имеете сетевое подключение, нО просматриваете кэшируемую версию Flathub" #: src/bz-window.blp:276 msgid "_Donate to Bazaar" msgstr "_Поддержать Bazaar" #: src/bz-window.blp:283 msgid "_Refresh" msgstr "_Обновить" #: src/bz-window.blp:288 msgid "_Preferences" msgstr "П_араметры" #: src/bz-window.blp:293 msgid "_Login With Flathub" msgstr "_Войти в Flathub" #: src/bz-window.blp:299 msgid "_Manage Leftover User Data" msgstr "_Управлять оставшимися данными" #: src/bz-window.blp:304 msgid "_Keyboard Shortcuts" msgstr "_Сочетание кНавиш" #: src/bz-window.blp:309 msgid "_About Bazaar" msgstr "О _Bazaar" #: src/bz-window.blp:316 msgid "_Quit Bazaar" msgstr "_Завершить Bazaar" #: src/bz-window.blp:341 msgid "Log Out" msgstr "Выйти" #. Translators: %s is the title of the current page #: src/bz-window.c:376 #, c-format msgid "Bazaar — %s" msgstr "Bazaar — %s" #: src/bz-window.c:596 src/bz-window.c:634 msgid "Failed to launch application" msgstr "Не удалось запустить приложение" #: src/bz-window.c:843 msgid "You can't remove Bazaar from Bazaar!" msgstr "Вы но можете удалить Bazaar иС Bazaar!" #: src/bz-window.c:1127 src/bz-window.c:1161 msgid "Can't do that right now!" msgstr "Невозможно сделать это сейчас!" #. Translators: As in, "1 Install" / "100 Installs" #: src/bz-world-map.c:604 msgid "Install" msgid_plural "Installs" msgstr[0] "установка" msgstr[1] "установки" msgstr[2] "установок" #: src/shortcuts-dialog.blp:5 msgctxt "shortcut window" msgid "Navigation" msgstr "Навигация" #: src/shortcuts-dialog.blp:8 msgctxt "shortcut window" msgid "Open Explore Page" msgstr "Открыть страницу обзора" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "Открыть страницу библиотеки" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Open Search Page" msgstr "Открыть страницу пОиска" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Remotes" msgstr "Репозитории" #: src/shortcuts-dialog.blp:27 msgctxt "shortcut window" msgid "Sync Remotes" msgstr "Синхронизировать репозитории" #: src/shortcuts-dialog.blp:33 msgctxt "shortcut window" msgid "General" msgstr "Общее" #: src/shortcuts-dialog.blp:36 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Открыть параметры" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Открыть сочетания кНавиш" #: src/shortcuts-dialog.blp:46 msgctxt "shortcut window" msgid "Close Window" msgstr "Закрыть ОкнО" #: src/shortcuts-dialog.blp:52 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "Завершить Bazaar" bazaar-org-bazaar-43ce9f7/po/tr.po000066400000000000000000002533211520414637400170420ustar00rootroot00000000000000# 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-05-16 15:27+0300\n" "PO-Revision-Date: 2026-05-17 13:23+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.9\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:45 #: src/bz-window.c:373 src/bz-window.c:374 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:16 msgid "New Window" msgstr "Yeni Pencere" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and manage applications" msgstr "UygulamalarÄą keşfet ve yĂśnet" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "Özellikle FlathubĘźdan Flatpak uygulamalarÄąnÄą ve eklentilerini keşfetmeye ve " "kurmaya odaklanan, Linux için hÄązlÄą ve modern uygulama mağazasÄą." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "Birden çok kurulumu kuyruklar ve gezinmeye devam et" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "Uygulama izinlerini kolayca gĂśrĂźntĂźle" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "GĂśzdelerinizi gĂśrĂźntĂźlemek ve yĂśnetmek için Flathub ile oturum açĹn" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "UygulamalarÄą GNOME Shell ĂźstĂźnden ara" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:30 src/bz-application.c:759 msgid "The Bazaar Contributors" msgstr "Bazaar KatkÄącÄąlarÄą" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 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:59 msgid "Exhibit app page" msgstr "Uygulama sergisi sayfasÄą" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "KitaplÄąk sayfasÄą" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "Arama sayfasÄą" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "Kategori sayfasÄą" #: src/bz-addon-tile.blp:64 src/bz-installed-tile.blp:55 #: src/bz-rich-app-tile.blp:141 msgid "Stopped Receiving Updates" msgstr "GĂźncellemelerin AlÄąnmasÄą Durduruldu" #: src/bz-addon-tile.c:167 src/bz-favorites-tile.c:155 msgctxt "Install Controls" msgid "Uninstall" msgstr "KaldÄąr" #: src/bz-addon-tile.c:169 src/bz-bundle-install-dialog.blp:126 #: src/bz-favorites-tile.c:157 src/bz-install-controls.wdgt:29 msgctxt "Install Controls" msgid "Install" msgstr "Kur" #: src/bz-addons-dialog.blp:14 src/bz-addons-dialog.blp:21 #: src/bz-addons-dialog.blp:70 src/bz-full-view.blp:606 #: src/bz-installed-tile.blp:92 msgid "Manage Add-Ons" msgstr "Eklentileri YĂśnet" #: src/bz-addons-dialog.blp:80 msgid "No Add-Ons Visible" msgstr "GĂśrĂźnĂźn Eklenti Yok" #: src/bz-addons-dialog.blp:81 msgid "" "Your current filter preferences are hiding all known add-ons. Try adjusting " "them." msgstr "" "Geçerli sĂźzgeçleriniz, bilinen tĂźm eklentileri gizliyor. SĂźzgeç ayarlarÄąnÄą " "dĂźzenleyin." #: src/bz-addons-dialog.blp:88 msgid "Add-on Page" msgstr "Eklenti SayfasÄą" #: src/bz-addons-dialog.blp:202 src/bz-full-view.blp:404 msgid "Downloads/Month" msgstr "İndirme/Ay" #: src/bz-addons-dialog.blp:229 src/bz-full-view.blp:440 msgid "Stopped Receiving Core Updates" msgstr "Çekirdek GĂźncellemelerinin AlÄąnmasÄą Durduruldu" #: src/bz-addons-dialog.blp:243 msgid "" "This add-on uses a runtime that no longer receives updates or security " "fixes. It may become unsafe to use." msgstr "" "Bu eklenti, artÄąk gĂźncelleme ya da gĂźvenlik dĂźzeltmesi almayan bir çalışma " "zamanÄą kullanÄąyor. KullanÄąmÄą gĂźvenli olmayabilir." #: src/bz-addons-dialog.c:333 #, c-format msgid "Add-on for %s" msgstr "%s Eklentisi" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:572 msgid "Show Less" msgstr "Daha Az GĂśster" #: src/bz-addons-dialog.c:347 src/bz-full-view.c:572 msgid "Show More" msgstr "Daha Çok GĂśster" #: src/bz-addons-dialog.c:397 msgid "Download Stats" msgstr "İndirme İstatistikleri" # 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:736 src/bz-context-tile-callbacks.c:186 #: src/bz-context-tile-callbacks.c:193 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:686 src/bz-context-tile-callbacks.c:176 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "TĂźmĂź" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "%s yaş derecelendirmesi bilinmiyor" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "%s, herkese uygundur" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "%s, kßçßk çocuklara uygundur" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "%s, çocuklara uygundur" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "%s, ergenlere uygundur" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "%s, yetişkinlere uygundur" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "%s, %s için uygundur" #: src/bz-age-rating-dialog.c:862 #, c-format msgid "%s • %s" msgstr "%s • %s" #: 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:26 src/bz-app-size-dialog.blp:60 msgid "Download Size" msgstr "İndirme Boyutu" #: src/bz-app-size-dialog.blp:33 src/bz-app-size-dialog.blp:81 msgid "Installed Size" msgstr "Kurulum Boyutu" #: src/bz-app-size-dialog.blp:61 msgid "Amount to download from the internet" msgstr "İnternetten indirilecek miktar" # Kasten daha açĹklayÄącÄą bir çeviri kullanÄąldÄą #: src/bz-app-size-dialog.blp:82 msgid "Size on Disk" msgstr "Diskteki kapladığı alan" #: src/bz-app-size-dialog.blp:133 msgid "Open user data folder" msgstr "KullanÄącÄą veri klasĂśrĂźnĂź aç" #: src/bz-app-size-dialog.blp:143 msgid "Your User Data" msgstr "KullanÄącÄą Veriniz" #: src/bz-app-size-dialog.blp:144 msgid "Caches, settings, and other app data" msgstr "Önbellekler, ayarlar ve diğer uygulama verileri" #: src/bz-app-size-dialog.blp:165 msgid "Cache" msgstr "Önbellek" #: src/bz-app-size-dialog.blp:166 msgid "Temporary cached data" msgstr "Geçici Ăśnbellekli veri" #: src/bz-app-size-dialog.blp:176 msgid "Clear Cache" msgstr "Önbelleği Temizle" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "Çalışma ZamanÄą Kurulum Boyutu" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "Çalışma ZamanÄą İndirme Boyutu" #: src/bz-app-size-dialog.c:220 msgid "App Size" msgstr "Uygulama Boyutu" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:105 src/bz-rich-app-tile.c:309 msgid "Verified" msgstr "Doğrulanmış" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-context-tile-callbacks.c:135 #: src/bz-releases-list.c:206 msgid "Installed" msgstr "Kurulu" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:762 msgid "translator-credits" msgstr "Sabri Ünal , 2025-2026" #: src/bz-application.c:772 msgid "Special Thanks" msgstr "Özel TeşekkĂźrler" #: src/bz-application.c:830 msgid "Logged Out Successfully!" msgstr "Oturum KapatÄąldÄą!" #: src/bz-application.c:966 msgid "Performing setup…" msgstr "Kurulum gerçekleştiriliyor…" #: src/bz-application.c:1052 msgid "Set Up System Flathub?" msgstr "Sistem FlathubʟĹ Kurulsun Mu?" #: src/bz-application.c:1055 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub sistem uzağı kurulmamış. Bazaar, uygulamalara gĂśz atmak ve kurmak " "için Flatpak kurulumunda FlathubʟĹn sistem geneli olarak yapÄąlandÄąrÄąlmış " "olmasÄąnÄą gerektirir. \n" "\n" "Yine de BazaarʟĹ kullanarak zaten kurulmuş uygulamalara gĂśz atabilir ve " "kaldÄąrabilirsiniz." #: src/bz-application.c:1062 msgid "Set Up Flathub?" msgstr "Flathub Kurulsun Mu?" #: src/bz-application.c:1065 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ış. 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:1071 msgid "Later" msgstr "Sonra" #: src/bz-application.c:1072 msgid "Set Up Flathub" msgstr "FlathubʟĹ Kur" #: src/bz-application.c:1407 msgid "A backend error occurred" msgstr "Arka uç hatasÄą oluştu" #: src/bz-application.c:1607 src/bz-application.c:3689 src/bz-window.blp:69 msgid "Refreshing…" msgstr "Yenileniyor…" #: src/bz-application.c:1771 src/bz-application.c:3687 #, c-format msgid "Loading %d apps…" msgstr "%d uygulama yĂźkleniyor…" #: src/bz-application.c:1824 msgid "Failed to open file" msgstr "Dosya açĹlamadÄą" #: src/bz-application.c:1929 msgid "An initialization error occurred" msgstr "İlklendirme hatasÄą oluştu" #: src/bz-application.c:2295 msgid "Checking for updates…" msgstr "GĂźncellemeler denetleniyor…" #: src/bz-application.c:2351 msgid "Failed to check for updates" msgstr "GĂźncellemeler denetlenemedi" #: src/bz-application.c:3409 msgid "Could not find app" msgstr "Uygulama bulunamadÄą" #: src/bz-application.c:3440 msgid "Failed to load metainfo" msgstr "Metainfo yĂźklenemedi" #: src/bz-application.c:3691 msgid "Writing to cache…" msgstr "Ön belleğe yazÄąlÄąyor…" #: src/bz-apps-page.blp:86 msgid "Show All" msgstr "TĂźmĂźnĂź GĂśster" #: src/bz-apps-page.c:229 #, c-format msgid "All \"%s\"" msgstr "TĂźm \"%s\"" #: src/bz-apps-page.c:478 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "%d Uygulama" #: src/bz-appstream-parser.c:303 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub SayfasÄą" #: src/bz-appstream-parser.c:324 msgctxt "Project URL Type" msgid "Project Website" msgstr "Proje Web Sitesi" #: src/bz-appstream-parser.c:328 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Sorun İzleyici" #: src/bz-appstream-parser.c:332 msgctxt "Project URL Type" msgid "FAQ" msgstr "SSS" #: src/bz-appstream-parser.c:336 msgctxt "Project URL Type" msgid "Help" msgstr "YardÄąm" #: src/bz-appstream-parser.c:340 msgctxt "Project URL Type" msgid "Donate" msgstr "Bağış" #: src/bz-appstream-parser.c:346 msgctxt "Project URL Type" msgid "Translate" msgstr "Çevir" #: src/bz-appstream-parser.c:350 msgctxt "Project URL Type" msgid "Contact" msgstr "İletişim" #: src/bz-appstream-parser.c:354 msgctxt "Project URL Type" msgid "Source Code" msgstr "Kaynak Kodu" #: src/bz-appstream-parser.c:360 msgctxt "Project URL Type" msgid "Contribute" msgstr "KatkÄą Ver" #: src/bz-bundle-install-dialog.blp:8 src/bz-bundle-install-dialog.blp:14 msgid "Bundle Installation" msgstr "Derleme Kur" #: src/bz-bundle-install-dialog.blp:147 msgid "Additional dependencies may take extra space" msgstr "Ek bağımlÄąlÄąklar fazladan alan kaplayabilir" #: src/bz-bundle-install-dialog.blp:181 msgid "" "Installing this app may require adding a new software source. Other apps " "from this source will show up in Bazaar.\n" "\n" "Only add this source if you're sure you trust it." msgstr "" "Bu uygulamayÄą kurmak için yeni yazÄąlÄąm kaynağı eklemeniz gerekebilir. Bu " "kaynaktan gelen diğer uygulamalar BazaarĘźda gĂśrĂźnecek.\n" "\n" "Bu kaynağı yalnÄązca gĂźveniyorsanÄąz ekleyin." #: src/bz-bundle-install-dialog.blp:357 msgid "Successfully Installed!" msgstr "Kuruldu!" #: src/bz-bundle-install-dialog.blp:381 src/bz-bundle-install-dialog.blp:463 #: src/bz-rich-app-tile.blp:186 src/bz-transaction-tile.blp:298 msgid "Open" msgstr "Aç" #: src/bz-bundle-install-dialog.blp:391 src/bz-bundle-install-dialog.blp:473 msgid "Show App Details" msgstr "Uygulama AyrÄąntÄąlarÄąnÄą GĂśster" #: src/bz-bundle-install-dialog.blp:440 msgid "Already Installed" msgstr "Zaten Kurulu" #: src/bz-bundle-install-dialog.blp:485 msgid "Installation Failed" msgstr "KurulamadÄą" #: src/bz-bundle-install-dialog.c:169 msgid "Unknown install size" msgstr "Kurulum boyutu bilinmiyor" # size_str = g_format_size (installed_size); # return g_strdup_printf (_ ("About %s to install"), size_str); #: src/bz-bundle-install-dialog.c:172 #, c-format msgid "About %s to install" msgstr "Yaklaşık kurulum boyutu: %s" #: src/bz-bundle-install-dialog.c:186 src/bz-context-tile-callbacks.c:104 #: src/bz-context-tile-callbacks.c:392 src/bz-context-tile-callbacks.c:409 msgid "N/A" msgstr "Yok" #: src/bz-bundle-install-dialog.c:215 msgid "No special permissions" msgstr "Özel izin yok" #: src/bz-context-tile-callbacks.c:68 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-context-tile-callbacks.c:75 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-context-tile-callbacks.c:82 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-context-tile-callbacks.c:92 #, c-format msgid "%d downloads in the last month" msgstr "Son ay içinde %d indirme" #: src/bz-context-tile-callbacks.c:132 #, c-format msgid "+%s runtime" msgstr "+%s çalışma zamanÄą" #: src/bz-context-tile-callbacks.c:135 msgid "Download" msgstr "İndirme Boyutu" #: src/bz-context-tile-callbacks.c:155 msgid "Size information unavailable" msgstr "Boyut bilgisi yok" #: src/bz-context-tile-callbacks.c:158 #, c-format msgid "Download size of %s" msgstr "%s İndirme Boyutu" #: src/bz-context-tile-callbacks.c:191 msgid "All Ages" msgstr "TĂźm Yaşlar" #: src/bz-context-tile-callbacks.c:203 msgid "Age rating information unavailable" msgstr "Yaş derecelendirme bilgisi yok" #: src/bz-context-tile-callbacks.c:208 msgid "Suitable for all ages" msgstr "TĂźm yaşlar için uygun" #: src/bz-context-tile-callbacks.c:210 #, c-format msgid "Suitable for ages %d and up" msgstr "%d ve ĂźstĂź yaşlar için uygun" #: src/bz-context-tile-callbacks.c:243 src/bz-context-tile-callbacks.c:248 #: src/bz-context-tile-callbacks.c:276 src/bz-context-tile-callbacks.c:284 msgid "Unknown" msgstr "Bilinmiyor" #: src/bz-context-tile-callbacks.c:253 #, c-format msgid "Free software licensed under %s" msgstr "%s altÄąnda lisanslanmış ĂśzgĂźr yazÄąlÄąm" #: src/bz-context-tile-callbacks.c:258 msgid "Free software" msgstr "ÖzgĂźr yazÄąlÄąm" #: src/bz-context-tile-callbacks.c:261 msgid "Proprietary Software" msgstr "Sahipli YazÄąlÄąm" #: src/bz-context-tile-callbacks.c:264 #, c-format msgid "Special License: %s" msgstr "Özel Lisans: %s" #: src/bz-context-tile-callbacks.c:281 msgid "Free" msgstr "ÖzgĂźr" #: src/bz-context-tile-callbacks.c:287 src/bz-license-dialog.c:133 msgid "Proprietary" msgstr "Sahipli" #: src/bz-context-tile-callbacks.c:289 src/bz-license-dialog.c:135 msgid "Special License" msgstr "Özel Lisans" #: src/bz-context-tile-callbacks.c:309 msgid "Adaptive" msgstr "UyarlanÄąr" # ArayĂźzde sığmadığı için new line eklendi #: src/bz-context-tile-callbacks.c:309 msgid "Desktop Only" msgstr "" "YalnÄązca\n" "MasaĂźstĂź" #: src/bz-context-tile-callbacks.c:315 msgid "Works on desktop, tablets, and phones" msgstr "Telefonlarda, tabletlerde ve masaĂźstĂźlerde çalışır" #: src/bz-context-tile-callbacks.c:316 msgid "May not work on mobile devices" msgstr "Mobil aygÄątlarda çalışmayabilir" #: src/bz-context-tile-callbacks.c:399 src/bz-safety-dialog.blp:27 msgid "Safe" msgstr "GĂźvenli" #: src/bz-context-tile-callbacks.c:401 src/bz-context-tile-callbacks.c:403 msgid "Low Risk" msgstr "Düşük Risk" #: src/bz-context-tile-callbacks.c:405 msgid "Medium Risk" msgstr "Orta Risk" #: src/bz-context-tile-callbacks.c:407 msgid "High Risk" msgstr "YĂźksek Risk" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:46 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:30 #: src/bz-library-page.blp:67 src/bz-user-data-page.blp:30 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ışı" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "TarayÄącÄą" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "Doğrulanmamış" #: src/bz-developer-badge.c:213 msgid "Developer information not available." msgstr "Geliştirici bilgisi yok." #: src/bz-developer-badge.c:219 src/bz-developer-badge.c:233 #, 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:237 #, 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:253 #, 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:260 #, 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:264 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "%s uygulama kimliğinin sahipliği doğrulandÄą." #: src/bz-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "Tam SĂźrĂźm NotlarÄą" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "Bu sĂźrĂźm, sizin gibi kullanÄącÄąlar sayesinde mĂźmkĂźn oldu!" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on Ko-Fi." msgstr "" "Bazaar uygulamasÄąnÄą geliştirmeyi çok seviyorum, yine de bunu tek başıma " "yapamam. Ko-Fi ile bağış yaparak geliştirilmesine destek olun." #: src/bz-donations-dialog.blp:131 msgid "Donate to Bazaar" msgstr "BazaarĘźa Bağış Yap" #. Translators: the %s format specifier will be something along the lines of "0.7.6" etc #: src/bz-donations-dialog.c:227 #, c-format msgid "What's New in %s?" msgstr "%s ile neler yeni?" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "YayÄąn tarihi: %-e %B %Y" #: 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 msgid "Cancel" msgstr "İptal" #: src/bz-entry-selection-row.blp:17 msgid "For This User Only" msgstr "YalnÄązca Bu KullanÄącÄą İçin" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "bu kullanÄącÄą" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "tĂźm kullanÄącÄąlar" #: src/bz-error-dialog.blp:36 src/bz-error.c:69 src/bz-error.c:88 #: src/bz-safety-dialog.blp:46 msgid "Details" msgstr "AyrÄąntÄąlar" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "Kopyala" #: src/bz-error-dialog.c:56 src/bz-share-list.c:62 msgid "Copied!" msgstr "KopyalandÄą!" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "GĂśzde SayÄąsÄą" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" msgstr "GĂśzde gĂźncellenemedi" #: 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-favorites-page.blp:5 src/bz-favorites-page.blp:56 #: src/bz-window.blp:360 msgid "Favorites" msgstr "GĂśzdeler" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "TĂźmĂźnĂź Kur" #: src/bz-favorites-page.blp:34 src/bz-user-data-page.blp:19 msgid "Loading" msgstr "YĂźkleniyor" #: src/bz-favorites-page.blp:49 msgid "No Favorites" msgstr "GĂśzde Yok" #: src/bz-favorites-page.blp:50 msgid "Applications you mark as favorite will appear here" msgstr "GĂśzde olarak imlediğiniz uygulamalar burada gĂśrĂźnecek" # "Bu UygulamayÄą Destekle" diye de çevirmek mĂźmkĂźn fakat bağış daha doğru ve yerelleştirilmiş çeviri olacaktÄąr. İşin içinde zaten para var. #: src/bz-favorites-tile.blp:60 src/bz-installed-tile.blp:69 msgid "Support This Application" msgstr "Bağış Yap" #: src/bz-favorites-tile.blp:109 msgid "Remove From Favorites" msgstr "GĂśzdelerden KaldÄąr" #: src/bz-favorites-tile.c:353 msgid "Failed to remove favorite" msgstr "GĂśzdelerden kaldÄąrÄąlamadÄą" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Önceki" #: src/bz-featured-carousel.blp:54 msgid "Next" msgstr "Sonraki" #: src/bz-flathub-category.c:93 msgid "Editing" msgstr "DĂźzenleme" #: src/bz-flathub-category.c:94 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:95 msgid "Mixer" msgstr "Mixer" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:96 src/bz-search-pill-list.c:77 msgid "Music" msgstr "MĂźzik" #: src/bz-flathub-category.c:97 msgid "Player" msgstr "OynatÄącÄą" #: src/bz-flathub-category.c:98 msgid "Recorder" msgstr "Kaydedici" #: src/bz-flathub-category.c:99 msgid "Sequencer" msgstr "ArdışımlayÄącÄą" #: src/bz-flathub-category.c:100 msgid "Tuner" msgstr "İnce Ayar" #: src/bz-flathub-category.c:101 msgid "TV" msgstr "TV" #: src/bz-flathub-category.c:106 msgid "Emulation" msgstr "ÖykĂźnme" #: src/bz-flathub-category.c:107 msgid "Action" msgstr "Aksiyon" #: src/bz-flathub-category.c:108 msgid "Adventure" msgstr "Macera" #: src/bz-flathub-category.c:109 msgid "Arcade" msgstr "Atari" #: src/bz-flathub-category.c:110 msgid "Blocks" msgstr "Bloklar" #: src/bz-flathub-category.c:111 msgid "Board" msgstr "Tahta" #: src/bz-flathub-category.c:112 msgid "Card" msgstr "Kart" #: src/bz-flathub-category.c:113 msgid "Kids" msgstr "Çocuk" #: src/bz-flathub-category.c:114 msgid "Logic" msgstr "MantÄąk" #: src/bz-flathub-category.c:115 msgid "Role Playing" msgstr "Rol Yapma" #: src/bz-flathub-category.c:116 msgid "Shooter" msgstr "Atış" #: src/bz-flathub-category.c:117 msgid "Simulation" msgstr "Simulasyon" #: src/bz-flathub-category.c:118 msgid "Sports" msgstr "Spor" #: src/bz-flathub-category.c:119 msgid "Strategy" msgstr "Strateji" #: src/bz-flathub-category.c:124 msgid "Audio & Video" msgstr "Ses ve Video" #: src/bz-flathub-category.c:124 msgid "Media" msgstr "Ortam" #: src/bz-flathub-category.c:124 msgid "More Audio & Video" msgstr "Ses ve Video" #: src/bz-flathub-category.c:125 msgid "Developer Tools" msgstr "Geliştirici AraçlarÄą" #: src/bz-flathub-category.c:125 msgid "Develop" msgstr "Geliştir" #: src/bz-flathub-category.c:125 msgid "More Developer Tools" msgstr "Daha Çok Geliştirici AraçlarÄą" #: src/bz-flathub-category.c:126 msgid "Education" msgstr "Eğitim" #: src/bz-flathub-category.c:126 msgid "Learn" msgstr "Öğren" #: src/bz-flathub-category.c:126 msgid "More Education" msgstr "Eğitim" #: src/bz-flathub-category.c:127 msgid "Gaming" msgstr "Oyun" # Oyun Oyna anlamÄąnda Oyna, Oynat değil! #: src/bz-flathub-category.c:127 msgid "Play" msgstr "Oyna" #: src/bz-flathub-category.c:127 msgid "More Gaming" msgstr "Daha Çok Oyun" #: src/bz-flathub-category.c:128 msgid "Graphics & Photography" msgstr "Grafikler ve FotoğrafçĹlÄąk" #: src/bz-flathub-category.c:128 msgid "Create" msgstr "Oluştur" #: src/bz-flathub-category.c:128 msgid "More Graphics & Photography" msgstr "Daha Çok Grafikler ve FotoğrafçĹlÄąk" #: src/bz-flathub-category.c:129 msgid "Networking" msgstr "Ağ" #: src/bz-flathub-category.c:129 msgid "Internet" msgstr "İnternet" #: src/bz-flathub-category.c:129 msgid "More Networking" msgstr "Ağ" #: src/bz-flathub-category.c:130 msgid "Productivity" msgstr "Verimlilik" #: src/bz-flathub-category.c:130 msgid "Work" msgstr "İş" #: src/bz-flathub-category.c:130 msgid "More Productivity" msgstr "Daha Çok Verimlilik" #: src/bz-flathub-category.c:131 msgid "Science" msgstr "Bilim" #: src/bz-flathub-category.c:131 msgid "More Science" msgstr "Bilim" #: src/bz-flathub-category.c:132 msgid "System" msgstr "Sistem" #: src/bz-flathub-category.c:132 msgid "More System" msgstr "Sistem" #: src/bz-flathub-category.c:133 msgid "Utilities" msgstr "Araçlar" #: src/bz-flathub-category.c:133 msgid "Tools" msgstr "Araçlar" #: src/bz-flathub-category.c:133 msgid "More Utilities" msgstr "Daha Çok Araçlar" #: src/bz-flathub-category.c:134 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:148 msgid "Trending" msgstr "Trend" #: src/bz-flathub-category.c:134 msgid "More Trending" msgstr "Daha Çok Trend" #: src/bz-flathub-category.c:135 src/bz-flathub-page.blp:122 #: src/bz-flathub-page.blp:178 msgid "Popular" msgstr "PopĂźler" #: src/bz-flathub-category.c:135 msgid "More Popular" msgstr "Daha Çok PopĂźler" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:168 msgid "Recently Added" msgstr "Son Eklenenler" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:128 msgid "New" msgstr "Yeni" #: src/bz-flathub-category.c:136 msgid "More New" msgstr "Daha Çok Yeni" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:158 msgid "Recently Updated" msgstr "Son GĂźncellenenler" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:134 msgid "Updated" msgstr "GĂźncellendi" #: src/bz-flathub-category.c:137 msgid "More Updated" msgstr "Daha Çok GĂźncellenenler" #: src/bz-flathub-category.c:138 msgid "Mobile" msgstr "Mobil" #: src/bz-flathub-category.c:138 msgid "More Mobile" msgstr "Daha Çok Mobil" #: src/bz-flathub-category.c:139 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:139 msgid "More Adwaita" msgstr "Daha Çok Adwaita" #: src/bz-flathub-category.c:140 msgid "KDE Apps" msgstr "KDE UygulamalarÄą" #: src/bz-flathub-category.c:140 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:200 msgid "App of the Day" msgstr "GĂźnĂźn UygulamasÄą" #: src/bz-flathub-page.blp:264 msgid "On the Go" msgstr "Hareket Halindeyken" #: src/bz-flathub-page.blp:276 msgid "Apps for your Linux phones and tablets" msgstr "Linux telefonlarÄąnÄąz ve tabletleriniz için uygulamalar" #: src/bz-flathub-page.blp:287 src/bz-flathub-page.blp:322 msgid "More Mobile Apps" msgstr "Daha Çok Mobil Uygulama" #: src/bz-flathub-page.blp:378 msgid "We​ ♥​ Games" msgstr "OyunlarÄą ♥​ Severiz" #: src/bz-flathub-page.blp:391 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:425 msgid "More Games" msgstr "Daha Çok Oyun" #: src/bz-full-view.blp:34 src/bz-library-page.blp:78 #: src/bz-library-page.blp:82 msgid "No Results" msgstr "Sonuç Yok" #: src/bz-full-view.blp:35 msgid "Try a different search query" msgstr "Başka arama deneyin" #: src/bz-full-view.blp:41 msgid "Content" msgstr "İçerik" #: src/bz-full-view.blp:105 msgid "" "This is a local preview, some details may differ from the published listing" msgstr "" "Bu, yerel bir Ăśn izlemedir; kimi ayrÄąntÄąlar yayÄąnlanan listelemeden farklÄą " "olabilir" #: src/bz-full-view.blp:108 msgid "Preview Store Appearance" msgstr "Mağaza GĂśrĂźnĂźmĂźnĂź Ön İzle" # Bkz: Support This App çevirisiyle ilgili not. #: src/bz-full-view.blp:234 msgid "_Support" msgstr "_Bağış Yap" #: src/bz-full-view.blp:454 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:541 msgid "Trash Data" msgstr "Çöp Verisi" #: src/bz-full-view.blp:681 msgid "Tags:" msgstr "Etiketler:" #: src/bz-full-view.c:180 msgid "No URL" msgstr "URL Yok" #: src/bz-full-view.c:198 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:199 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:206 msgid "More Apps" msgstr "Daha Çok Uygulama" #: src/bz-full-view.c:207 #, c-format msgid "More Apps by %s" msgstr "Daha Çok %s UygulamalarÄą" #: src/bz-full-view.c:214 msgid "Other Apps by this Developer" msgstr "Bu Geliştiricinin Diğer UygulamalarÄą" #: src/bz-full-view.c:216 src/bz-full-view.c:315 #, c-format msgid "Other Apps by %s" msgstr "Diğer %s UygulamalarÄą" #: src/bz-full-view.c:225 #, 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:317 msgid "Other Apps" msgstr "Diğer Uygulamalar" #: src/bz-full-view.c:319 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d Uygulama" #: 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-install-controls.blp:62 msgid "_Open" msgstr "_Aç" #: src/bz-install-controls.blp:77 src/bz-install-controls.blp:134 msgid "Uninstall Application" msgstr "UygulamayÄą KaldÄąr" #: src/bz-install-controls.blp:87 src/bz-transaction-dialog.c:230 msgid "_Remove" msgstr "_KaldÄąr" #: src/bz-install-controls.blp:121 src/bz-updates-card.c:164 #: src/bz-updates-card.c:183 msgid "Update" msgstr "GĂźncelle" #: src/bz-install-controls.blp:144 src/bz-installed-tile.blp:105 msgid "Remove" msgstr "KaldÄąr" #: src/bz-install-controls.wdgt:32 msgctxt "Install Controls" msgid "Cancel" msgstr "İptal" #: src/bz-install-controls.wdgt:35 msgctxt "Install Controls" msgid "Cancelling" msgstr "İptal ediliyor" #: src/bz-library-page.blp:32 msgid "Search installed apps" msgstr "Kurulu uygulamalarÄą ara" #: src/bz-library-page.blp:50 msgid "Clear search" msgstr "AramayÄą temizle" #: src/bz-library-page.blp:71 msgid "No Apps Found" msgstr "Uygulama BulunamadÄą" #: src/bz-library-page.blp:90 msgid "Search Store Instead" msgstr "Mağazada Ara" #. Translators: . #: src/bz-library-page.blp:100 src/bz-window.blp:111 msgid "Library" msgstr "KitaplÄąk" #: src/bz-library-page.blp:128 msgid "Pending Updates" msgstr "GĂźncellemeler Bekliyor" #: src/bz-library-page.blp:155 msgid "Downloads" msgstr "İndirmeler" #: src/bz-library-page.blp:198 msgid "Recently Uninstalled" msgstr "Son KaldÄąrÄąlanlar" #: src/bz-library-page.blp:249 msgid "Clear Finished Tasks" msgstr "Tamamlanan GĂśrevleri Temizle" #: src/bz-library-page.blp:334 msgid "Sort By" msgstr "SÄąrala" #: src/bz-library-page.blp:348 msgid "Name" msgstr "Ad" #: src/bz-library-page.blp:354 msgid "Size" msgstr "Boyut" #: src/bz-library-page.c:180 #, 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-library-page.c:193 src/bz-updates-card.c:433 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u GĂźncelleme Var" #: src/bz-library-page.c:203 #, c-format msgid "%u Installed App" msgid_plural "%u Installed Apps" msgstr[0] "%u Kurulu Uygulama" #: src/bz-license-dialog.blp:94 msgid "Get Involved" msgstr "KatÄąlÄąm SağlayÄąn" #: src/bz-license-dialog.blp:111 msgid "Learn More" msgstr "Daha Çoğunu Öğren" #: src/bz-license-dialog.c:127 msgid "Unknown License" msgstr "Bilinmeyen Lisans" #: src/bz-license-dialog.c:130 msgid "Community Built" msgstr "Topluluk İnşasÄą" #: src/bz-license-dialog.c:203 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:206 msgid "The license of this app is not known" msgstr "UygulamanÄąn lisansÄą bilinmiyor" #: src/bz-license-dialog.c:212 #, 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:220 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:226 #, 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-license-dialog.c:356 src/bz-safety-dialog.blp:49 msgid "License" msgstr "Lisans" #: 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:110 msgid "Finish" msgstr "Bitti" #: src/bz-login-page.c:664 #, c-format msgid "Hello, %s!" msgstr "Merhaba, %s!" #: src/bz-metainfo-preview.c:84 msgid "Select Metainfo File" msgstr "Metainfo DosyasÄą Seç" #: src/bz-metainfo-preview.c:87 msgid "Metainfo Files" msgstr "Metainfo DosyalarÄą" #: src/bz-metainfo-preview.c:141 msgid "Select Icon (Optional)" msgstr "Simge Seç (İsteğe bağlÄą)" #: src/bz-metainfo-preview.c:144 msgid "Image Files" msgstr "Resim DosyalarÄą" #: src/bz-metainfo-preview.c:231 msgid "Preview" msgstr "Ön İzle" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Tercihler" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data refresh is paused" msgstr "" "Ağ bağlantÄąsÄą ĂślçßlĂź — kendiliğinden mağaza verilerinin yenilenmesi " "duraklatÄąldÄą" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:258 msgid "Refresh Manually" msgstr "Elle Yenile" #: 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 End-of-Life 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:126 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.blp:89 msgid "Vertical Stripes" msgstr "Dikey Çizgiler" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from left to right" msgstr "Bayrak renklerini soldan sağa gĂśrĂźntĂźle" #: 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 "Lesbian Pride Colors" msgstr "Lesbian Pride Colors" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "Male Homosexual Pride Colors" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Transgender Pride Colors" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Nonbinary Pride Colors" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "Bisexual Pride Colors" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "Asexual Pride Colors" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Pansexual Pride Colors" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Aromantic Pride Colors" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Genderfluid Pride Colors" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Polysexual Pride Colors" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Omnisexual Pride Colors" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "Aroace Pride Colors" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "Agender Pride Colors" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "Genderqueer Pride Colors" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "Intersex Pride Colors" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "Demigender Pride Colors" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "Biromantic Pride Colors" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "Disability Pride Colors" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "Femboy Pride Colors" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "Neutrois Pride Colors" #: src/bz-releases-dialog.blp:5 src/bz-updates-card.c:155 msgid "Version History" msgstr "SĂźrĂźm Geçmişi" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "_SĂźrĂźm Geçmişi" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "BugĂźn" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "DĂźn" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "%d gĂźn Ăśnce" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "%d hafta Ăśnce" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "%d ay Ăśnce" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "%d yÄąl Ăśnce" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%e %B %Y" #: src/bz-releases-list.c:196 #, c-format msgid "Version %s" msgstr "SĂźrĂźm %s" #: src/bz-releases-list.c:251 msgid "No details for this release" msgstr "Bu sĂźrĂźm için ayrÄąntÄą yok" #: src/bz-releases-list.c:263 msgid "Get More Information" msgstr "Daha Çok Bilgi" #: src/bz-rich-app-tile.blp:158 msgid "Get" msgstr "Al" #: src/bz-rich-app-tile.blp:173 msgid "Uninstall" msgstr "KaldÄąr" #: src/bz-safety-calculator.c:87 msgid "Unknown Permissions" msgstr "Bilinmeyen İzinler" #: src/bz-safety-calculator.c:88 msgid "Permissions are missing for this app." msgstr "Bu uygulama için izinler eksik." #: src/bz-safety-calculator.c:101 msgid "No Permissions" msgstr "İzin Yok" #: src/bz-safety-calculator.c:102 msgid "App is fully sandboxed" msgstr "Uygulama tĂźmĂźyle yalÄątÄąlmış alandadÄąr" #: src/bz-safety-calculator.c:108 msgid "Network Access" msgstr "Ağ Erişimi" #: src/bz-safety-calculator.c:109 msgid "Can access the internet" msgstr "İnternete erişebilir" #: src/bz-safety-calculator.c:111 msgid "No Network Access" msgstr "Ağ Erişimi Yok" #: src/bz-safety-calculator.c:112 msgid "Cannot access the internet" msgstr "İnternete erişemez" #: src/bz-safety-calculator.c:117 msgid "User Device Access" msgstr "KullanÄącÄą AygÄątÄą Erişimi" #: src/bz-safety-calculator.c:118 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:120 msgid "No User Device Access" msgstr "KullanÄącÄą AygÄątÄą Erişimi Yok" #: src/bz-safety-calculator.c:121 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:126 msgid "Input Device Access" msgstr "Girdi AygÄątÄą Erişimi" #: src/bz-safety-calculator.c:127 msgid "Can access input devices" msgstr "Girdi aygÄątlarÄąna erişebilir" #: src/bz-safety-calculator.c:133 msgid "Microphone Access and Audio Playback" msgstr "Mikrofon Erişimi ve Ses OynatÄąmÄą" #: src/bz-safety-calculator.c:134 msgid "Can listen using microphones and play audio without asking permission" msgstr "İzin istemeden mikrofonlarla dinleyebilir ve sesleri oynatabilir" #: src/bz-safety-calculator.c:140 msgid "System Device Access" msgstr "Sistem AygÄątÄą Erişimi" #: src/bz-safety-calculator.c:141 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:147 msgid "Screen Contents Access" msgstr "Ekran İçerikleri Erişimi" #: src/bz-safety-calculator.c:148 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:154 msgid "Legacy Windowing System" msgstr "Eski Pencereleme Sistemi" #: src/bz-safety-calculator.c:155 msgid "Always uses a legacy windowing system (X11)" msgstr "Daima eski pencereleme sistemi kullanÄąr (X11)" #: src/bz-safety-calculator.c:161 msgid "Arbitrary Permissions" msgstr "İsteğe BağlÄą İzinler" #: src/bz-safety-calculator.c:162 msgid "Can acquire arbitrary permissions" msgstr "İsteğe bağlÄą izinler edinir" #: src/bz-safety-calculator.c:168 msgid "User Settings" msgstr "KullanÄącÄą AyarlarÄą" #: src/bz-safety-calculator.c:169 msgid "Can access and change user settings" msgstr "KullanÄącÄą ayarlarÄąna erişebilir ve değiştirebilir" #: src/bz-safety-calculator.c:175 msgid "Full File System Read/Write Access" msgstr "TĂźm Dosya Sistemini Okuma/Yazma Erişimi" #: src/bz-safety-calculator.c:176 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:183 msgid "Home Folder Read/Write Access" msgstr "Ev KlasĂśrĂź Okuma/Yazma Erişimi" #: src/bz-safety-calculator.c:184 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:191 msgid "Full File System Read Access" msgstr "TĂźm Dosya Sistemini Okuma Erişimi" #: src/bz-safety-calculator.c:192 msgid "Can read all data on the file system" msgstr "Dosya sistemindeki tĂźm veriyi okuyabilir" #: src/bz-safety-calculator.c:200 msgid "Home Folder Read Access" msgstr "Ev KlasĂśrĂź Okuma Erişimi" #: src/bz-safety-calculator.c:201 msgid "Can read all data in your home directory" msgstr "Ev dizininizdeki tĂźm verinizi okuyabilir" #: src/bz-safety-calculator.c:209 msgid "Download Folder Read/Write Access" msgstr "İndirilenler KlasĂśrĂź Okuma/Yazma Erişimi" #: src/bz-safety-calculator.c:210 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:220 msgid "Download Folder Read Access" msgstr "İndirilenler KlasĂśrĂź Okuma Erişimi" #: src/bz-safety-calculator.c:221 msgid "Can read all data in your downloads directory" msgstr "İndirilenler dizininizdeki tĂźm veriyi okuyabilir" #: src/bz-safety-calculator.c:242 msgid "Can read and write all data in the directory" msgstr "Dizindeki tĂźm veriyi okuyabilir ve yazabilir" #: src/bz-safety-calculator.c:266 msgid "Can read all data in the directory" msgstr "Dizindeki tĂźm veriyi okuyabilir" #: src/bz-safety-calculator.c:281 msgid "No File System Access" msgstr "Dosya Sistemi Erişimi Yok" #: src/bz-safety-calculator.c:282 msgid "Cannot access the file system at all" msgstr "Dosya sistemine asla erişemez" #: src/bz-safety-calculator.c:289 msgid "Uses System Services" msgstr "Sistem Hizmetlerini KullanÄąr" #: src/bz-safety-calculator.c:290 msgid "Can request data from non-portal system services" msgstr "KapÄą dışı sistem hizmetlerinden veri isteyebilir" #: src/bz-safety-calculator.c:296 msgid "Uses Session Services" msgstr "Oturum Hizmetlerini KullanÄąr" #: src/bz-safety-calculator.c:297 msgid "Can request data from non-portal session services" msgstr "KapÄą dışı oturum hizmetlerinden veri isteyebilir" #: src/bz-safety-calculator.c:345 msgid "No Service Access" msgstr "Hizmet Erişimi Yok" #: src/bz-safety-calculator.c:346 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:354 msgid "Verified App Developer" msgstr "Doğrulanmış Uygulama Geliştiricileri" #: src/bz-safety-calculator.c:355 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:364 msgid "Proprietary Code" msgstr "Sahipli Kod" #: src/bz-safety-calculator.c:365 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:375 msgid "Auditable Code" msgstr "Denetlenebilir Kod" #: src/bz-safety-calculator.c:376 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:516 #, c-format msgid "Use the %s System Service" msgstr "%s Sistem Hizmetini Kullan" #: src/bz-safety-calculator.c:520 #, c-format msgid "Use the %s Session Service" msgstr "%s Oturum Hizmetini Kullan" #: src/bz-safety-calculator.c:524 #, c-format msgid "Use the %s Service" msgstr "%s Hizmetini Kullan" #: src/bz-safety-calculator.c:534 msgid "Can see the non-portal service" msgstr "KapÄą dışı hizmetleri gĂśrebilir" #: src/bz-safety-calculator.c:536 msgid "Can talk to the non-portal service" msgstr "KapÄą dışı hizmetlere konuşabilir" #: src/bz-safety-calculator.c:538 msgid "Can own the non-portal service" msgstr "KapÄą dışı hizmet edinebilir" #: src/bz-safety-calculator.c:553 msgid "Global Menu Integration" msgstr "KĂźresel MenĂź TĂźmleşimi" #: src/bz-safety-calculator.c:554 msgid "Can display its menus in a global menu bar" msgstr "MenĂźlerini genel menĂź çubuğunda gĂśrĂźntĂźleyebilir" #: src/bz-safety-calculator.c:559 msgid "KDE Settings Integration" msgstr "KDE AyarlarÄą TĂźmleşimi" #: src/bz-safety-calculator.c:560 msgid "Can detect when KDE desktop settings change" msgstr "KDE masaĂźstĂź ayarlarÄą değiştiğinde algÄąlayabilir" #: src/bz-safety-calculator.c:565 msgid "KDE Global Settings" msgstr "KDE Genel Ayarlar" #: src/bz-safety-calculator.c:566 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "KDE masaĂźstĂź tercihlerini (yazÄą tipleri ve renkler gibi) okuyabilir" #: src/bz-safety-calculator.c:571 msgid "Secret Storage Service" msgstr "Gizli Depolama Hizmeti" #: src/bz-safety-calculator.c:572 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "" "Sistem anahtarlığı kullanarak kendi parolalarÄąnÄą saklayabilir ve geri " "getirebilir" #: src/bz-safety-calculator.c:577 msgid "Desktop Notifications Service" msgstr "MasaĂźstĂź Bildirim Hizmeti" #: src/bz-safety-calculator.c:578 msgid "Can send desktop notifications" msgstr "MasaĂźstĂź bildirimleri gĂśnderebilir" #: src/bz-safety-calculator.c:584 msgid "System Tray Integration" msgstr "Sistem Tepsisi TĂźmleşimi" #: src/bz-safety-calculator.c:585 msgid "Can display an icon in the system tray" msgstr "Sistem tepsisinde simge gĂśsterebilir" #: src/bz-safety-calculator.c:590 msgid "KDE Connect Integration" msgstr "KDE Connect TĂźmleşimi" #: src/bz-safety-calculator.c:591 msgid "Can interact with devices paired via KDE Connect" msgstr "KDE Connect aracÄąlığıyla eşleştirilen aygÄątlarla etkileşime girebilir" #: src/bz-safety-dialog.blp:59 msgid "App ID" msgstr "Uygulama Kimliği" #: src/bz-safety-dialog.blp:69 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: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 "" "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:167 msgid "Safety" msgstr "GĂźvenlik" #: src/bz-safety-dialog.c:226 #, c-format msgid "%s is Safe" msgstr "%s GĂźvenilir" #: src/bz-safety-dialog.c:231 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s GĂźvenli Olmayan İzinleri Yok" #: src/bz-safety-dialog.c:236 #, c-format msgid "%s is Probably Safe" msgstr "%s Muhtemelen GĂźvenli" #: src/bz-safety-dialog.c:241 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s GĂźvenilir Olmayabilir" #: src/bz-safety-dialog.c:246 #, 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:150 msgid "Reset View" msgstr "GĂśrĂźnĂźmĂź SÄąfÄąrla" #: src/bz-screenshot-page.blp:161 msgid "Zoom Out" msgstr "UzaklaştÄąr" #: src/bz-screenshot-page.blp:171 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:117 msgid "Open Screenshot Viewer" msgstr "Ekran GĂśrĂźntĂźsĂź GĂśrĂźntĂźleyiciyi Aç" #: src/bz-search-filter-popover.blp:18 src/bz-search-page.blp:83 msgid "Filters" msgstr "SĂźzgeçler" #: src/bz-search-filter-popover.blp:35 msgid "_Verified" msgstr "_Doğrulanmış" #: src/bz-search-filter-popover.blp:42 msgid "_Free/Open" msgstr "Ö_zgĂźr/AçĹk Kaynak" #: src/bz-search-filter-popover.blp:49 msgid "Non-_EOL" msgstr "_Yaşam DĂśngĂźsĂźnde" #: src/bz-search-filter-popover.blp:52 msgid "Filter out End-of-Life apps" msgstr "ÖmrĂźnĂźn Sonuna Gelmiş UygulamalarÄą SĂźz" #: src/bz-search-filter-popover.blp:57 msgid "Categories" msgstr "Kategoriler" #: src/bz-search-page.blp:58 msgid "Search Apps, Games, Software" msgstr "UygulamalarÄą, OyunlarÄą, YazÄąlÄąmlarÄą Ara" #: src/bz-search-page.blp:70 msgid "Search Filters" msgstr "Arama SĂźzgeçleri" #: src/bz-search-page.blp:100 msgid "Clear Search" msgstr "AramayÄą Temizle" #: src/bz-search-page.blp:192 msgid "Categories Unavailable" msgstr "Kategoriler KullanÄąlamÄąyor" #: src/bz-search-page.blp:193 msgid "Search for apps using the search bar above." msgstr "YukarÄądaki arama çubuğunu kullanarak uygulamalarÄą ara." #: src/bz-search-page.blp:219 msgid "Browse Categories" msgstr "Kategorilere GĂśz At" #: src/bz-search-page.blp:361 msgid "No Applications Found" msgstr "Uygulama BulunamadÄą." #: src/bz-search-page.c:247 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "FlathubĘźda \"%s\" için sonuç bulunamadÄą" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "Video" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "Ofis" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "Takvim" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "İletişim" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Paint" msgstr "Boyama" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "Torrent" msgstr "Torrent" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Emulator" msgstr "ÖykĂźnĂźcĂź" #: src/bz-share-list.c:123 msgid "Copy Link" msgstr "BağlantÄąyÄą Kopyala" #: src/bz-share-list.c:134 msgid "Open Link" msgstr "BağlantÄąyÄą Aç" # Konumu gereği başlÄąk dĂźzeni kullanÄąldÄą. AyrÄąca Zaman Çizgisi yerine Zaman Çizelgesi çevirisi yeğlendi. #: src/bz-stats-dialog.blp:27 msgid "Timeline" msgstr "Zaman Çizelgesi" #: src/bz-stats-dialog.blp:45 msgid "Installs:" msgstr "Kurulum SayÄąsÄą:" #: src/bz-stats-dialog.blp:54 msgid "World" msgstr "DĂźnya" #: src/bz-stats-dialog.blp:68 msgid "Since 4/15/2024" msgstr "15 Nisan 2024 tarihinden beri" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:125 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM Toplam Kurulum" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:128 #, c-format msgid "%.2fK Total Installs" msgstr "%.2fK Toplam Kurulum" #: src/bz-stats-dialog.c:130 #, c-format msgid "%'d Total Installs" msgstr "%'d Toplam Kurulum" #: src/bz-tag-list.c:78 msgid "No Results Found" msgstr "Hiçbir Sonuç BulunamadÄą" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "\"%s\" Etiketli Uygulamalar" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "Arama başarÄąsÄąz" #: src/bz-transaction-dialog.c:154 msgid "Keep User Data" msgstr "KullanÄącÄą Verisini Tut" #: src/bz-transaction-dialog.c:155 msgid "Allow restoring personal settings & content" msgstr "Kişisel ayarlarÄąn ve içeriğin geri yĂźklenmesine izin ver" #: src/bz-transaction-dialog.c:164 msgid "Delete All Data" msgstr "TĂźm Verileri Sil" #: src/bz-transaction-dialog.c:165 msgid "Permanently erase user data to save space" msgstr "Disk alanÄąnÄą korumak için kullanÄącÄą verisini sil" #: src/bz-transaction-dialog.c:190 #, c-format msgid "Install %s?" msgstr "%s Kurulsun Mu?" #: src/bz-transaction-dialog.c:195 msgid "" "Select which version to install. May install additional shared components" msgstr "Hangi sĂźrĂźmĂźn kurulacağınÄą seç. Ek paylaşımlÄą bileşenler kurabilir" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "Ek paylaşımlÄą bileşenler kurabilir" #: src/bz-transaction-dialog.c:200 src/bz-transaction-dialog.c:229 #: src/bz-transaction-dialog.c:274 src/bz-transaction-dialog.c:576 msgid "_Cancel" msgstr "İ_ptal" #: src/bz-transaction-dialog.c:201 msgid "_Install" msgstr "_Kur" #: src/bz-transaction-dialog.c:218 #, c-format msgid "Remove %s?" msgstr "%s KaldÄąrÄąlsÄąn MÄą?" #: src/bz-transaction-dialog.c:221 msgid "Select which version to remove." msgstr "Hangi sĂźrĂźmĂźn kaldÄąrÄąlacağınÄą seç." #: src/bz-transaction-dialog.c:223 #, 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:246 #, c-format msgid "“%s” is High Risk" msgstr "“%s” Çok Riskli" #: src/bz-transaction-dialog.c:250 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:259 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:275 msgid "_Install Anyway" msgstr "Yine De _Kur" #: src/bz-transaction-dialog.c:330 msgid "Failed to load transaction dialog" msgstr "İşlem iletişim kutusu yĂźklenemedi" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "TĂźm uygulamalar zaten kurulmuş" #: src/bz-transaction-dialog.c:549 msgid "_OK" msgstr "_Tamam" #: src/bz-transaction-dialog.c:565 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "%u Uygulama Kurulsun Mu?" #: src/bz-transaction-dialog.c:573 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "Aşağıdakiler yĂźklenecek. Ek ortak bileşenler de kurulabilir" #: src/bz-transaction-dialog.c:574 #, c-format msgid "%d addons will be installed." msgstr "%d eklenti kurulacak." #: src/bz-transaction-dialog.c:575 msgid "Additionally, addons will be installed." msgstr "AyrÄąca, uzantÄąlar kurulacak." #: src/bz-transaction-dialog.c:577 msgid "_Install All" msgstr "TĂźmĂźnĂź _Kur" #: src/bz-transaction-manager.c:795 #, c-format msgid "Finished in %.02f seconds" msgstr "%.02f saniyede bitti" #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "Uygulama Eklentisi" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "Çalışma ZamanÄą" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "Kuyrukta" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "Bitti" #: src/bz-transaction-tile.blp:230 msgid "Cancelled" msgstr "İptal edildi" #: src/bz-transaction-tile.blp:254 msgid "Error" msgstr "Hata" #: src/bz-transaction-tile.blp:312 msgid "Cancel Transaction" msgstr "İşlemi İptal Et" #: src/bz-transaction-tile.blp:436 msgid "Show Error Info" msgstr "Hata Bilgisini GĂśster" #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "%s Temizlendi" # Transaction dese de para ile ilgisi yok. O sebeple sadece İşlemler diye çevirdim. #: src/bz-transaction-tile.c:360 src/bz-transaction-tile.c:363 msgid "Transaction Error" msgstr "İşlem HatasÄą" #: src/bz-transaction.c:344 msgid "Pending" msgstr "Beklemede" #: src/bz-updates-card.blp:23 msgid "_Update All" msgstr "TĂźmĂźnĂź _GĂźncelle" #: src/bz-updates-card.c:211 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "%u Çalışma ZamanÄą GĂźncellemesi" #: 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:33 msgid "No User Data Found" msgstr "KullanÄącÄą Verisi bulunamadÄą" #: src/bz-user-data-page.blp:38 msgid "User Data" msgstr "KullanÄącÄą Verisi" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "KullanÄącÄą Verisini Çöpe Taşı" #: 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-window.blp:87 msgid "Curated" msgstr "Özelleştirilmiş" #: src/bz-window.blp:99 msgid "Explore" msgstr "Keşfet" #: src/bz-window.blp:219 msgid "Refresh completed!" msgstr "Yenileme tamamlandÄą!" #: src/bz-window.blp:238 msgid "Main Menu" msgstr "Ana MenĂź" #: src/bz-window.blp:249 msgid "You are running a new version of Bazaar!" msgstr "BazaarʟĹn yeni bir sĂźrĂźmĂźnĂź kullanÄąyorsunuz!" #: src/bz-window.blp:250 msgid "See What's New" msgstr "Neler Yeni GĂśr" #: src/bz-window.blp:257 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:302 msgid "_Donate to Bazaar" msgstr "BazaarĘźa _Bağış Yap" #: src/bz-window.blp:309 msgid "_Refresh" msgstr "_Yenile" #: src/bz-window.blp:314 msgid "_Preferences" msgstr "_Tercihler" #: src/bz-window.blp:319 msgid "_Login With Flathub" msgstr "Flathub İle _Oturum Aç" #: src/bz-window.blp:325 msgid "_Manage Leftover User Data" msgstr "ArtÄąk KullanÄącÄą Verisini _YĂśnet" #: src/bz-window.blp:330 msgid "_Keyboard Shortcuts" msgstr "_Klavye KÄąsayollarÄą" #: src/bz-window.blp:335 msgid "_About Bazaar" msgstr "Bazaar _HakkÄąnda" #: src/bz-window.blp:342 msgid "_Quit Bazaar" msgstr "BazaarĘźdan Çı_k" #: src/bz-window.blp:367 msgid "Log Out" msgstr "Oturumu Kapat" #. Translators: %s is the title of the current page #: src/bz-window.c:376 #, c-format msgid "Bazaar — %s" msgstr "Bazaar — %s" #: src/bz-window.c:585 src/bz-window.c:623 msgid "Failed to launch application" msgstr "Uygulama başlatÄąlamadÄą" #: src/bz-window.c:830 msgid "You can't remove Bazaar from Bazaar!" msgstr "BazaarʟĹ Bazaar ile kaldÄąramazsÄąnÄąz!" #: src/bz-window.c:1114 src/bz-window.c:1148 msgid "Can't do that right now!" msgstr "Şimdi yapma!" #. Translators: As in, "1 Install" / "100 Installs" #: src/bz-world-map.c:604 msgid "Install" msgid_plural "Installs" msgstr[0] "Kurulum" #: src/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Genel" #: src/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Page" msgstr "Arama SayfasÄąnÄą Aç" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "KitaplÄąk SayfasÄąnÄą Aç" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Refresh" msgstr "Yenile" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Tercihleri Aç" #: src/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "KÄąsayollarÄą GĂśster" #: src/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Close Window" msgstr "Pencereyi Kapat" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "BazaarĘźdan Çık" bazaar-org-bazaar-43ce9f7/po/uk.po000066400000000000000000001725401520414637400170370ustar00rootroot00000000000000# 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 "Вийти" bazaar-org-bazaar-43ce9f7/po/vi.po000066400000000000000000001376061520414637400170420ustar00rootroot00000000000000# 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" bazaar-org-bazaar-43ce9f7/po/zh_CN.po000066400000000000000000002553261520414637400174250ustar00rootroot00000000000000# # <>, 2025-2026. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-05-06 14:13+0800\n" "PO-Revision-Date: 2026-05-09 19:20+0800\n" "Last-Translator: <>\n" "Language-Team: Abkhazian\n" "Language: ab\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Gtranslator 50.0\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:45 #: src/bz-window.c:374 src/bz-window.c:375 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:16 msgid "New Window" msgstr "新窗口" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and manage applications" msgstr "发现和管理应用" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A fast and modern app store for Linux with a focus on discovering and " "installing Flatpak apps and addons, particularly from Flathub." msgstr "" "一款专为 Linux 设计的快速且现代的应用商店,致力于从 Flatpak 远程仓库(特别是 " "Flathub)中发现并安装应用程序及插件。" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 msgid "Queue multiple installs and keep browsing" msgstr "排队安装多个程序,同时继续浏览" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:16 msgid "Easily view app permissions" msgstr "轻松地检查应用权限" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:17 msgid "Sign in to Flathub to view and manage your favorites" msgstr "登录 Flathub 以管理收藏项目" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:18 msgid "Search apps directly from GNOME Shell" msgstr "直接从GNOME Shell中搜索应用" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:30 src/bz-application.c:758 msgid "The Bazaar Contributors" msgstr "Bazaar 的贡献者们" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "The home page displaying Flathub apps" msgstr "展示 Flathub 应用程序的主页" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:59 msgid "Exhibit app page" msgstr "展示应用页面" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:63 msgid "Library page" msgstr "库" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:67 msgid "Search page" msgstr "搜索页" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:71 msgid "Category page" msgstr "分类页" #: src/bz-addon-tile.blp:49 src/bz-installed-tile.blp:64 #: src/bz-rich-app-tile.blp:140 msgid "Stopped Receiving Updates" msgstr "停止接收更新" #: src/bz-addon-tile.c:155 src/bz-favorites-tile.c:157 #: src/bz-rich-app-tile.blp:172 msgid "Uninstall" msgstr "卸载" #: src/bz-addon-tile.c:157 src/bz-favorites-tile.c:159 msgid "Install" msgstr "安装" #: src/bz-addons-dialog.blp:14 src/bz-addons-dialog.blp:21 #: src/bz-addons-dialog.blp:70 src/bz-full-view.blp:606 #: src/bz-installed-tile.blp:101 msgid "Manage Add-Ons" msgstr "管理附加组件" #: src/bz-addons-dialog.blp:80 msgid "No Add-Ons Visible" msgstr "无可见附加组件" #: src/bz-addons-dialog.blp:81 msgid "" "Your current filter preferences are hiding all known add-ons. Try adjusting " "them." msgstr "您当前的过滤偏好设置隐藏了所有已知的附加组件。请尝试调整它们。" #: src/bz-addons-dialog.blp:88 msgid "Add-on Page" msgstr "附加组件" #: src/bz-addons-dialog.blp:202 src/bz-full-view.blp:404 msgid "Downloads/Month" msgstr "次下载/㜈" #: src/bz-addons-dialog.blp:229 src/bz-full-view.blp:440 msgid "Stopped Receiving Core Updates" msgstr "停止接收核心更新" #: src/bz-addons-dialog.blp:243 msgid "" "This add-on uses a runtime that no longer receives updates or security " "fixes. It may become unsafe to use." msgstr "" "此应用使用的运行时环境已不再接收更新或安全修复,继续使用可能存在安全隐患" #: src/bz-addons-dialog.c:330 #, c-format msgid "Add-on for %s" msgstr "%s 的附加组件" #: src/bz-addons-dialog.c:344 src/bz-full-view.c:568 msgid "Show Less" msgstr "显示更少" #: src/bz-addons-dialog.c:344 src/bz-full-view.c:568 msgid "Show More" msgstr "显示更多" #: src/bz-addons-dialog.c:394 msgid "Download Stats" msgstr "下载状态" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:736 src/bz-context-tile-callbacks.c:186 #: src/bz-context-tile-callbacks.c:193 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:686 src/bz-context-tile-callbacks.c:176 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:711 msgctxt "Age rating" msgid "All" msgstr "所有" #: src/bz-age-rating-dialog.c:747 #, c-format msgid "%s has an unknown age rating" msgstr "%s 的年龄分级未知" #: src/bz-age-rating-dialog.c:753 #, c-format msgid "%s is suitable for everyone" msgstr "%s 适合所有人" #: src/bz-age-rating-dialog.c:756 #, c-format msgid "%s is suitable for young children" msgstr "%s 适合幼儿使用" #: src/bz-age-rating-dialog.c:759 #, c-format msgid "%s is suitable for children" msgstr "%s 适合儿童" #: src/bz-age-rating-dialog.c:762 #, c-format msgid "%s is suitable for teenagers" msgstr "%s 适合青少年" #: src/bz-age-rating-dialog.c:765 #, c-format msgid "%s is suitable for adults" msgstr "%s 适合成人用户" #: src/bz-age-rating-dialog.c:768 #, c-format msgid "%s is suitable for %s" msgstr "%s 适合 %s" #: src/bz-age-rating-dialog.c:862 #, c-format msgid "%s • %s" msgstr "%s • %s" #: 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:26 src/bz-app-size-dialog.blp:52 msgid "Download Size" msgstr "下载大小" #: src/bz-app-size-dialog.blp:53 msgid "Amount to download from the internet" msgstr "从互联网下载的大小" #: src/bz-app-size-dialog.blp:73 msgid "Installed Size" msgstr "已安装占用" #: src/bz-app-size-dialog.blp:74 msgid "Size on Disk" msgstr "硬盘占用" #: src/bz-app-size-dialog.blp:121 msgid "Open user data folder" msgstr "打开用户数据文件夹" #: src/bz-app-size-dialog.blp:131 msgid "User Data Size" msgstr "用户数据大小" #: src/bz-app-size-dialog.blp:132 msgid "Caches, settings, and other app data" msgstr "缓存、设置和其他应用数据" #: src/bz-app-size-dialog.c:99 msgid "Installed Runtime Size" msgstr "已安装运行时占用" #: src/bz-app-size-dialog.c:99 msgid "Runtime Download Size" msgstr "运行时下载大小" #: src/bz-app-size-dialog.c:204 msgid "App Size" msgstr "应用大小" #: src/bz-app-tile.blp:57 src/bz-developer-badge.c:98 #: src/bz-rich-app-tile.blp:104 src/bz-rich-app-tile.c:304 msgid "Verified" msgstr "已验证" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:88 src/bz-context-tile-callbacks.c:135 #: src/bz-releases-list.c:206 msgid "Installed" msgstr "已安装" #: src/bz-application.c:737 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:738 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:761 msgid "translator-credits" msgstr "Shinsei , 2025" #: src/bz-application.c:771 msgid "Special Thanks" msgstr "特别感谢" #: src/bz-application.c:829 msgid "Logged Out Successfully!" msgstr "登出成功!" #: src/bz-application.c:968 msgid "Performing setup…" msgstr "正在执行设置..." #: src/bz-application.c:1054 msgid "Set Up System Flathub?" msgstr "在系统配置 Flathub?" #: src/bz-application.c:1057 msgid "" "The system Flathub remote is not set up. Bazaar requires Flathub to be " "configured on the system Flatpak installation to browse and install " "applications.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "未设置 Flathub 远程仓库。Bazaar 需要在系统 Flatpak 安装中配置 Flathub 才能浏" "览和安装应用程序。\n" "\n" "您仍然可以使用 Bazaar 来浏览和移除已安装的应用。" #: src/bz-application.c:1064 msgid "Set Up Flathub?" msgstr "注册 Flathub?" #: src/bz-application.c:1067 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:1073 msgid "Later" msgstr "稍后" #: src/bz-application.c:1074 msgid "Set Up Flathub" msgstr "注册 Flathub" #: src/bz-application.c:1291 src/bz-application.c:1778 msgid "Checking for updates…" msgstr "正在检查更新" #: src/bz-application.c:1411 msgid "A backend error occurred" msgstr "后端发生错误" #: src/bz-application.c:1611 src/bz-application.c:3655 src/bz-window.blp:69 msgid "Refreshing…" msgstr "正在刷新……" #: src/bz-application.c:1775 src/bz-application.c:3653 #, c-format msgid "Loading %d apps…" msgstr "正在加载 %d 应用" #: src/bz-application.c:1833 msgid "Failed to open file" msgstr "文件打开文件失败" #: src/bz-application.c:1918 msgid "An initialization error occurred" msgstr "一个初始化错误发生了" #: src/bz-application.c:2339 msgid "Failed to check for updates" msgstr "无法检查更新" #: src/bz-application.c:3373 msgid "Could not find app" msgstr "无法找到应用" #: src/bz-application.c:3406 msgid "Failed to load metainfo" msgstr "无法加载元信息" #: src/bz-application.c:3657 msgid "Writing to cache…" msgstr "正在写入缓存" #: src/bz-apps-page.blp:86 msgid "Show All" msgstr "展示所有" #: src/bz-apps-page.c:229 #, c-format msgid "All \"%s\"" msgstr "所有 \"%s\"" #: src/bz-apps-page.c:478 src/bz-tag-list.c:91 #, c-format msgid "%d Applications" msgstr "%d 个应用" #: src/bz-appstream-parser.c:303 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub 页面" #: src/bz-appstream-parser.c:324 msgctxt "Project URL Type" msgid "Project Website" msgstr "项目网站" #: src/bz-appstream-parser.c:328 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "问题追踪器" #: src/bz-appstream-parser.c:332 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-appstream-parser.c:336 msgctxt "Project URL Type" msgid "Help" msgstr "帮助" #: src/bz-appstream-parser.c:340 msgctxt "Project URL Type" msgid "Donate" msgstr "捐助" #: src/bz-appstream-parser.c:346 msgctxt "Project URL Type" msgid "Translate" msgstr "翻译" #: src/bz-appstream-parser.c:350 msgctxt "Project URL Type" msgid "Contact" msgstr "联系" #: src/bz-appstream-parser.c:354 msgctxt "Project URL Type" msgid "Source Code" msgstr "源䝣码" #: src/bz-appstream-parser.c:360 msgctxt "Project URL Type" msgid "Contribute" msgstr "贡献" #: src/bz-bundle-install-dialog.c:240 msgid "Installing" msgstr "正在安装" #: src/bz-bundle-install-dialog.c:254 msgid "Installed!" msgstr "已安装!" #: src/bz-context-tile-callbacks.c:68 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-context-tile-callbacks.c:75 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-context-tile-callbacks.c:82 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-context-tile-callbacks.c:92 #, c-format msgid "%d downloads in the last month" msgstr "过去 30 天内下载 %d 揥" #: src/bz-context-tile-callbacks.c:104 src/bz-context-tile-callbacks.c:389 #: src/bz-context-tile-callbacks.c:406 msgid "N/A" msgstr "N/A" #: src/bz-context-tile-callbacks.c:132 #, c-format msgid "+%s runtime" msgstr "+%s 运行时" #: src/bz-context-tile-callbacks.c:135 msgid "Download" msgstr "下载" #: src/bz-context-tile-callbacks.c:155 msgid "Size information unavailable" msgstr "大小信息不可用" #: src/bz-context-tile-callbacks.c:158 #, c-format msgid "Download size of %s" msgstr "%s 的下载大小" #: src/bz-context-tile-callbacks.c:191 msgid "All Ages" msgstr "全年龄" #: src/bz-context-tile-callbacks.c:203 msgid "Age rating information unavailable" msgstr "年龄分级信息不可用" #: src/bz-context-tile-callbacks.c:208 msgid "Suitable for all ages" msgstr "适合全年龄段" #: src/bz-context-tile-callbacks.c:210 #, c-format msgid "Suitable for ages %d and up" msgstr "适合年龄为 %d 岁及以上" #: src/bz-context-tile-callbacks.c:243 src/bz-context-tile-callbacks.c:248 #: src/bz-context-tile-callbacks.c:276 src/bz-context-tile-callbacks.c:284 msgid "Unknown" msgstr "未知" #: src/bz-context-tile-callbacks.c:253 #, c-format msgid "Free software licensed under %s" msgstr "根据 %s 许可证授权的自由软件" #: src/bz-context-tile-callbacks.c:258 msgid "Free software" msgstr "自由软件" #: src/bz-context-tile-callbacks.c:261 msgid "Proprietary Software" msgstr "专有软件" #: src/bz-context-tile-callbacks.c:264 #, c-format msgid "Special License: %s" msgstr "特殊许可证: %s" #: src/bz-context-tile-callbacks.c:281 msgid "Free" msgstr "自由" #: src/bz-context-tile-callbacks.c:287 src/bz-license-dialog.c:133 msgid "Proprietary" msgstr "专有" #: src/bz-context-tile-callbacks.c:289 src/bz-license-dialog.c:135 msgid "Special License" msgstr "特殊许可" #: src/bz-context-tile-callbacks.c:309 msgid "Adaptive" msgstr "自适应" #: src/bz-context-tile-callbacks.c:309 msgid "Desktop Only" msgstr "仅桌面端" #: src/bz-context-tile-callbacks.c:315 msgid "Works on desktop, tablets, and phones" msgstr "适用于台式机、平板电脑和手机" #: src/bz-context-tile-callbacks.c:316 msgid "May not work on mobile devices" msgstr "可能无法在移动设备上使用" #: src/bz-context-tile-callbacks.c:396 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "安全" #: src/bz-context-tile-callbacks.c:398 src/bz-context-tile-callbacks.c:400 msgid "Low Risk" msgstr "低风险" #: src/bz-context-tile-callbacks.c:402 msgid "Medium Risk" msgstr "中等风险" #: src/bz-context-tile-callbacks.c:404 msgid "High Risk" msgstr "高风险" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:46 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:30 #: src/bz-library-page.blp:67 src/bz-user-data-page.blp:30 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 "猝线" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 #: src/bz-search-pill-list.c:67 msgid "Browser" msgstr "浏览器" #: src/bz-developer-badge.c:94 src/bz-developer-badge.c:98 msgid "Not Verified" msgstr "未验证" #: src/bz-developer-badge.c:210 msgid "Developer information not available." msgstr "无法获取开发者信息" #: src/bz-developer-badge.c:216 src/bz-developer-badge.c:230 #, 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:234 #, 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:250 #, 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:257 #, 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:261 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "诼 %s 应用 ID 的所有权已通过验证。" #: src/bz-donations-dialog.blp:74 msgid "Full Release Notes" msgstr "完整发布说明" #: src/bz-donations-dialog.blp:108 msgid "This release was made possible by users like you!" msgstr "正是有了像您这样的用户,Bazaar 才能顺利发行!" #: src/bz-donations-dialog.blp:116 msgid "" "I love making Bazaar, but I cannot do it alone. Help support further " "development by donating on Ko-Fi." msgstr "" "我热爱开发 Bazaar,但我一个人的力量有限。如果您愿意支持后续的开发工作,请考虑" "在 Ko-Fi 捐助我:" #: src/bz-donations-dialog.blp:131 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:227 #, c-format msgid "What's New in %s?" msgstr "看看 %s 更新了啥" #. Translators: this is a release date label, like "Released February 9, 2026" #: src/bz-donations-dialog.c:243 msgid "Released %B %-e, %Y" msgstr "发布于 %B %-e, %Y" #: 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 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-dialog.blp:36 src/bz-error.c:69 src/bz-error.c:88 #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "详细信息" #: src/bz-error-dialog.blp:47 msgid "Copy" msgstr "复制" #: src/bz-error-dialog.c:56 src/bz-share-list.c:62 msgid "Copied!" msgstr "已复制!" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "收藏数" #: src/bz-favorite-button.c:388 msgid "Failed to update favorite" 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-favorites-page.blp:5 src/bz-favorites-page.blp:56 #: src/bz-window.blp:360 msgid "Favorites" msgstr "收藏" #: src/bz-favorites-page.blp:17 src/bz-section-view.blp:144 msgid "Install All" msgstr "安装全部" #: src/bz-favorites-page.blp:34 src/bz-user-data-page.blp:19 msgid "Loading" msgstr "加载中" #: src/bz-favorites-page.blp:49 msgid "No Favorites" msgstr "无收藏" #: src/bz-favorites-page.blp:50 msgid "Applications you mark as favorite will appear here" msgstr "您标记为收藏的应用程序将在此处显示" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:78 msgid "Support This Application" msgstr "支持此应用程序" #: src/bz-favorites-tile.blp:119 msgid "Remove From Favorites" msgstr "从收藏中移除" #: src/bz-favorites-tile.c:357 msgid "Failed to remove favorite" msgstr "无法从收藏中移除" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "上一页" #: src/bz-featured-carousel.blp:54 msgid "Next" msgstr "下一页" #: src/bz-flathub-category.c:93 msgid "Editing" msgstr "编辑" #: src/bz-flathub-category.c:94 msgid "Midi" msgstr "MIDI" #: src/bz-flathub-category.c:95 msgid "Mixer" msgstr "调音" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-flathub-category.c:96 src/bz-search-pill-list.c:77 msgid "Music" msgstr "音乐" #: src/bz-flathub-category.c:97 msgid "Player" msgstr "播放器" #: src/bz-flathub-category.c:98 msgid "Recorder" msgstr "录音" #: src/bz-flathub-category.c:99 msgid "Sequencer" msgstr "科学" #: src/bz-flathub-category.c:100 msgid "Tuner" msgstr "调谐器" #: src/bz-flathub-category.c:101 msgid "TV" msgstr "电视" #: src/bz-flathub-category.c:106 msgid "Emulation" msgstr "模拟器" #: src/bz-flathub-category.c:107 msgid "Action" msgstr "动作" #: src/bz-flathub-category.c:108 msgid "Adventure" msgstr "冒险" # 不用“街机“遵从 https://flathub.org/zh-Hans/apps/category/game/subcategories/ArcadeGame 的翻译 #: src/bz-flathub-category.c:109 msgid "Arcade" msgstr "游䚐中心" #: src/bz-flathub-category.c:110 msgid "Blocks" msgstr "方块" #: src/bz-flathub-category.c:111 msgid "Board" msgstr "图板" #: src/bz-flathub-category.c:112 msgid "Card" msgstr "卡片" #: src/bz-flathub-category.c:113 msgid "Kids" msgstr "儿童" #: src/bz-flathub-category.c:114 msgid "Logic" msgstr "逻辑" #: src/bz-flathub-category.c:115 msgid "Role Playing" msgstr "角色扮演" #: src/bz-flathub-category.c:116 msgid "Shooter" msgstr "射手" #: src/bz-flathub-category.c:117 msgid "Simulation" msgstr "模拟" #: src/bz-flathub-category.c:118 msgid "Sports" msgstr "体育" #: src/bz-flathub-category.c:119 msgid "Strategy" msgstr "战略" #: src/bz-flathub-category.c:124 msgid "Audio & Video" msgstr "音频与视频" #: src/bz-flathub-category.c:124 msgid "Media" msgstr "媒体" #: src/bz-flathub-category.c:124 msgid "More Audio & Video" msgstr "更多音频与视频" #: src/bz-flathub-category.c:125 msgid "Developer Tools" msgstr "开发者工具" #: src/bz-flathub-category.c:125 msgid "Develop" msgstr "开发" #: src/bz-flathub-category.c:125 msgid "More Developer Tools" msgstr "更多开发者工具" #: src/bz-flathub-category.c:126 msgid "Education" msgstr "教育" #: src/bz-flathub-category.c:126 msgid "Learn" msgstr "ĺ­Śäš " #: src/bz-flathub-category.c:126 msgid "More Education" msgstr "更多教育" #: src/bz-flathub-category.c:127 msgid "Gaming" msgstr "游戏" #: src/bz-flathub-category.c:127 msgid "Play" msgstr "游玩" #: src/bz-flathub-category.c:127 msgid "More Gaming" msgstr "更多游戏" #: src/bz-flathub-category.c:128 msgid "Graphics & Photography" msgstr "图形与摄影" #: src/bz-flathub-category.c:128 msgid "Create" msgstr "创造" #: src/bz-flathub-category.c:128 msgid "More Graphics & Photography" msgstr "更多图形与摄影" #: src/bz-flathub-category.c:129 msgid "Networking" msgstr "网络" #: src/bz-flathub-category.c:129 msgid "Internet" msgstr "互联网" #: src/bz-flathub-category.c:129 msgid "More Networking" msgstr "更多网络应用" #: src/bz-flathub-category.c:130 msgid "Productivity" msgstr "生产力" #: src/bz-flathub-category.c:130 msgid "Work" msgstr "工作" #: src/bz-flathub-category.c:130 msgid "More Productivity" msgstr "更多生产力" #: src/bz-flathub-category.c:131 msgid "Science" msgstr "科学" #: src/bz-flathub-category.c:131 msgid "More Science" msgstr "更多科学" #: src/bz-flathub-category.c:132 msgid "System" msgstr "系统" #: src/bz-flathub-category.c:132 msgid "More System" msgstr "更多系统" #: src/bz-flathub-category.c:133 msgid "Utilities" msgstr "实用工具" #: src/bz-flathub-category.c:133 msgid "Tools" msgstr "工具" #: src/bz-flathub-category.c:133 msgid "More Utilities" msgstr "更多实用工具" #: src/bz-flathub-category.c:134 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:148 msgid "Trending" msgstr "飙升" #: src/bz-flathub-category.c:134 msgid "More Trending" msgstr "更多飙升应用" #: src/bz-flathub-category.c:135 src/bz-flathub-page.blp:122 #: src/bz-flathub-page.blp:178 msgid "Popular" msgstr "人气" #: src/bz-flathub-category.c:135 msgid "More Popular" msgstr "更多人气应用" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:168 msgid "Recently Added" msgstr "最近添加" #: src/bz-flathub-category.c:136 src/bz-flathub-page.blp:128 msgid "New" msgstr "新应用" #: src/bz-flathub-category.c:136 msgid "More New" msgstr "更多新应用" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:158 msgid "Recently Updated" msgstr "最近更新" #: src/bz-flathub-category.c:137 src/bz-flathub-page.blp:134 msgid "Updated" msgstr "最近更新" #: src/bz-flathub-category.c:137 msgid "More Updated" msgstr "更多最近更新应用" #: src/bz-flathub-category.c:138 msgid "Mobile" msgstr "移动应用" #: src/bz-flathub-category.c:138 msgid "More Mobile" msgstr "更多移动应用" #: src/bz-flathub-category.c:139 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:139 msgid "More Adwaita" msgstr "更多 Adwaita 应用" #: src/bz-flathub-category.c:140 msgid "KDE Apps" msgstr "KDE 应用" #: src/bz-flathub-category.c:140 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:200 msgid "App of the Day" msgstr "每日应用" #: src/bz-flathub-page.blp:264 msgid "On the Go" msgstr "随时随地" #: src/bz-flathub-page.blp:276 msgid "Apps for your Linux phones and tablets" msgstr "适用于您的 Linux 手机和平板电脑的应用" #: src/bz-flathub-page.blp:287 src/bz-flathub-page.blp:322 msgid "More Mobile Apps" msgstr "更多移动应用" #: src/bz-flathub-page.blp:378 msgid "We​ ♥​ Games" msgstr "我们 ♥ 游戏" #: src/bz-flathub-page.blp:391 msgid "Games and apps to run your favorite titles" msgstr "运行您喜爱的游戏和应用" #: src/bz-flathub-page.blp:425 msgid "More Games" msgstr "更多游戏" #: src/bz-full-view.blp:34 src/bz-library-page.blp:78 #: src/bz-library-page.blp:82 msgid "No Results" msgstr "无结果" #: src/bz-full-view.blp:35 msgid "Try a different search query" msgstr "尝试不同的搜索关键字" #: src/bz-full-view.blp:41 msgid "Content" msgstr "内容" #: src/bz-full-view.blp:105 msgid "" "This is a local preview, some details may differ from the published listing" msgstr "这是一个本地预览,部分细节可能与已发布的列表有所不同" #: src/bz-full-view.blp:108 msgid "Preview Store Appearance" msgstr "预览商店外观" #: src/bz-full-view.blp:234 msgid "_Support" msgstr "_支持" #: src/bz-full-view.blp:454 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:541 msgid "Trash Data" msgstr "垃圾数据" #: src/bz-full-view.blp:681 msgid "Tags:" msgstr "标签:" #: src/bz-full-view.c:180 msgid "No URL" msgstr "无链接" #: src/bz-full-view.c:198 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "该应用程序具有 FLOSS 许可证,这意味着可以审核源代码的安全性。" #: src/bz-full-view.c:199 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:206 msgid "More Apps" msgstr "更多应用" #: src/bz-full-view.c:207 #, c-format msgid "More Apps by %s" msgstr "来自 %s 的更多应用" #: src/bz-full-view.c:214 msgid "Other Apps by this Developer" msgstr "该开发者的其他应用" #: src/bz-full-view.c:216 src/bz-full-view.c:315 #, c-format msgid "Other Apps by %s" msgstr "来自 %s 的其他应用" #: src/bz-full-view.c:225 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s 未安装,但仍存在 %s 的数据。" #: src/bz-full-view.c:317 msgid "Other Apps" msgstr "其他应用" #: src/bz-full-view.c:319 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d 个应用" #: 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-install-controls.blp:62 msgid "_Open" msgstr "_打开" #: src/bz-install-controls.blp:77 src/bz-install-controls.blp:134 msgid "Uninstall Application" msgstr "卸载此应用程序" #: src/bz-install-controls.blp:87 src/bz-transaction-dialog.c:230 msgid "_Remove" msgstr "_卸载" #: src/bz-install-controls.blp:121 src/bz-updates-card.c:161 #: src/bz-updates-card.c:180 msgid "Update" msgstr "更新" #: src/bz-install-controls.blp:144 src/bz-installed-tile.blp:114 msgid "Remove" msgstr "卸载" #: src/bz-library-page.blp:32 msgid "Search installed apps" msgstr "搜索已安装的应用程序" #: src/bz-library-page.blp:50 msgid "Clear search" msgstr "清除历史" #: src/bz-library-page.blp:71 msgid "No Apps Found" msgstr "未找到应用程序" #: src/bz-library-page.blp:90 msgid "Search Store Instead" msgstr "在商店中搜索" #. Translators: . #: src/bz-library-page.blp:100 src/bz-window.blp:111 msgid "Library" msgstr "库" #: src/bz-library-page.blp:128 msgid "Pending Updates" msgstr "等待更新" #: src/bz-library-page.blp:155 msgid "Downloads" msgstr "下载" #: src/bz-library-page.blp:198 msgid "Recently Uninstalled" msgstr "最近卸载" #: src/bz-library-page.blp:249 msgid "Clear Finished Tasks" msgstr "清除所有已完成的事务" #: src/bz-library-page.blp:334 msgid "Sort By" msgstr "筛选" #: src/bz-library-page.blp:348 msgid "Name" msgstr "名称" #: src/bz-library-page.blp:354 msgid "Size" msgstr "大小" #: src/bz-library-page.c:180 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "在已安装应用列表中未找到与 “%s” 匹配的项目" #: src/bz-library-page.c:193 src/bz-updates-card.c:426 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u 个可用更新" #: src/bz-library-page.c:203 #, c-format msgid "%u Installed App" msgid_plural "%u Installed Apps" msgstr[0] "%u 已安装应用" #: src/bz-license-dialog.blp:94 msgid "Get Involved" msgstr "参与进来" #: src/bz-license-dialog.blp:111 msgid "Learn More" msgstr "了解更多" #: src/bz-license-dialog.c:127 msgid "Unknown License" msgstr "未知许可证" #: src/bz-license-dialog.c:130 msgid "Community Built" msgstr "社区共建" #: src/bz-license-dialog.c:203 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:206 msgid "The license of this app is not known" msgstr "此应用的许可证未知" #: src/bz-license-dialog.c:212 #, 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:220 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:226 #, 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-license-dialog.c:356 src/bz-safety-dialog.blp:53 msgid "License" msgstr "许可证" #: 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:110 msgid "Finish" msgstr "完成" #: src/bz-login-page.c:664 #, c-format msgid "Hello, %s!" msgstr "你好,%s" #: src/bz-metainfo-preview.c:84 msgid "Select Metainfo File" msgstr "选择元信息文件" #: src/bz-metainfo-preview.c:87 msgid "Metainfo Files" msgstr "元信息文件" #: src/bz-metainfo-preview.c:141 msgid "Select Icon (Optional)" msgstr "选择图标(可选)" #: src/bz-metainfo-preview.c:144 msgid "Image Files" msgstr "图片文件" #: src/bz-metainfo-preview.c:231 msgid "Preview" msgstr "预览" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "偏好设置" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data refresh is paused" msgstr "正在使用计费网络 - 自动储存数据同步已暂停" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:258 msgid "Refresh 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 End-of-Life 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:126 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-updates-card.c:152 msgid "Version History" msgstr "版本历史" #: src/bz-releases-list.blp:27 msgid "_Version History" msgstr "_版本历史" #. Translators: something happened less than a day ago #: src/bz-releases-list.c:122 msgid "Today" msgstr "今天" #. Translators: something happened more than a day ago but less than 2 days ago #: src/bz-releases-list.c:125 msgid "Yesterday" msgstr "昨夊" #. Translators: something happened days ago #: src/bz-releases-list.c:128 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "%d 天前" #. Translators: something happened weeks ago #: src/bz-releases-list.c:131 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" msgstr[0] "%d 周前" #. Translators: something happened months ago #: src/bz-releases-list.c:134 #, c-format msgid "%d month ago" msgid_plural "%d months ago" msgstr[0] "%d 月前" #. Translators: something happened years ago #: src/bz-releases-list.c:137 #, c-format msgid "%d year ago" msgid_plural "%d years ago" msgstr[0] "%d 年前" #. TRANSLATORS: This is the date string with: day number, month name, year. #. i.e. "22 March 2026" #: src/bz-releases-list.c:155 msgid "%e %B %Y" msgstr "%e %B %Y" #: src/bz-releases-list.c:196 #, c-format msgid "Version %s" msgstr "版本 %s" #: src/bz-releases-list.c:251 msgid "No details for this release" msgstr "未提供变更日志" #: src/bz-releases-list.c:263 msgid "Get More Information" msgstr "获得更多信息" #: src/bz-rich-app-tile.blp:157 msgid "Get" msgstr "获取" #: src/bz-rich-app-tile.blp:185 src/bz-transaction-tile.blp:296 msgid "Open" 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:63 msgid "App ID" msgstr "App ID" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:104 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:150 msgid "Reset View" msgstr "重置视图" #: src/bz-screenshot-page.blp:161 msgid "Zoom Out" msgstr "缩小" #: src/bz-screenshot-page.blp:171 msgid "Zoom In" msgstr "放大" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "截图轮播" #: src/bz-screenshots-carousel.blp:117 msgid "Open Screenshot Viewer" msgstr "打开截图查看器" #: src/bz-search-filter-popover.blp:18 src/bz-search-page.blp:83 msgid "Filters" msgstr "筛选" #: src/bz-search-filter-popover.blp:35 msgid "_Verified" msgstr "_已验证" #: src/bz-search-filter-popover.blp:42 msgid "_Free/Open" msgstr "_自由及开放源代码" #: src/bz-search-filter-popover.blp:49 msgid "Non-_EOL" msgstr "非已中止支持" #: src/bz-search-filter-popover.blp:52 msgid "Filter out End-of-Life apps" msgstr "筛掉已中止支持的应用" #: src/bz-search-filter-popover.blp:57 msgid "Categories" msgstr "分类" #: src/bz-search-page.blp:58 msgid "Search Apps, Games, Software" msgstr "搜索应用、游戏、软件" #: src/bz-search-page.blp:70 msgid "Search Filters" msgstr "搜索筛选" #: src/bz-search-page.blp:100 msgid "Clear Search" msgstr "清除搜索" #: src/bz-search-page.blp:192 msgid "Categories Unavailable" msgstr "分类不可用" #: src/bz-search-page.blp:193 msgid "Search for apps using the search bar above." msgstr "使用上方搜索栏搜索应用。" #: src/bz-search-page.blp:219 msgid "Browse Categories" msgstr "浏览分类" #: src/bz-search-page.blp:361 msgid "No Applications Found" msgstr "未找到应用" #: src/bz-search-page.c:247 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "在 Flathub 中未找到 “%s” 的结果" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:72 msgid "Video" msgstr "视频" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:82 msgid "Office" msgstr "办公" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:87 msgid "PDF" msgstr "PDF" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:92 msgid "Calendar" msgstr "日历" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:97 msgid "Messaging" msgstr "通讯" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:102 msgid "Paint" msgstr "绘画" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:107 msgid "VPN" msgstr "VPN" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:112 msgid "Torrent" msgstr "Torrent" #. Translators: Search suggestion: the english text will be used for the #. search regardless of what you put here, so don't worry about the string #. yielding poor search results. Focus on correctness and friendliness, #. etc #: src/bz-search-pill-list.c:117 msgid "Emulator" msgstr "模拟器" #: src/bz-share-list.c:123 msgid "Copy Link" msgstr "复制链接" #: src/bz-share-list.c:134 msgid "Open Link" msgstr "打开链接" #: src/bz-stats-dialog.blp:27 msgid "Timeline" msgstr "时间线" #: src/bz-stats-dialog.blp:45 msgid "Installs:" msgstr "安装:" #: src/bz-stats-dialog.blp:54 msgid "World" msgstr "世界" #: src/bz-stats-dialog.blp:68 msgid "Since 4/15/2024" msgstr "自2024ĺš´4㜈15日开始" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:125 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM 总安装量" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:128 #, c-format msgid "%.2fK Total Installs" msgstr "%.2fK 总安装量" #: src/bz-stats-dialog.c:130 #, c-format msgid "%'d Total Installs" msgstr "%'d 总安装量" #: src/bz-tag-list.c:78 msgid "No Results Found" msgstr "无结果" #: src/bz-tag-list.c:90 #, c-format msgid "Apps Tagged \"%s\"" msgstr "标记为 “%s” 的应用" #: src/bz-tag-list.c:103 msgid "Search failed" msgstr "搜索失败" #: src/bz-transaction-dialog.c:154 msgid "Keep User Data" msgstr "保留用户数据" #: src/bz-transaction-dialog.c:155 msgid "Allow restoring personal settings & content" msgstr "允许恢复个人设置 & 内容" #: src/bz-transaction-dialog.c:164 msgid "Delete All Data" msgstr "删除所有数据" #: src/bz-transaction-dialog.c:165 msgid "Permanently erase user data to save space" msgstr "永久删除用户数据以节省空间" #: src/bz-transaction-dialog.c:190 #, c-format msgid "Install %s?" msgstr "安装 %s ?" #: src/bz-transaction-dialog.c:195 msgid "" "Select which version to install. May install additional shared components" msgstr "选择你要安装的版本。可能还要安装共享组件" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "可能还要安装额外的共享组件" #: src/bz-transaction-dialog.c:200 src/bz-transaction-dialog.c:229 #: src/bz-transaction-dialog.c:274 src/bz-transaction-dialog.c:576 msgid "_Cancel" msgstr "_取消" #: src/bz-transaction-dialog.c:201 msgid "_Install" msgstr "_安装" #: src/bz-transaction-dialog.c:218 #, c-format msgid "Remove %s?" msgstr "卸载 %s ?" #: src/bz-transaction-dialog.c:221 msgid "Select which version to remove." msgstr "选择你要卸载的版本" #: src/bz-transaction-dialog.c:223 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "卸载后将无法使用 %s" #: src/bz-transaction-dialog.c:246 #, c-format msgid "“%s” is High Risk" msgstr "“%s” 是高风险的" #: src/bz-transaction-dialog.c:250 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:259 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:275 msgid "_Install Anyway" msgstr "_坚持安装" #: src/bz-transaction-dialog.c:330 msgid "Failed to load transaction dialog" msgstr "无法加载事务对话框" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "所有应用都已经被安装" #: src/bz-transaction-dialog.c:549 msgid "_OK" msgstr "_好的" #: 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-dialog.c:577 msgid "_Install All" msgstr "_安装全部" #: src/bz-transaction-manager.c:784 #, c-format msgid "Finished in %.02f seconds" msgstr "在 %.02f 秒内完成" #: src/bz-transaction-tile.blp:129 msgid "App Add-On" msgstr "应用附加组件" #: src/bz-transaction-tile.blp:158 msgid "Runtime" msgstr "运行时" #: src/bz-transaction-tile.blp:182 msgid "In Queue" msgstr "队列中" #: src/bz-transaction-tile.blp:206 msgid "Done" msgstr "已完成" #: src/bz-transaction-tile.blp:230 msgid "Cancelled" msgstr "取消" #: src/bz-transaction-tile.blp:254 msgid "Error" msgstr "错误" #: src/bz-transaction-tile.blp:310 msgid "Cancel Transaction" msgstr "撤销事务" #: src/bz-transaction-tile.blp:434 msgid "Show Error Info" msgstr "显示错误信息" #: src/bz-transaction-tile.c:107 #, c-format msgid "%s Freed" msgstr "%s 已释放" #: src/bz-transaction-tile.c:360 src/bz-transaction-tile.c:363 msgid "Transaction Error" msgstr "事务错误" #: src/bz-transaction.c:344 msgid "Pending" msgstr "等待中" #: src/bz-updates-card.blp:22 msgid "_Update All" msgstr "_更新全部" #: src/bz-updates-card.c:208 #, 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:33 msgid "No User Data Found" msgstr "未找到用户数据" #: src/bz-user-data-page.blp:38 msgid "User Data" msgstr "用户数据" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "清除用户数据" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "已删除 %s 的用户数据" #: src/bz-window.blp:87 msgid "Curated" msgstr "精选" #: src/bz-window.blp:99 msgid "Explore" msgstr "探索" #: src/bz-window.blp:219 msgid "Refresh completed!" msgstr "刷新完成!" #: src/bz-window.blp:238 msgid "Main Menu" msgstr "主菜单" #: src/bz-window.blp:249 msgid "You are running a new version of Bazaar!" msgstr "你正在运行新版本的 Bazaar" #: src/bz-window.blp:250 msgid "See What's New" msgstr "看看更新了啥" #: src/bz-window.blp:257 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "您已连接网络,但正在查看 Flathub 的缓存版本" #: src/bz-window.blp:302 msgid "_Donate to Bazaar" msgstr "_向 Bazaar 捐助 ❤️" #: src/bz-window.blp:309 msgid "_Refresh" msgstr "_刷新" #: src/bz-window.blp:314 msgid "_Preferences" msgstr "_首选项" #: src/bz-window.blp:319 msgid "_Login With Flathub" msgstr "_用 Flathub 登录" #: src/bz-window.blp:325 msgid "_Manage Leftover User Data" msgstr "_管理遗留用户数据" #: src/bz-window.blp:330 msgid "_Keyboard Shortcuts" msgstr "_键盘快捷键" #: src/bz-window.blp:335 msgid "_About Bazaar" msgstr "_关于 Bazaar" #: src/bz-window.blp:342 msgid "_Quit Bazaar" msgstr "_退出 Bazaar" #: src/bz-window.blp:367 msgid "Log Out" msgstr "登出" #. Translators: %s is the title of the current page #: src/bz-window.c:377 #, c-format msgid "Bazaar — %s" msgstr "Bazaar - %s" #: src/bz-window.c:586 src/bz-window.c:624 msgid "Failed to launch application" msgstr "启动应用程序失败" #: src/bz-window.c:825 msgid "You can't remove Bazaar from Bazaar!" msgstr "你无法用 Bazaar 卸载 Bazaar" #: src/bz-window.c:1110 src/bz-window.c:1144 msgid "Can't do that right now!" msgstr "现在还不能这么做!" #: src/bz-world-map.c:603 msgctxt "As in, \"100 Installs\"" msgid "Installs" msgstr "安装" #: src/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "一般" #: src/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Page" msgstr "打开搜索页" #: src/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Library Page" msgstr "打开库" #: src/shortcuts-dialog.blp:20 msgctxt "shortcut window" msgid "Refresh" msgstr "刷新" #: src/shortcuts-dialog.blp:25 msgctxt "shortcut window" msgid "Open Preferences" msgstr "打开偏好设置" #: src/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "展示快捷键" #: src/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Close Window" msgstr "关闭窗口" #: src/shortcuts-dialog.blp:41 msgctxt "shortcut window" msgid "Quit Bazaar" msgstr "退出 Bazaar" #~ 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 设有一个\"精选\"标签," #~ "可由发行商配置,以提供更本地化的体验。" #~ msgid "Adam Masciola" #~ msgstr "Adam Masciola" #~ msgid "Nucleus app page" #~ msgstr "Nucleus 应用页" #~ msgid "_Donate to Bazaar ❤️" #~ msgstr "_向 Bazaar 捐助 ❤️" #~ msgid "_Synchronize Remotes" #~ msgstr "_同步远程" #~ msgid "Synchronizing..." #~ msgstr "同步中……" #, c-format #~ msgid "Receiving %d entries..." #~ msgstr "正在接收 %d 个条目..." #~ msgid "Indexing Data..." #~ msgstr "正在索引数据……" #~ msgid "Close" #~ msgstr "关闭" #~ msgid "Copy and Close" #~ msgstr "复制并关闭" #, fuzzy #~ msgid "Open App Library" #~ msgstr "打开应用库" #~ msgid "Installing .flatpak bundles is not yet supported" #~ msgstr "安装 .flatpak 包暂不支持" #~ msgid "Download & Install Application" #~ msgstr "下载并安装应用程序" #~ msgid "Install Other Version" #~ msgstr "安装其他版本" #~ msgid "Keep Data" #~ msgstr "保留数据" #~ msgid "Open App" #~ msgstr "打开" #~ msgid "Refreshing Store Content" #~ msgstr "正在刷新商店内容" #~ msgid "Flathub" #~ msgstr "Flathub" #~ msgid "No background tasks!" #~ msgstr "无后台任务!" #~ msgctxt "As in, \"100 Downloads\"" #~ msgid "Downloads" #~ msgstr "次下载" #~ msgctxt "shortcut window" #~ msgid "Synchronize Remotes" #~ msgstr "从远程端同步" #~ msgctxt "shortcut window" #~ msgid "Quit" #~ 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 "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 "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "过去 30 天的下载次数。点击查看此应用程序的下载统计信息。" #~ msgid "Remote repo name" #~ msgstr "远程仓库名" #~ 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 "Removing" #~ msgstr "正在卸载" #~ msgid "Halt the execution of transactions" #~ msgstr "停止执行事务" #~ msgid "Browse" #~ 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 "暂停事务执行" bazaar-org-bazaar-43ce9f7/po/zh_TW.po000066400000000000000000002261021520414637400174450ustar00rootroot00000000000000# 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 "重新整理" bazaar-org-bazaar-43ce9f7/screenshots/000077500000000000000000000000001520414637400177715ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/screenshots/bazaar-dark.png000066400000000000000000006465701520414637400227000ustar00rootroot00000000000000‰PNG  IHDRcśLůZsRGBŮÉ,gAMAą üa cHRMz&€„ú€ču0ę`:˜pœşQ<bKGDTTT3cÁő pHYs  šœtIMEęžŐ IDATxÚěÝwœu˝˙ń÷̜˛˝gÓ릑Nč ‚€Šˆ….˝ökš^ťxýÉEAĽ‰€¨ˆˆ˘ -Ô$@BŇIŻ[˛ý”™ďď9çě9۲ťŮž×óńϞ9sćĚÎ ›Çyűů~žhĂâŔ0cóÁYćU8cqŕ 2ŕÁŒ5„>ŸŔtĆôŃś˝Ę¤Ÿk “ßtéçýő{(c ˘ĎłŃq€ĄÉôÁk˝Ş?CŤë­Apź`č0ÝXoşš^Ő_áFWŤďşş˜ź§×őG¸ŃĐĹęĆűâw§ťý_L~îĘó^Ő×FW‚—Ž„1TɀÖöWٲżŸťĐôšž 4öŹtśŽ;ĄL_˙`đčJż—΂—î„2}ČXý°ĎŽ„.]}ÜßqĘ0‡†ž|şÚ°ˇu“\×QEŒQתe:;Ž.;ĐʘŽVĂtôźő’źŘźżőgľ÷ Oű›žÚ¨%SH`,e/ŚŐ{;Ş|éő*™ž†1=­†é(€I˙9yÂZ?vˇ™/žö×´×kç1=ŒńÔy0ÓŃgڇ0VDz_= 2şÄt%„I.VŤŸĽś!ŇÖČń€Ą/=ńZýœş(ígŻŐĎ…25˝2lŠť•11]†”ź8j?IŻŠé¨— €Ô~o˜ôޘö‚W~ĆĐzűŽ|VëaJݶԝ0ڧALë G™!Œ“ś$­ßk‰!JŔ×^uJú’ Yâ’b‰G7mąŐʸ­öáuđyVŤŸ{ČhϘöšövÖ Ćig Jʒœ1cÖńápřđ@Ŕ™cŒ5Á˛TŹĚaIűăŁjË2›ăq÷H$˛xőę•/ĘešÉ&™]¸jКąŐ~(ÓşoůZ=ŘŽ+=b҃˜dL íç`âçěüüüâ‰+΃çĆăńŇx<Žx<.ĎódŒáöÝfY–lŰV H.•ąXěÁM›Ö˙ąŽŽŽZR“ü&Ś– ™xÚĎ]iöŰ^™ý†] cö7äyg:Žó…††Ž:PąXLápx^IɈ­{÷îZŻöűĂHÝlĐť?Mmus•śżÖĄL0??ż8++üĹŚŚ&Ž6ššš”•ţb~~~ąZfNĎ5¤–"ŠűyIv­ł ™Ö?ˇ×;&4qbĹyŃh´”“Ŕ`Ẏ˘ŃhéĉçI )3ŒI/<é(i/3é”ÝĂcľ:ůšő°%GR8 žFšĘ`PI4ô=WRX-aLë>šIÝ_Złđx;šâ:cˆŇŒłŽ‰ÇăTŀAÇu]ĹăńŇ3fŁö‡*ĽçRC˜¤@7śílšëŽ^ˇ$9ĄPčˆx<ÎŐÝâ8ŽÂá°BĄ€lۏ<Ď(+*‰č@ @âń¸BĄĐ’žSŰj)3˙HŸeI­ÖďWGaĚţžŽ‚—öĘxœ`00ťš9ÂşÄqĺćć*++Üîëśm) * *//WÍÍ544ô8”‰ÇăĘÎϖ_Ó^ÎѓŚÝםRÓ^O˜ö^k˝.ĆcMđ<; ěWvvśňóóşőžŹŹ°˛˛ÂŞŤŤWOfröřî\† Çq¨"Śľüü<9ŽÓÓˇw%ÓčqćŃW+˝6ÝÓţ”––ę÷żżWsćĚV8ćî`ĘÍÍ,űlÝ ˇ×hcuq]Ÿ())Ńý÷˙NÓ§OÓúőtŐUŸáî`ˆq§ĂY“DVVř@Şc’z=űčíʘ~ b~˙ű{5cĆt­_żA^x‘öěŮË Ŕłż‘.Żźň’~ó›_Ѝ¨(ľŽ°°PˇÝöK˝ňĘK´ď.ęŐźĂč—áHéb>BĄP§ŻoذQóçĎÓ­ˇŢ˘˘˘"ꗿüš.&'ąKHRPRŃ…GźZSłŻ×žőĚJŸţôĹÚ˝{w1Cˆă8űnÔS••Ur]ˇKŰjéŇ7Ž–T#)&)*)žXÜÄâĽ-&í19*ýgŠŮ—ěĄ|ąŞŞŞtŃE—j͚ľŞ¨˜˘;îř w0CŒëşjnŽôú~››#]bú“=Ô/XeeĽ>ýéK´|ů;]•ŔĐŃĐĐ0$öŮĂá‚UVVꏳ>ɝ Ŕ庎ęęꕟŸ×+űŤŤŤ”U1Ň0¨ŒĂCSS“ęëźšĽžžAMMMƒö÷$ŒƒFccŁęęę{üţşşz566ęß1ŔeƒISS“˘Ń¨rss••îŇ{š›#jhh´C“ŇƀAÇu]ŐÖÖŞĄÁQ8V(R m[’$Ď3ŠÇăŠFيD"C"„I"Œƒ–ëşjllôCşƒž1ýˆ0 Ćô#€~DЏcúa @?"ŒčG„1ýˆ0 Ćô#€~DЏcúa @?"ŒčG„1ýˆ0 ƀƒ†ç55E´sgĽšš"ň<ÓďÇ@‘HTcǎŃ)§ź_cǎQ$í÷c Œ Ďó4fĚ(IҘ1Łäy^ża @?"ŒčG„1ýˆ0 Ćô#€~DЏcúa @?"ŒčG„1ýˆ0 Ćô#€~ŕ`01Ćp†Ë˛8 ĐC„1PƘԂĄÇ˛ŹÔč ˜ Œ>5şHU˘ŠyYĘqziÔÜ­÷÷í_QßîˆŁëim}łžŘYĽ‡wV+ΨGč ˆ2GşcÁTMĎËâd Q9Ž­ů…9š_˜ŁO)ŐgŢŢ J—óűĂ˙•ţżé\Ww,¨ ˆFfćgëöůSdšqNěď{1§ýÉOç+#ˆ†fćgëÜąe2Ćăd@'cĐŻ\×Ó# 9ĂÔ#‹äş„1ĐÂôĆ$KšTĹ WÓň˛$Y̎ ŒA?3Ę 8œ†aĘżś1Đ€~ÄÔÖč [98ŻšeY}˛ďď~÷Űşč˘ ;|Ýu]ŐÔÔhűözńŗôŕƒÖ֭۸(*c ;Žă¨´´TsçÎŃg?{ž~ú)]pÁůœƒa €a/ëűß˙ŽN8áýœ ŽaJ†…%K–Ś~./ĄńăÇgźnY–Žšćj=˙ü œ,Š0ŔçşŽÎ9'sŇÉ'Ÿ¤_˙úV9NËě]sćĚćdp„1†ĽgžyVŻžúšŽ;îŘ´ľí7ž7oŽÎ=÷luÔQ*/ĄP(¤ęę­\šRO>ů”üŻr]7ă=_üi}ç;ßęňńüđ‡?Ň=÷ܛą.++KçwŽN9ĺdM:UĹĹEŠD"Ú˛eŤ^yĺUýáԆ ;ÜgOŽű‡?üžÎ?˙źÔóˇŢz[çœsž>˙ůôÉO~\#GŽÔwÜĽŸüä˙¸‰€>B`ŘĘËËËxžxń’Œç–eé›ßü†.˝ôâ63?•—Pyů :ńÄtŮeëĘ+?Ł]ťv÷ڹ͘1]wß}‡FůG9Đ̙34sć ]tхşńĆëžűîďÓăţú׿ŞË/ż”č'4đ0ŹX–ĽńăÇëŰßţŚćϟ—ZFőӟޜąí5×\­Ë.ťdżSpϚ5KżůÍŻdŰ˝ó'ł  @÷ÝwO› Śľ@  ď|çtňÉ'őŮq—––ę ™i čOTĆňÇŃúőŤ;|}ýú úć7żĽwŢY‘Z—••ĽĎ~öڌíÖ­[݇~DÍÍÍúÔ§>™ŃcfŢźš:î¸cőâ‹/I’6oޢ˙ű™6ŸeŰś>đ3‚’ĆĆÌĆÁ—\r‘ĘĘĘRĎ]×ŐC=˘eË–Š˘˘B—\r‘–?Ď×^{ľžyćŮ^9îÖƏ—:†7J˛ÔÔÔÄMô!ÂĂښ5kuď˝÷iŊ닋‹őđÏ¨ŹŹLeeĽĘĎĎׅ^¤}űj%IO>ů”^ýĺŒPeîÜ9ŠPăšçž×sĎ=ßćóžţőŻę¤“>ąîßřŸŒŢ/ťwďÖĂ?˘#F¨ŹŹTO>ů”nżýÎÔëÁ`P_üéÔó9sćȲ,cř¸Űłző]}ő5Úşu7 Đc kÓ§OӍ7ţ@ŸűÜ şúękRŐ1;věĐ÷ž÷ƒvß uĚ1GˇÔşMk§Ÿţ!]uŐëîż˙ýíoOfŹ{đÁ‡ôŕƒľť1cĆhÌémŽ' )‰ôÉqőŤ_'ˆúa €!Ďu]]pÁEŠçYYY:účŁtĹ—) I’FŽ,×wüZúĐGTWW—Ú6ëĂ>] .Ќ34fĚh•——gL‰ÝS§Vč'?ůqĆşĺËßэ7ţo‡ď™>}šN?ý4rČLMžŻˇŽťąą1cř€žG`Xh=SŇK/-Җ-[ôŁý0ľnäȑúřÇ?Śűîű˝$ż’ĺťßývF˙–žČÍÍŐŻ}›rrrRëöíŤŐő×NąXŹÍöůůůşéŚëƒ<ĽGŸ×[Ç-ůa €ţĹlJ†­ż˙ýmÖ-\x¨$ićĚşĺ–Ÿľ 4Ö­[§G}\ßúÖwťTÜtӏ5eĘäÔscŒţëżžÖáПýč‡m‚˜††˝ôŇ"ÝqÇ]zčĄG:üŹŢôĄS3ÖÝqÇ]ŠŮZ+..Öi§enűíwę曎x<.IşňĘË;üźŢ:n‡ĘĂRII‰žýí˙ił~űö’¤ńăÇgŹţů33Śg ;jĎqÇŤ/}é ë^ý ýô§?ëđ=ăƍ•mgţé˝÷ŢűSAŒÔR˝ÓžŢ8n‹ĘCžă8züńż¤žçććjܸą ƒmś}úéI’ęëë3֟tŇtüńďÓÚľë4kÖ!úÖˇţťÓĎ3fŒnšĺć6 s-ËŇ/~Ń6ŒyýőĹş÷ŢűÚ|Ž$]ýľşëŽ{8:ďźsŰTÚ¤;Đă0đc sćĚŢď6Ď?˙‚^~ůIŇ+ŻźŞ~ôŒÔk#F”éwżť;cűĆĆĆŤLޏâ2ˇY桝}$•$mŢźEۡoט1cRŻ]pÁůşŕ‚óSĎ”››Űî~ô¸ <†)8(<÷ÜóúÜ瞘zţ裏ˇ™)ÝíˇßŠUŤŢíđőîN!äşŽžűÝČuÝv_ŻŽŽÖ÷żc‡ď?Đă0đc KMMMÚ˛eŤž|ňďúĚgŽŐW\1Ä'ę˘‹.ŐM7ýTŤV˝ŤĆĆ&íŰWŤˇŢz[_úŇWtÓM?íłc{ć™gőÉOžŁ§žú§öîÝŤX,Ś-[śčĄ‡ŃgœĽ;vtřށóvŞjIJ,n~ƒJCC“Ž:ŞĽ˝ŔkŻ-Vnnś$Ѝ¨PK—žq´¤I1IQIńÄâ&/m1i&ů8ígľúY•1ýŠ0 Ćô#€~DЏcúa @?"ŒčG„1ýˆ0 Ćô#€~DЏœô/K•oďTŽŐ79`łeTżiƒ‚áŹ>ŮÜrU°śZÁŚXŸě?Šnűm§oößܨ˘ĺť2VŸěżŢó$YÜć@7… ĘUńÁĎŞtę1’¤Ęľ/kÝż~ĽhÝNŔ0Dƒ~f´;îjR°o˜:ۨžŚZ%#G÷ÉţS 8W…M5}˛˙ÚÂ<Ő{ŽJú(ŒŠŻŠ–m•őQłŰu%ns  ,' 1 ĎTqő*3KĄź’Ôkĺs>¨Â‰ Uˇc•Ş×˝Śío>!ăĆ9iĂa úçK‡eÉ#˒ś¸1M űäs*mO{wôYÓ`GĽŃ…*ÜŢ7aLeiĄă•B}˛˙š˝ťs\•y}†m‰ÇeY-ן/”N?NsĎűžžoËr˝yĎľ5˙ÚzęőzéŚ÷ęç˙őË ľT^ŚjUľöe­űç-Š5Ő É˙>Cy%šôţËU:ýX˛ Ô\˝];Ţ|BŰ?:`ŔŘ#?ŠńǜŻ%w]ĽXCľŽţü#ÚňĘ´íőG†ÇßD' yüTœëp›p~ŠÂůďSŮô÷Šěľě/Ëx2Ăa ú÷ ˆeéůćfŸ•Ó'ű_Š)öÎUĚ^Ř'űßjíSxá$_˛ŠoŽ˙)Š4ŐŠ"+żOöżfůbe…âšë›0ě…HŁ,Ťo[QŐlzK‹ď¸,őüĐKĽmo<˘Ý+ž‘$šŃŚ>ż7˝xŻöŹzN’”U8JźN3Ďú––˙ńŤCîżÉpÁH-źü׊Gęľé…ߊšvňGĎĐÄ÷_Ž‚qsľň/ߑLďU;Íţä÷äyŽV=úýNˇŤßšV•Ť_”ičŐß÷Ř/˙U˙s§v,}b@Ďű˜C?ÚiÓZńäĂ4záÚžř1ţ!cĐŻ,ËÖóшžaŒœ^ޜđ$­ ĆdŢzC<ű Ůvď†ƒś¨N:bšŽťűŮ^ďÇńl[ËgO•ŰPŻŮ˝|~ŒçiíŰoČ ĆuŚzż{wÜ=Ę 8}zš‘Őď\Űň{W‘ş=ëúZ¤śĺó’sÎů‘œ`śÜXӐúorÚé_TŹąVoţîšŃfIRŐşWTšöv՝*]~Ź*×,ę÷ăÚˇy™öm^6l˙–TŮý÷L9’0`˜ ŒAżŰkI6ÔëSy˝[ýńz8Ş}ś‘Ş÷jŮ+ĎjÁq§ôęţ×Z•ŞWL^IžV8KłŸ]ŃŤűőČšŞÎϗéÍşVPÜŤűsŃżUWS)ŮŇâpTGFzw(ÔĂőőŞ´$gÝoc<[ă9WĄźRŐnyGŤŸř‘šŞw¤^/›ţ>M:ńrĺ”NTsínm_ü¨ś˝ţ°Œńşüž—1ތqSëF/řˆĆ}ޞKĆ)Z_ĽoţU›^źO’”?fŚťňŽ6űŠßšN‹ď¸T’T8až&Ÿx…ňÇ̔qăÚóî‹Z˙ô/ÔK’˛ŠFiňŽVIő˛ƒYÚˇi™Öýë—jÜłQ’4ócߔe;ňb•Ďý 6>{‡śžöçŒĎ 喨túąZńŕ§‚˜–cY­ľżYĆk99e“5őÔT8aތÓŢ5/iýÓżL Ď5˙ÚtâZ˙ô/5ĺäk.(WíÖz÷Ż7Şšf§ŽžáAe•$œ{Ş–=đe5VnŇџ{XŤűĄ&žďbs‹ľčŚÓŰff;!Í<ó*Ÿ}ŠâŃí|ëďÚđěR⟡7”iÁĹżTݎwľőľ‡tĚţ"IšqĆ×4㌯酝$/Uٌ÷iŇ —+§l’˘ ŐÚąô m^tżŒçvz.‹&Ş)§\ŤźQÓä6×këŃćďÝď˝.(WţŘٝncܘv-ZŁćXÉąůcg+”?‚ŚžĂS[Łß${ˆ8ŽŁŰęjŐŕy˝śďfËč_ّÔóŸř“˘‘ŢŤPˆÉŐŰÖNϒń,˝|öąŠfő^˜Ńë§'×XňŒ­g*÷*ҋç'Ňܨ˙ö`ęůż˛›ązݞ§Ţót{cÇɸÖ-] ňY'ęÝÇnÔ˛ž˘P~™f|ôŠ×‹§ĄŮçܨ]˞Öâ;/׆g~­I'^ŽI'^ŃĺĎČ)›ŹŠ^Ť]Ëţ)/őƒ†y§iÚGž˘í‹Őâ;.ÓĆgďĐÄă/Uůl? lÜłIoţĺÝÇ~ ăšÚšě)IRvÉ8-¸ř5ěŮ 7ďšVďüů›*ž´@SNš&ń“ŁůŸţšÂ#´üO_כż˝FƋiÎŮ7fۈ™'(ÖTŤ7űí\ö6Ǟ7jš,ËVőĆ%íţnۗ<ŚŞuŻřÁM^‰^v›â‘z˝uďőzçĎßTNŮ$Íťđg’ŐÁ…óJ4böÉZţÇŻjńW(•§ég|M’´äîŤUóޛŞŢ¸D/ß|ŚŞßkůÜ Ç^ uO˙BKĂs=ḠŠÝ­%w_Ľu˙řšĆ,w˙!pĹ?›Ńʎ=ž˝SţsWFŔÎ/UĹ)×ň Ŕ0@e Äž Ł/UíŃŻJËx¸’ą¤?ĺ6ŠÎn /jkŞôč˙§łŻűćW22zŃޢϕ‘䊜(OO|ţ#úřMđp%cYş˙‚¨&?WžgÉŠ:לoŐ%cÇđp%c<=ţŰ[TżŻşĺüŰFä5ęŇşÜNd=I_­ÜŁ}Ž=čŇ]c<-đŠ7ŐJ’6=fžĺW9ĎŐÄ÷]Ź­ŻýY[^ý“’ěݤ#4é„+őŢswwXá0íô/jęiŸ—%Ér‚ŞŰžJ˙sgęő]ËţĄš‹ŠŰ›Úď˜ĂĎRá„yÚ˝âßrcMŠ!8v ¤i§}^•kiëŤ~`ÖTľUŻÜrvFÄŽwţĽ˛™ďOübŽ–Üu•ŒKU´l}íϚŃ- ć*Ö¸O’Ô°÷=mxćמŸ`vĄŒëŇĐŞą‡\ńh“Vţĺ{ŠJ”wüşŽůÂŁ*vtËP&ËÖężţŻÜhŁ$ió˘űuČÇż-Y–bűk¨’皊ÖWľ nWŐşW;=†Úm+ľâPڐ IDATńšťýßm÷9á\MűĐ´ń?w´Šěiď^ˆÖW)ÚPĽhCeęó'źďbí^ńŒ6˝řťÔ~Œf}âťÚôÂoSU?­ĎenůŮÁ°öŹüš÷íTóžzíç¤*—:“œžş#Ő—hËŤjţ§o–egţ3]:íţ Œş'9Ť’mŰz-׏kŞôâ҉7–ôל&­ ĹÚźśnśú÷C÷čƒç\Ö㌲FFoX;´Iu2ƒńü0Ćx–Ö͝˘g/ţůŒőśăhÜŃç*Ô4eUţ¨éŠÖďMż¸qČI*7KŮĹă”7jj"Ü §6iŽŮŃéů‰5í“ĺťÔë&oÔtŐnY– b$)Z_ĽŚŞ­Ę==Ƹ‘†TăoS-ËČv‚ŠĘĄö4×lßďőŹÝş2óů–ĺ˛ƒaeSýŽu=şGňGĎĐŽĺ˙ĘXˇoÓ2Yv@šĺSUłéÍvĎeލÚóîóZpémŞŮđ†Ş7˝Ľ˝ŤžďRcZM˙nˇ[ ~@tíć ôçhłśíÝĽ›JF(ˇ›,͖Ńs›´Ş &é˙<Š}U{ôąË?ŻP8ť[űÉŐ ömQŒç‡$ţbÉ$B“7NY¨ĘŇB}ü7W¨9Ú˝ăĎ ëţóĎĐňCŚúűWÚgČfžŻŞŃžX\——tűř#͍zěîŸkÝňĹnł(+ŞjÇčüúl…M÷B”zĎÓUîŐË^LÁ>šŞźŻyń¨6ţçNíYőŸśAN'łřDëŤŐ¸ˇeF­eü/ű…GU>çdm{ý?ćM:ńríXú„ŞÖ꤭•[4ńřKÚěgÔükäźiéÝ×d|‰/š¸@s/ř?U­Y¤ŞKŐüöS*7WŁœž€Štؕw)ZżWťW<ŤĘľŻČ¸qÍťđ§Ýť†;×ĘOœÓŢ5/ľy}ĚagŠyß.¨R'!›1sýŒşpĎö l K:ůŌъ?Sůcfޤâ(•M?NSNžF+ţ–öŽ~ŠÓýW­{55dM’,ŰŃŘĂ?ŽKy#§*˜[Ş)'ľ?\Ťrí+üă0 Đ3ý.˝r" ęăéC;ˇęţşZĹťđ­ÎXŇŇPT7ÖwÄ$­yűuÝöÍkőĆžĚhFÚńw,OŹj=ćŹŃfS'ĎSbąüž.‰çŽ‘\ciőüŠúŏŻŇk'/”×…@Éؖ6[?üŻ+ľěŠr_mă%*bďIňŹTŸ˜äđĄTőJ˘ż‹ń¤úźl=yŢIzáÔ#5óÍušž|˝JöÖŞ°ĆćRST ĘŇB­<¤BËfOUu~?$Ék١1-Ô2ŞpL÷żŽŚ˛[ç§Ţ6z<§IĎe5ë‚ “:=˙—>őŚŞl[Áp¨×§'ďo›^şWsĎű‰"ľ{UšöeeÖ´Óž¨š÷–čÝżţo‡ď ŒPިiţŃpžF-8]áüŞ\ëŐiÜťYĽÓŽŐŢŐ/ɍ6hܑŸRNé„Ô4؁pžćœsŁölPýŽľ*ç‡ ĆóTˇ}•+7iÔźŠtĆűÔ´włŠ§ŠQ >"ˇš6ľËv4ćđO¨rí"唌WĹŠ×÷čŹ}ęg:ěŠßháwhëk)RťGů٧kÜŃçiďęSÏś/yLcŽř¤9ë´ůĺ?)Î֔“ŻQĂîuÚۍjHí^O9Bš#&ŠšfWˇŽ5ˇźB“?pĽvŻxVš#ŚhĘÉ×hűâÇäĆü~15シ1‡ŸĽúŤŠŰŁąG~*Ľ¨ú=*7Gű6/SăŢMÚźč>Í=ď&5î}O•k)§t‚Śţ%m_ühŞ_L{ňGĎĐü‹oŃşü\Ő+§t‚ ÇĎÓŽv%ˇ=ťUż}ĽÂ3ŽoȌ;ęěŒŔ+]íśw˜I €0čšdď˜ôçĄPP5qKťŚäkהާ˝ŢˇĽç˙Ďz]MĽ–<÷”–<÷T§Űĺ™ô¤%„Iö‹ń!LKPăWĚÔćkŃ ‡ęĽăMźĎJ{_ËśmöiŇöŮj]z1LWż§öŮfżçż&P(h÷š5Uë^×;ţˇ&p™&pšÜhŁvźőw˝÷üݝžoâń—¤†šŃf5ě^§ĺüŞvűÓJŻţŰ˙ӌ~] .şEńćZm[ňWU­}9őţâŠG)ŤxʞŠÇjá塧֝Ńf˝řăS´ýGĘ-ŐĚ3˙[’ĽŞuŻhË˿ט…ţl@ ť7hĺ#ß֔SŽÓ¤/WÝöwľáßżÖěsněö9ˆÔîҒťŽŇ¤.Óä.W Ť@MŐŰ´ůĹű´ő‡Sc"u•zóžë4őÔt輡&Śś^¤őO˙"ŁĚţl}őO*;K‡]}Ö<ńcŐl~ťËď}ď…{ý÷^q§âŃíXúWmxöŽÔëŸ˝CĄÜÍüřˇoŽ×Ś~—QQ$IëţyŤf|ôk:bîŠzíśóý{ŕĄojň —kŇű/S´ĄJŰŢř‹6/şżÓcŠŮôŚV=úM8îÓŞřŕőŠ5Őj×ňjĂîčŇďRšţ5•ś c$uÄHRőú7řÇ`¸|'îÂz+íyňg;í1š8‰%XB’‚’Š.<â՚š}œmd0í Ir]WżžęčNß÷—–őůąúÍZ‚O™U,iĎ; \’5‰m\/-pi̤B™dߘ´°'šý¸_}­ßŽË'Ţ?ŻÓׯ˝óŐÔÖC=Œě_' yü´ËMzŤ7,Ö˛?|EƋsňPCC“Ž:ęđÔó×^[ŹÜ\ż˘ş¨¨PK—žq´¤I1IQIńÄâ&/m1iéÍÓżđśůňKe îËHŤę˜ÁÄőZ‚7=@‘2ƒYíTĎd1ŠuíUä.~Ŕ“Ř(ńš;4Ž%€Ž3n\Ëř˛F/VŻęćÝÚ]żY[kŢіʥjŽR} %ƋkűâÇ´}ńc ĺPĹ)תtúą’¤Ę5/kýżM€aŠ0j0TDŽKŸZP¨Ů‡){dXŠ5Źx@ďĆFés> f;ŘŞyof?dąZ=o5|I­*d”Y!“Ţ$xz4O§6”kN<_śńgRyŠLܓ‰{r➠"ĺ„ 4"żBÓG¨ˆçę˝˝KôΖǵˇöÝ~ż†L´nV=ú}NŔA‚0ľqyÝpĺĺNÉń‡ōLÔSA–ŃąššňÝ=ú#ÚY<"sHRr‘Z.ň§ťnŠ‚IŤ‘Ő˛.ýý‰×ËܐÎoŻšnĄäXţ‰kdKĆąäٖœ˜'ĹýŮwŒ$Ďv4ąěp*=L›+—ę­őżUcón.0 B„1r*FőĘ~Ëҕg—(gVޟ˜ÄЊců–”W*]ąíIݔsƒYU-Íw[ő†iz”ÖCĆtźîČćb]ԗŽV™>–=^VŔň— -+dËJUÇd‡~P“¨„ą–_ɓśŘ–%[~ELňŃĺä:…EQ8ç°así`¨#ŒÁAgFžĽ˛šůRÔHQOŠř‹‰z2q?‘ë7ČUźeęę Ľő:|窴ŔĹX܌&3tq=Kžke„0ž+•yYş(<Ů•X,Ç\젝˘äd1Ž-ËöĂËśdŮ~b+5ÂĘL_ĄL^Éy˛Ľ\|cppÝđĆŇńGĺË$*bLÄó—hb‰xRÜŻ’1n"˜I„3žkôńŘbYŽiU Ó~ĺK*„qÓŤiüpćB{œ˛l;˜¤’”d0°ý &ꤧ+JüŹÄ{”zH=i]Żb[Y }ŠĂwSN&Ǎv”=*$Ĺ<ż*&-„1QOŠľTČXQ#ĎőĄŒ$WĘϊęĚ͋Z…0‰ ŻučŇ̸Éuž4ÍËÓť0cÖĽÔ/9{’'/âúSZ{&ąR}ld˙“ţ4É´zžx=5[V¸‚›a šŽŃěCó¤d˜¨ç?F’ĄŒ‘ő+fóäĹ=şëVU2ŹVQS]ťĂ’•/mÖĽő‘9Í+k= “Ŕ¸žÂÄJÉd’MuÁ‹'żOK˛š%ŃGĆÄ=Ýřš^(œŤ&+”Ö'&­‡LF(#Zō‘•%Œz-AŒkRSY§Śą6~ŁŢÔgťiAŒ—Ć“hm“V)“ĚšJTĎXĹÜ0ßU9Îć91…ƒTÓ^9–ü$¤%đđŤ$ iËď~›ę“űă÷ŽqŹ¸‘—d ÜFłĺ9Ý3öTć˘TeŒ•Ę´TČŘK1ă)Ů$ĆH Ä<Ůn˛*ƖeűǕdRł-ůŐ1n"„ioIVÉřŒI ]JţěÉ(Śđ°żîÁ° YĘuBʲl§eZpte)îšjö\5¸QŐƛU‹ôÉGeŮŮ Ű9 ŮaŹ€+ŕ¤CętYrM\qWԋ(â5ŞŮkâ>@ [yžŃ„bËďăH–ëO’-)˝úD‰éŸó@c$ŻĽyŽĺIžçɊ+QĄâ÷Žąâţë§4/×S ‡i[¸4U “ŮСĽÁoÜEedäůeÉľ,Œ%Çľd[žd[éYLbF^˘ş%YýK{Œyé2i•2É`FJô—ń‡ŤňpŽĘĂy [Nć 1=gŒ–­<ÇVžÔČPŽ"ĆŐîH˝vGzgVŽź@ňœ9 śúh3O—‘-G!ËQČ +Ď)Ť˜ęÝZŐÇkšŸ ‰0ĂŘĄŠČq-yĆögP˛ĺ—ŔŘÉ~1‰‘@JL#-?Œąź–áJĆM&”˜†Zž¤¸'/ŃC&čĆuéć§őƒ)d IJΠ”>ŁR­çĘą­ÄĚFţŽ’A‰mYţ$Oƒ•ţĺNiý^Ú Z’Ă•˘Uʤ-~v×:Ç j|v‘ňœ 7~?[ŽĆgŞ8˜Ł-M5jtc=ÚOĐ Ť(Xސ5źŤľUč”*ŰÎSMŹR1á&8ČĆ`X‹iDŽ‘‰H–ăQ2vbx’hؒ˜`ÉJ>&“|ôÚöŽ‘›čă%fVJ4ó]ŕnÔW×üL;s:ŹŔ— NgůĹ7Ž%9–Qܲä$˘śaŒü@&˝L2”i _źvB˜´>2ňvÜŞau­‹ƒŮš’[BőËČs‚:$ż\ŞTëŢPœl;OĽĄň!YýŇS!+Ź‘áąŞŒîV“WĎ p#ŒÁ°cÉh~<*M IrL˘WŒRC€<Ëo“ b”Şd%Ć%ĂůĎ]vĽd…Lňšĺúu“fE´+ťĐ ՁćŘ9ńţtÓ˛äʒc,9–Ä؉ &˝6Ćř5;‰ś5-=`’•1ńÖ1^ű2Éǰˇ{Ř\ëâ`śŚäÄ $c4%§XŐĺ@&ŰÎSIpÄAÄ´œ.Ł’ŕUĹD p#ŒÁ°3ľ>˘\ÇHŃDăƟĘÚöŤbL˛An"wI”1˛ŒßČWž?DÉJ WRjV#IŽ—jč›lę›—&U7kcIv‡Ç‰ŽS0ëp?ˆ1ɞÂFŽąd[ţ€)[JÍňd”lec’ß2;’é LŤ!KńŒj)Űl×9Ç R3ˆLÉ-ŃŞşÝű˛´Â]EL{JCĺÚ‰1d ŕ Eƒa%äzšČ8–Œ-YŽ%“¨ˆńe4îő{Ƥr˜D0“ŹˆiŠŽ1ÉJ×kiô÷Ő1ž< ŚďiЖ°âŽÝîńŢŤÔěš ZŽ\ËČITĆؖ‘ düĎNUë(1=śüĄFéÕZEj3ÒçeDůĹML;#Ű´˘ţu5¸~˙–OŒź\vëŠŃVÖ/ŃĘúĽţqeMŐôźyĘwŠő"ÚŢźQď4,V̋vë÷Ëscc€A wę$Œ)ĚĎU$•çe~ᚻŁNVĚ]Œë%†(%›÷żgŒ•ś”čÓR{’L>Źd“mbˆ’?N(Ń´7Q!ă%fTňűČ˜Ô KV\šľŚJŻĎ/o˙ a|Łb‘•Їń÷ËA•¨ŽIZňLŰ@&˝‘Ż_Ó6i=l)7ţŽ ĚćĎŤmŰ**ě<äˆÄă~Ă wđešł ćKӎW ĆłtÚČ隑7Bžd˜ÎŒž^ŁÖaLŘÎŕßŃÖ´œŮ’¤EU˙ĐŽč69V@§–­\'OŁÂ´ľy˝ž­|,ă}šNN+;GFFۚßSČknţ’¤Ľľ/iCă*e;9:šô* ŽĐ¤œéÚŘřnˇŽ-lçĆĆŤśąIŁLQfyHë׹UVTزb´ôöěÁő{„%ďt‹ŰŕˆĘ{ün#ŠŽĄyŔĎkŽęö{&ćwű=㳋äȒŰAH´l:Í^kŠ+ fŻIWI’šÜF˝×´Z3sh\xrˇĂ˜Ÿ Y6§ƒM,‘˙—x°ŠkhRĚř™j˛l§ŰďiˆGť˙/Úa#ůĚęD_˜+&Ąë+ŽŃI#*”ç„´˝ŠVť"őÝţĚQá|5z–Ö7TŠŮÄuxŃX]7ĺŘ6Ű]5éHínŽ×žh˝Ść–čËSß§‚ ˙…ţýĽ“tőä#5.ťPëęö*ęĹőžŇIúÚ´juîÎ3[ŮNP››j´'Ú ĘhKsçW*7kg¤Ž×ŽQŔřěßřý4*<^Gž¨SG|JŮNžÖ7ŽÔŽČÖ6Űç8yš˜=M’´*Ń+&?ŕ{űb•wGM´R’Tě~đ7Î úa ĽŞÚ†nM‹žĺŁęÚúAq,„1ŻTmîö{^ŢťiżŰüć˝×ôjŐyFš_0Z珛ŻĎ>MWO>RYv÷ż`‡í€n^ű’îÚô†~śv‘§]“! IDATŒ‘Ść–hBvQĆvďXŠŰß{]?Zýœ*ŁĘ „tTńxٲtćVĄ?o]ڟ­_¤ď˝űŒŞc••§cJ&fěgeÝn}}Ĺ?tÓÚ´žĄR÷l^â ą&ývób­­Żěľkäô8pHü°Ź^ÚN* –jbö4ĺ9…jtëTŻiˇ¨fFî|ٲľ#˛Y5q˙\-żďML™_ňyĐę~ĺ–CpĐ!ŒÁ w]UČc…ęÚzĹ]oČ˙ßv­ŇŠÚÝ]ŢţÝú=zlçŠýnWęîMočËË˙ŚŰß{]/WnRĚótDŃ8]0~Aˇsw¤^;Ő(ۚ÷iOÔŔĆdeÎB´lßIRÔsľ˛nwj›âPś =uďó+=š˝¸ŢŮç÷Ž™œ›ę,ŠŮÖŤ˝búBňčŹ^ÚN’V׿Ľżěź[ĎU=Ą€Ôü‚c5=/ózeŮٚ”=#q?ź™Z31IRP™ĄKňyĚDůƒ€ý"ŒÁ ŐŠĄ9‰`őMÍjŠÄÍńĽyžnݰHŻVmŮďśKkśë–u/+ću>ÎĘ׊#§é˜’ jtcZ\˝U÷l^˘ßm^,Iš_0*c{+­bĂąŰ˙ÓkˇŞęp’łúXŚĂ}ĆťИĚýǍ×o×Č5;WĐ Ť,8ň˙łwßńQŔ?{5˝š„ŢA:iţ¤÷.)˘`Ă"bÁ‚ €4Q¤"Jď %ô$$@IH%ÉĺĘŢ>\räR/ír!Ÿ÷ëuťÝŰ237;űÝŮYx)Mă&aÄcÝ#Ü×›ňSe9ÂS=çç!äˆÔ…#&Ă#ľ“DÓŘ<îĘr•é‰\OôqůŢś’N""""˛=cČŽi´:htz°‹LÉHŐé‘jGH5l܃$aUŘ9lx3ÇyEcyči¤ź×á(SbXĺ&x͡%jš˜NĨîT MŰN­h:ŃŽéTr ‰k…l—éŁrAÍ´ď×vöB9•#ŕ&Ńbžvžžš ÜLË OMDœNƒƒiĺ–îUrĽ†îŚä(0Śg‚źČóČPŔ€CzĎ!C I€`ĘižŒdNxŃŤ?ţç5Ţ*SÚČźU•Ňś9Ů<ŻJć€NŚG–ßJ+&Ý#m8 ’2'ó<Žr'Ôp4=YëAjhĘ&ƒ1DDDDe oT'ť'Š" ˘ 2A™L`‚Ř€$I00ŘÁ€˝™%‹:¸Č•>ąßńč&RD†Wij^D‚„oaÇŁ›V/+$%7ŸDفŤ7>ŠÓq: T2œŚmŰŔ4.KĎ uQĂŮß4ę A ËĄ×Ć¨ÇäZ/ŕ^jj8zB€€ŰIń@“ĹÓŰbşůÔÁóá­r†›R$Q‡€Ř{0BÂöˆíŰß{MÝ+ĂÇÁĺTŽx”š„SąšƒóXŤ . >ŽŰ {âjbdň(3Q •źpO R *<çX ľA%S#Ts!)7‘"ć=Đđ1áŠwQĹĄ:yöB’12'(5 ’ˇ’.›ç­ăÔ A‰ÇşGˆÖ=Ę´ЏžtM]ۢ…[Ôvj 'š3‚ńú„jó˝_:#{•5 ĆPŠa”$hRő$ ™ r™ 2… ršÂ% Fƒ˘d„A4B¨•ö[5$RQAĺ\¨eŠFŒ^ƒ Ő[CVß;‹€Řů^ÎO!'ŃŤB]´ô|ĺ•Î0JF„$ÇâßÇ!ćAƒo>‰Â_×Đͧ6œĺJ\ˆŔľ'‘˜P˝u–ĺĹęR°/ę6V2=§ý\ÜŹż)Ë|?‡Á°ĘMŕ¤P!(9<¸d~lőą˜Pč$Ý}ę ŽŤRENƄaKÄ5čňčU§OÁĆWĐŤB=ÔtňBUGc YŽ5ŚŔEî–ďeĽ˙ş[{ţ•Tž O;tÖwnŠzNĎăĄödéˇk Čą#]@üaÔsn _Ç:p–ťĂ éŽ ĹäóH0Ä”2%j;›Až™|1ŰĺÜIž Q‹şNMŕ˘p‡Î˜Š{Ú \{rFä˙Ö/­1…ƒ1D%I€Ţ`„C$‘$)íÖ´:=RuúR=°Ź]TrTJ8¨”PŤUpPĺÜëDk0Âş!R‹1Ł×B+‰PňVšKńř1č?Č!Ă­¤č-CgąíáMl{˜{š}‘ˇą/ňśĹggⲿćtěý<ÇśšŸ9‡sœž×2fŢ:˜ă´ĂŃÁ8\ŕtŐJ"őY{z¤5Ą‡ůëՔ~űQuuH0"B†”›%j86ŔsŐQŮĄZ†$çňi„7“/ćd˝Qm‘kóÜŽ0Ím„inş<‹Đ#Ő¨aEDDDDTÖÎØd_$<ъpubJŘŁ¤Těaüž(mŞ:¸z9}t3ĺž79–1îrŻ|/S#&#,5wSn Y|şühÝC\LTŁŞcMÔvj7EšŇ÷›YhˆˆˆˆĘ cČ.‚I’ @BŠ•=ąG )ó8+B ŢĽM†§ŇŠŔcÇPńHőˆŇ&ç<ݐG™ T‚őcǜŒ?ˆh]8$)ű  ^Ň"$ĺ&îŚÜByUE%ąÔ¤—NŇ"ÉŔ` QYÄ` ŮAĽAƒ*L ;t7:‚`aťŻ‰GW@*ýOÚ:Ž ˇć:O’A—ç<%üăĹ}M|žłĹëcPA]%ÇŕJfQZëĆň‘ !Z÷°TŐuń:öĚ""""*Ťřhk˛łB§Â(ńQÖöĆh”p÷ąśD{Äd”"ę’ˌą!ÉąHó~ ş^Ň"FUćÓ+F˝Ä§(•U ƐÝŃ€Ëa L;s14Šű ’Ĺé5I‰řD­’#I‰CœŢúAh5Ć$ÄęŁí&°gŰ䫏†Ć˜Ä˛CDDDT†1Cvu’ršÇcĄŐ‹L;ĄŐ‹8š\n‘Wö NŻÁÍ'QH˛˘W­$Q›O˘ňˆI§1&!R]ꢓ´ˆÔ†3CDDDD Ɛ}ŇK2l:uŸˇ+ŮI’°ůô}čŒöۋ!EÔ#0)÷S •Ä+nZIÄýÔ&E[ukRÎżs-˘uHc âŮ Ś‰Đ#AŒA´.‚ˇ&ŕKv&ýŠJ2™ aąZl?÷ĂŰ×Č:“Ę&$IÂśł“ …BiÎ#{ĽMF”6nJ5Üp–Ťŕ “C!“?ý–ЏوTوdQ‡DC*őEPH2$"ɐ™#Ô2'¨dj(ä‚Âę~íŠ% ’:ŁZc R–#""""˛Ŕ` ŮoáT(p6$‰)ˇńF÷pPą¸§Ě§ź+ößƝČd(•Ľë҉zm‘ ¨řĽ5 \QŮ8ße˝IďJĽw˘4˜ąá,zˇđEŰşŢL b&INFbËéPhEÁ"#p \"""""˘Bc0†ěRƀŒ\.‡A’aKŔ}ě˝p_jQ!EźaŠđ$@/ŠĐ§Hˆˆy‚?N†#Y/AŠTB.,ň„ˆˆˆˆˆˆ Á*A€JĽ„Ć`€ZМĄR*á v€Vo€Vo€Ng0˙­Ő‹ćż˙>˙2YŮŤÚh4âס;e›.é镬Ő[|ŽMiMDDDDDDŃÁ˛[{Ç<ýLÎ™•4ôz ŽŽŽËËf0FůN/Ae›DDDDDDT4řhk˛k™ƒ‚ áţădŤżŸj€ He8ý Ÿ^ Ä-cČîe ‚ '#­ţîýXmś==ĘNÚ.˝ˆ!"""""*z ĆPАgCbq;"1ĎďD&ę™$ZPĄT˝ŹÝ§‚Ś1DDDDDDŃÁ*5҃ …żşŔˆ„ç KĹŠ (Ş—Uŕ†˝Ľ‡5űPôb †ˆˆˆˆˆ¨řp_*UŇő•d üz(u+š˘ąŻ;Ü•ĐëED&¤ŕfxîÇĽB­VgůnYHŸt?ÎOz1CDDDDDTźŒĄR'=X vp@Čc-n? 7A€BĄ„ƒƒC–ůËj:I’AŹJ/bˆˆˆˆˆˆŠƒ1T*=˝eIžícŤTČ>-ärär5ӊˆˆˆˆˆ¨1CĽƒ L+"""""˘Ň„řŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6¤`ĺM¨Őj¨T*Čĺr(r‚`Óm$ ƒQĄÓé Őj!I3‡ĺƒĺ¤ €ťR„‹B„ŁĚ•L‚B›ĺ 0Q€Ć(C’AŽ˝"‹F™ŠXǰ|1™ÇŹ;ˆě ƒ1Dš@Éĺpvv†ƒƒÚ.ČJĽJĽ"m{\‘šŞErr2DQdf•ńňÁrbŸĺFxŤ đR‰YślƒJ’š8Ę%8ʍ(§4@pŁ“#ZŤ€FdGŮg˝n`ĂňĹüełî ˛/ ĆĺŔĹĹNNŽv˝j88¨‘’˘ARR3ĺƒĺĎTvĐĂG­`ŰŔ‹ľ$IB9Ľĺ”Di•ˆHU2ÓĘXÝŔ:†ĺ‹ůËXNJ˜ŁÜ_GĺĆRłÍ>j=\"îiTě%SëÖ1,_Ě_ć1ë"Űc‹‹(ĽR‰rĺÇŃŁÇr]g§N1gÎWŮ>Ý($$ďź3qqqšcd2žűîtěذaĂF,^üËمäd üüZ™ßœƒłłŠˇš‡‡;.\8Ű@<=CÚKL{3ź¤ ˙§،#Óߌc;łĘ˛ĚW%ó2jÔ+ć@ĚęŐkđĎ?Űáě쌏>ú-Z4Gűö/ M›6°Ť},ĚM–ü™0áuŒ=ĘüŢß˙UŔ˛eË+VČ÷2őz]Ú VâââŽ#GţĹôéÓ3g~…nÝş˘jŐŞ(WÎ...Đéô,'6ŕŽóŐH?¨Ö,d?Ź;¤d>›`j¤FÇ%ĂËĂ Ÿ,:‚ÚϕĂ[/ˇ@“Ú>3ŕyü˛őR–eunĺ IŚ-<ŒŕűqćĎËš9`Ö¤N¨ńœÖĚîgń˜x Ÿ Ĺ㎠ZqR-Iܕ"bu|˛Eaë†tÆ EÆ qęÔi´lŮ*•ŠçŃľk×PšreL™ň!öíŰoŃCĆÉÉ Ë—/E:ľ­^ϝ;A˜4ém$''[|ţŐWłŕăăC‡ăɓ$Ť–ŐźyS 4׎]ÇîÝ{x,˛łň5qâđöö†ŃhÄoż­ĆŠS§áć憷ޚ„ÚľkačĐ!Řźů/Üż˙ Ëw[´hŽ-šăÁƒpěÝťmg$?ţx*|}ŤB’$üóĎ6\źx •*UÂčŃŁŕââ‚éÓ§áäÉS9Ţ.íîîŽ3ŚCŠTBŁIŲeËŠ>}zŁGî¨Ył&Ţ{ď̚5;×í~ď˝ẃ˜Ă‡ŕ§Ÿ–°l1Cd’Ţś–‡‡Ŕ`0ŕ—_V™oIÚ°á´hŃ WŻžiA™‰?˙ź ˝{÷IJeËQŻ^],Zdşr•ą o^&MzăƍŹZľÚüyz0fßžýءo?d;ËIńqQX[bľJîčÚŚ:Œ’„ďWŸÂľ hth^n.jDD=Á”‡°áťčßš.bâ5Řy,CťÖGjbßÉÜdŮUŰĹÉT>ż˙%ŤˇÁËĂĂş7€(IŘź˙ŚŐűČ`Láë†téŮůó@­ZľĐ¤I¤Śjđ÷ßŰđöۓЧOo”/ˆ‡ćďôčŃuęÔĆącÇv/ď˛V͝:uDϞݱeËßćĎ˗÷BĺʕđďżGńŮg_X˝Í5kÖÄúőkńüóM ŒaS|ĺëھ눈ˆŔŁG‘ŘśműÓߎ‹ žúj&A@… r Ì?… Ć0í'ŤV}:uŹ_żK–,3ĎöěYÔŠSŕŕŕc0Śwď^ć[Ť/ţ ˙ýŕÜšó¨RĽ 7n„=şcѢŸĚ˝cŇĽ_ 4h †9műŻaÖŹŮęá²E Ć=Łäňü`>|=zt‡BĄŔ+݌ŔÖ­ĂĹĹC† $&&" ŕLŽYÇĐĄĂÍӚ4i‚Ÿ6,CBîbÔ¨Ń:t>účóvˇ+°Ž)ůňľyó_ďe2jŐŞ‰—_xüř1nܸY*~ĚăÂçqŰśmÍóíÚľŻ˝ćîÝťÁŰť<°nÝz;v<×őůůľ`şE1c.ý!7‚ hÓŚľůbP:ŁŃˆf͚™Ű°<ŔÔŠÓ <Ë1CôŹţůŤŕ;Ž/żœ…ńăÇâíˇ'áíˇ'™§œÁ˘EŚą@ň’~UáÚľë€îÝťAŻ×gŰĐ=ţoŁJ•ĘčÜšć͛‹ţýY}• żűH…Kť]ťvăľ×üąlŮÓ{˘wî4ő‚‰ŽŽĆ믿‘ďe–/ď… *˜˙~ü8ŚPóąœ•ĚúŤ|MëšňćČŮ{P*d˜ývg¸9›şŞŤ”rřVtÇó ăůřÁ€Pth^MëT(’í˝u÷1ŔËÝąXö‘u1ÍJ6­fϞ…Ž]ť0 rŕŔAŹXńłEÎÇÇÇ|‚[ŠR%ó˙é@TTTžHŔüľŸ<ŽQŁş9p2~üXóźĐ¸qc̝ű-žűî{‹6™UŹX™ĺi!!!YćËČĹĹsćźm.cÓ§Ď@aĆe٢gŸWIeš ů< (ĐŞUK‹KşúőëĄYłfy.ăŇ%ÓŘ=zt7ýe2téň?\šr5Űů˙‹˙„O>ů׎]‡ŤŤ+źźźŠmŠpi÷Ë/Ť°jŐoxôč=z„_5˝€Ÿ^†S§ţĂŃŁ‡ąxńBÔŹYÓŞeśmŰgΜĹŮłçŕççWčůXNаAŁhySÄA%ÇÜ÷_2bŇ]š‰ř'Z‹Ďî?25`˝=KĹ>˛n Ś™ý¤•\.GłfMŃž}űLÇŠŘşu3śn݌޽{|}}͟mÝş>>>ĚßRšÇ...ću´më‡iӦ㥗şâç@Ł1]Č{ď˝wŕŕŕăr]\\ K RRž~ćęę’eúL†—×Ó^yýúőeÝA”6ąˆňáĂßGż~}ĄP(°dÉ2źôR7ôď?'Nœ„ťť;ŚNýÝťwËuŃяqďŢ=tíÚršmÚ´†§§'.\¸˜íüJĽŽŽŽhܸ1ŞWŻ†Űˇo#""‚™a§ VŽüƒ Ĺ ACńË/ŤĚO41M= T*Zľj‰ß~űĹŞ€LťvmqęÔiœ:uíÚľ-ô|T2ŇoAquRÁËÝ)ËtŸrÎć[ŰzśŻ‰Ułú`ÉôžL8"˛Ú矉:Ăß .\¸ooo|đÁdóţčŮĎăŒăŔŹ^˝ǎ‡F“ŠS§NcŊLƒ‚7mú|ŽëHJzppČz!ŔÉéégŮ .“ÉeKfذĄhٲ3Ž( ĆOŽŹäęęŠúN:ß_Fƒččh|ţůćƒßđáĂr]Ž\.ÇącÇáááć͛Ąsç΀ӧłÓŰoOÂáðrĺr$''cîÜůůÚn>Đ6ĺjŐŞ…Ĺ‹âčŃĂ8uęż,˝`&N| íÚu@ˇn=ąsç.¨T*|đÁäÜ+i™ -[śŔ™3gpúôi´nÝ*Űű§­ĺ¤hň1œJL‚éŠä٘dźýíŢ,ŤîâWŻôlxąU5¸ť8ŔAmş›8:NS*ö‘uƒ˝oˇŃ|Ęš\Včýfcť´EwîaÌĎ͟Ľ÷Ć€ţýĄ]ťh׎~ýu ŔüYťvđđáCćo)Í㌷(ßž}Űâ{ÁÁ!íڜ…““ë"cˆ2œdŹżÚŮŮ2™Ě|ĚźcÚcbÓGŸĎ‰ Řż˙  UŤ–hÝş%BBîâîÝťŮÎżiÓfLœřŚM›Ž” –.]ŒúőëË>RÁÓŽV­ZXľj%Zľjiń”„ězÁ$%%aŃ"Ә2Ď?ß$×ĺžúę(¤¤h ÓéĄ×’’‚‘#Gx>–“˘Ľ3Zß}úr ŠŃÚĄyU$Ľč Ď&ĘQ>ív$•ŇňdůňČRąŹě[tôc$''Łm[? ţ2ěoŐkҤ‰€Đа2—fö^žœœœ°gĎ.ěÝť 3g~‘ĽÝbnđËäüM”‘<žrĺé`ďMšXś1š6mjţ;ăŰ2;sćLÚ2ečŃŁ‡EśOŸ^ć ÉŮłgł|÷Ÿś!44AAÁX˝zmZP§"Ţ˙=–-˘L8€/•i˘(BŠ´îg…ˆˆ‡¨\šÚˇC‡ÁŢ˝űŕě쌷ߞľÚ4ţĂšsy?éâΝ;¸{7;wB•*U°|yÎO։ˆxh~zŇsĎUÁťďoÍp IDATžƒöíŰăÖ­@Ť÷‘Šż||đÁd¨T*ěŘą‹ý„¤$S×]Lžü.úöíƒ>˜Œwß5ő„yňä‰9X“›qăĆB­Vaßž§Â?~Ö­[_ ůXNŠ–Ć(ƒŁÜşŽ#ĎÜEŻŽľĐŐŻœÎ>řę׸ Śř›óMg”$Ěa~[í#źn°'FŁ?ţ¸Ÿ|ňqžOŒîÜ 2?Ţś iFE_žRRRކ ˘GîHMMĹńă˙ÁĂĂcÇžfž/§'=ĺ6“}äńéÓG•*U0nÜÄÇÇăüů hÝş%ƍ¸wďnŢ4=}ŠGî˜1c:‚‚‚đÖ[ď"55ťwďÁ˜1ŻÁŐŐď˝÷.ÔjBCďĄwďžhܸąé˜vđbbbłloúĂ)`͚ľčÜšęÔŠ~ýúâčŃc8qâ$˃1D€N§ƒƒƒÚęFěěŮs°`Á|8::⣏>°xô4›ďÇÍˁđĆŇhsœŻcÇđńńłłştyÉĚÉĎ>Rń—&ML“Œŕi/˜ž}űdésůň•<ťßΘńüýGŁV-SݚťXłfmçc9)ZI9Ę) VÍ{ďa"ö AŻöľ0ăőöPČł9Ô ´kúœĹg{ţ ƃČ'Yם˘ƒłŁ 5Ťx"$<ÎŞm¨_˝< 6Q“Ż}¤‚× 9„ŹůŸŢű2sľpâÄ ÄÄ|„ .ZŒEQ4Łâ)_ß}÷=–,Ylž:ý–ętçΝĎňhätŚńęVáÁƒđBo3ŮG‹˘ˆ/żœ…… ˙ÎÎΘ:ő#‹y“““1sćWćöGŻ^= T*Ń AÔ­[WŽ\E||žţú[̞= ŽŽx˙}Ë[ŞCCCąpá˘<ˇŰ`0`ö쯹jŐJ( |ňÉ4Œ5‰‰‰,[D ĆPY§Őj¸Z=˙ĽK—ńĘ+ŻbôčWáç×>>>0  ť‡Ă‡`óćżŇ–™ˇýűMÁ˜ë×o <<ŽŽŮ?-ĽeËhٲŒF#"##ąző;v<ŸűHĹ]>Ň{¸d ĤˊĚĉoĺšÜ'NZuÉÚůXNŠV‚^ÁI°úžöŐŰŽŕ9W4ŠcݓJŽÜŽÄšW˛öďů0ôíXó>|)ßŰ}äL¨• zc {ěČ|sç~ƒŘXË Zăƍ””„ččhŚÇ OŸ>Í<ýĽ—ň—×éóűí\‹1@ÂĂĂ'''Lš4ŐŞůf{´uëß8yňTŚGůşs'ŁFůĂß˙U´k×>>>Đjľ š‹={öbűöć[Šł ĆäôćoéÍăë×o`̘ń;ö5´iÓˆ‹‹C@ŔŹ^˝ááOąmŰ4jԁˇ-z]=z ožůüý_E“&Mŕęę‚G"qäČŹ_˙‡šm“÷śßÁÚľë0nÜX”/S?ÂçŸɲE@°âs!ĂűôżeţOÉÓ^Š´— €€G‹­OćůňDĹÉÍÍ­ĐW8íUjŞ6_W¨ŕĺcůňĽ$ “&˝] éÖř嗟ѨQĂ\çšví&L˜ČrbCžN:Ť{ǀB.ØĎŁÇ 5!ËᑝFIž˙‚ąfLjböĽB†‘˝ŁSK_x¸ZW‡Ĺ&hp( ›܂hĚűöŞX˝÷RTĚä"ۀářńăđúëărŠRŃŤW_¤ŚŚňXÄś ó—íO–-zŚ$'kŕç×Ęü> ŕœMÇ=<ÜqáÂŮśâččŇ^bÚ˘á%eř?ý€›ńodú›Á"ŔôT /ŻrĎäžĹÄÄň^Űg¨|,[öš5k–ë<.\ÄŰożËrbCŽr#ęšä˙dľjE7tńŤŽŚu*Ŕ§œé)Qą)¸|;îf{k’­&9@#r̘˛vě่ĺ‹ůË?yMśSťv-âöíYe:uDpp ŞUŤ–íűœźúęHbűö­L`ś‹­Ýčç×’$! ŕ,ęÖ­cNŤć͛e™÷óĎg 88ě-˛í9ňtëÖŐüţ㏧ŕŘą#,źÄ` ‘˝š0a"†‰éÓg ..żţú3^ye†ŠÔŽ;1pŕ‹×ăǏłVČ2VÉö"&&;ś‡ŻŻŻĹçC‡FTTt‘Žëűďçă˙ë­Vk“}ť{7Á AC1}úg¨_żV­Z ™L†ƒÁĎŻ=Ž\šĘBPÄ<<ÜŃľëK8vě? <JĽŇŚëďÜšƎc~ĎźśOÆ ō7€AƒŮ2ű5BÆ ™Čl7‹_ě„Ó§,Že1115ę‹ůÔj5 ˆČȨ"]˙ȑ#Đ˝{Wf•*lůS™vîÜyœ;wűöíÇťďNßnƧŸNƒ““# |ůňX¸p.]:‡Ë—ĎcéŇĹć “&˝‰›7ŻÂŃŃ4oŻ^=ˆĄC‡”J%Ž^˝„?œlž‚1~üXlܸ7n\ÁŢ˝;ŃŹYÓˇmĐ ءo7nŢźŠƒ÷aĈ—-ŚżúęH8°7o^ĹĄCű1xđ ó4ggg̛÷Ž\š€sçNcذ!Ěě=ąĹŐŤ×,^ƒ<ěŧŸ~‚k×.aĐ P(˜2ĺCœ:ő._>_ý5jT7/+ŻéT4oăÁƒpŒ9Üü™ 1âe9byĽ-Ż<Éë÷řńÇSpňä1Ů_éž7ď;lŰśŐbz˙ţýpřđ~\ştţţŁŃŠSGěßż7n\Á˛e?™ë°ě¤ŚŚâęŐk¸rĺ*öî݇_]…jŐŞĄRĽŠYÖ_ľęsXšr9Ο?ƒÓ§Oŕ›oćŔŮŮ9Ë2ąeË&ěŘńÜÝÝX€˛1`Ŕˆ˘ˆ9sž†§§'şuëb1˝fÍذanܸ‚öâů矷˜^ľjU,[öΟ?ƒŤW/bůň%(Wޜůä&88ož97ŽÇ­[×°wďNóUűyóžĂ˜1ţ¨RĽ2‚ƒŃŤW‹źţŕƒÉ¸qă \\\ĚëwîÜ GˇřěŕÁĂčÝť<<Ü͟őéÓJĽóć–vyĽÇącGĐ A}s˝•ąWـýpňäq\šr3g~Á _Ä` ‘˝úý÷ prrBŤV­ V­ú5ÂoL¸qPŤV-ŹYł …ű÷€JĽBŰś~€:¤ý˙ UŤ–prrÄţýÍË=z-ú Æ˝ŁQÂ÷ß—ívtíÚóç={öbŕŔ!řűďđő׳1`@?@“&ńŢ{ďŕ×_WĄgϞ؜m;ž˙ţ[4hP0k֗čÓ§7ŚO˙ cÇžŽž={p\;U­š/\\\0zô9ň/>ýt^ye8ŚOŸ—_~‚ ŕ?ÖĂÉÉ ňœNEwR´cÇN :Ä|űP‡Śž2{ö쳘7Ż<)Žßcűöí0vě,^ź3f|‚×_‡ˇŢzo˝ő.ţ÷żáď?ÚŞĺT¨ŕƒž={ŕɓ'xü8&Ëô… ˙žž1bƎf͚˘gĎó888`ĺĘĺpqqÁkŻCBB" P6†ŒŁG!88—.]ĆË/łč­Zľ>>>;öu|ńĹLLšôŚĹ÷ß˙=¸ššÁß,FŽúőëaΜYóźůćXştştéŽ[ˇąlŮOđőőŜ9ß`ďŢ}EíŰwƑ#G-žˇiÓf(•Jôęő4oěóç/ ((ÝťwĂ÷ß‹őë˙@˙ţƒpôčqüňËĎšžRţ˝ôŇ˙Pž|yěۡťwďAíھџyóB-ó嗇!&&çΝÇîÝ{Ńż_888˜§ůĺç4hžřb&̇îÝťZÜF[šreŹ]űBCC1pŕP̛ˇÓŚMĹřńcďžűúőë‹?œŠ>}úCŤŐ™§ąÝřě´óĘg___TŤV GłŘŽĂ‡@’$sŔ FŽŽƒBŻ×›?Ë+íňJ!C†!>>'OžBűö‘¨XąÚ´iƒ÷ß˙k×ţŽŃŁGĄWŻžŹlˆÁ"{ đň*‡-šŁQŁFřęŤ98sć,Οż€/żœ…Úľká…Ú"88!!wÍW;thUŤVŁ}ű :th‡âÚľëćĺoܸ 'OžÂőë׹aèUŤfśăDřűżŠK—.ăÇ!0đ6–,Y†€€3=úUŔŐŤ×ĐŚÍ Ř´é/čőzÜťw‚  víÚPŠTčۡ7ÖŹY‡]ťvăęŐkř裏!—Ë™Á%dĚ‹{͗,Ydž–ššŠĎ?˙/^Bbb"^~y–,Y†˙=ŠŔŔۘ>ý3x{—Ç˙ţ× …"×éT´Á˜M›6ĂĂĂ˝{÷Lk@ŽŔšsçjq[ž×ďq͚u Æ ĄP(°gĎ>ăߏâîÝĐ\{K5hPß\Ož<?ż6˜<ůĂlo“...pqqAPP0z÷î‡-[žŽ;ĄT*ąlŮO¨UŤ&üýÇ 66–…'ŚŰC`űö€mŰv }űPĽJe@˖-PľjU̞ý5ÎŕÔŠÓX°ŕG‹e|ôŃTŒ台°0čőzDD˙|&ۍĎXť1Ż|~ńĹN CXX˜ĹvĽ¤¤`׎Ý9rA@ýúőĐźyslŢźĹbĐúźŇ.ŻôˆŽ~Œ‡áŃ#ÓËh4ôz=žürΜ9‹ůó >> 6`eCvCÁ$ z*ýjPLL *W65’ƒƒƒÍÓo€yÚÁƒ‡ĐĽËK¨^˝*VŹ€eËV`Ĉá¨_ż:vlY,?..ÎüˇF“j>™EŃbžĘ•+ă… ŸÝž}ÝťwřřxcöěYxá…vˆŒŒ2ŸĘĺ2xzz@ŠT"$$ÄüÝřřx‹u“mmßž+W> 61ńiρ¤¤$sţ—+ç GGG̘1ož9!K™Čk:Ap˙ţ?~/ż< ǎý‡.]^´iÓ-ćË+OŠë÷˜œœć§N§3OE1×nŘZ­C‡‡ŤŤ+6lX‡Ýť÷fšš™10uęGXťÖtuňĉ“˜3焆šÜ遪ˆˆÄÄ0““1cL=•–.] QÍ'9Æ ŏ?.B… !!wÍß ąXĆđáĂ0qâpuuEhh\]] —[ćóƒáN‚4ˆŽŽ†UŰř矛°xńBTŞT }úôBJJ vďŢhذ<==pÂ<ůňĺ-ś— ÇŰť<şty)íx#í˜.ǰaC0{ö×HNNÎ÷2ťuëOOOřűĆ¨Q#͟ϟ˙=ţţ{ʕó„Z­Ć;wĚÓbbb,ę§Ę•+ÁÍÍ §NˇČűôŕí’%Ëáŕŕˆ9sž‚—W9ܸq?üđ8vě8ۍĎPť1Ż|6ݢt,Űcéü‰!CŁM›ÖčŃŁîÝť‡S§N[Œ‰dMÚĺ–%$$Ŕ`0X;3ö´!b0†ČŽŒő ’““qöěy4jdäŽV­ZÔ­[Ç|âű÷ÄoźŽ~ýúâ̙łˆĹɓ§Đľk4hĐß}7Ż@ŰńđáCÔŹYÓâłşuë˜×űŢ{ď ^˝şčÔé%ÄĹĹĄrĺĘ8~üĹ´Uűě óçK—ţ„ĄCcѢŸĚW×ëÔŠű÷ď§ý]ËâDý›oćŕ믿ŪUŤsç~ƒ6mZg:N<í)ăááDEY7H恇‡ž=ťŁwď^Řž}4ů¤ÎÝÝcÌłřNN'@”齌ƎG"Íůšpáôë×7nĘ÷2‡  QѡďӓŢ×^#†ŁFęˆˆxQQľjUótWWWxxxdh< 0˘řô¤V’L˙?yňsçÎĂ̙_ĄjŐç0sćXşt1š5keqĚvcén7ć–Ď2™ ~~m°nÝúlˇíâĹK¸qă&zôč†îÝťaÝşőŇ P†íĎ+툞EźM‰Ę´V­Z˘uëVčŮł–,Y„áÇá믿…FŁÁ… qăĆM|ńĹgđókƒ6mZ㍯žDppNž< ¸t颢˘1~üX9ň/ŕȑ1fĚkxň$ gŹÚƒÁQѰaCxxx`ÝşőhŢź>ř`26l€ˇßž?ż6Xż~ӕľÚžžUQż~=‹Ç¤ęt:ěÜš ţţŻ˘_żžhҤ1ćÍűŽćR@Ż×cÝşő4h Ú´iwww 2›7o„››{žÓŠč>|?Ć´iSńĎ?˙dš•'Ż<Éďď1((˘(bʔáç×&źŽŚMŸ/śý[˝z-?ŽÁÔŠe™&—ËqüřżXşt1ęÔŠ ™LI’đäÉómŹĽĽ˝|}}ŃŻ__ôčŃ=Ëş č‡Aƒ I“Ćřż˙›ƒÁ€;w0őČ+_Ţ ­Zľ„ŤŤkśÇĄ-[ţưaCńüóM°qăfó´ľkG˝zu1tčxzz˘E‹ŘźůO´lْ\D†‚'NâŘą˙ĚedçÎ]¸~ýşy|Ąôú§eËpppČň>Ł * C‡öX¸pąEš›7oôz=^~y´Z-vďރącÇ k×.¨S§žýöks;řçŸmHIIÁ´iSPąbETŤV ˖-ÁčŃŁ˜מwď.´lŮÂü„°””‹e°ÝXúۍšĺłŸ_Čd˛\ˇý?ţÄkŻůĂŰŰý•őëÖ¤]^Qż~=4jԈƒôƒ1DĽÁʕ˱qăz|ýől¸¸¸`ěŘńć{äF#ƍ{7nÜŔŠKąrĺr„„ÜĹkŻ3_í‘$ ‡‚ŤŤ+>b>¨zx¸ăȑłt#͉(ŠXłf†Œ‰ßŔţý0eĘ4ôěŮ[śl A1cĆřűďm€~řWŽ\ĹÚľżaŊe8tč°Ĺňžüň+ěŘąsćĚÂŇĽ‹ąsç.ÂŞU+ń駟`ŢźĚóFFFá㏧ŁGnŘľkúôé…;˛–‹ĺËFż~}ąaĂď¨TŠ"Ţ|ó-ó7nÂ͛ˇđűďkЧOŻlˇuӌͨWŻ.nŢź…ëןŽ[ąwď>L›ö)€mŰśbúôiزekގˇQţ´lŮ5kÖ0ă3ú믭hÚôyÔŤW—/_A@Ŕ|űí´o˙B–÷–ÁÁ˙ücšĚřřx:tƒ›žŢ÷ůç3ąoß~,X07ŽÇ‰'Í=sÓ­oţţcQŠR%lܸK–,Bhh(ÖŹY˜={.]ş„eË~ÂΝŰŕää„×_ó™ ƔŐvcnůÜšs'œ5÷¤ËÎśmۑ’˘Á‡“u°xkŇ./‹/ŤŤ+ślů“O™¤RC°âs!ĂűôżeţOÉÓ^Š´— €€G‹­OÇÇ'0ľ‰ˆˆˆŠ˜Z­ĆWđ駟™O ‰ŹĽP(,NxϟŔúő°`ÁB&ĺéŔ˝Ř°áüöŰ&•*ÉÉřůľ2ż8ggÓŁç=<ÜqáÂŮśâččŇ^bÚ˘á%eř?ý>źŒ#Óߌú—Ů@DDDDTöź˙ţ{čŐŤžřb""bđŕđđđ°úÖ˘nÝř¨h˘‚b0†ˆˆˆˆ¨ úý÷ xîš*řńÇđôô@XXŚNý§O0qˆˆŠƒ1DDDDĽ˜VŤE­Ző˜”o?Ɣ)ӘDD%€řŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC ĆŮƒ1DDDDDDDD6Ä` ‘ 1CDDDDDDDdC [ʤz•JxâęÂÔ&""""""˘‹ç*ř˜ß‡z•CďrW7W\¸PüŰ`“`LXč=$ÄÇ3ljˆˆˆˆˆˆ¨D%Ľha~…”' w›loS""""""""˛!cˆˆˆˆˆˆˆˆlˆÁ""""""""b0†ˆˆˆˆˆˆˆ,Ućl IDATȆŒ!"""""""˛!cˆˆˆˆˆˆˆˆlˆÁ""""""""b0†ˆˆˆˆˆˆˆČ†Œ!"""""""˛!cˆˆˆˆˆˆˆˆlˆÁ""""""""b0†ˆˆˆˆˆˆˆČ†Œ!"""""""˛!cˆˆˆˆˆˆˆˆlˆÁ""""""""b0†ˆˆˆˆˆˆˆČ†Œ!"""""""˛!cˆˆˆˆˆˆˆˆlˆÁ""""""""b0†ˆˆˆˆˆˆˆČ†L"˘’#AĘös‚Ĺ´Ěďóúź 2.ËÚőĺôÂnWa—[”ŰbMz綎âJŁÂ–ƒâ*SÖîŻ-ĘtAö×eş¸ňÎVż5{Šlő[+Ę2]ő‘5۟ݲe]oÎieúL°h˜ĺ4=űmËi›˛ßלŚç'˙2okvëÎizú÷­ÝöŹŰ•žţ§ËÉë{ŮĽ`ʓ‚ŚUzžć–VٕĺźŇęQT,|ŤU3Ďv˙!*ú”ƒ$nnޏtă*ƒ1DDv×@Ë|Ÿ˝ô´f@2fŹěsŹ1˝1—Ţč!׎‘™çĎižŒÓóűž°ë,Č6ćwJKş”śź+HްLłLłL?űeZ Ȅ´“)­{˙Óĺ@$Azf21’ČäŞ×¨˝zĄQăĆpuu… “?ݤžŚŤé,Ńň3)SP kţfÎŻěʃ < Xžhf˙ݧßËţűůŻÇ,ŁtÖîCĆíxšČe;sŰ˙ŹëÎí{™×cž¤–Cţ垗RĆeŽżŮœ~o9 ŹýÝf—ˇ/sdÝ')ŰňcM“yýéyS}i™çČąüćç8”[úĺUo ‚€C‡ţE˙ţ˝ÍŸUö­‰Ž]^4I lŮţƒ1DDv„‘˛ţ­P*áâęŠÚuęŔ××*ľ*ˁۚF_N€ŒÓ26Zňłüœ——˙eXťüÜž“ŸíÍŠATŘĺç–îM—œÓÚ˛ĄTŘźł6?Š"݋:m‹*Ýsj¤UŢe™Î|˛Q\yWÔi[\y—]cźŕi[°ú#˙ËËýdť°ë˛E}TŘă€NŤCXX‚ďÜÁ“'O`ĐëMËJďóŒd$Hţ “ hÓś->úx*žŤę ľZ ™LV$啈JNŕí Ô¨YÓüžjŐçаQĂՏ Ć Í"#ČdPŤŐh޲%^ó 4hĐ*•ÚÔ0Ítľ ä68ˇŕEÉo[vWKlž%YśĄ$ÓNú`qĽ2óČŹ÷ż –5_ŸĺźĚ쯞"‡ułLgw…°ÄJ’Ý”ikňŽ$ŇĹ~ˇÍžň.­^2:ˇnÝÄ/+VâšsĐjľŒFËjĽ´Ç(¤§˙+• TŻYN™‚ÚuęŔŃщm!˘g„RŠ„JĽ˛xŻVŤmş ĆY× }ÚFKk¨ŠŐjôĐďN~žĺĘóJŮÉXi{:— ,űDe€ƒƒZˇńC͚ľđÓ˘EŘšm;R5˞7(˝˝c2ë%N.ÎčÖŁ;ŞVŤĆ@ 9cˆˆŹkĄĽŸ)‚é^Җ­[á÷ރWyo(JŚŠ(Š0 Чwý/%Ň1 … …ršź KAzŻ˝(!I+Á JpR pT ĽÇDD%,íç]žź7ޙ<#Âpę4 ĂÓ ĚłĐ;&m\7774nŇÄćWˉ¨l`0†ˆ(Ď&YÖ[7\\]1nÂë ÄP‘0HMM…VŤ…Ńh,•ű KťmĎÉÉ)˙˝d҆`ŇŒ8ŚÇš0-RtFTt—ŁC-ÔôV@Îh QÉ 3ô~Q(đňňÂŘ×Çăúľëˆ‹7_ŹH?n–ęącŇűJĽň˙Ů{Óç8Î;Ďóóü!ż~ëmJĹ2““Süň—żâüŘ8'Nœ¸­m—›xĆ‚ \q–ţŁÜ@†(-bŒpő 8Ž/›+&I’şąż4dG)ŐĚWÔŘĆň¤Ësş4˶֗ťTuçÜŞďöZk‰˘ß÷›ß{šßŢH\ŹÂSÇ'b˛ćÁjlyďt•Îůlč0Íś.îŤ[-_ľvI˙Bę5´źË5Ú˙i+ý\n wĎy¤y\¸Q¤16Vs [k)•JDQ´DXĐZăű>š\nI˘ŇŠ0 äíˇŢŇóÓÝBEźöÚkŒŒŒđĚ3ψWŒp›‰1–™ŮÖ­[ÇŢ˝1;;ǁÇóŸ—됈1‚ ×Y”ŠÇÂű~ ášO¤.Łřó˙÷/ČĺrüŤßűd~ŽČS_ţëÖőáyI’P­VŠVŤÍ.A4_;çšÂN’$cŇ*`+ÜŃn„Me2™UO4Vƒ.5™‰˘ĎóˆM”¤Y; `”Â:(U#*G¤%eOŸ>MWWWłmßv+ěÇRŠÄ?ýÓ?ńňË/Ł”â‹_ü"_úҗhoo_˛\š\ŚZ­AŕűţŸS˘("ŽcÂ0ü”šz„;ibU*•¨Ő"l˛ ô/ Ěfł—<†ÖŻ­řY­–†2 …%ŰQJ5Ĺ×ćuňV*u÷ˇß~›|Prʡçy#Iç“O>桇ćÝwßĺ­ˇŢâ˙đ9qâkÖŹáŕÁƒ>|˜Çß÷ń<—^z ­5;vě T.Ţ2×`cAî"D‹n$Żýę Μ9‹çyźţÚDQÄ믿ÁŮłgůŸ˙íŃÖÖĆää$ß˙ţ÷9sć ­­­ěÝť—7ß|“?üĂ?¤\.“$ arŕŔjľJ)Ž?Î3Ď~󧘓žüôSřžĎO~ňSÖ­ëăĉ|őŤ_ĽŤŤ ĽŐjľ)jTŤŐڈ4??Š‡dłŮćwçóůkz7Ű9ǏücŽ=ƟüɟP­Vůя~ÄťďžËă?Ţ4XgggůáČ{ď˝GGGßűŢ÷hiiiŠ3a6sełYŹľÄqŒďűMďŁl6ˋ/žHąXäńǧťť;ő֓Ó]ˋ/žČ+ŻźJ'M%Äó5_ůĘWřâżxÉu¤"ěřř8ů|žbąŘ[㋅‡ťy¸)ĽxňÉ'y뭡؞};ů|^Ąp[ß ń}c ĺr Ď󚥞{{{ٰacccőe*• ǎŁłł“JĽÂşuë8zôˆtڈ1‚ ‚pgłeËGĂ÷}††63:6ĆđđN>ó™‡Éd2Í|…BĎ}îslŰśóçϓ$ ÓÓÓ|ôŃGLLL°yóf^yĺ˘(bxx˜‘‘~üăłyóf|ßgvv–ţţ~Nœ8ÁÔÔ$}”pěŘ1†‡‡š˙ţűŻŠFÇ‹%Nž:͏ň3žđĽ§y¸s§kÝL•ňÜťÁçKŰBţŞľÖZŹMÚ*• ###üěg?ŁŻŻŢŢ^Ţzë×lßž c §OŸŚĽĽ…­[ˇň˙řlÝş•bąČđđ0ěÝť÷š‡źóÎ;|ď{ßcýúőXkš˙ţű9ţ<Ĺb‘ÖÖVœsĚĚĚ055Ĺ}÷ÝG&“avv–ßüć7ŒŽŽ˛fÍvěŘÁĄC‡˜žžŚ˝˝0 9yň$CCC?~ĎóčííennŽš_wďŢÍŢ˝{ĺĺ]<ązôŃGŮśmÖ.xšŁ›bĺĺŽĹFčÜěě,ß˙ţŁ­­•ŮŮYžţyzzzšË]Ô ä.đ†YŒďű c­ĺĺ—_ćů矗P%áśÁĂƍƒÄńcXk Ðçž{Žçž{Žééičěě$—Ëqß}÷ŃŐŐEoo/ÖZúűű™˜˜ §§‡ŽÎvÉ#bŒ ‚ ÜŮŹë_ÇúőýAŔŕĆAúÖ­c×đ0ša„’ {>ŸÇZËěě,GŽáÜšs”J%ÚÚÚH’„l6K&“Á÷}:DOOçϟ'›Í222B­---źňĘ+<đŔ×öGš…°Š¨Q)ÎŇ×z‚}†}{ŸdM{†ŹŻ8T_&Ž´Nx˙ŕ!~řa<ăÓRhĺ_ţĺžň•Żprä${ÝˡÇ8yň$ǎăßü›>Ž?Á“_ü‡ćđáŘż?ż˙ÝßGŤk?qĘĺrŒŃ××G­Vcjjꂜ…B;v022ŠS§Xťv-?üáéëëăüůóň˝ëűß~‡]ťvQŠV™Ÿ+ňށßđüóĎS‹jŕš\žŔyőŐ_°wď^9PîbΞ=ˇ~„łŽŽ‹(´†Ý{vÓŐŐuéCqQ¨d†tuuňâ‹/ňůĎžé5ˇšpĘť‰FˆÖŽ;Xˇn1Âm7~[Z[¸÷ŢÝXç0ZŁë7[ş×t5sŃĺr tuu ´Fmí­őmljnO1FAîH˝ˆĂ‡ŁľfëÖ­ôőőqöě9˛ŮšÜó€L&COO[ślarr’RŠÄ™3g˜˜˜Ŕó<˘(˘­­ąąó8çčîîfppƒây'Nœ@kMĽRA)(•ŠXk—ć…¸vć ]ŻJćŔ9Ú[ňźůć›ô|í‹2Ś>ůSœ9}šƒżyŸúEľ155Vœ˘ŁŁ“|žŔÔdú^ĽRĹZG{[ƒƒń<ŸżýŰżĽV܈6\ăę/O>ů$?řÁ8yň$•J…×_'žxb‰ÇĘüüů„o~ó›<řŕƒlßž#GްqăFzÖöbŒGKK 7n¤ŻŻBĄŔć͛ůÎwžĂččhę-SŠ'…Bg‘;ów1Î9^~ůe^xá’xĄ’’6đěłĎňĽ/}é’BŠçyc°ÖŇŮŮÉwżű]Â0¤VŤŃŇҒŻőŞJ‚ ‚ˆ1‚ ‚p×đЃPŤFh­xŕ{ikkgÝş>ÚŰ;0^šœśP(°gϞćDĚó<žzę)Źľlßž}ÉdŹŻŻŻ9ÁRJŃߟ ËEç\3OĚľž+îyĎëyz{zٲe ýýýôôôđĚ3ĎĐŇ҂á•fϞ= ďDŠ´­›7oÂ9^rˇ~hh­5<ňÖ&ő÷}}˝$‰ĺĽ—^"—ËńČ#\áBŠ´Ôďŕŕ ýýýÍś 6“Ł6–fűöíÍţokkcçΝő-ižöľŻaEĄ–”/衇šű- I@9†6oŻ…ťĽ_ůĘWxęŠ/c“†Z+<ßťěŘhTIŠŐjřžOww÷Ű_\ĄMA1FAÔĺŘľ{;‡w6'řJ)ZŰZQ* öAĽŰi„ő46Š”şlŇ݅őŽŽ‹ŰśšmĎ3Ď|uI›•RŹíéŽoŔb<…6Ţ*ˇëЊfě{m _ůęÓüÖWž\3(wÝöçb‚ úOk}YAȰđ€r˜ú6”‚t—™+G{ Ð ¸°´üjŽI­5š\­5ľz˛ěĆv1—+-‚ \"Ć‚ ÂÍž{ZkŹľŸ˜łŞJFË']Ť _‹‰üâ0†Őloľť+ÍUqąeo”Xąš}đi۲|’-ŸćYNĂ.—Ëáű>Q5ĹĎóđ}_„A„km˙I‚ Â͝DyžG&“ĄRŠ\RšŐG†xž'" ܆Ç/¤iK<ťäxA¸>ˆ#‚ 7‘ĆÝçl6ŰŹvÔ(!{;L‚œsh­/¸{~ť´_„ĽÇ3ˆ#‚p#1FAn" ‰XžďßvŐJOŢ$„FAauˆ#‚ 7‘K݉žTRÝ[MěXœX„AA„K#bŒ ‚ ܢÜ.˘†jVřFAa5HZtAA>5"Ŕ‚ ‚ \9"Ć‚ ‚ ‚ ‚ Ü@DŒAáš!ž2‚ ‚ —GrĆ‚ ‚p͸TŇaAî ĆÇÇQJřF:CáS"bŒ ‚ ‚ Ť&Š"|/#!‚đ)‘0%AAAA„ˆxĆ‚ ÜD$¤CA¸YHŽ'A„›‡ˆ1‚ 7 k-ÖZ’$†(ŁÔÂëkůÂ÷.m]_ßĺoĆwJżÜžý"űNúEöÝ-Ů/Ćó0ZŁ´8Ę ‚ Ü DŒA¸Á¸8ĆV*päĚáØŃQ° …Â-yžŔ–^ô9PŹj˝ËÚč,čW˛˝ĺË]ěůJÚŃü}WÓçpji?-ßÖŞÚłx;Ë÷ă•üŽU´çŠÚĹʓ˛+íëúJÍś]m{Žf,|Ú}~Ůö,ęű+Óע=—ÚΕĂ+ÝWkǕloń2WÓWkǕno5űüŚŽbŸ_‹í­¸žR¸ž^’Ă¨Ą!t&ƒňdZ ‚ bŒ *ÄXK<7‡úĺ/đŢ|5?Ö^ýOAAX-JáFFP‡ŢÇ>ň(vßç0­­Š÷ŒpçŮKl EăŽŔMŰÝnQSá.FÄA„b÷*l’W*đŢü×~ĺ˛1wú~Ż?Źt… ˇÖě•$čbýúkT[Zq?ŒÉd$léŽŰŐŽţhŘ# ^‘‹Kš,Ît%ůěV“whůöœ[Đa$o‘p7#bŒ 2†ŹĹNMá> ވ0wËž—.áÖź0MPóóx"Ú˛ÝÓ#bĚH”8Ś‹1cł-CgާŐ\ŠkŠsîS‹'qbŠD–s3Î:: í9ϤăMDánDÄA„bó:\’ĚĚž;+BĚݲ߼ A¸UQ`q(çĐçΑĚĚ`şşPĆČÄřN˛=œžŹňßŢ-stÜxŽŻ ‡<˛) ZáV'`L*ĎÔb‹ŻëˆjŘ›¤šíŒďĄLúđŒÂ:p <­H’4_“ŻSH)…§ĄĹĚU,żř¨Ä/%$vö*žýP ­9Łeź w'"Ć‚ Ü ŹľŘ(‚JE:CA¸É(+T*بvEá)Âmb{8Çż*rčléÍpv&ćՏ+äLÄ٢á3CfJ1'&÷o9;]ćÜlĚýë|ΞbnäAyŽ(śÄĆĂäó[ťéîëdcO–÷NGô´(Ö´ź{˛ĘŚNM!빤ʎƒďiމUĚ?ŒŘܛ%JŕGk<:Xb熌žü”Ô9‡ľvÉuÎĄľĆłâň‡Öş)0.ߤ^9şîśx˝Ĺď Âő@ÄA„‰“1‚ ­vmr"ÄÜqťta&q„ł†$qX›†MGľ˜8ňŔŞŐ q \˘)NM1óń9Nžs;>Cd5ó: fBj&$2Ö/“KŹ-l \Şbł>Îj˘j—’ŘŐj¸Ä#vš8ޘg-ÎAâ ą`ťę@ŠjľĘšsç8{ö,Q …b`p€ xsÍÍÍqöěY<ĎŁżżŸL&ƒľ–ééiŢxă şşşčííe~~žîînşşş0ĆE###8p€‡zˆÁÁALÂuCÄAAA„; ç Çă[BÎMĎqf<Áژű=v śą=ŽÉç:ň>ë[KčŮq֍ü†ŕČQl ‘ˆuHÍST”ĄŚ=ŞÖ#‰5ĽÓó”‚ivoiĄˇ+K6ôřě=Y|ßÇ3Š'śBxFӚR¤9;3Ă{çŠXŤŘŐłžŤŤ.˘¤Ő.EEźđ‹źüŇË(­ÉfłŕŕŤ_ý*=k{ĐZăHCŤćfçůł?űĎ ďÜÉ׿ńőtâëyÄqÂG}ĚŚM1ĺr…żűŰżăţőż&fÉd3X똚œćƒ>dp`#SS3>|˜{îŮž=ťń;‡‡Q(6ŇÚŇFľRcnnž™é~ţó_°qăFÖŻ_O.Ÿçž-[ŠTŞźüăŸňĆŻłgĎn:;;1F¸fˆ#‚ ‚ ‚p‡áœ#Iâ¸F%śžiŁŁ-"‰J‹e”ŇÇčŠ ˘Ÿü3œëጏ §Vieˆ•G¤|Ş: ŞĘÎăŏJÉßÜăQ šx{ť8pXÇébHd›](ň1:\’óĺŇárŽ(ŞqâÄ jľš\–L&Ëěě,ţçΞ}űxď˝÷Řłg6l Z­ňú믳˙~*Ő*>đ_˙ú×y饗ؾ};ƒƒƒ‹Eţâ/ţ­ĺr…gŸ}–|>Ď /źŔž}ű8wî,QTăěŮłŒł~ýzXÂ5Cd=AAA„;„FZk-ĽŇ<ĽůYBĘ<¸ŽJ{&&Ž•¨”‹TJsD§ăýô‡řǏ˘ŞŐ´Üů˛Z€‹E™Xj: ęĽ9dć#ĹO?rüÍţ*§Ć‹‹ó”Ks”Kó”ËséŁ4OšńÉđ…M1íYˇ @ŞT„aáßU„Ď~óYž~úi’$ĄqŔů‡ď{8ç0ưsx'•Jß÷ůw˙îĂ9‡ďű<˙üó|ík_#“Éđ§úż’$­<ţýż˙?Ň$ÇID&“Á÷}††6óŕƒbŒ!›ÍňG˙Óa­% SŽ)"Ć‚ Âľ˜ŠšúƒTˆąÖbëÖ­9ąĹ‰#ˇ×I .ś,1ŠgŒQ* {XxWŒ×ó<ňy|.ťd•ŽŁ|>Á{a’Ë喆BšĹŠ]QRJŃÚÚşäA¸Vˆ#‚ W5S8Ň*Ö9,ąsDIB $(’Ś öň —7Cˆ‹Œ Ün“`ĽĐuÁĹ8…xZa´BĄŃ ”Sˆ›ŒpÝĆŕ’+ ´g-_ÚR"çCPš&¨˘<‡ó ]ą˜8ĆKb<፞öńm•81„JcŃŘXÁDLrJÓŞTŚ.úÚ)”s”‚€*Š_œ0~kkD[& YÚÝĄpő0%…rjy—KW\•wŮBʒ/VŤ_OŽ"Ć‚ ÂUZźÎAâ,‰łTŞ6¸ţőC›1…–TtiŘrőťç &ňĽHCLφ‡ÍĹ*N,ĽŒ5Ť]÷RË^Ëu/ÖÎ+ůžů]Wđ}‹öő•÷˙§Ůw‹?żšßy˝ű“žk5ýrą‰ÓÍÓ+żŻÂÎÍQ9ň úěYÂ$Á‹Gš0C‹#\WܒÓQąŚČx “9ŒCy ʁá ą‹đm ßzř‰G  ‰őHľŕŠ1ö¸%3â‚Řtăşî…ŁRQĘxŤšŸ~ě‘ `ß`D{ÖQ‹Ö)r~ŇlžÜoDŒAáĘMÝz’ÄÄYjÎRv ÷ěŚí™oŕľw€ç§bŠr IeëŽb&ž1×aZ˛X$Y.˜\é˙+0rU€EC,ŠŠMŽ3ű˙@é7ĽĄî;#áJ aŚ˘ůŐH†Ç+´Ůt„ *pč’ĐA”ŕE5ë[ÄzŘÄ`•Ië)UŞ‡Ę˜Pˇ¤‘=ő|1Ú)t]”‡VYJJQtŠźďS‹áŮá‡Ç=j‰âń„@ťÔłô&ŽńGœÔ„›„ˆ1‚ ‚pUÜk扉Đ$ýëé|öˇńşşÁ™˜ßdŹsT*â(ÂÚ +v8ˇ*˙¤ŐOŔëłpŁ5A†a:”ş@ŒîÄóiu˜ć€PhĎ'ě]Gűo˙ç'ڍž:…ÁA}"ÚČăDČŽ#š„Żm+‡+ćIÂ,&˜C.ÍhÄ›DÄşVb4‰…¸TŚt´ˆ™ÖřäQƁKKa+çФyc¸P.Ŕ…U4G'ĽšâţŢž†@ł?iíŻĹŽb͒4Gl!ë§!Ö9j x: źôAިYË\Ĺňćń ďŸIčmŐܡÁgSˇOŢ7\*nęJüW¸:\䪢–mXŽ"Ć‚ ‚pىWš¸7MŇὝ0í(ĎkޡÖ6+=7–$ŽŠVŤőęK˜ĆÄ7Iâ8Ć9‡çyWľŸ”RЧT]€ń|Ďóšó%ăÇ9â8&I|ßGkÝ\qe‚~“sçšăÇ9‡ÖşšŻVZŽąOľÖřž1ĺyxídwď$>}*Mň Ídż‚p˝‰řYC_‹% ť¨ĺ×ă'ĐaŒŞ9ˆ*˛čHáUk‰&qŠ(N`fŠřt 5éđUgbp6}`Óđ$\úš4TIŰFȒنTkŽR Ҥš}- WrŚMě?ѕ×td5ľÄŇŰę1_sB˜­XBŁąr˘X…–ŒÂ:˜)[ÚsŠ\şŔT"ÇĎ>¨ńëă5ë˜,)NM'üÎýš{ÖčUK*Wn1\NâFÄAAVo[)WcŔj…×ݙ 1‹¨VŤŒŽŽ200 e1ođ$ş11ž”×ÁÄÄ'Ož$IÚÚÚ"IŞŐ*Ćx8gÉçóŤE{ÚXkWôĆYźěéÓ§y÷Ýwyä‘GXťv-ĆJĽ333´śśâœŁĽĽEvć͜ÄĆ1GŽĄVŤáœŁ˝˝ŢŢ^‚ hމ†S.—›Ë)Ľ‚ -—ëů(ăc:ť¨éôNžkŚđ9F¸ţĚŐ ΅ä‚*Ů\âšÇÉÎ}‚ŠfPąƒ$AE(Lě’*ľZDetšĘČ,śâatgbŹKKK+×`ę¢sh :uüJEkńđđcEœŔąYÄ)Öä´NŐJĄ—Š&ĽšĽ-Ł8p:˘%ŁřpÔ˛ąKsl<ڧĹ0]JĽÎŠrĂ!Ńqôźĺą!­gfŽœŠÄó÷ŹńxçTĚéé„-k<Žkú‹ňĘ]pŁ@1FA„KZU ë4ˆiZZÖZŞŐ*ăăăźńĆ´śś’Ďç ĂPşî1Ë=Lš6ď˘ tľZĺĉĚÎ΢”bjjŠöövjľ¤łłk-(ĽČd2M/šuë֑ÍfWÜörafĽö•Ëe:Ä_˙ő_ÓÖÖFKK ů|ýű÷377GGG“““lŰś ­5ĺr™ ‚€ůůyÂ0$ŽcÚŰŰYłf͊ŢÂŐc­eff†bąŘôŒYłfÍËEQD­Vă“O>Ą\.ăy;věŔó<<ă”N}$dM¸Átfcžś-NŤ)C5ŰĎůÁ߼uäřöĘú$6!˛Uj.a~ŚĚĚä,ľ™í4~ lę ăphş.(6Kh;×e–{δ%Z3†‡ 5ŒŚYMiľaJŠŞâxdcŔ/?ŠâkĂ菣żMóÁلîźbŚäě„ÄÂń‰Sż÷‘XhÍčzž&0Ęb´Ł-Łî3>—¤íP w}Ľ˜KjŻrţ1FA„O!É,<&YI’pâÄ 8ŔÁƒÉfłěŮł‡7J§]kűV-Lp/ ńYŮýŰŐóÉDQÄúőë ‚€ńńqĆÇÇŃZ366ĆącÇhmmellŒîînÂ0äüůó žńoÍf?ľXtćĚNžĐě\çc- ÷)櫎=ý>yM!„É˘ŁˇUÓ]€8q´ç4óUKKF7#E{[5[ÖxźwŞĘĄs1qëŰ=ÖľńSDŒA„ŰY”i^d=ĄĄ!Z[[‰˘ˆ/|á d2é¨ Ě,eVΝŤ”˘P( ”b||œŽŽFFFxâ‰'˜ŸŸgǎœ9s†L&ƒ1†žž´Ö8çČfłÍu?m{zzhiiáÉ'Ÿ¤˝˝ŽŽŽŚ7UEtttÉdXťv çΝc~~ž­[ˇrúôiślŮB&“Ą\.Çąěôë(Ä(Ľđ< pÎáűţű])ŐôLŠ˘ˆçž{Ž(ŠĐJ<–„›O)Ň|2áѝ‹ÉůŁNg‰Ű 1ü#˙;ÎN’X‹˛ “ř8 Niœv -j(;t’žWŽéą˘eQX´KPÎŚ–P ŠýŒ†łó†jŹXßcÔęC”|ŁŘ˛ÖÇhęö°nAfWó<Šuí­šT|1 ˘Ä`ôBÚŽ\ ůňސÖŢ;łś ydłĎ†]÷‹šF |/ąp#١œDŒAá1+M¸}ß§ŁŁƒ‡~xŐyG„ŤŸCCCÍďn|n¤r×uA)…1†­[ˇR­Vhii!‚ – ‚€(ŠnŽCß÷ńü´ź˝ťƒüaż_ĆÜíCg. Sň‰N:‹+ oúSĚÉ˙ˆQ˘´NËŻk‡R:ővQĽ˘´ tTdQ6Aš…#"­¤ÔQ \úĆ)Z[|6ôűhĺx°Ż–Š$ZĽáMŤ>SaE‘ŽŤ—­ëęŠIU˘ôšž^°ěK´†|hřüÖ,ŸÝ’.ăkĐZ]˛’ŽŐ•˘żŒbăVq}DŒAáÉdŘşuŤ^×Y„YnÜ6”‡0­D>Ÿg׎]‹ uݜ„Ż$đŹFčil§áIłŇňZk:::řć7żš¤­aŽ8Ům´cĽœC2śŽŁąěy 4÷A#lyŸcČĺrÔj5Źľčzyó4_Ě 3ąŰybßٙ&,.e€Ü&”jšĂç}śv×h ݂¨ 4č IëƒĐ˙?`쟡ŐžŠë‚ŒIÓŠşĄ@Í% ‰­ËŒ\R/ëŢČ“ŠžV ?ÚCžEƒƒăÓ‘…­]ŢžśÔ2qć‚ĎÔĘ Ż´ŹQ`ŽŚWąü’ Öjńyaľj bŒ ‚ ŤłÇĸşa‚Ěňžö<L&CE7,ijCT ‚ŕ˛++ĺyšX9kG7ŐĺăI˝Ľ<ĎkŽE•ĆNÜqIbÄCˇ ľD3^Ô ś+\¸l@* &OŇţ8ÎkĹ;úbô(JǨzi$Ľ h•Š4XÔźƒ„EL=ŒKP€o íĂ]toĚŕi&™ŮŞ˘–¨zl{u‡Ćr”ë}œŠŤ]uYłE^8Žńي˘Œd™şS1FA„;f‚Ř˜/ÎőĄľ& Ăz™éë;\< —ęFw b ěwáVŁ#óĺ{b´}ąái˛ŘÂ.jƒ˙ ţČ˙…śG@ŸFDn]U˛>šđŠĆŠ]=5|ý)m‹fůÂ4ęFĺcR€kxźŠ…w‹n°ŕűâę"QúXégŞzhW=rý­´U3ôjIąmw›˜cÂŞ1FAX2‘źÔ˙ˇßäHöŠpcǃ1‚ ܊X§ˆĂ^ Ę+`[f.qäG˙ OĂPK=c…*5ţWĘÁœƒDĄL€ëĎSxî^ň÷tăgź%çĹŘ6ô„FśuĽ?˘W‹°ŐeíBŕĎ•:şb hcŔ3h߃ŔĂ ZŐŖş ă‘ƒr-ĄZsDʧíŤWĄr ĄĽ~ó€´,¸§žŻÉřšŹŻŇJPKźeä:s§ bŒ ‚p)ŤLş@áŞ'ÂkíUQI¸˝hĎ$<ą)a‰SÇĹŽüJá­ÔZb&ś´˙řî4ZY”ą bPŽž¤(­ َô>˙ŮĄ d 9ŒYc´‚]kŁf)ꦕáVik8‡›-ăfçqŐlšsĆÝ@SĹÖ{ĎzUČ Ú 4ĘݧrJ9qŒÍ&ĚT’„%ib.›ăŚ.Ö(,ĄŻXS0´ç žFî0݁ˆ#‚ Źdď¤FEÝP°Ö.M*ç.óÜŘHă˝ oĺ÷~aC.\wĽĎëˤąěşšźx*‚psϧŽjľJTŤ.ş}/7–éŠć­ÓYčŤŇ™‹/ž7Ś>fľ1řŮV’ö‡-“˙Ÿ“ƒ2͐%´‚LHźŚˇí1‚#סŽ0›ÁoŠu[ÂÁ{Ł!ľDq__Ő㍔]… âp•vr’8bœK]m’eęn' đLĂxÁEIj F_‹#:}Š’ŮFT‡AiS8Ëč\Â\ّÔC¨Ś‹–ĂçbŹ…š…Ąn  ałÖA”Řş‰ŁĐ*ő†!rœąd|E.HßDŒAîx!&}NœĽV,c犨$šzűĺzŰJáÂżľ€ő¤~r3I„›K’$DQ´Bn ÖA-ç,ŐŘ%ŠĐťt~8ĽŔŸLžçbVŐhý{L4چö<Ľ*ސÁ+˜ Ýčő]Š=P‰°ŸĹyÓہ*dšƒ´4ˇIo޸¸.ÚÔU*WçRFá,P­A5†ÎĘč4)q¸b՚ĂisP3e›†ƒŐťř—GjäE[V“T‡ĎĹŹk3x˘ÄqfÚrj:ŚŻŐprÚ˛ĄĂcC‡F+°‰cl.aC‡‡62–EŒAîA&5–*3sŘŃ ¨TQÖŢú W ç*•*Źí"‚zR=dA„ť“؉iŇç-Śⳃ°śpÉKiý9­H—o]K-|Šů֝ŘňYâę<6QÄś€ ťńňÝtĺó„™Ě’°¤%ZŠƒń˘âýłŠFіŃlé´4łÔ^Î.‰b¨Tq.-Šu¸‰9ě;Gq3ĽÔCG)ěČ8ᡣ TŞÇl]‡›+cOO ×wcĎNŚaN•řčkˆß9†Ę˜Ą>Ül‰äĚzM+x;9Ÿśáô$ŢÓ÷Ą Ůf“]œŕj1Ę7$&‹›,öS”jŽ{×űŹk÷8?—př\„u…a˛˜đË#Uœsd<Ĺ|Ĺr~>a]›Ć7ŠlTŠAbŠ˙/ˆ#‚ ÜÉJ Î9˘Z ;>Ĺ2jy¸Đâç[ ˝ áJ•XÜÄ ĺlˆßю2Śń‘¤ŔAîŽK:đá¸ćŸ?ĘВóůőل(Šňôք(Qäü´ uŠŚČç•H‘ ,Ö)Ş1ä|EMľP ˇ’Ém ŠZ Y_QsĆóĐžf6Ňx ĆQŠ4žvĆQŒ4sřÇ<ŠI€żz7âß>féZílÔĽŒŞ‡P+­P-YTg nžÖ˘Úň˜=ƒŠ0c>ş§řĐ)toŽŁťŰpÓ%¨F˜Ą^ěůYÜt •X”ď“:Ęámě!>tşZ0›{ \K“őޅśDÝq@-qŤţ9qby˙tĚÚ|tŢŃjJáâ3 űP|ęDŒAîĂ Őr [0Ëó˛ř>*B‚1Š4Î^¨z,Î#łœ‹~ćHË5,˙l‘Şb-nn*•cȁJ’™"ś˝œŽßxS˘Ĺ‚ wJáP5 4ý!Ž˜(Ő87o81ĺóđú2łUÍń)Ÿűú*œ/Ê{z+ŒLŠ‘fxMÄŃéŁ`K§ÇŃIśŒ#&|4°ž5FË{Ł[ťbBĎą˙lŔžžˆJ oŸńéČ$œžŐěđ¨ĆŠCń٪˘+żĘ+łÖŕ\œ¤Ő›HĹďÁ!bŁqł%ĚîAĚŚžÔFP. CŇ:őpq¤áE“sÍMÚůşíŕ›ÔSŚTEuˇ@šŠšGwäqžĄŸć„qÓÍbHi˙ÖZ7Í™ŹŻ˜­,UOb çf,Óĺˆr䈒´Š’EŃݢ93íĐ*MďúŠŔcINŸŐ$]DŒAî IF[{a]ĎCoÄűᅨ޵ź+źŒ,żásá  +j#Ľ2ń_ý ÉĎ^ÂÍĎCҸäę>˛'ݏW띶ŘÍźńÚI‡ ‚ ÜâúKZ^Ľ°’IJĽŒZŽŻ26›đ@ôˇĆôb˛ž%ç[:2 ßąž-bm!T6uÄÄVxŽ­]ցoĂkc”J=`öôÖ0Ęákx°Ż†oFÁgÖU ˝ôőŢ ŽŮ Ź-(ŽŒĽŰ´‰Łԯ卸´(Ďŕ2!Şš€KRąĹhT'~W;_AˇçSϕşĄ ظŁ@…~ë'¨ľm$œ†Ö,şż´F…>f[?Ş#Ÿć‰’4°VéşÖbśöŁŒŠ—äŽ—Ľö<đŇ|1FAg^s~ޒ,ş^ÖbÇŁ1;ű '§,ĄQ(ĽđâŢ ť×ĂLْőSárd…‘XkcA„ť˜ŔGmĆű˝oa¸|˙ć†*9 ńžűmČdH~ř#ÜÜÜjí:a‘řbU)­őńţĎľÖŇa‚ ˇ ľZ•óăăléč䚝–÷ÇbvvÁŢ y!œ"Vgţ°ţÚ÷\˝X3xžkúĽz~ýľ‚źďšŰČ 1ZôÂëVőż3ńÖIKd{Ö%äL•RŃŇÖÚ„—ţ1F§‰rKŐ´$QCěP ˛:ôš D”§Ą=×ôŽ­_ôP‰Ĺl[my”oŔ:ĚîATWçTŕąÄýEŠTiiÍâęšiTÝ#FˇdęËŤşˆ˘čÎ&Š q= đł÷fńÂÓ°­×áiU[ę!W@k&]?04űV+đ˘§Ĺ["Î"Ć‚ w JŃčńžó-Ěý÷B˜še|fU[+Ţó߼HţáÇ0=ƒČ1ŤgjjŠC‡1::F ďfý†őő*ćéNŽă˜ˇ÷żÍđđ.ňů\ZEBŠúŁ^ŠsGA¸—íÔ;Ć:ÇěĚ,aŕ1Ô2Oő ”K—K¤v-?OÝ`;š h 9_ӑ3„ž„)ÝŠˆ#‚ ŹÂĘ`ö=†ŮűđoąK‡1¨Öźg~ wü$ÉĎ•†q;1^V×}† xýľ×ů⟤X,ńĘËŻ†!÷Üs'Nœ`bbœýűß!Ÿ+055@ww7Ĺb‘Ą-›8uęŰśm#—ˉ #‚p‹ 3´ˇw23=Íüü,Ĺbé&…›j!Ä ĐƐËć1~Ȇ aŘř/żŹ.ŸAg}\5•jőÍŢ˝{™ŸŸgzjšóçĎóîťءﳟůć|!z‚ŃŃQ†‡‡Ľ3áBľdş%×yĚ)E†lÝş•łgNáy!APÂŮF葻d ˇ+ý˙JŽm4ů\5=˝ôőőŁľˇ¤PăĹô"Gşă´AeuZL`­P×㈎—äžŘˇ+­ńtVú=î˛-[œ´7őF•1}'"bŒ ‚pYX‹‹ă´˘Ŕ&ٕ×b]ľô=k!I°V“Ž­5žďăžç1??O{{;ĺr™ÉÉ ÖŻ_ďűŒœadd„ůůYZZZČç źúęŤ|îsŸ# CéLA¸žďŁpTĽ+„„R c …BŹíé#Žâ‹ˆ Ľ™Ż´î`ÓXě¸á.Ô.Ÿ+@)ń š\ĎóĐzAÚš”çNs)ľTšu÷ÁڍŽx_ w&"Ć‚ —6´œ#Ž#ĆNžaâ÷ęŢ2Şi„-~}Ąšąôł•Ö[ɨS‹îŮ­´ ˇÄÍWĄœĹŤTX;>A—ě˛%mł˛VHjźďű›7o¤Đ’ăńĎîĺ?˙…–Ÿyä‹ű <ϧľľ•ÁÁÁÔHđ<ślŮB’$Xkń<G÷>J’$Ôj5Ž9Âç?˙yÚÚڤÅŤŤ+Í;ç@^ä 7ĺ[íńt˝sĘ,o‡x}w3"Ć‚ K ąe“ëq}înÁé„|kąI";p#wšçÁrŁŰC6›[ň˙ĺ¨VŤ<đŔtuu‘É~@Ű IDATdnˆ/2y„[ď˜ů4Ű_|]Z|ó@î&DŒAVi9ĽnÄîJÜ띪וäňŐÝ"wœĺë^l–nZlšŐʋKS§˙'uCxqÜţĹś•>G__oÝ˝ÜÖóő¸eëɤY¸Ô˜LÇKc"ś0LŐ céÂ1بź"⌠\żëōھÇÂ݈ˆ1‚ Â53Ž´nN÷qNaíÂÄJ鋬ět}vUŸ€á‹Ň4cÉ3ç.[ĹRXÜľ+xÄ,ĎÚç,Ćt}~Ú;”Zk1¨…+Ÿ ÂĘâחĂZ[Ďe•ÔÇŹŒ9A¸VÇäÍČg$^1Â݊ˆ1‚ ÂUăű>7đŰżý,;wnăŘńüíß|ŸĂ‡>Ä:Gkk ÝkşĐËcĹľ˘ŻŻ›|! &&Ś9ôţŠĹš\†Ď}n_ýęÓ ŕĽ_ág?{šš˘xŔʊ‹' mx"X›z´ŁI’„ŠŠ)Ęĺ2ľZ$I.™gŔZŰoŰěîľUDaU“/Ľß w—ÍsÔŔÓLđÇ­Y2Ař”W[ź:‘ Üiˆ#‚ \5íím<óĚWyđĄűȄ>­mťH’„łg˙ÓÓÓ(ƨzůĘ´J/CAŕœĂ÷}´ÖhĽŘ˛eˆď|ç[´ľˇ€s|ë[Ď12r’ýo q—Ë Ó¨ŔtWOw/:Ą]Z5#Čž={–żüËżdlt”÷ߟRŠÔěCľ$ý¨[’ˆTi Îáů>ż˙űżĎwžóňůźÂe&}+'ń\œçčrë§Œ¸Ę Âmueş U›áVEÄAáŞéěě gm7žgĐZĄ”ŚŁ­ľkÖ073‹r ĺŠ^—°ľŘÄŚď×ʁVŠ{śl!› Roa°yÓFź{ëěʓ5ľXŠ÷™KM‚ž1 ƒąsŁĽâýď091Ů\NkÝ oj,ßxÝř ŕȑ#T*ršÜ OȸبżŃŐ@„k3A[Čse•_$ÄAnżk "Ć‚ ׀™éĆÇÇŮźy#Z+’Ř233ÇÔäÎY../p*­ŢtâÄqţöŢ,FŽ,˝ďüťĆ˝ą/š3“™Ü‹UĹÚKÝ]KwŠÔínKd÷Hƒ™†m <@ŔŔ°Œý2/z= ćmŒy˛Ç€4c¸muK˛¤vŤťş[*ŠÔľąŞH™\“šgFDĆv×3q3rc’,2™,žČĚ7îrî9ßůŸoé´;ؖEÇt:>ˇnÎ!cľţ0Ð .`­V+™ŕĆ˝ëÝKÚ.Ćô_Blw<ĎŁ^ŻŁiNĂ0Čd24›MLÓ¤Ýn“N§1 #ŮŻŚičşÎĘĘ ĂĂĂÉ~4MCÓ4â8&ęUĚjľZd2 Ă@×uÍf˲đ<]×Éd2¤R)VVV‚ ɋÓ˙\2_­Vą,‹(Šp'9f!–eÝИţ9[–uW§÷7AŰŤú—BĄP(_&”ŁP(Š/ĚęęňÇ˙™\.ϙ3§˜ĺOţäOYYYM&ó{ašćŽmQóŮgůĂ?ü#~ý7ţ.ađӟüŒĎ>ťH†IQ%Ĺţě?ąíŠ'Apůňeęő:Nç OˆŰí6.\ Őjaš&™L†vťM§ÓÁśmVVV˜˜˜HfłIąXdrr’7nP.—Y]]ĺňĺËčşN>Ÿ§ÝnÓl6aIJ,ŠĹ"GŽáâŋ,,,P(đ}ŸRŠÄĐĐ•J…[ˇną°°@&“Á˛,„躞-‹‹‹´Z-Ž9‚eYTŤU¤”čşNE„aˆëşÉ1œ8q‚BĄ ׁľQ…BĄP(ž|(1FĄP(_˜0 špé ˙űďý˜ŚIt:a!€ÚF“f{[ľ”nĽ¤+ł7śx\ARŇjwřÁ˙”˙ňăwˆăĎóť"šłÝƒaIƒy96C;zĺézś„a¸g؇”ÝjWBƒlZâŘ­śEŤŰ57MÓp×ui4´Z-Â0$•JŃéxd2Yćçą,+ht]§ÓéžçqëÖ-––V( ŹŻß Nł¸¸D&“&›ÍâyŤŤŤŒŽŽ˛˛˛’$^^^Nœţqt:<Ď#Ÿ/†kkŤLNN233CŤŐ& cęőů|ŽL&ÇŇŇ Ÿ VŤŃlśŠ×AŔČȨc Í*ŠƒçA†ý†gů~Ďç°öCw:ŸÇĽďü2œƒc …BqhˆcI‡Ôjőƒ. ăx_™íDQLŤŐJÉ*ź!Ô-Úíőía#›ŰÉóg=ž÷›5ţŕY~úŽł#ŞmŰLNN˘ë:Íf€Z­t6×jœ:UĄ^ŻS(äBŕ8ŠTŠršĚçŸÎČČŚiS*•đ}Ÿ\.KąXŔqt]§Ýnáş.†apîÜ9˘(bhh(ů×uŃuŃŃQRŠžďcŰ)jľ:ŁŁ#d2YZ­6ăăăT*CčşN*•BČĺrH“Ď( =¨CĹdłYՈ ۍď(ŠˆăĂ0”0ŁP žçáyuóŽ jöƒ™ŰˇĎĽĹ΁߲L씍mY¤@SI|ĎŁÓń’Ú]yŰfMÓ°SŠ”}¨ÂQűyŢşâhk"dÓ4I96Śy¸űÍ0ˆńźžçoćüÝ%!ÓěľŰÜ×.QbŒBĄP(ŠC+śěg´lőŽŮĺ0ńŞé˝˝Z׸pĹd˝fnzĹ ěƲ,†††RR,˜˜˜¸Ť ůŠS§’óßňzš\ÚQCÁŘŘXňżmŰ[>S,) ťŽĆ ~ďök6xĹŞ2ĘŻÝö'„—/_抧žR‚ŒBq@“üzƒj­J§ÝéyH~ąýšŚAĘqČçňäň4M;gšŸkŹş^§Ůlây^’kěnB`§lŇŽKŠTÂNYźŠ˘ˆvťMľZĽŮláoTÓ4q›Bą@&sp×űné IëkUÚížďoY  Ă$•˛ÉrdłŮ$ˇŰnăłc …Bń¨L'r™Š_BÖśLŇŽƒbǂ’Řö÷Ýźöŕö!@JRq„Lj |â[ČnFË^Űąť-7*‘.]ľ¸r=GÄťT´Ů­Tń–ﻏUŽ;‰!wUúŰ=‚öÚ˙öăV<šIÇěě,ǎKň)Ї7IŽVŤÜž[ îyąöś÷_ď˙=؇î÷\FQ„çůÔku&™ —ĎŁë÷Y–R†!‹ ‹ll4ˆ˘8ŮE1QbšćŽccI…I’÷°Ňjśh4šLĎLašć–ʁjńII§ÓannŽvťÝ˝?QLÉ-6Z†x^‡FłÁŘŘů|ţĐxöôĎáöíŰtÚAî‰î&đďz Ö7ę9r„B!˙Ľ_üPbŒBĄP<~S탞ٓ˛mŢúŐŻsîĺAh;'1ĐŽM"ˇü‡ŠýŔŽÄO[nž?yŻÄ1zŤÍÄţüíć:=flzzôd-šťpąósÝßž/ˆc MŰý˝}ُżňŐétĐut:M†t:RŠŚin ƒÚyA „ ÝnŁiétz‹¨†!Bˆ-Ťhw:–0 q'ŮŽë:aEAÉd”đ(zś^ŘÜgŸ}Ć'Ÿ|ÂÔÔĎ=÷œş0 ĹC¤Ůl˛´´”„ň„aČÂÂŮl˲X\\dhhĂ0X[[CŃőéy î7Î,..cV7ÄS<ꊈQłśşN˝žAË-âŃňňŸ~ú)Żžúj2†!ˆ˘ˆFŁÁ§Ÿ~ĘĚĚ ĂĂĂÉŘăůËK+ŒŒŒ íŔÍŠŽˆą°°€çyČXĐl´ů裏XZZBJ‰ëşœ8q‚™™„Đ ƒ˜ĽĹel;E:íŠ6+Ëk´šÝâˇoßćĂ?Ä÷ý$Yţđđ0O=őT׋5–,--c[6éŒűĽ~ţ”ŁP( ą”Ä"Ą ó€V ݲžÇŽÍpâ+ŻŔaœ Ę6„żüŠšĘŽÝvϑąÂw§]ÄqL˝^'Žť9V|ß§Ńh`š&őzß÷i6›†AEDQD:ÝMĚŰ/s-Ľ¤Őją´´ÔKüŰ!ŸĎă8­V‹FŁ‘ˆ0şŽăyŽë’ÉdvËňň2abŰv˛"'Ľdii‰t:ÍĆĆRJRŠžç144¤Ä˜ƒîăâ˜FفŽëŒŒŒ i­V‹t:­BĂî@ÇÄR˘ ~ Ĺög.đ¤ě ՗.]âç?˙9Ď?˙<žçńŃGńöŰoÓét8ţ<šŚqöěŮ$OW,‰Â(+úÉÚűbťďűTŤU2™ĚC5!‚  Z­őźFşß{ĺĘ>ýěSŚ&§¸uëgϞ%NÝŞů—ÉňĘ2sˇć˜%NóíoŰś‰Ł˜jľFŠTŢSěŘc÷ĆƝN'—Z­ˇnÝâÔÉStźŸţ9/^äw~çwĐu˝ç…âŃnˇqœÔĄč;Ű퍍dÜ]\\$Žă$Ż\Űü|ˇ""?`ee…tfęŽöŒc …Bńđd ’’ĎÖëü‡+Wů_^|ś'ĆLȒM×0 ă¤(Ž‘şNŹiDŞšě+¸ ŽĘ~y*ŃŐŮ4 „ą)ś ţ}ˇhš†eYA$ń-•J‰J>Ÿgii‰fłÉää$N'1Ükľ…B(ЍŐj4 ,ËJViłŮ,N‡z˝žxSŘśMÇA@*•Jž~Ůěľľ52™ Žă°źźLĽRÁó<šÍ&ívť;™ˆ"|ßß3żŒâáł°°Ŕüü<Ůl–ŮŮY …ŽëŞ sÂXňťż<Ďo8ÂéBC娸Ť‰~×KŃ#–1 őú͘‘‘šÍ&Žëâş.ëëë\ştŠ'ڈ¤­Őj\ž|™cǎ1;;‹ëş‰—ÍłĎ>ËččhŇGA@EčB{h‚LłŐ" úŽža2;;KĘNńÉ'ŸP,1 ƒ0Œ0ŒnHR.—c||œvŤÍsĎ=Dž‹ /đ„axŔâ›÷Čó|d,“˙ƒ Ŕ˛,fŽÍ°śśĆ… X]]íŻč×’z˝F>Ÿ;bLľşNF‰]˘iccc<űěłŘśçyřžď{Ég˘(Âóý/ýs¨Ä…BĄ8äÄHü(â—ËËüÇŮ[ü“ł§0“8ŕĂlr?ČÉŹšZ܏ˇ=OËŕk›Űd/qž¤RŠAJd‚vZm‰Zď}bÇžˇäa[ż#Úí6śmă8ΖŐȕ•˛Ů,šŚŃl6ąm›(ŠĐ4bą˜|—ëşřžŸxĘô'–e‘ĎwŤ0ůžeYIě|_ęG*•J’ŻŽŽbšÝJ Śi&űč݆aJĽ”'Ć#@Ó4NŸ>͉'’6ĽÂĹöÇŇ5žwę(˙úӋüćą)^ĆŇ44Ą=ŕ~XńeŁ/Z#ťýeY?~ŒĹĹœ”ĂĚĚ WŽ\I’Ż —.]bjjŠjľĘ|@ÇüčG?â™gžáňĺ˔ËeĆĆĆNň–ě}„A@ź-Éřř8çϟgrr’8ŽůĹ/~Á믿N>Ÿ§Z­Ňjľ( čşÎŇŇů\ß÷qgÓ‹ťcăÁŤ1€ě-šH‘\ˇĺĺe~řĂ>###ÉŘŮĎéŕyţ=Wą|Xxžż% ţ=2űćzSbŒBĄP(ň¤>]Ťňç7çůŻNL3Í˘đ $ăüŮîě: JşFJ„FÔ­QřŚ; 5‰&% äÖď¤ŒÁó TÉ{ďJÚÚEœŃ„ŕ•s—ŽD˛OciUçňu8֑rgâÜ~bÇÝʆ !Čfł¤Óé¤dt˙óĹb‘l6‹Žë‹Ĺ$f|ťűąŚiäóů¤”tßŕÔul6›„#m7֏ł_]i||œ8Ž“˛É}Af||<•ú?ť%xT şŽŞr˛šLgłü×'fřáő[8şÉs•˛bwőźú֊5ɏ&Űq˛Ůlâ%ŇIă8ŚRŠpńâEĘĺrvšÉd¨ŐjÄqœ<ĎÉ~˘˘ŃO´ŰŻžÔĎ3::Ęúú:ǎăĂ?$ +ŔŻŹŹ0?żŔüü<ĽR‰Ë—/óôÓO'ÇŽu]FŮ3%’1QËĺ( X–…ëąşşĘ׿ţőăsĘś͢BĘśé´;[ŞZ]˝z•fł‰ŽëÄqĚęę*Ď>űěŽgţe•ŁP(‡^Œ‘4‚SÓHé:ŰF ň<˘_ź‹\XčĹŹlł¤$‚Ď2YŽ;)b!čzŐ 4!’•Şí•DďľÝŞ' R<Î6›Ă˝çŽ‹& 0Œ|ŸřóËŞÁܧ8#ŃXŽMĐňjäŠ9âP’Jw‡ŐŐŹ­­Ąë:•J…Z­†ßs!v‡›7onšoƒ uˇ‡L zŽěghő˝#Eqy1úűÜÇnß­DĹc÷üöÚmJ7°4FĐŤR˘Ú˛bŸ>Ń0 씍ś!ˆ{ăi_$w]Ó4ĄT*ń+żň+źóÎ;X–ĹkŻ˝†iš¸ŽËÔÔóó󌏏'9N<ĎŁ\.ôůÓ4Ńő‡›7Ncšć–J=ăăăźřâ‹,//SŻ×yóÍ7ÉfłÉ‚Á‘#Gh6›\ťvŃŃQŠĹ"“““×HÇ0ôGăŸ+–e"4 ˘n˜O&“áĺ—_ć'?ů őz™™&&&v,BäQ5ĽBąHŁŃ$ęĂŃŁGY[[caa!Yyć™g8rdr‹`Ű֗~ŒVbŒBĄPr4!xa¨L;ŒřĂk×I›“™ Ś&ö.‚†Äď@üáGť~_ŒŕśmóăáaŽĽSHň[& iŽŻózľŠ3$pŕ ťJNâĄńčV°śť ËX°^/Đhů´ź!Â(¤ŃZòšV§RŠĐét=ŁĘĺ2qcYV’ßennnÇýŢŻÜôýLô>”řňxˇaE7ďÍFƒď_˝ÁËĂ^*¸÷¤â1ľ/4l6C˝Vëć&‘ÝPĽçŸ>Ńßxă$LôčŃŁ‰ŢĎű166śĺY|ńĹoÇž@`Y&…bnG1ƍiY‹E:n՞BĄŔŤŻžŠă8¸Ž›$qďŸC6›ĺĉÜž}›RŠ„a=z”´›Ń˝>…bĂ4śşĺŘýä 9ÖÖW C)ť‹ ÓÓӌŒŒŕyŮlĂ0Ďšsç’Dž–eqâĉ-ÇkY•ĄĄ/ý3¨Ä…BĄx ƌińúř)Cç._埞;‹Š™w˘Ă@Ŕ”Iˆv?…ĆĹlŽy]Ç%đ`ă”ëŢw\^\YÇ Â}"9(Ĺ<ÁşĚ~'›$‚ë×oRŤŐ˜_XH*eÄqĚ/ůˤÄôââbREóóó˝/%n(m{?Žřˇ—ŽđćřŻ ă†Ę˛Ľ¸k\×exd˜…ů%‚ HŹnCúĚv1gżgŇ4MFÇF$ˇŚ …N‡Z­„TišśE´č_>Ÿ'“É$çÝ IĂ0p]‡JĽŇőčyD}šŽëLLLpăĆM:m/9Î~rĺÁű¤iŚi244„՝CŸ¨ë:ĺr™ h4H))—ËI˛üţýé˙6M“ŃŃQRvJ‰1 …BĄ8“ ŔŃ ž6:ÂWGGxŘfAW̸űźj\uښ@#đT ’eËâšc“‹<Œ}ňčuíľjžß„ľűwW8;}ęožů&WŻ^% C]ď&Ç˝äźÝ’Jƒ†l’Ȱl›Ż}í5U†XńĐéˇßî/šeۓˆ­éü‹Îu'nŞ’’â>&ĘÝDćľjŽ×!Žâ/4‚ @ÓuR)›Bž@6›9™~XŃČČ0ŚitËv‡a/)ýÝcš&éL†bą€mۏţˇm&aeu•NťC8PRź˝u]ÇśínNś\.ŠŞt(ěMrlĆĆFYYYĄÝé „’ śEŰś)úmć˟„\‰1 …Bń˜  q Žç}#ŒcD/iî'FŔœb>ewM°‡0xjH!ů ŸçLŤĹw˜ptÓúĆ*„aWfđww{ˇügĄXä_ţŤ•T_¸ŸzşĄoМĄP<,úeyťŠQÄí‘ehý*+Şz’âţčć‰)Ëu“ôŢKž˝ź/t]Ç0ŒÎ["XśÉČč0ĺ°DF]ť` `Ň_Č­ O˘W€ 쇥_Ń4 7írÄI†aâľÚżţý÷üőžűű˘iÇM1qd<9‡Áţ|÷6#÷÷ž_‰1 …BĄŘ•v D1™ž‰żűđ m]çf*EŐ0‘âŢ}št:˝oŃ ‹WLłŮäúőëxžÇčč(ăăă4 ććnsâÄńű Ézmgqq‘……,ËâŘącd2™ÉţÍf“RŠD†!HĽR{^Ű+WްžžN6›ezzÇqRRŤŐđ<‘‘%Ć( …âË=ŮÉš)ÜăGYoa!RĆ˝ź0ý ˛ ücńC ę~Ť6”CŰĂkĂĐ4ŠvŠœi˘ďRšSqŻ“ÝÝŽÝ~Űîôş¸Ç÷ďˇMĄP(_xt•’›7obŐjo‹'ŹĆÔÔ/^Ä2MfŽăŇŋMcbb‚ęú:ívÓ4™žžćĘě Ý T*qőęUjőßúÖ7ŠÓétxçwxńĹŠ×ëź÷Ţ{8ŽCŁŃ RŠëëëœ:uŠÉÉI4M;tFƒŮŮYňů< ‹,-.Óh4°,‹óçĎcšłłW(—K<˙üóVŐ0Š"Ž]ťF*•bee…t:ÍůóçŠ×7xć™g¸xá"vĘŚT*ńчqúĚiÖ×֙ššâÖ­[¤3i&Ć'8˙Éyœ”Ó=v]pýúuŇnšŢ˙Ă0šví:†Ž3==ÍÇç?ćĽ_B7t<ĎăčŃ)%Ć( …âKc–%ˆ ĆŇéŽa"AŠÍŠąÜńŠ öúBŃŻ'"”ŁP( ĹݎŤ=/…ÉÉIÂ0äűß˙>ožů&–eńáSŤÖX[[gmm…‘‘Q<Ďçʕ+ U†¸xń“““ř~ŔĽKŸSŻ×YXX ^ŻóőŻ ‰ăGëŮ(Ľ¤ŮlrůňeŽ=JÇüěg?#›Í2??ĎçŸÎĐĐŚi211q`BĆ˝Ď癞žć˝÷ŢcllË´™ŸŸg||œgŸ=ÇĽ‹—¸qó:?řÁrîÜš;)ťĄÎ§N˘^Ż3;;ËýŃqęäięľ nܸÁ /źŔĘň*?úŃák_{ C7šqă&###\źx‘Ŕš=7O6›eccĂÔĽ\*sĺĘUÖV×Y]YĽZ­222ŠĄ›üÍßź‡”’o|ăÍÇúŮSbŒBĄP(śd[Ŕ1°*ԏ×Ý.ŠśsŘő? P•J…ršŒ‚ŠŠŠCZZ­Őj•™™jľ:™t–™™2™4Ž›&—ËaŰĎ=wî@Ĺ$]×q‡÷ߟ xá…h4d39&&ŽP(X\\ä…^ŕ;ßůsssd2Ęĺ2WŽ\!›Í222Â_˙ő_“Ëĺp—tĆáâĹ‹ŹŻŻ3>>Îđđ0ž×!Năş.Žëâű>A`ZÖcýÜ)1FĄP([ĺ‹-ÉCÄ>bÇa<ţ]ˇŞŤP<ŽýĐ}źŽP(îmB}ćĚ<ĎĂq2™L’“ŁX,ńkß|]׉ăŰśIgN0=sÓ4)—KDq„”۲čt:IůâŽç!„ŔqœGz~ŽëňĆoŕş.Śi233ĂącÇX__Çu]NŸ>M­V#—ËÚž%—ËńôÓOăű>NĘé ډn躎Œcʕ"śmč9†Áɓ'Y__OĒ×^{(ŠHŮ)˛Ů4ŚeacăŁřžźě IDATŐP†‡+ŘśŚë?>Ă+ŻžŠ›v0 ƒ^xŽă`ĽR0а- ;eńţ/ÉožžěëqE‰1 …BĄ¸CŇTš—Ý?Őj•[ˇn111AťÝfyy™§žz ]סtaŇh4ĐuL&łcRő ˙ú˙úżq\‡gž~†O?ý”bąˆëşŹ­­!‘üÁď˙xžÇňň2oźůďüôΞ=ËÜÜĺr™ľŐ*7oĚńŮgŸQ­V9sć ׎]ă×ý×ůŮĎŢá{ßűoďŤmIŠĘ[+ …Bń¤Ű›Â>Íçs|ăođoźńČÎ[Sˇ^ĄP(Š']×9yň$ŽëňŐŻ~•fłAŁŃ Žbâ8&—ËQ­V‰˘ˆńńq˛™,ŐZ•VŤ…eY4MFGG™žž&—Ëńâ‹/bőňřžßM4˜ÉÇ1ögĆôô śBJyĎ? …BĄP(_”gŒBĄP(O0B,ËâÔɓLOϐN§ŠŐę8ŽĂńăÇIĽRTŤUt]gll MÓz• <N:…mŰ=z”ĹĹEŽ]ťĆôô4ŽăP(ČĺrŒŽŽŇjľřůĎÎo˙öocšĘüP( …BńdŁŹ!…BĄP(žpt]çľ×ž†m§°m›\.ƒ Ć'ĆŘŘŘ ŸĎŁë:íÖ ě”M˝^Ç0 ňš<ăcäóyžţő7iwÚźňĘ˸i—S§Ov ĂŕâĹ źöú׎ 4ţڏ3ŞtľBĄP(žě(1FĄP(Š'MÓ¨ mVÎJţvÓ.ĺňf‡\ŻRFĄOśĽ3ÝdźĺĘÖJĹb7p†źýkżJ:NźbTؑânŘ­lhߣÄ…BĄP<.(1FĄP( 5Ů%Žă‡ H¤ěNű%9Ł(R°ű´Éݡ÷Ťg VŃPâ‹BĄP(W”ŁP(Š-ÄR˛lýiŽ.4҆AÚ4şĄťÜO#h…9ËÄэ: ¤$–M´ť<&Ĺnßnr\]ג˙ď—{)MŠPÜš]n–­ďţí¤ěЇq,H‰S…b×vDŽ~›Ŕk˘ üůŠ'ƒƒS”ŁP(Š-óFđď.]áßĎ^EC‚œeńÚč(˙řQ&ŇiLíNĹřşŸi†żů*|ý˙ôÜSź6:†Šßíŕ&“É×^Ünśřl˝ĘT&Íą\S [îă çŔnՈ„Äqˇb’ŽkÄqÄíۡŠŐjÄąě݃-ŸŘeŰćkşŽ111AŠTR“cĹĂ4‘{mY'Â-m}đo…âÁ!ƒ:Ň[Cb!•ŁPáúFƒš°Ä/—Öh!ŔĹߙçWLpťŃäß^şĚŐúӏ#"wž8ćWođÎíůžcňÓGys|”Ťő:pů*WëcŽĂ˙đôSdL‹^żÉť‹‹lŽaňňp™Ż ńłŰ 4ƒ€w—‰¤ŕ>Ćď_žĘĽjXJ*ŽĂ?żÄd6ˑŒËß.Ż ÄHŢ_^ć?Ě^'cęœ+ůd­Ężżr—‡Ę\XݞÚńxĄRaąŐćƒĺU~xíoŽóĂk7Č[ż61Á‡Ťë\ŠÖř•á!Î \ŞÖ9‘ËńՑ ,ŻňWóKœ*ä9S,đŃę:ŽŽđüPA哹Ă=†î6‚ Š"˘8B]1%ŽAFŃÖŹŞ„Ą#ČH@ϓĆ÷}â8î}.ŚŐj†Q/ *Fʘ\.GłŮ" CâX⺆Ą'ĄMqܝ\7 \×EÓ°öÇ1Íf“L&ƒiDQ´%oˆE1AĐjľÉĺ˛[rŮH)ŮŘŘŔóâ8ćúőÜşu‹ršD*•B×u\7ͅ ŠŐj‰řpěŘ BlŰf~~ž IĽR¤R)1M“JĽÂúú:…B?ţ˜“'OpćĚi—¸uë““SĚĎĎ344„Žë|üńÇlll066ĆĚĚ kkk”Ëerš,ń?abb‚fł‰”’\.‡a|ňÉ'źôŇK´Z-Nœ8ď{ܸqƒL&Ă_ýŐťźőÖ[\˝z•7n066ĆéÓ§ŮŘŘ@Ó4ĆÇÇ9ţ<–e1;{•ršŒçyŘśÍĘĘ ĂĂCŹŽŽqćĚ|ßăłĎ.ŕyĺr™VŤĹÔÔľZL&CŁŃ`llŒŤWŻR*•đ< řôÓO9~ü8KKKčşNÇhšĆÜÜ'Ož$ŸĎ=1bŒ[EĺŁ8˜QQľ3…BĄÄ…BĄP<ěÉpşcČq(Ů6Ż ńTŠÄËk $śŚ÷ćĺHA(%˘÷9Chˆţk=ă5–ŔĐ4BSqRQŒGü›Kłüěö"“Ů ‘Œ0´î{G]‡ď:Á{KKŹz-ţÍĽţß+Wů__>GËm@ăŐá!VOx|˛śÎ‡+ëüxn‘§oů—/ŸĂ5 ´Š,OäýÜs˛şsťfK˘ëdľšăâyq'űi^XŔË9¤ŚK´Ž-[ĹĎói44 LÓDĘŽçI­VŁŃhŕű>A0==Íŋ—HĽR¸ŽKľZĽÓéŕ8Ůl!F€ Čd2čşÁÚÚ:KKËĄqţüy\×eee…ńńqňů>ÎG}D˝^gllŒ\.—xŘ,//EőúétM6ę jľWŽ\áůçŸç•W^á… †WŽ\!Š"jľív›FŁÁĘĘ ­V‹őőuJĽ###,,,0>>ÎÜÜů|ž—_~ů óŠŮ:A~đ%ŮŠ=Z›jk`ŒR÷IńhĆ%Ć( …âQZFüă3§řÚčpw&łiŇŚÁnÍń|eˆóŤëT›‰´ËT.ÍF“ż˜ťÍíBž‹ŐZ7‚s•Ž.óáĘŽĄóÎíE6ü€˙ů…gř›ĹUŇŚÉ[c\ŠŐšVo‚čVdšk6yşTd(eó˙\şĘş×ažŐA׌&¸Ýjňy­†A; y}l”šçńƒ7™­×đăW w÷Lě…TŹ43G'ét:Ôj5<Ďë +’j­ĆJ˝z‡ĹbIąX ›ÍB„ MLL†ľZvťÍŘŘ(ívMŒŒ !Śiŕ8BˆD¸‰ăˆ\.G&“ŚP(`Ű6š\–ĺĺeŽ=ŠŚ ŁűšB!O*eS,™˜˜Ŕó:”J% ĂŔ0t*• š\–őő*ŽăĎçąm›ŃŃ4M§RézŹ,//säȢ(ě 69&&Ć)•Št:ĘĺŮlŽl6CĽRauu•ééiÚí6…BĎóI9(ňäó9 CG×SŒ1??OÇLLŒÓlś C§X,öBĽt\׼X,&%Č'EĽR&ŠB2™,Ůl7dëË4áí šŚÝEWĽźoBÇ1QF¤jkZ€Źü}[CŢwß1čńšë~vł¤ÓÓÝ×˝|~3öĄ}ţŽ÷cˇĎßëůÉ/řů‡ô}B%đU( ĹCŇXşyśĽ;ŢhôÉ†äÍń–:mţfa…wWH›ß9z„3Ľ"–Ąąćuřéíy>[ŻuK` ‰&ŻpŤŃâůy>^]#g™|kjœ1×ĺĺá ?_Xä?Ě^Ă5 şN/ŚŚ!ĽäĎnŢ&ˆc‚(捣C—;Óűź¤\.vŰoŻ-?űě3)pś&€ź6ĽR‘‰‰ń-űššbrr T*•äô…ĚĚezzjŕœwVůéçľBcll”Ńёßˇ˘ĂččȖóú˛1žçqíÚ5Ž?ŽĘ¤+)q,ń|Ÿv§C$ÍC#Ć|Ńš÷Ą8VşŽŁkšŽ#z 7RČű4¤”ÝœgQDÜtżü2•Ëč!]Yí`Š(1FĄP(ž¤ÁĽo ő šmYC p oNNp˘çD>ˇÍÍfůŢÉăź62B; )X3šEŰâéR‰ßyú,ˇ \ÓÂÖ46‚€ăů,EŰâż9yœ—†J´ŁˆŒipŚXŔ2tž{|š‡ĘqLÎ2Ů –͐ăđ['Śye¸B#q él†×!oYü÷ObąŐĆÖ5N˛ü“§NqłŃ –’źeqşXč…LŠÉÜ ÁşUŘű˝NŰśiľťĄ2őz=Iô;77×kPbWł{ű$ú‹TşŮM,éŁëĐŘľŮMôx÷ ˙=_&!ĺÁL~cÚí6Ÿţ9SSS躎ÄĹ###–Wjdó똆q_ß˝uyWąy°żîz+ˆ­}n/ɰÜ}Ôß|mŸůűŕ÷ߋăƒŘăřŀoEňZŻÂĄn¤]‹L:EʲťĎ{ďÝw;nK)‰Ľ$ C<ßÇóÂX…ŃƒcÄŔŮí˛–œéĂÖGz•亥ąJŒyhúÁČ$JŒQ(Š'F‰‘Ä€˝•'ĄíÅK×9[*ňTЏŤ)dj‚ÉLš#™Lbô&G7xŞXŕLą°Í@ěţ5â ťŁ;Œ­#™4G2é-‡Ó˙îŹi1‘Θ˜1´ŠńLŠÄÓĽžŠ*bNrœ,äÎG*ˇň} Ů˝­ę( Ń4‘$¸íçuą,‹‰Z…ęĘŽBĚvŃĄ?ÉîW5ÜžßDť˛˘őź¤śś×Í KwłŸí•ŠśKß[ça J\¸łsůňeŽ]ťĆ•+W8{öŹş(ŠG†ç…|ryĺ†Ą?¨•ňžˆ"wFÄn Č@~4­ű‘ô#b@ü”;Bh;ú@)şůŰäĎĂm}ĽŘ˝—ŰXlůnĎĄuEfŰ2ф ٤ę-ÝürٌɉŁy&†r8N Ă0öSąvˆGQŇîxtB ÓÁDÇ蟜ÜS›ÚűöČ;¨KťŒobŔÝGĆqWlbwukťŇťťÉ;+]şŽ“ɤťwF‚”ń@UA5Ć<.ă´c …≙u‹ä—†2Ţ&•ě>öď4{6Á˝Ţ%îřß@8‰źÓçśZ+›ŻiťîŠí܇bö50vľ7zł”1FŁ—d}}FفeY,.-őĘXďnŃFQÄęę*qă8N’$wtt”Z­F˝^'“ɐÉd’ĐÇq°mť7éЈ˘ˆjľĘęę*…BFى”03s”0 ń}?É)ÓÍc ëzŻ<őŚđŇétX\\ĞʤőČČČ@ÉęŐj•8Ž1 ƒl6Cš\NÂŞÔEőîUżD¸ŽëřžmŰʃHńH"ÉFÓĂŽwĐĐJš”ÚŚ ł§0Đ ‰=ĄC žă„;ń<Ůöş”Ý™XöźjäÎ`ť ĽDxľě)-őBŸ5 CŁRÎQŽ1tzmƒĽĽu:žOK SÇśş}tËit:aD!cbZšŚ%ĎűÝxTĘ8&ˆB:~Œž*Ą™4!xŕJ˝‹Ól6Řh4pR)Â(BZOlŠ“Đ¨ąąąŢ7ö=nD/LW×tRN–(Ščt:x^ˆa8)Ë2ˇŒ÷’ƒKq°(1FĄP(ž´‰¸”]ϘžVŃUdŻ’źă睍_ńS–w-üě%ËHvô ź;ÜÇL&KŠT"ŠťÂJŤŐ˘Ýn“Ëĺ|˙ŽIűĽŞ=ĎŁVŤáű>šŚ%ešËĺ2kkk,,,ŕşnb$Z–EłŮ$“É$ՅÂ0¤Z­öňÎčDQÄňň2KKKhš†eYŘśMťÝ&›Í266–ä°,+ŠN”Ë刢ˆt:M˝^Çu]šÍ&žç%šşÇě'ůiGÇ\ťv›7o2==ÍÇL*•âčŃŁęâ(IŸůĹű„(Ƀ5){#;GźîkÉH}ÇqSl&ąJĆŮžGŒ –]o˜¤ď–[Gbší3;žQ$šÜ&Ä 8€hšAŠXŕřą)żƒ”’ńń –mqýĆxt]çôéÓĚĚĚ Ľě†:(Żœ2D†őr‚ȁP›nhÜˇ_O]śˆ(˝đ$Ů]ÎŘžšedŢ[ —[$¤E•M­]ÓŽ”ˆŸŮËWŸéŁGÉç3˜–”’ĄJ–ĺĽ:C#cÔj b {^%÷šçEr0ÉzűלRŠ$‹ śmŁëaQ.—ąl<ÄĽďŃ9x}„ÄqLłŮä˝÷Ţ#ŸĎséŇE˛ŮL2žůAŔĽK—ŘŘŘŕÖ­[źýöŰ*„I‰1 …BĄx4łoˆ%|źşĆccřQĚrťC,Ąęűä-‹wř•‘ÚaDŞ7‘m…>şĐw]Ş~ŔĽj“ů,A€Žf3qL' q ƒ•އ­kŹu<†œ)Ý`ÝëĆ ëÎÍůľuŽŐ7xk|œůV‹‚máč:ŚŚŃCb`Í (§,ÚaˆĽiÜj6Yl­rŚPÄ1u‚(f4í`j `ĄŐ!ĽiŹvÚhšĆ‰\Žvąîyä-‹”nP|ŠśMŐóp ƒőŽÇHÚĹ5Œ'ˇa좘éŽI+řŕłó\úü†aŕyşŽŁé-ą‡2hBvUşmŽě}Ä4ÍÄCƲ,,Ë"—Ëáyśm“Ďç ĂnŮčţçú9t]'ŸĎăşn×°ô}4MGÓ42™ ŠT*1T'캎oqsOĽR˝ĘG]#4 CŇé4RĘ^)k­çI†Žë(ƒőŃo# Ĺaę"Ľdo‘bÄ[›“ćmŻ$jĆŚˇ‹Ř–4¤ëŇëŒĺće_řônŮ+ůK’IFö˜^/rŰ9ěxş)źÄ=Ů-_#ŀ0!D7ÔT×ôîáĹ˝ó–’8îţH 2î…ßlËçuJś6őî"Œçy´ŰmLÓL’‹ëş˛{m‡‡‡1-]×ðJ40}!ĄN‚ ŘĹŰF&ýŚŽëŘśľĺFQŔ/~ń Ν;§že%Ć( …âŃ!ˆĽdĽí!?ŠXétXíx2ĆĐ`ąíąîyĚ5›XšÎRťĂń\ŽËőß$˝IţfżÚö´‚ÍńjsˇÝĚjbS@Ů KŰÎL Cm 6âNĘÔćľÉyv÷! K+ äÔ™Ó %†Šqűö*žç…!ó +LŒ k×n.áů>śĽÓ=ęűuš}ř%ž›Í&sssT*Z­aâ8VŻ TľşŽŽ‹<Ďےđţ‹˘ë:•JeK>~5ĽL&ĂWžň•Ţ‚‡IąXHrŻőó´}ë[ߢ\.Ť‡Y‰1 …BĄx”ÄB)ń˘ˆNâE#ŽËű+ŤdLK×Yëx\XŻs$ăŇ FÜ×66đăKd ‹…V‹Élš‚mpľŢâh&M'ŒšŐ¨ňĘĐ0?m̓łrŹű>AH&Ř,M§œ˛ˆ%ŘşNÁ˛9żVĽ˜BÏ"Žn4˜ĘféD!9ˢćÍfp “vâ:ąŒůd˝JŢ28™Ď"Ľd&“ĺƒŐRšÎPĘÁéyé4ü´aŇ bn7ŰŘşÁ‡+kÉd(Ś,Ţ]XfČIQHŮčr üç“ÜN:ÍëË]s/ŠťBĚŕjjŃşľŽGawľö.D‘;ýwööĂI”óO˜•ŚxxjĚ]ˇ?Ř* ôšÁv){"ĚŢĺrş^$qRň$§˝$žÚ^zßě^ ˆe’vÇwöňcI)“&šWr~š)ň9XŞş7vĒZ­ÉĹK×(sčşNŤŮbaq•(А–WkŹ×›hBŕ!Rƀ~ho˙ŢĽÓéÄ#&›Í}ďƒ0 qœabŰ6ŠTjÓsćC?Źwł-‰^ČŽƒŽws×čz?tJO"*• Ĺb1Šf¨PbŒBĄP(!5?ä?Í^'o›¤tĹV‹ŔC &&mčBK†şůWD7ÜČď0šNńW‹KXBă;ÓGЅĆXÚaŽŮ"k¤ WÖ8‘ĎsłŮŕr­Žch؆ކ†Db !‘ i!9Ë$eŒ8)2ŚŽ.tţfi™r*…Ľël]#kYÜj´sjžŽéHŕzىŁ l]Ç1 ľL~š˛ÂÉ|f'ŕT1ÇOo/đtŠČŐúF/Üęáş9?ô ÇŽńŘ=ęŮę[ÜŹ{Ť˘Q÷šičWwxČ%ĄŠý&L Ĺ#Őmî”p…­aAbŔťełHőV}%–r—†Ý-ťűęČ­#Y/„H|nđ d?ďöDžńnĎXßÓfŰq&˘LˇZ“„,,ʞśVë…ěDÝrĎ=‚0" ٤:”ŘötHŮ;„R`í’uřA÷IťUBě†őšd2F’tžż˝˙™) )”ŁP(Š/bLč:˙ݙý…04 ’’Ż˘ϔJ ᕡáÍAřľ#ăÝŐ8!xk|œXĆpŇƒĽ˘{ůezÇ.ˇ)3I$žďwË0ýTú[ź:Žý‹Čť]ő~)çÝĘ{†ƒÝ‹`rç÷>:1¸” ­Ä…BĄPrt!С Ř÷:š`ťKq,ťBĎh:…Ľkű–ž,żŮUv6ť—vcĂźCDS =z”ßýÝßí–ç IÚĹ`Ý^ÍĄŸtwzzzĎÜ, ўK)ŐĹPěÄWö… š™˜ˇŸde›÷˖ńN”’îWJúzyX6ß&{ĺšă$‹tE!{žŹťË˘'uh‰83P;IţŰ;†^b˙x šo˙˙AľŁV%]ydw1gó{%ÝښčîCëeŢ)Éä|¤† vťÍĽK—'“É$Uü<Ď#Š˘$Ą|?šťŚiĘ{DĄÄ…BĄP<žčš`2ă&ɏÝ!`||œŃŃŃűŢKż*‘š$+&Iĺ—8&Žť“S…âZ^R Iěxe°uâÜBß71˜Kfˇ v›e§ăž—J$%qź)”@O„]QfËqôrĹ1ŕiŇl´%DĘžďĘf˛Ţţ÷Ų[ő(îULŹaÝÄ´ž3¸Ÿ3F“˝$Ă˝p% ”˝đgŃKƒÜ–zףúôŕ’ď şŐňŢ}÷]fŚ%ůSç˙gď͂$ťîóÎß9wÍĽ˛2ŤŤz_Şťą@$h"i‘”†śŹąfB!YŠ˜p8&Âáe†ŠĄ,Sv„Í šy°Â/~r8b&‡g(CâČ#)(‚ś( +EtčľşkËőŽçĚĂ]ňfVVٍęŽĎG6Ş*—›7Ď=÷ÜsžűýżŻFšŚôú}Z­ŁáŃh„R óí6gϞăȑĂF]bpÇaČƒ]™™IĚÁFQZdîěűńFLٚąÇ`ď ¨üŸÜţXŚ UÖ%K2ńR=šů fgLh”Ö!ŁĹ–——†žU…Œ.b˛sŠÎ<˝TĄĚŠl{s]1"<7đŐrjłOQB焌žü>ůvdž-INú(Đr{]ܰÉö?˙Šw7ŔPJÉącǐR2 iľZAHŒˆ˘˜$N°m‡4„áĘ KKK,--šëŸÁ‡!c Ć>/e<ęgÇ q*‡(¤ě{ľLÖĂĂÜýŽČ˜ˆ™"VÄÄP9&*ƒćÁRxś(­QŞ(ŇcBDgţjՏ+U+‚˛ěG–c‚¤ZBUl_kAŠ.=bT• Š8řNŞX˛˙ü“¨źŚP÷LN"÷o‘š˘§š:U”PéÝÍ0ô}Ÿ/|á %I›)6ÉS›@ˆœ*ŇĽý\-cźÎ î c``````@ĽŹ\ G)J'ŐŰ*ČŤˇD)#­)ó;§w°zĨ# öś¤MëŮżWÓŹ‹°ĄLĽ˘ÇĺB ŇâĹŞř‘:™I~áߕmťđ‰Ió‰)KćCS)‡R˘¤WԄ‘oĹpXÉY!*aPhtfć›ďŚĚ÷ł(ŸB钐zş0IŁľľk孖eݖwYńڃp Šúľ|4`Čúݘˇ_íŇRĆžł” UNƒ°A}ÎĆődůŘvěí&“ˇ3Ů4Ţ4w}\%}‡Ö˘|NTX=sDŐĽoVšT(c&u‹—ž0…Inž^zŹ„AŁ•)dL)_(U7j&?ŻęQœmC”׼NŠź dţýľ%łżÇ×1Ńjĺvy,/ĘĹDĆwő›Ěúšă­Ďü;߆ŘŇ{vÜ×rŔÁG†Œ1000000 ‰*-5ňĽä}§ňq­5:™,ţOӔ8Ž‘R2đ<ĽZkjľÚDĨĘo gąÚ˛ŹÝO’ŰśËT§ę{Ň4%I¤”¸Žkîě=ů2-oŠ/Tȓą¸DĎ|oe#mZI3RR˝•t.ˆ*ČČMweĄLAB„*ěłÇ”Ră%=eęËd)ŃY ňŇ"]Ą*¤˝¨>‘łDRe„Lń}…Î ˇŤŞËěĺťK0řž‡çyH)>BýŇTŃď÷ !cČƒŠĚÓÜ ŸL‹ń´{ëäM¨#Ö˘5ęÔ9ŞkĺÔ])Ĺęę—/_ŚVŤ‘$IIş¸ŽË‘#‡ËŘQ˲X__GJIĹ ‡#lۢŰíŇl6éőz´Űmâ8ćĐĄCôz=Ň4%MSlŰćÔŠ“†Œ100ŘýE0”ž*ՅńäH˜ýWU^[}ŘŽÔ)˜•‚)J“Ô˜,Qz*3[1×é" c\)R„hBj„Ξ/ˆ”Ź4)Sͨę~Šń÷,˙`œ|EŹvu7ňŤCA •l”ČůŠÜ;Lg%K˛ŇÓQ×ĺç~hÂ"ó‚ÉR”䁝&lŽ˝@'YsHŽ„…†ÄłŇą°,›4Œ2Ԑ1Gq4#L†Ă>ŽmăyţśZ…bEŻń\úIĎsŸ>\>!ďźó.WŻ^Á÷kœ={– .`YI’ŕ86ŁŃˆ Ξ=Ë`0Ŕśm67ť\źřçϟçĺ—_ŚŃh0??Ď`0`}}ƒĽĽ%^|ń%†Ă!išrčĐ!šÍ&'Ož0ÇĐŔŔ`)™bą/&üN ĄH"*ӊň˛1•˛´ˇš.U1b\ŞT)-*>ވ‡."¤äéEYŠš˘FP1™:ŚŘDާ• 6¤ü^żŻÂŒćVm’ÇB)ƒÔČ|[Jdż——˜üł˛ÍŠmČ­ʊKVA؏˖ĆĘJČüe gúXH)ŻŇ°>Hů8âů !ŁXŃŽŰÜ{Äaą)9ˇhńŕQÇfÚĚŔ1wwąĄQvť .˝ƒß^D,,!¤FY)ł4 !А˘˛nő˜Kjo„ĚСVó°m‹FŁĆőëר×}l;›z´Z-ćççYXXŔśm”R\ťv !$Žă°śśFEœ>}ŠFŁN‡X–ÍĄC.]z—8ń<ß÷ËÉśÁďĆœŇ`_÷OʘéBQ"*šŞBÄž/UŇBTů ĝAi¤[ÄY—ž.Zƒ§ÝiĄ =Lfœ›'Q3…JE•-…Li\GšçWFÄl-J­şŞL¤Fĺż 1EbˆŠ˛§œ”)“”rr'SđLXřî>ÁĄŤŤŤ\şt‰vťĎóđ}Ÿ7näŠĘSlnn"Ľ¤ßďcYsssܸqƒĽĽ%FyÍÚKąćĎŢ řżŸďqłŸ˘´ä|Ęăo>VĂuúƈv]pzÁ1'˘!c >Ş„Lsź„x÷]úíaÝ%ö-R­ŃžíŐp<Ysš&7x>yˇŚSďL,˘}ßçÁäţűďx_ϘăǏÓnˇą,›ĽĽ.?řÁ¸çžó|ěc!ĽäôéÓ!p‡§žzŠ8Îźd,ËF)CĆ|P˜|ŚiĘh4˘Ńh˜ăj°ß†Č˛œhŇX7K0Ňj\ 4V.L‘Œš‰Hv]’rBŁ”Ę+GÇŢ-eœ{%UI‰ÂŔˇ`CĆBG1A$鱟Mnš;ÄÓyuR5'‰’ŠŠč*DČö-gj´`ŹŽ)ÎÉ"Ć܊2ŘzźM˝7ăIQ"ë8.ŤŤk4)ď˝w)/‡ŐÔë úý~YV;?ßââĹw8yň/^äÜšsĚÍÍݑŽu˝›&+@%iIj.řŽähK˛>Pœ^0§ !c >ŞŤaZCˆű˘7?OœĆŹD×xă\ŸÖ…~ěăQcŢęd­ĆĄĂÇ86lă9ބ2(eŢZkšÍćÄ$yz‘íyŽëĐh48zô0BˆŇČ×qĆw-ËÂ÷)—B8fŃţÂp8äťßý.ŸűÜçpsl î>S–˛ädLa€+Ęç3>AiMŞ2RfěÁRŒ{•l%1Yč”oĽ4íUZ•ę›1ß3vk) ÍĽ˜ôąŃ9ÓSúˇˆĚ4wˆĘvŤ¤Đňh˛”h “¤ÇĆźşđ†A$ĺŘ@XëÜôˇ(y•Ҩr_÷†Œń<ĺĺejľ:žďă8FŁôB”Ş™z˝N˝^çčŃŁ(•˘”*Ż?{ KÂ#'žťhgŚÍJóꥀóK.ž“pm-ŕÉ{çţ™”űĆ˙ŞDĽ˛œ3ü$ů†Œ1000000(çŮ˝~ŐÁ€@H67n°Öx[_ágüe<ĺŃŠ/pĎąą=Kú&‚÷8團ëW'^Őß ŚXŘLO¸Šż-K`YrË6Ś_7ýYŰ=>ëďęk§›H<™Aě”Rܸqƒ••VVV8~ü¸iƒť>.d‰ÎŐ EůPaŽ[%cĘHęŞ:F4ĚXŮ2IÄ0áá˘*ĆÓdL9–R$'&źĹřĽ**œj2Ň8ÖşJ UŸŻ>˘g(x˜ ç9Ů#Šń3'x”ŇIŢ^…%Í´mďŒŮe¸ŽËáٗŮÜ\vC`~~>?▤Áâââ{\[đä9Ÿ†+xíJD€-5Ż^QwŸşˇÉbÓ:ا‘ÖÄqLżßgss“nˇKšf†ýśmÓhĚ1??OÇźţúëźů曼űîťŹŽŽ2¨×ë:tˆÓ§Os˙ý÷óŘcą°p°ĺB†Œ1000000@ŠJšřÎ_ňĂź„R ˘nąţ€Ă⺏çĎłmp˛ľŔ|뽤Ď_ňGzsj.l!=”Rôz= S˝lnnâ8ív›~żOˇŰĽŐjQŻ×QJ•օBRŠ~żOżß§ŃhRJ:TŢaÓZ—ńÖE$ö´ébšŚôz=,Ë"Š"Â0¤Óé0p]ß÷šyó&N‡0 évť!p]—N§3ĄĘ1ŘŰɺ֚őőuŽ^˝Ę`00‰!űŚoRĆMgD‰ŇL¤ž2ŠŇĺď…J•‡3^&ȘąaďŘ`W”ę=5bâ•óŠŮÚďŃz’řŃłŠ‘“ۑ×UâZŠ1‘S5–yŞRő#˛R&˝g$Ç´ićľNŔű%7ÝiXśú¨!c .Ň4ĺ˝+—ęAAÓćfÍăÓĂűšçĐ˝ôF=ÚÍnFŤ<{ůżpá̀όÎâ´ěmU)I’0 ŘÜÜ,eŕĂáĎóŘŘŘ`uu×uŃZÓjľp‡ đ}ĽƒÁ€7n”)Lý~ŸN§Ăćć&h­q×u ‚€FŁÁĄC‡J´ëş!ˆă˜(ŠĘ&Čaˆçy ‡C˘(b4Ç1Zkęő:sssĽœÝ`ďź?úяxóÍ7ąm›^xĄ,300¸;rěCA(=6č­.:/1Jő˜X)ŸČ$ĹĘ[0& Âc’ˆ“ž4ůďşJčˆ)ĺĘ-HŤrJ•Ę Ë\]ő†)M /§­ž1Šr¤âŸ,Aş&7ň%…tË}ݍqDĺîÉmÜv$8î,ŞFĎL}:Hs‹Ë—Żđă˙׹óřqßlnnňüóßçŇĺË–´üZYśü~xá…xá…xüńÇůŐ_ýUNœ8XɊ†Œ1000000ČŚČRœŇD§ZzČȏƛ\J/Ń]ŮŻő^cŐîq}°‚Zm0ě-rÝžĆňás“ÓÇÜď%I’$ĄÝnÓëőHÓŹ_Q5§N"Š"l۞PźfŽľZ hľZŹŻŻ—D‹)eI°H) Ð$I&ďÜJ‰mŰÄqŒeY ćććp‡(О ‘mO;…b§řƒ˝‡”’x€x`˘ÜýÁqʌ)JˆŠ´¤*™’ęq‰’šd*}ylú;ą`ŐŐR¤qɒ.ʕ&„Ećˇ"Dc]źĆ9S%m s_QUȈJŚţ_e TI×LŤc˛mIDFé"UК¨¤Kł_Qm×=8˝‹ëÂ^ř˝Ü}2ä`އZkFŁ!ؖƒc;X–Ĺ…‹oóÝżx­Çg‹ś2ňćvŰú…^ŕĹ_äďüżĂĎţěĎ2ĆŔŔŔŔ`› ŠY\|´ŽçT ýA^qśďRK|Zل}(Ž`”&ŮÝXŠi*wá4"ľXkô!žHkŘâ¸hLLžŇ4%Ié÷ű?~œz˝ŽeYôz=Ž=JE$IBłŮ,‰“z˝^–*u:™\šŃh09qâśm377‡çy%ŠcYVůž,ei<O’¤$bZ­Žë˛°°ŔúúzYŢtčĐ!Z­–e•*×uń<Ďtó;yFUH´&#*AÇb_ś˝ÁV.&3ë÷ëDU1Ç-/üdŇ w"Š(cf¨K˛ÔčqI’Ňc%KY~¤E-­EFŒČ˘éqŒuF„K,K ĽŔś,ę5—šďŕşҲ¨ű6ś-ŮŘąş1dŁDié3ŃCuůc’Śbź[ôh•c’!óHëüA•ç( @’3IbWτą]ÎŘ,vZÝ86ĽźvL“łÎ‡ťŽLeLaЛąe}úŻźĚkŻ˝6îmşŇŃ> ”Rü›óoX]]ĺ—ů— c````0uArlp]Lc읇-ţęąĎĹ1J+D5Ő T•ů¤Zi…@`Ë,^Úu˝‰I””’N§SţÝhŒ‰šZ­†ďűe‚Ĺv“]!FŁ|oužďăg‘JčYfŰś9räȖď\;iO†¸“äĚž€ë"ňŤ!eŚĆFÍD”u‘r”/"Ś0ő-Ťĺńđ¨f/$+&čĹgdcłŢf-Ž(ÚM#‡çi4|jžKÍwiÔ<ĎÎ|¸l‰ď9xŽ…mK,iá:– F!ÝAÄF7ŕĆڀőnŔz7`8  Qœ’$)išďEŐXlbʔ< e%úťZęU1’g÷ĎŚńFťÝ.ׯ_Ç˛Ź’\‚×uévťDQLŤŐÂó\ƒ!śöýţ€ZÍg0°´´XŢ ŘKŢiiš–ʐâšVÜÄ8¨R–7O^yĺ^ýő-ž0E_˙°‰JßřĆ7!cČƒ;ˇş@4š¤K‡ą77M{ěťEĄ’Fmކ?işXL’D•ZYZT}>Čbťjš xcřj`pűH—#šM„e™Ć`’ű/ŠÇŢ1…gLŞ™đaQŞx˝˜0ÔU#í6cT}—üPń]Š4ş|Š@0ÂÓ]"áܑ“9ÖaĄ=‡ë8Xś…eI¤ˆŞúCŔóó5Ž“+^ňňŤ0J¸šŃçĘJŸwŻlrmĽÇzoHkŇT‘Ś UFwW}Lti؛Ľ'em ľČĘśdfę;Áœä¤Î^ÚRJŽ_żN­V#Š"ćććÈz˝Á•+W8|ř0++׉ă­5śm3 ‘R–eľľZFüď%R$ %I‚ëşÄqœ§ eţfQŃnˇ,!cŰ6GĽŮlňƒü€W_}uËő:KS(!ŠŐjšüúĆ7žÁĄC‡ö}ɒ!c î,Ű&iľˆďšëĘeDPÜeČ,›Y1qÔń0ĄŚ92^śˆ’¨š=rf7ď8šťúű}q/&—úÜUuŒ”hß'ž÷^ä|;űű#["öÁ 4¤yTłŞ$*Ľšœ|Фiň˛%56đ%+ËՑ3÷y)z€‚FݧŐpi4\ćç|‚ !ˆŇD‘*Ew˛˛6,˝W¤Ö$*euuÍőźőَń\żćњkŇYhł´ŘáčŃ#>źČÜ\˒ tYb¤ŤN1"Ť&ň|‹c‡[>4ÇĂ÷!ŠR‚0a0Šč÷CV7FÜXrýfëC†Ăˆ4U ŔΡĄ‹äŚź=„ŠŤž7˘ôљe&ź[ׂFŁÁă?N’$8ŽS–ĄÚśÍéÓ'q—4MÈ$I"SIĺŻ7oŽŇjÍoQpěŇ4ĹuÝ<ćšÁ`0"I2ϲ0Œ‰ăôŔ’1EÉqaĚ^”ˆíZM’–,÷?,ţíżýˇÜ˙ýűÚÔא1wčB„ea5›$ŽëbY˛4u/^kŰŮrşjŸľSŒçy%7“*'] űEфJŚ:‡´Źƒ}^Z–ĹóĎ?_~Ÿâ;OŮśDişüű˙ďůęWżjČCČdé2,"úŮ/’œ<…űúkX׎e–ň>ŮĚĽn>y)ó%ÇŻßćĆę–íM˝N†‚bĆÂAÜbĆŤŠ÷ÝŢm}F.kžŢçYmůŒ]\ŘźßöŠçK)6šT+HR@ —TkHÓq$¨Ř2żżĽóű=żĂ5ÄśĺýĹd°¨KOӄúœÍ}ś ’Ź‘ĹmŹuv7k~ÁĄHSS*d°÷ČJ&&˝ö/“Ý˙׎ ŮâݤÂB‹Šä1E6Ýr >QߏěÉMÇĽD;NřŔ¨űîÇi6ą,)˛2sW›:÷‰AŁt5ňYb[dĺB2#ą¤-ą- KJ\ĎÂą-:ó>‡—ć8ÔŠstąIŤéăçţ-ŮŔŹP:…4͝—kh™Z#„ĹĘzKĘźĎW8ž‰řë|ľ&ŒałąŃÍćR"- Çąé´[œśmSŤe„Kh­óŸăůŮĄC‹tť›ÄqR>fŰ6JeĒçš4›™‘źmŰe2 eYĚÍÍqýúőňűĹqŒ”ăr›FŁQĂűžO„aH­VŁÓéPŤe¤XŻ×c0EB\×AAŤŐ*IŸƒŠţđ‡\¸pa‹/Ü,Ňf7ń /đňË/ó裏2ĆŔŔŔŔ2ŰóśMňř y4ť €?ƒýłÎ*–8>™ĽâĆććÄÄr7ȕCĘd}ď–+Ĺ,—C‚;§ßg17kq—m|„Śܑє§ŔŇŔŮsxżńżýťô  ¤Ŕ˛mlÇÁsœ,U,_|›3xň)5&`tŽtńm‡fłĆb§NkŽĆŇBƒfÓĂ÷l<ĎÂś$ŽKŠfČCƒ˛ś ŠJPq…8ŤÝŢ-Q† aӞob[ŕ؂(ޘĺÉNZWłgÁTe*š4IX‰bnŽŽóÚk?Ć÷=ęő:žď˛°Đâřą#œ>u‚…Cź\dLn$I’'ĽFłyöiޘojšçxNĘú㈠L˛˛*U|˙,HIçž1J匿ť<˛,‹N§ĂÜÜ\N$eÉyFŁô+IÓ4WhdĆՎc#ĽdĎIKĹw. ĺ'IĽLS”ÂTÉá‚Xp]ˇlťbŠç‹Ďp‡N§S*bß!°íƒďĺô­o}Ťl÷Y*ĆâąB1óŐŻ~Űśů×˙ú_Óëő>Ôg˙ń˙ą!c ˜ÉĘüŽ‹ÎgS…Ęb'érvw“3Á6000řɆ`\¤ĽU˙LÂ÷–Ou8wĎYÚó jžEłááű6ś“•9śÄ˛s剨\oľš(Ë)Ӗ”&Iâ8f4Š GôűCş›}ÖÖťÜX]çúő5VnŽ2Œxྒྷüżţß!eöĽĘ¤b,\n˝…™^ü*@§™'ŽFِőő.śmqőę .\¸Â‹ľ×8ł|‚űî[ƒ˛$'Šífj‘¸ü>QĄ”Ę|YdVöŁQIŁ4JhĄRVb°§Qíz_ĎóđˇÍžďŰn_ŠsĐuÝmöíŕbmm_|ń}żS•ČĘ|}Nó•Ż|…őŻţՇ"d^xáÖÖÖXXX0dŒAËś‘zrⴓ ƒÁn,VÍľćÖhÔ\ž|â,>tĎu¤EĘŘü6[DŚ$ŠFŤĚë%NR’$SśÄqÂp8b4 čő‡ŹŻwYßčrĺę Ž]_çĘŐŹ­oŇë ٘T)@g‘Ôž`XÂ.•6Zi@Ż•¤ĽI‚f’P˜ĽL($1 q×u˛rkĎĽÝ>„çş(ĺŠSŹĚ#Fĺܔ¤^ÜWşŰýP̰ç7ß|s‚œîŸĹĎ4MY__'F¸ŽË?úGżÉżřżĂ™3gř˙ŕđőŻ˙s666Ćýš raD]ü§?óYÇ1dŒÁ­'Íw+)DoI?0Î3{ŃĆfĄd``ˆƒý‡8Žšpáożs•őő V×6¸vý&×WÖ¸šśÉĆF(LPiF0d ĚÂŇML”2QhĚE B?•š\žš˛Ž%ćÜůŕ ţż?ůsž˙Ă1Ů5QˆŒiX¸‡môu…5Rh„ –+@ ŇP!ԘÉ\`Śn´TJ‹śccÂ0$ISjRŕز\}jľ•XŃy,vőR2MÂTýcśžwż—=‘>ČlŃ<íYR¨hâ8‹îőG4ç ‘1J#ČJą¤P(kr+ZkҢÖj9ĽFƒfł‰‚(Š˜›k†!ŽëŃhÔčőz8ŽĂŇŇ"ŽăŇínŇlÎáű5’$Ľßďăş>ss­Œ(°Źr›ť… ŃüŮ[!ßykÄú0­řť?3Ď_{¤Ž-áĎŢri-ážĂΞ=WŚç/˝^—7ß|ƒˇŢ|ýč-Â0$ ’8* ›‹kťËś¨ůľÜ:WÍäý°ŰíňO˙éoóôÓżËéÓgřú×˙9_ůĘ˙ź 39ˇdfĺišRŻ×qX–M’¤w}Œ4dŒÁOĐbáƒLfâ8Î&ƒ9c°ű ¸ânj1q6k§jewi“$%MՇęĎ{ )%śmăyŽăÜő~z;Ÿo ägˇŸëť´ÎŐ8rzˇaă/Řř –+q›.מ_Çöm´R´NÔq6—žłĘĺďÜ$ĽcäV,ƒ`Ś†ŇYRQ’$ś-ËçcÜ _]%aĆdőłýÍJľ‚eIFAŔĆzšyÂhĐŠBH‰´$Zé,"]ĘÜPXÓiwĘňŸ0J2o)idNHIHPšžF+ŞDsďV’˘Œľś, ­5Ng˘Ń-K2??Ö:›?~´˛#şœ÷T㪠…Ě´ ň=oŞqHŚ ŠVxR` M§Ŕţ$c ăÝ7V¸vý*ŤŤŤŹ­Ž2ö FB€ë8ؖ…Ş×ǝ´rłEVoź%qÜŞOˆm۲(WĘă˛ôRiY8ŽWŮgEˇťI­VĂśď%bČƒm‰˜ ‚`ËdäĂLÔ§ˇń“vçśPůžO­–ŐŚW'wăv2¤LľÍ’$!BƒĄY0ށčô]NٰŘy_ă˜4Mń}ĎóĆƨwi‘´“óŨňfCJAkŽAËŻqěsm,ÇBŘ`×’0Ás9öd‡ZËcă˝>"…ţŐ!˝ŤTŞ&Çô[>zűăF1I’äDŸœ$Zr_™1ľ2Đ8ţ=áIłš¨xŇŘś…%%*ÍJG¤%š2IJ-lŰ*˗Š÷%Š]öł8É˝`”FUm<´F(BĺŢ1y™Ň­›âĄßďÇqyu§Œw]­5śm“Ś)…ZľÚöYuFv ‡C”RÔj5|ßg4ĘLfă8;>…NkçyÔëőmc°ˇ,Č%üÔi‡—ßsyűFZňĂË!ÇçmšŽ&ˆRŽÍűűöZkęő:qŁrĽŽă0 Bć7J<â8.ßkYĂáŃhTŞY…¤iJ†ŒF#Ň4-/Jˇ<ĎŰ1ăڂGNzüÓżfsŁ—’&B…cÁçŹă9’ý§T1/꓎XŇÂś˛›MľZ0+J˜ŠžÄ¤zLO1O?ýťœ9łĚĽKďńľŻ}őőľqO)U0)dŚÜ’r|žĺ˘ŤfłI'lln27×â§?óNgÇÇȐ1w I’†á– Ű´zăĂLŠß‹m~Ô|ŮMăş6ó󭙲XS&0Ů‹ƒü.e˝^CkĹĆĆ& w­_dĂß÷ )¸KÄV%‘x`ŽőV2ŚŮl˘đç|üśÇú…:҄ÛIOsóľÁZŠ`KNsaPz[M+J#`•fĽJBdĽCeššŁˇ/[1Ř:ŠşÜnÜĚĚTS’8Ź[÷•EqĚ`ÓlĽyrNć]٧ĆuĽňąJ_­Ô¸}vi(ˇ,‹ůůyZ­ÖÄ~OĎC˛çE™Uő×b\ĘT1ŐmlGl}E\§!™ŻÉ-nt–%śU3í—qĂóĚú}똰U8kܖĚĘŐqčú7Ł Tš@kÍ~TÇH)Ëň­~ż?ž÷ä„ČÂÂ/^œHězżńŠÝnóôÓżËňň2ďžű.żő[żU*b2™“^blř[ŸŇůÉOâ8ÎDIJľmŞ“LĽň'ĘŮłË<řŕƒ3 ’zđv‰™˘MlŰĆ÷}†ĂŃžYl&IÂłĎ>‹ëş|úÓ…ď˙EćççyčĄóśœ!ÍŽLđ÷ó‚yoÉŽěü}ůĺ—iľZ,..ňń|ć3ŸĄŮlNô/•OޟyćžřĹ/–fœBnŢź‰ÖšĽĽĽ eUAř^¸pk׎ńéOúŽËŇ óóťĽŕ2%}n‘ŮhÔIú)+ßYEUBd$Œž\¤k‘G?çőC…NF~ť9‡"ŞŒ„Üş/\Œ‚”ÂłĺÄľL‹Rw2CَnOLţ,úĹôcĄ´šŃĽßíf~5šQo˝áÓhř´ŰóšR§˛ßŇψG Je‹qĽłr¤ŞŻMőÚŹňżő.ˇť]~˛7çňîĐU{qžŸŸgqq‘ ‚ ČűEvÝ;zôč„Ęu's§Ÿ~šłgĎrńâE~ó7“19%–Ö™A/UFWĘDƒRá-…dii)3äv]šÍćžPĹ2ĆŔŔŔŔ`&iđAďč|ĐEśeY,..277Çőë×Y^^ćľ×^Łßď3??OÇlllđŔ†!ďžű.RJΟ?Öš7Ţxƒ^ŻÇ… XXX`mmË—/“$ išňŘcńŢ{ďąśśF„<őÔg˜ŸŸżŁ“5Ľž_CJąm;T'&ťľpŇZ°šŮĺć5Nž<É3Ďü!çΝçľ×^ŁŰí˛źźL†lnn2 x衇Đ:#iÂ0Żźňƒź­.\ ŮlrćĚi^|ń%:<účŁ:tčŽ÷™ý˘Š)Ĺ×_ŤWŽŃškóö/°°ĐÁ˛$—.]Ś^Żą°°@ˇŰĽ^Ż—FÎív›S§Ní›(ä[‘`{5ć¤iĘťďžËáÇŠŐjźöÚkœ={–ˇß~×uiľZœ?ŸőŮ0 yîšçx衇xőŐW‰ă˜ĺĺežyć”RüŇ/ýWŻ^ĽŰíňđĂ#„ŕĺ—_ćć͛!xâ‰'Ę´—;Ů7ĆýTcîEĆš ݎŤcsŠ"›ňEzS¤KţR1Ë8WƒbFÜ4ŠŒ”JqœlŤË˙V`Č=côLőĆ­"­g=çšs-ĽCs™!jţa…AjV*2šĽÇ\N"j!Ľ5Rd J"Oa*I)& |w“k8hdQQ6űşŚ÷ńy’•r}ţóŸgqq‘gžy&+Q˘(GĚϡšqcĽ<‡Ş˙fˇ xë­ˇř'˙äŸL1“MĄË˙ŠT†Q’*5Ńď;FťÝ.“î ˘ß1ű’yżëݜŕŰjˇ;9r”(Š9}ú4đČ ?ŕÄÉźţúëÄqÄ{ď˝ÇącÇřŃ[IgĄCż7`eeËśpl‡(Œšxń\ÇᇯžĘSŸyŠ^ř>asĺňe: žó˙Â'>ń‰˛†üNśŤmż˙‚{/&ZkFÁ(/Urxă7ůło}›ĺłg¸té2kŤk,.-â86ßřĆ78{öžçŇíöpťŒ7_]]ĺŐW_çúľëüÂßřëü‡˙đůű˙ďޕ oaX,>îö¤ťPmœ?ż˙űżĎŃŁGI’„K—/ąžśÎúĆ?˙ó?ÇłĎ>ËŠ“§ˆă˜ľő5~áŻ˙u3ćä~JI’’$)qœ°žśÁţÁ7ůň_ű2oż}Ë—ŽpĺĘΝ?G„ ‡#._şÂ… X_Ű(ŁĎ˙ňG?ćĎżűç(ĽGtťÝ˛ʒVž8źóßoź00טƒ!z Ťťg@]!dr˛Mż?Š0í R%F&ÇÍpffł–(Vëe’RAÂźßb}Úădű13OSru׹ˇě´Č ™ńggŰO”ĘĆJ— âL(˛ˆk‘El ])ÇQ{ç…R˝Ĺ—i˘ŞJ°íöŰA˘4›Cş˝đڕĽ5 ‹cm›NMpϒá9Iݕűr )Ť Üwß}SFÉ­gΜćƍ•óKąĺş‚ř˙§ łßńqą§5R‹ňšÇI’nńޓRrĎ˝÷`ŮČ̔9‹1ß'D–f fMLîâä '›'NŇi/přđažôĽ/ńŕƒbۧNćĚéeFŁ€••,Ÿ9ËącÇ3uA>Ĺł¤ĹŁ>ĘŇŇaŽ\ž‚”{čaőâ_ţƓ˝ťcŔ§”ŚßďÓhÔů[ëWéőzX–Ĺ#„0Œ ‡?~œ}ěc\ž|Ľô׈˘°œ8 ‡#Ţ|ó-šÍFŠ8ŞŐę<ů䓴Űíť´ˆßçÎ#|œĽĽ%Ţxă úý>IœňÉO~ŠĎţĚg9wî|xߊbfőÝ˝Ü?!śeąšŃec}3'LRZZ°zs›7WétŽ=ΑĂGH’”ĹCK|ůżů2gN/síęuî˝ç>Nž8Ĺݒ÷séƒ}=ĚH‰˘ZÖ°M,´ĹâRߒ„Qĺ?F ŚđʐožĐ 4ŸvřŠS5ţüíŤ}ľ…źŘoČJąýň_­VŁŃ¨Ól6Y^^ćĉĽŻZŚnľó˛ń1!–ŚŠ4MĘ9Hv<˘LőĹĽ_Q'„aÄp8d0ÇÉÄ5Ťřœcǎ1??ĎúĆQaYžżb2ĆŔŔŔŔ`_1–%q]×up]—zĂgŽŐŕŢűÎóŢĽwřöˇżÍg>ó|ßC)•×­×xꊧřă?ţcŽ9BłŮ¤Ţhäw>šÔjujľsssܸqƒ?úŁ?˘×ëÝľ MEh­˜•NąwÇ\Çáŕçţçh4?~Œ—^z‰˙çßŕ‰ÇŸ@ xůĺ—X[[çńŠ×kü§˙ô RJ>ýéOóđĂó˝ď}¸Ÿ÷ŢËJÄćšMšÍúm™ď.Á”Ľ}ěĂqęő:­V‹_űľ_ă_ţËÉňň2Ď=÷‹‹‹|ţóŸç(ăT[­ÍćÜž"bfŐóď%ĄPÄÇ~â§>Ářżţ#Ď=÷O=ő­V !ßüć7iˇŰ|éK_â[ßúĎ<ó óómććć h­9|ř0gΜá›ßü&çϟǶmžýíoó…/|/~ń‹üŃý­V‹cǎíŘ|ˇ(ĆŻĺ@_iĎĎcY—Iăd’´¨źFŒx'4…ę‚ÂnWL& U˜”íƇٕjG’Ş•Śš‹BˌœÉ-âśĎ÷­Ÿ™Q@AEC0čđk5RÇ­V Űs°mťźŃŕŘNć‹$$:I3ňFgß6‹.xŞIâ'K!Ţýń%Žc._žĚp8¤ß0$IŠS'xűíˇ‡8ŽW–ŒÚś,ˢOŸ>ÍÂÂÂ3`O•ć­k Ł Eäţ9Ÿ8éplŢÁśŕŢ%—ŢPĂÂÁ˜CşŽ[śk•|řá‡YYY™ęwâ}ˆÂIös|Ęd}5›艱śđ ‹˘ˆvťÍęę*őz˲pg_ë2ĆŔŔŔŔ` cYÖń™$c,žxüqžxü š_ů•_)ŸűŰűoßb6)řžPüQ>ü7~áÁŻýÚŻąššÉřC677P*ĽŃhÜqŠoáÁ˘”şăƂ}âQűÄŁĺߋ‹‡řú×˙Łáˆ÷ďţO~ćłOńÄ?UŞ4>űٟ™ŘĆ/˙ň?ÝđüôO˙•=™Dďd‘ŠsÔ]Y\ςçyü˝ż÷÷rwNÁÓO?]>÷‹żř‹ĺďżţëżžĽ÷łŔ^—€w0Ϟ=Ë?ţÇ˙8'ÚR.^|‡ĽĽEžň•Ż”çË#<2ńŢĎ}îsęSŸŕóŸ˙üÄăO>ůä]mďbÁj™{adž=‡%e™b¤+fź˘˛ Üڈ ]đ4Zl‰zžŽYŽ’2‰# G(ĽpĚ°´ˆôľt’“ˇ&bŚ}anu^kĹi;ś‹ăř8žÇB­S–I ƒáßóčvc––ŽF žă`ÉBIŁĐŞČŃÖeŠbLZiA´Kiĺb=›Çt:r•LFĆX–Ĺ}÷ÝÇęę*–e!JĽĚĎĎăű>Zk666X\\źsc„<|Ňĺ[? ĚTižť8ädGâ9‚7.őůÂc3“t“dĚÜ܏<ň/żüň–r˘éyčväĚôk˛šŞ˜(EK’„0 Y^^ŚÝnSŤŐ¨ŐjX–U&J2ĆŔŔŔŔ`_BJ‰ă8Äq|çĺő‚Ű_(‰[-Ž4BjćZ Ν_ćúőë<ţÄOŃlÖďxš’‚4Őtť}ÚűGŃáş|ţŻ~–vť}›wđEţqGďYŒyLż?؟ \ążÉ•L¤ŤÇńŽśŻČdřBÂŇáCüÍ_ú›HküřAlËba˛_’; >Řqlˇ›HË*ɔŹ@HrËŮ^„ZOřšäę‘÷ťFL.>EÉ[ †#R•âšER‘B P$YLӇ8MgŮĎuđ\—Ѩë:šH‚ďšÔ\ :¤ťŮŁÓ9ÄhąrmóçŽc' I"KSŢjŠR§@h 2'Şö`Č,‚śĂ‘#Gś}îŘącwôœumÁc§=~ĺ“Mţë_ŽHRĹć0ĺ[Ż÷YlÂŁË ćýƒAćn—dU2gϞ% CŢx㍉ǧI™Y׼÷ťn%IRŚ×9s†ĺĺeZ­Žë–7šćçç÷ÍMCĆĚź¨9Žs÷™=ř>śmsâÄ Nœ8qW¸Bƒž—•´ě‡šm[Ü{}F˘ě5“Ś)››Y]żQě>ǙZŢůD!sss<öŘŁž=mŰĆqÓGň5DBťÝÄ*Ë!*1ÔyI‰Ĺ •ňŁňuӃŮôß5ó\ËƟ‚ M<Ç͍sJ+â$DYë6ť×LNĺ:eŰR€ ŚYĎúŻç¸€[–%ĹI’— ÂÜ\ƒZ­†đlÖdH˛ŞsSít†ď”Č”<+g$Jď/ÂőN_›Ľ€VMđß>Zăçňň´óŹ˝™‘5ÓIŒűužUUĆTűZ1 !řřÇ?Ž”’×_=+mË ĽÔŽ|ĘŞŚËĹż$É|f„Üwß}œ={ $b 2ŚŐjíŤŘsCĆlA!ĺTJ‘$‰i]"(,Ë"IbÖÖÖPJŃl6÷ŐóBČÜÉ$Ł0 ŮŘŘ`4 Jă?ƒÝ'cŚçŹIľÁΈ˜BoÚńCC{ţ}p9GŁÇ'ÍŘ>F‹ăÄ$•S–.m7žęœě ‚Ě4˝nĄTš•ť ĐE9qfěťUŢvýŻúŮRZh Ž#Â4ÍĚE™’%QJĺĆŤ2O†Űd08qę(66AŁÔdŸŻŞíJâGŽâ'ýʰ„Ŕrž#oűŘíˇůN•Œ)öťč/Eßůň—żĚââ"Ď>űlŮ7,Ëzß4ĎYmR(şľÖ<řŕƒœ={ś$-˚đ’iˇŰ†Œ100008ÓFŁÁ`0 MӉ;if1ńÁÚ4“ďÚ¤iÂÚÚƒÁˆFŁŽďű&tՉVfÄ8č÷(•bYv9Á:H“ÔƒÓćúŔ-öË9^ŒŽăPŤŐJĽŃN˘‡ öéqŐ0?ßBZr‚PŠ$fEKŒYĄR^nTUÍŃ×әKĹ6ś2d~,I˘p=+WŢ(4™‰ůn„ăN°2ßÉ4MHă×ő° )–-B˘44 ´Ö\šrasüř\W'Š$MKďšj l9žä~1ŠPűNcđáŕyޖČđB3 8věO>ůd9ˇ|ýő×YYY)Żë!łÓ=…ŚÓéŕyŢé3AţĺŞKCĆBŚŐj†a.“NÍÂěC"ť;”% ŒF#ƒAž ¤&ŇvzŒfŰmˇŰ}ýNˇąWűXÜŐ*~Z–…m;Ś4É`_Ÿßžçe%Ś”” QÓwÚĹÚíVŽŃ)fŇjcÚX"3AĔ„ĚÔŚC݈ IDATű´˜|b˘ŸEÇ$iŠëXůu)"v1°4ř%+qÝnŁžˇq$ľR)I˘BRó}~ę/ű’*R•…u‹Ţęľ­ş0–2/żš‹§Ävĺ˜ŰĚź˙XŻ×'Žĺ†!Ăá'N°źźĚŸţéŸŇétřô§?͏ücŽ_żÎúúú‰sŤś×ZsôčQîťď>~îç~Žď}ď{ŒFŁň}…§ú÷~S$2ĆŔŔŔŔŕ– i!žçáyI’LÔč|¸ `ľNzVťN“ťĄJÚIŠÄn•S|ŘýŻJÚgÝáÚIâÂű)şvňšÓ.;ůÎ;m—ŰÝż~睴Ýnő™Ň'vă¸ěô5ďˇoŰ˝ŚJN÷Óé ƒƒ‡zÍÇőÜźhĘ7†)ŚŹAӜNfzž—é\8ŁŃePUa“ůÎ ˘0&Ž#,)qm+ó\Q ÂÚÁXPMUúć,jhLEQLŻPoÔH“ÇőHÓ\ő`Y8śŕĚBs†J‚0%ˆb˘8’Ős˘÷Î>Siéިďâ8ćúőëh­ ‚Á`X~ďNgáp@FÜźyĎó8wî,›››$IJŤ5Ç`0$IbŇ4ĺüů{hľššówv´šŘńëˇG]×ݒ¤ľ&Žcęő:‹‹‹ôű}z˝ [ ľäȑ#t:jľ\˝z•~żO†ĽLĄ8lˇŰ9r„……,ëťVŤmQă(Ľ&<ЊRŚi˘Ü1űĹ]j !c>=1Š]}4xiúwƒƒŘ‡ Ǣ٨çĽGcţbÂűĽBFäŁ}ţÜT “G]—ޘIĘf‚Ń91…RhlTš˘u (’í¤%ˇ"23¨(śšÜ†”١ŮlăćqϞççs€ńulvżÎ˘™ËRŹ„&‚ĚƒFh•Ś{rܢ("Š"Ţyç=‚ ŕȑĂY‰•RlllróćÍŇ[d4 ˆ˘ŰśISEEy‚Tš—ƒí=1’Ś)QMܜą,Ť,˝ŮËqi'DĚŹůĘŹż b¤řťřgŰ6Ífß÷yë­ˇĐ*Ų$iްr/"­5ˢ>}š ¨Őj3oĆŘśÍh4" ĂRSýŹjŒ{ńţb[Űݤ0dŒÁYL˜ĹĹiKƒ& ŃúрëÚ4›ń˘ľ¤Yrň%?ĚZĹÝyĆľGĹ{„(˘œuIĘTI˜íŽq†!Mł^ĂuCŇ8ÉIž­dőÖ›ŮŃÚŰ-ŔĽ”ĚÍľXXXšý5jť÷k­šGZ5íFkBăŘŽí”m%ĺî{x8ŽĂšsçňI>A0âÁ,Űë̙3yűLĆnowŢNżćÎÓDHDŽaˆeYÄqLżß/˝S&íöüŽ2ŰíĂvÄ]•„™&dŇÜÜšşĽžďO¨!+Yk44 úý>/^D)űčEĺq)Ú˘?]lżšśT}Îśíœ8S3÷ľ dęőzY>MĘ2ĆŔŔŔŔŔŔŔŔŔŕ#FƲőŕĂśmęZŽqÉd-Z§DÁ$Ž&”BÚHÇÁőXśĂ´~FW÷EíR^LTjhĆKÄěˇ8QDa–lčŘ­Bk6…đ­K §í‚ UĚÖžY–…Vź\vŽ$ĐyěuJ'ÄqśČś,Ť’Ô–m+IÓ|Q,ˆc ťL\*•Š[¤”ĚĎĎŃl6X__ŁVŤ†Q^Â˘ąŹŒŕH’$OTUć¤ĚôśŚÉš­ăŸâć͛YęœëVTcb‚đ)ÇqŢö֖Ď+~w]—őőu‚ (Ă&¤¤žKĚŘcŽ^ŻAůwAČçG•šS¤Œ!c î2śsň7¸ó‹ŚńäâĂˑ vű<)ääłď\íĈÖŕ΍if<ťőxżŸÇ@s=š>hE‰E­ôŒ‰Ł€8N(O„™ŮJž˜L˘PośŤŒ´Ö…ďdRڊ)‰™ĘÇ H’”0Œď;H Pi Ť;„@Ľ‚4USăeNéÉ í[â˘ČŠŠzŚôËŠ˛TŠœą—LšjR•˘ľB)=Aô(5&e¤”H!÷¤LŠ@EŒFAîU’yŻ4u¤´Řśă8„aˆëşřž_úś8Ž‹)žŸ)VşÝ.žďcŰV™Ä$Ju1oŰAŇh4°m‡'NĐívŠŐjĽĚtšÍ`0Ŕ÷}z˝JŠü5ĐhÔq{GăË,o—i˛eÚĎeú5!U”ôŘś+Xś–)UŐ%Ueűë´Ŕó|â8Ş$†‰- cĹ|L)ľí5˝hkĎó¸|ů2Ýn7'ol--RŤeĺRB:Ľď`0ČI31AxůžÖ`Y2÷ˇq c```đ“´8™žŕě-ŚkŻŤÇhúPM߉1¸s‹ĂéߡKPš&]ŞwÍ îŢqŰÉXhŒŹďîqŞ.Ě yš…‡ÉΒfŁ–)ZҘ8 rJŚx‘–Ĺüü<ŸúÔ§xńĹYYYɔIL…¸nmlâ+ôdôő”đâNeЉ Ph|×Ćs$BşF€ĘĄÄ˛˛Ň" AĹ%A2IˆL_ăś&C%JY˘“ŽÖT1öŸŃeĚv68Ž•§CeęĄTĽ™•/ć…ŘÚ*Ű*I… Šö&jŘq”RĚĎĎ3ŽH’„Á ëşůO§,Mň}Ÿ8ŽhˇŰĽ’˘:f‹ű‚ˆň}oâó ˘ĽÚśB CNů<ëôýĚ 9I:Nů9BŤlf{óÇśÚg %KAŚsžio—‚đ¨žĆĽFŐ¤Źä˙gďMƒě<łűžßó<ďv×Ţ74 4@ŕ¸‚äl”gą\$G§ŮąŹ’eŮ·¤\Ž$NUĘŠJ9•|ČRVŖě¤,{di$–‘-iFÖp†ĂáN‚$‚Ř—FŁ÷îťßű.ϓďŇ÷6şIŽsOUŁŃ}owżďűlçüĎ9˙öźżťú%Š˘ěgRđćÖ3Űds5ˇÔVĹXÚvBÂśę’ěżfg~–4@ #M§ÝA,š”rĘčŽ÷j¤q@ŠuĚm“fű{aŸ[ĺŽÓ}7›&mŰŃŁF„A†HaĹ­9;ĺ°ŃHŠߘ¸ĹE޸eHĐlwŻŰ‚ŕt>h­i4}ęĆ@jl;‡Öq%Žă¸ˇŤt:MlŰĂqA¨éř>QßťR ‰ŠŸˆŒFÄHR)ŹÜ;uF †††˛Żăś˘-+—ËŮóřHĚýwÓśžŽÝîjśî1îŢ{ťŰÓJ–î6¤hIĄř`şAóôg!ŽJŻ% cŇć0 nŠTížoˇÜßvY˛mgÉn*OĆÄײ,ĆÇDzVŁFŁM„IrFi(Űś˝%+o ÚhŒŮ“6'Ę_}0Śo}ë[ß>Y–X–Ľ°mŤďř~ČN1’ ł`¤Ű J丟\őe¨?ôą2D‘ŚÓńą,ë–l~úIO¸ÓEt¸Ĺiđnángžoź§g†Q˘¤˘2>ˆíUfŽcő8ćďuœúcöŁďŠ’̝Îý„=Ľ,ő×vh‹(ÉŞń ­fÇv‘r‹dc0B é&ďMůbśŔ´X&…ÔL&™˝ßčHÓîřDFhÁfS ­žnÓhV(ć%ś @HƒDe:ŃÓŢ­t'ł•B ď‡ĚĎ/Ól:?‘چź—'çy ÇA ’ÓEIĺŻN@ŮDž:%jU ~ƒH ”‰0NŒÎ°Ę>JűĹ­ŕĹîטžAV8 n÷^ŰÝVÔ]=š'JŠŹG‘€)AĆò]-)U!J+xş!A°şşĘňňJÖňսǛm„|b<Ś{~vƒ1ŰŤ'SŸ ý-Ë&Š4ÍV\™ŚŁHdTĚůc%Ŕ“H*ÁDźnńć|0ąĆô­o}ëŰxČĆY ~$ ŚˆÜY'ĚqlZ­vOv¸ť"&Ťţóý(ŒU,ja˘‚@śŽÂ0¤P($ÎŐV–ëĆěíÖÓíËšömťŹn܏Uڒ°ŐBŚăî]´Çě¨|\­ň¸9NL4š‚d}@Ś{Ţmń­¸žăŘXĘ&čšďaňƒü€|>ĎĂ?Ěćć&Őj5KôKšU cv'[ Ěöúc ‘Ö´Ű>:!ç #M‚HPëHW6*ť 9×Á˛ăŞ)$R ´yűuąÇDH‰@˘ Aˆď'< 2V ą”E†T*•Lž8—÷J†(2XR‘ł,찃n g"š–MNk:Ž‹Q —óŢm×Ď'öœťý­lIÁ”´Z%áŇĎÝ>M*ůœ‚)éZO)eęřžŸi5M*ѝ‚6JĹäËJI*Ő*׎^eii‘ĽĽ%´ŢNźađ­ŕçvëžĆî5Ń]՗Ëĺ3îŸ-ŁŢ˝Ź€J+€ş?şŠŇ÷öÁ˜žő­o}ű˛éÁáy^?Hřˆ9?śmŃju2&-ݍ3÷Ü"ŁŘˇsŹl|?ŘĘú&ëĘqœ‰ď|p֟ˇ~¤­Q¤{8â€_d*!ˇóLű<&ď˙˜Y–EťÝé1;Ě˝4‰âšŽkŁ,;ćIÁςźfłÉŸ˙ůŸsěřńŒ{@H‰TVĈž6:ş(dLO*eИĆľĚ16: <ĎÉ*l7‡íäƒA7ńjMJšĺ’G>ď`Š(k‰ÖZlSX˘K9p›Ň’#bM%­ –R„Ą&Œ Ŕs=JĹb;quŘÂĂvˇÓF>ů0 ’ŠH)j*Od4ží Eü\,)ŃBýXέt~íÔ&˜‚'ťľĆíÓ[UťÝŇÜiuK†ŮçôĚLÁ›ÔßéömҏN§“;qőM˜okŤŤŹ­ŻŇnˇp]bĄ€Á°˛˛B˝Ö`mmĺĺeĆĆ'Č÷ŕŠž˝4a˛˝Eu;˙ÍvŔ¨űů¤Ď.őҏneŤnĐ4U¨JŚť•vëŰŚX*ôÁ˜žő­o}ű$şqĐbY2sxŇt˜1!śČFˇgHz3ĐŮĎ bâżwd{ř(†„¸­Ë1„nFźŻYł˜”.şĺŔ ´ç—9’ň™Ţ{élűB|T†Š{$>ÄŔqëswO{äóĽŰ ${2sI1lˇŃ´š†ńts\D>*‘I°ą›lœŮů™Ä­A–YMAi˒=rˇç×ă”kŢ\‡ęDěDę(”ĘˆĄ„eßŔôÇi÷yŤ”DëcŹ>ŕ¸mŚr×uđ\7ć8ąÝäyEY\ŤŐřá3Ďtíűe9X–݌(ÝrÖÂdˆŒIĽۖěá‘ŽđÄŁ÷łßƒEŰ!—sCř8ÂRY§ŸÍ ÍÂĹy†ËŠńń<ĎÁľm˘( şÍ­çĎö?!ď5Éů‡Œ!­falá…b!Ÿâß+čjíj¨ńQ´ňš­VE@eRۚŔhGža~Ěć•ďű4›Íl˝ …ŹâłÓéĐnˇ3đ P(ěJ*œú—Ý•†)Ń­p”Vžuˇb§`D nÄŔM@Ľ˛IłŮ¤VŤá¸ľZ•••eÚÍ&F“z˝†eY Điľh4›ŹŽŽRŻ5h4Z4-˘ŽĘ’̇MIŹŮňůnˇ1éľn݌ Ă0dşď­”Úţţn Ś„‘¤%)s ršĹbŠĆô­o}ëۏÁœJŚGRššÚ:Œâ2é˜ >¤Ztüřk%Ž Ľ"ä<…ĽdBˆůîén2ˇTҰÝn'*ď˝­Şťô=s’{ZohB cE‰”ĆŇĆôäO> `{勹sđCÄĄucZ(5ˆVÖô<_#c9Ń],uŹş“Čď8NićVJI.—{GĐÂĐĆĐ ëMMŮä‰â#ÝZę|űnźI㏠|üľUÂkWč\żN¸0ëk˜v;vĐJ%ÔŘ8Öô ÖĚ>œ™YěRaY1Tö.ÖĂöňńݔ†vëíę۟Eúűť_OÍÂXmwŠog¸˛q5ńş 77ĐöMäŻ@ŕ#to$˜8ú3”":pâŤ˙9ÖĚŇMĽ,źŰ3Šo=A\fŠ<žç"„BŮ.ś1~;dL’é¸8^> @w˜ƒ W…m[”Š&'†Ůťgœýű&9t`š™˝ )óH)étB–V6¸zm)V3üŽak_qsy„Éáxy°É՛xv“rޢwni‘Ţ­eIŠ051˙K8śĂääʒXVŹÖąB‘m+,[b[‘Ń!Qž‡čřaąƒDH‘ý ĽŽăŕ9w^š& ä],ě[­VśOşŽKEIŤÂNäăçÜa}}ÁÁAFFF’ö×÷ś—A@ĽRĄP(PŻ×)•J¸Ž‹Ne[­N×uł1„XĄhmmőőuöî݋”’BĄpKŰO7'L†YőGjiËQ7!s÷yÔ]yív›ŤWŻpíÚUjľp Ł… ~ťƒRŠršŒRŠÍÍMÖ×6¨Öęńߎ4~ÄŐ4]¤Á=‰Ĺ—Bzb7ł›Ú^ĘIăűţ-ÜcŰçuĘwăşn˛Ž=ňů9Ď#—ó°mŰś°,;ă’ů ÎĎ>Óˇžő­oš“—T؝Ľ.ÓĂśŐš>ďsö‚áÚźĄVt:iPŠEĂôÜsěŸq),„Ün ˘ľŚŃhđŻ˙őż& #fffřěg?Ăĺ˗™˜˜ŕŔťfeşڝěňĺ˜?ž/|á ™šÁJ-ä•yŸs‹A‡Çmœą™˛˛’í­rń=%ť[ĽłćGdL,/ęű›h˙{ ×ŃšŸÄv÷Ć`œéM˛Ľť˙ՍMţâ/žË7Bđ䓟caa/ůË;:ŤŤŤ|ç;ßáŔ<üđĂŘś˝ŤŒ$@.­źr-ŕúFÄp^rτͣűKđaĆśĆô<žłý5­5­ĺ%šßýÁ+/]ť‚Ů\G„aVm‘r&h% \91Agî.ěÇ?‹÷ĐŁ8ĽꋞúĽĽ%žzę)–––8zô(Ÿ˙üç{Hß.‚€7Ţx!G̀ŃtÝůžĎ÷ż˙}N:ĹÄÄǏçć͛ĚÍÍą˙ţwý|ˇ_ϝ2śg4Ó1źEPŁű}]ÁB´ąFří?ŔýŁ\YDDáVuŒ1`"DŤf¨WžŁÓiţ—żŒ56ƒgďy?Hœł˘¸ž ŁÄ|Lk“¨˛'c$B(l7‡Š(ôŃ:Üjő eŮ(ÇE¨­3- ÇĆsmĘĺăcƒ˜fv߇ćf˜™dh°”´ôi|?`cłNĽŇ`e­Ćš+뜿˛‰ß‰É弐ąLBXŠÖ(ËB9^\ŃgçŠW7hm4ńjuĘ…źƒJwŰ”Ľâ+)Čç]¤´“ށTŕŘ Ű‰9źlŰĘ䁼”ŕÇ׍Ni"žĆxa#‰É~…ąüőűk­YYYAk͍7hˇ;‹EŔ066ĆÂÂBĆw“&”R,--ąśśĆsÔjuŽšç=+Ľ ‹”’ľľľ IAß÷ŮÜÜdppĎó2pEkMľZĺüů󌏏Á-k)Č$ĽĚڐśËY÷‚7ŚGć:nÚí6`hľÚTŤU^~ů ćőęt:4[MšQ‘s]ĆĆÇq;űűžřńç0 ‰ÂřžşŤW{÷˜Ý”obRp3ýÜM&Üét‚ ´Ů)!!•DIIŠT¤Ë>t:mŢzë/^âÉ'ŸĚł‹˙éL‹z[c,lDŁ™´i•ˆ1˜^Đ÷{DîH ł]2~-" ڍ?Ćłž|:­1¤DZyŒČŹ-ɼ㕴[-.]źĚŘř Š4őz“Ë—Ż°˛źÂäÔ$arăĆ <ČŮłońĚ3Ď200ČľŤ×š>ýűçČç=VVV3ՄƒçRRiiž˝Řáĺk>íPăHÉr5bπd˙¨”™¨aăŰ͡>ƒ‰""ß§öúIšßümÂÓo`6ÖbyŐdAŠî>(‘t”uÚčZ…đÚU˘soœ{“ü_ţ îô^¤e#2Y权w­5ßţł?§Őnrß}G9}ęMfföáy׎]ăŔ qóć"7oŢäŔý ręÔ)ÇĄÝnsůŇ”Ľ˜Ý7Ż/ĎĺŢ{ ”âôŠ3źüňŤ<úč#ĚĎĎó˝ď=MF,/­°źźÂý÷ĺ­ˇÎaŒĄT*RŠTđ;÷˝………Œ€S I˝ŃŕŽSŻ×8wîŒsŕ"—[ĺŚ(Џté2WŽ\%—ó˜;p€ąńą 8{'ŕj§ď#X­Gœšésa%äŕ˜Ĺ‘I‡Ń˘ÄR%TFôœK}ۚ~€18ś…—K¸Š„Ŕ ąÜĘőşömCř‚xO7€ĐˆDU,﹕źN+[śIwˇżlVčTĽPŹ„‹Cĭ٤ÍÄÇśŒq¸Ó­šśmł˙ţäďŞŐ*ǎݏ1GŇěě,–eő´ůc8pŕ@"ÜŔ÷ƒ]×˙í^Ăčč(Zköîݛq›Ľ€IąXĚ*^ş u…LOO36Ë5ď”@1ĆĐnˇŠŐj!ÎνîJß÷3 Šť˝'ýlŰv2Μyƒ……ë”JeĘĺr RDšz˝ŤŽyێ[—G144ÄČđ0‘Ö4M–––Y\\ŚÝiĄťTś'TŘŽ1=;é5Ś÷ĐýZ†YUŃÖ÷ˇË‹JĽĂĂĂäźš\Űś˛Š˘”˜;atćŸú€FŁŽm;}0Śo}ë[ß>ŮNYXoőED Μ­ó[ż/X^•áîŮó´˝Ń´Z‚7 ŻöůĎ~ŞĹĂ–plŤç¸{ťěŽçĺxěąœ;wž_|‰ĺ夔ü›óÜ}ř666yůĽW8ó曌ŽŽđ‹/ąoß oźńAňéO?ÁÓO˙€ááaĆĆF9{ö,śíbҌ°ÖМ]ôŠ45–<˛ĎáÜrČĽ••JČř€…Ňr‘”çýĆŐNň‹: hVž~˙‘“ IDAT§lý$ †(ü6íú~ Ľ{@Z‘¨2ňœ]ď[ęĆvť1šÍ Ď?÷"íV‡Ó§OóŘă'8yň$łłłüöoýé ?*•*˙ň_ţ:Gᅬo~óřÚ×ţ:Żžr’ˇŢ:Çßţ…ż•ýúĹjÄkó:Ą&o)ž˜sxńšĎÉyŸ˝ĂJ~˜Űۡšě6&AťMĺOŃü7˙ }ő2DQdކ´˛sý*áÍÔŽ]%ü;üĚ,VYçNˇŃhpýú|˜'Nđďssa‘ŻýßłžąÁwŸú>?˙ó˙ß˙ŢÓä 9”RÔj5:í6/źđ"ŽëqĺęÂ0bbbœK/Ńj59uę­VÜŽő•Żü‡ßuG3×oˇÜLŃ^źŠűkuń$„´<¨DóeĽÁ°É¤|‰śŞÉě•EŹßţWąTŽR„Ół´ţť˙ďÓŠ'ŘšeŽĎ=ű—/_&—÷xőŐ×ř_ű9FFGnÉđn˙śW Ëo65ż˛Ák×;„ÚđÚuÉܘĎßx¸ŔžAĹGOBŚĆôĚ K:kcp‹źhÚôś“Čç"bĐB*E!ç2łw‚ƒű§Ůˇw’}łěcxpBÁĂum0PŠ5ŘÜŹłQŠÓh´ ŁŰV4›ÍkŸŤ7ŰŹnĄ&:¤•6v§sÎs=Œă&2ÁaÄűޞ°-—ŃŃi -—ćú&׍XŽ`` O!ďöŹ”ŒW*‰ŁěždŽÉÉdâ5¨Ł˜äumŁĘúFJSPkFQĚŠ# ŽR‰BSWĚX–˜ˆN§sÇ%­Óv$Çq8xđ ’ĘŚ-2řö\.n™*ň=źqďĹRu˘í׼”"ŸĎ'gx"îyŮäóůŹ}I)ľŁđCL^+śdŽc2îv67ťÉӛÍfĆ c[­fƒ›7X]]ĄVŤĐ¨×(—ŠTk5\×ÍȨcŕ&$Œ´‰ø F´ýdŽÄ­y#Ł# yJĽ<š|Ž'Aľý|ž¨éôRޜ”łŠ›&}-ćÚÉS((”(äóär9ňůśW;ĹŐ¤2Ť6ËxjŒ! ăVľ0Šb˛ů´ýŰÄÚ}0Śo}ë[ß>ůŽ^ĎEšvŰđÂ+~÷[.ŐZœô5ŕ¤_ă0E‡‚Őu‹Ż˙ž¤ŮŞđřكäsŠwŠĽ„DZłšYĄRŠd%ĐFŽ?ÎŤŻźFÇď†3{÷ňŮĎ~š yć™r÷ÝwÓnˇYZZ"|>ó™Oł°p“ŠŠ)f÷Írúô›ŮýZ2î“/ş‚GgsTÚ͐Š%cgÖ|ŒŇłFhżŇBXů¤ Aô´:ľ›Ťä:ßD˜fęrಀn˙;ZęŕäŚPʎۓžœˇ ŇĚZ„a„*qÂGî=ÂččÍf“7np×]w1<<ĚţýqŤŮŔŔ>ú0/\¤Ůlâ¸BH†‡‡łš(Xîw˜˛yîRŠŔ’1ŃÝÇěL˛^QDĐjRůÁ÷ŠýżżóW!Qšx§2€[Ŕ­ăƌW^ ůČż˙ČMNĄg×ßĺ8B –WVhˇ;<÷ěó áş.=v‚S§NsöěY,ËćąÇNđüó/pńâEîžű0<ň.\Œ3œQÄĽK—đ<ÁĄňů<–Ľ(•K,--łžžĆćć&—/_Ą!Ü- e˘‚帝,ŻXáĺĘŐŤ´ZMĆÇÇiśšěۡżö×~–ďďćäúőœ›ăšgŸcdt”ÉÉIΜ~“ńń Ö×יŸżÁŕ`#$›-MĂ7ěPL(ŤšşoŘlęţř1ŮCÚžŃqGŠ”GČxŤPJâşcĂĚíŸćĉű8ńđ§˜Ý;‰TŠ´KÉhƒďŹ­WY]ÝäÚőEŞŐ&AМŁT,P(:\şžÁšË+,­5‘˛L&`‹eRáX‰F ˆ°ˆŒƒŃš0蠍Ćqllžöń˘6^äJ‹H*VKcDŔfŕǀŽeŁ”¤œ$ԓll.ső­+L—˜ž! âľŐnŃéřllTYYÝäâĽ\žśÄĽ+‹´|(ŽR( ăx„tp,éƒ1>QŻM!Dú; WI€1p`şÉ”ś#*ď ‰÷÷FŁIĄĎxqŢ+ň^€˜î÷îôóÝ˙ď&­MůPŇם_‹˘řľ0Œ2š4铒źo)ؑľVšŽ‹ďű=RŐËKŤÜźy“z˝žN‡0ŒŰâżŃfss#ƒ @'71‡Rúu+%m^Z,ŰÉŞŠśsńĽÜ,ŰýߔŁ/–Óö CÇľĎąÁ¸Bˆ˜Ó-öŻôÖď3"ŽÂfŤĺ?}>AMŠÔwÚŚťćÇɄDňZŒé[ßúÖˇO°m•nŠě€:ŃçOž/¨7ä-§vŘŽéń=zÇnkuŕĎž+)—Zý™'Ř7;CľZezzšááaććöłźźĚää$Ĺb‘_üĹ_`ccƒ‰‰ ŞŐ:—.]b}}}űöń™Ď>AŁŃ`hhˆĹĹE”˛8p`?–ełgĎ$űo˙MŽ]ťĆŔŔăăălllP,Ÿ#—ËqđĐĂĂĂ:ÄĐP™œçâ:IŁŐbłRg}­Ććf-㝱-…Ł;ŹmÔxëŠC­ihˇuRý˘‰´ZŘJŕX2i_Ő&Diƒkň‘cB¤$ćőAMË@ËĘŁÝ!$#:ŮŔlŰM*]B‚¤ B(†Čy:a‹+‹mV+xó‘‘‘ ŐŽB´\„er˙D×üíĢ(ćÚą”…JřŚŇ=$•NÁ‡0 ü66IŰá6ÓĘÔ0 ŠTŞŸ8Rj!Ȟ_Úf“śËĽÖ)ŸJš đ<×uŠT*\šr…͍|ß§Z­R­ÖśüPâqs‡ąŃ"­QJ Dœ¨óý•J5!&ŤTٞŕHů^ş ƒ{™.?Ş—äW ĽŠ Ł#xž“€.%$RH ٍDŸÓ]ë4Šb˘m­uʘ¤'Şş}ŕ´'666X¸qƒVť3<đ@Œé[ßúÖˇ'‡ołđÂIÍüMI˘Z™¨˂‰qÉčˆd~!bqY#eL‰0:"™Qllj—4›š0ŒÝÁŇ*<ű’fvĆgtÄCě䧇öC=Řóýn5–´/ŕŕÁšž÷•JĽě˙‡Îţ×]wíxż#ĹgIŽLÚh 㼘,Đěâ||”ü̉:řŻ}‹üŠo˘Ä2ňÚ3pĺNí"͉‡ńŤZË›ç;¨…}TĺăäĆV)Í]Çđ–ˆš.Œ&§Ÿ§QݤŢÚGYĺš˝YyőNćş.űöíËždpp°ç=SSSLMMe_—ËĺěóäääŽăšš­sc6Sƒ›MÍ@Nłe –}ŒŔ˜@‡źzó4×NńHčs ŸRP(`Ýó)œGGLďƒb ¤Ć —°Z§k† .#t;^p˘+‹':ú~ĺ ŹŃű8=`O÷x:t¨çOOLL011‘}===Íôôtś<úč#„aČŢ˝ÓLNNfżoddä–{íÇt=Ś­gÝÖ˝> …BĎkÝď칏ˇ'żs&ý2 ⱙ8„řÉ˙Ęcpĺ$œţ.fă&GŕŽÇŕŘ@HĚËĎ"^z– PBœř<ř8üő_€ˇŢ€ďý)"đQÍĆŰgRJNœ8Áđđśm333ƒ1&!$wřéŸţŤ4[MĘĺ2{÷Nó׿öst:mœĂqlΟżŔŔ@9)—ƒˆŠŧşźxĹçÚzÄ=“÷ďuŘ;ÔwÁ?.űˆß‰ƒź\ŢĺÉĎ>̉‡>EŠ\¤\.b'°AŇîřŹ­­RŠÖŮŘŹŃh$$ŚZƒ0T+UVV–XY]ĽR­Ńń#P#„ÖFĒِđľBGHBTôÚĆ'‚RĐÄ6BZ*‡P˓DÚ&2iM¤##ŹDÍIę(†*´ÁH‘e˙E×z°/W@됖ߦąWäXvĚK#ݸm9 C”"#ů•I•BZýjb¤“€"ݒÍŰŐ}âu§î¸šŇ;Š<~<ŃsoZGW§|*ÝŐi˘%mSZ]]Ĺ÷}0ąĚsĄQŻ7ŃF٤DH…´mňůŢśą(Šh4Ôë üvă’ů(Ý\Cݝ鸧DÂٚ’ôTót˙xx˜ĄĄ!rš\—ď'bŸÁ¤S9%ݍÁ–ë¤@Q6/ˇž_7'ÖšVŤEŁŃŕěŮłDaóÄĐQH­Vëƒ1}ë[ßúöăbA šx9ŕÜCœ@Kzˆ•ŕž#ŸyĚĄX¸´Ú†v'U‹ׁ|NŕĐh^xĹ祓ivJ†půšäÍs!'Ňärň#qĎBF‹Şpů űtgHG!ĽkäŸ˙M”_×"żú"łPőçż~ÚŤŁ„›*x)ž ršźĹÜ˙„áý×QžF(eZÄE•°6ˆ˛ a—?°x—ťĹł“eÉǃÉLC­Uç7ţ‚ęœÍÔ%šĽfď ˙ĘĎâ~ů+\b‚ď^ˆ¸|^c[‚ă3GxňSŸaL}ŽţoXŐ˙ÚO MJ$Ť­ËtVżEX>„“sz‚¸÷:vŁŁ#|öłŸšĹü°ćűą&Ól޸örý:Âr_ţ˜ž”…Ů{/o>yę7ŕúY8|¤‹řżƒxíĚż Ÿ˙+0˝ňELŽ€ř˙ž ľą g^%úܗPšů#lŰćȑ#>|wdvĺ‰ÇAë­l>’`zŠýű°oßžě5™”ayśŕ‘ýGŚšČť‚‚#qŹ>QîÇŒéř!‘Ö8ŽĂŢé‰D–X!ŐjőÍ*KK돎Uiˇ;XJ’Ďš¸śd˝śÉŋ—šxé2›haŰŽcă8ga Úf„Čx Á6HĽCĘAi4R@Ĺ.Z.ŐÂĆ#2€Ř,G˘Cƒ2V,Š4ív­5–mĄ„B%\p–WđőHGAŹäćKIP+0脧$ć/ą,7Ťjˆe–Ľ’9ű%1ZK"ÇĆkEĆź1‰”t*÷mŮ=Ąwh˙ŸTy°$!Ő7ÁÉák‘ Ďˑó<"ŤÍĽ*)8†!ëëX–˘÷(—cŐ¤´š&ÚzŤ—ŇýOИ ˇŐjBÂcł]B;]3ˇ´iůzFo]×Ögm;”ËelŰώŁÖi˘D› lŮ„dŕˇŰ¸÷´.š\ŽË—/Ój5ˆ•ĽÄu˝l(ű`LßúÖˇž}ˆN^úšŐŽ8)duĂJZb˘ÔŃÁĂÇmöLnĄűžˇó!ăyP* Žľšš¤™żĽ#TŞ’ó—B>uOˆçЎ ¸śŤ&lĆލsóNéö—vjńř Á‡Ű/Đ~^řŹő5„€…’>alIIžf<řu6ë—¨5ˆŠ„Ú5ËŹvZ†{˙ę34{”eČËFEíú'vť>Ă÷:&ďôó˝ă˙ŁÍííżw§y÷>Ž0έ]âtí*шĹsw—Ůťćă¤Á´—ĂţĚO ćçůúY‡ßz9`šŽ Âx*|űŹć÷^“üŁ/ŢĹw˙Ÿč3 §ý:čvŇܔ>Ł6Şń2aóś7°Ł2SęŢîÜŢÉÁý°÷Šěďů>&Œ€FöÄ*5J! #˜\Ff`˙qğýKLaÚÄŔúżůŸ‘G†Ą¸Ş~3: B"˘üXUźMđÖˆědÝ/ugó•?EďŽ"p-kIF ĺéÎĘ ’Îi?đéř|ß§Ůjłź¸ÁÚz…j˝AFxŽ…ëڔ ŤK7šzíkkk4›MڝtΉD˘ŘÂó–÷nŠ šÍfv0şŽűށbYćáv‚Jß÷‰˘hG Ç;aŠ![.ĘRčz•`s,Y,ÇŐPI[ÚČČwß}7/žř"őz3‘~V´Ú Çśńź¸jKI…ňâ3*‚Ě/ô<!Őj˲{™nŕ$­Žą“סˆ†%‘(sEŤ~ b)+S€J×O÷ř`Öo\,yꊧ˜ššB)ĹáÇc‰ÁB!+AmľZY˙íŘŘ ĚĎĎóŔP­V)‹Y–$ÍŔu›çΝăʕ+?~œŃŃQ´Öllld@A§ÓĄŮl2<<Œă8T*:ĺr9ťŽfłÉÚÚĺr™\.G§ÓÁu]jľWŻ^% CŽ=şŁĚĺíWR‚ťpoŁ„Œw4ŔŒ*Č9 „qÝÄȁSäöţ_źţüݰpöӈ@Ń:ýiđŠŻüĘőM Ó1ÄÜBEDÍŤ˜áGwĺ/ŽŐj|÷ťO“<řŕqZk ‚€Z­FąXäÜšs„aČC=Ô¸|ó›ßdjjŠVŤĹáÇɜ jľĘÜÜš\LŘW.—X__Ď2l§NâŢ{ďe``€őőuőc ‹‹‹üţď˙>|őŤ_͸jž˙ý§iľZ1ĄěÁƒLMMfDłĺrůŽs„aČůÚUBa"Ăü Ăs‡ĘLmŒ’ü’y†řćŤ6šf7܍ůuÍŻ>đüľĂ¨ÁĎĂň7Ý%=.á&ş˝@¤5Bޞ! ÐłgĎňěłĎ266–ń€ŕĐĄC †!ŤŤŤ P.— ‚€o}ë9qâů|Ž‘‘ęő:ľZ‰‰ *• Zk …BbÔëuhľZX–•Źšš\ŽÍÍ ˘(b`` [G###cxýő×ń}ŸĂ‡344DľZĽ\.ăű>ŤŤkÔj5^}ő$Ÿţô§9{öM|đ.˘; ȈÉC˜Á ¨.ŔüÄoücĚĎýpđѝ[Œ# IDATX]­]…ďü+xč§I+„™Ú‡üˇ˙=ćĄ'ŕ¨7ŽÁ˙óĎOý)„!fhć#mçmďz˝Îňň2J)†††Ţvnvƒ¤ÍfÜ’Ďç{Ţ˙Ł}ťýlETŤU”R”Ëe*•JśOŠ>Đt‡÷‘ˆľľu~řĚËĚÎîax°„$bu}…ŤWŽsńŇejŐŘVRĄ,•ÍŽë&Ŕ‹G>—ĂKţďy.žëຎëap脒ľŞO3°°Ć|+AÜänľI”% u„6ŽăŃhŁ "K ”!a!,—ČZÍ&Ž\§ëş8śŠ9_Œ!ŒtҒçâ&mu–eé(Œ_„Čp×kT7 4UĆÇ™˜fxpÉąQîÚ?ĘŁ‹Užőç§9ýÖ"Ae@śLř<Â0¤ăˇšS=Jie…1Ďó20 ]Oq›Y\ńŃpwKFÇď'ŤvÝUKËÚj'ÂqA)Ź‘ ˘NÓ¨Ő6ˆ‚€Đv1BŃ #öLNphnŽ×O˝Ał' ,Ë¡š­6–Š ĚÇÂśŽëáy^ň˝¸'>ę´>Tą:VĚ;#łj˜Tn;őű¤”()ёĆ÷; ĺň–mc’¤ďűٸmß˙L2GˇÇ ´€IŸU7ˇMJpŒŃ ĺŒ Šâ5ĐcúÖˇžő퓿ěĆřM˝Ą0:AúeLĚ;9.ł˛řFĂpăfDĄ ™šˆżE°ź˘ŮŹjŚ'Ľ’@I‘Œ)VV5&‘űk4%­śÎší–ËĺřÜç>GŤŮâřÇq‡Ë—ŻpăĆ Ž=ŠďAHłŮâäŤ'9xč`FjŒa~ţWŻ^ĄT*qéŇe&''đý€+WŽRŠl˛źźÂ#<Â͛7DëˆC‡e×Ňnˇ™ŸżA„?~œvťĹŇŇRJ<ĎŁZ­%$™šűîť8sć žď311Áý÷ߏ֚3gޤZ­ŕ8SS{X\\äŢ{ďĺäÉרT*Ď=÷Üó#hbyŃĐH°Äچ|€qÚś sy6ZűŠwŚhtö˛č î¸H!:W^ż—ńĂĎSzd)L;mú×[Ąäč°w,ˇMÉîFFF˜ĄŮlňć›ob Ap_šrß÷9věśmoő Ĺc=Ć믿ÁÚÚ:§NfϞ=LNN°žžA]`zzš×_ű￟łgĎf ÂŮło111ÁkŻ˝^Žcǎá86aąşşĆŘŘxZBťÝfppááa<ĎăÚľëŹŹŹ°žžÎWžňSwŒIU&–ý„ĐĆĐQš÷ç8zÝchQc?t‚K›pf!"Đ]™gśQř!üŕbÄrłĚtá8RüNÜ2Đ%{-tĄ73nÁnłm›ŁG˛źźĚĄC‡ç‡?ü!•J•ĺĺež|ňóźöÚh‘Ďçš÷Ţ{q› špážç1<źĆââZGÔë b^7¤¤”źţúëüĺżü“œ>}ŠĄĄa666Ł\.óÖ[gQĘbrr’ůůy …BŚÄUŻ×“Œ~cǎń /đĽ/}‘k׎QŠTÉĺrALfxúôćććŢW0ĆŰG4ş3˙:"hÁé§nóľ “‡ Ý€vsăâďC(áÜiŒaeß ×ŕßţsğ š5ŒčąIĚÁ{IeÜnëęüůó\šr%Q„s2iďîě.+++ĚÍ@)Ĺüü<žp×][{ZŁŃd}}ńńq<ĎëiWËĘéՏn~šÔnÜXŔq&''n!ÓüáŸexx˜Ç;ÁŤŻžĘącDz1˝gSߜ椲,šÍWŻ\ç\§ÍęĘ"őFŔ÷ŃƐ/°“*×ułŔ5Ÿ/šœC.cJĹ"ĹŇM_píF…ů 5Ş ŸVG†0Ôas~°Ő $\.éGw@ž0™ŃńۉňŒÂQÚD´[>‘6 E Çş9śíb[NB˛Ťńý:*Š’YťÁ˜€F3JŔ&‰i0˝…äě:9w“ůů%JĽcكĚÎěa˙ţ=Œ ąwj€GOsîÂMęő62 ÚĽHĽ°l‹|FŘŞAčřďżGk6›üáţ!arđŕÁŹĘSA ęő:őz=KůžO˝^π c řžă88ŽĂĄC‡Čĺr™š™&Âv›,Ë"*”Ń^Zľ‚ëظś:zs™ƒ#EVF†šąźFFD‘Ć÷cŔÉś-ÂČ Ú ™´Řś…ăŘ‹EŠĹ"ÓÓ{céóV‹Z­ÎĘĘ*zƒJ­'%P/‚ đRJŀĽJÁŸÁĄň…"B|ßÇ÷ý TN÷Ęԇx; ş÷őÚ“ČdşťÁ˜ŘWH˛^ĆdR×ƀeő+cúÖˇžőí“ ÇěŔŐiAvóŔěŒDČ­Ş˜ç^ňyăLČŔ ä'˙’ËžIÉęšćťOwX\ÖÜ5gńWžä ”ˆ%U§%oa|°„‘$Œn#“@|ř­­­łźźÂĺËWFkƒ1‚—_~•={ŚxđĄ{úskľ–ĺpĎ=Gřć7ŸRЄֆĺĺeŞŐ/źđ"÷ß? ‹T+U&§&{PŰv˜™™Áu=nŢ\¤Ůl°şú˙ł÷Ţ?–^çççœ7ݜ*çÔ9°ŮÍL*™¤%‘”fdaÉc 0Ř1v˙€Áţ<ż,fƒĹ,Ö Œ!Œ­Ăز=Ś"EIT3´Ř cĺtŤn~ăŮŢPˇB7›b“j[őîşU÷Ö˝ď9ď9Ďó=ßçű]ĽŮ ÝK*• ŕŰţäó9LÓ˘X,Ńnwđź$şví:Ď=÷,Żžú”ŹŽŽpŕŔŞŐ Ęĺ2š\–T*őъlÚШ LÚämŞkc>ÍrŽW/|™›Ő§°Ő _F5ËĄřôŃ´›Şł=x4R` ČřЖ ˇQĘż§d ĚÍÍăűkkkôôô°¸¸„‚ńńqšÍ&ŠTz[vłŮćťßýš\ž™™in\żÉĄC™››§Ó邹šyJĽ"kkkĚÍ-`Űz{űF×M~đƒrćĚ Ă`ff†B!Ďĺ˗cee•k׎sřđ!2™ Ÿţô§¸}{–……EŞŐ*J)VVVyă7xńĹL lßAů>JřŔjVňĂCym6čëfá=‰ŻöśPW]_{žĆ\Íd$;€ąɖŤ>ByI+Ŕ6ę˙Ĺ]č†5Ćľk7h4šüĂß˙N=üPd5>Fš\ŽĆnßwšző*€ƒ‡đć›oqćĚ:6‹‹K,//á8/^Â÷ÚíKKË\źx‘ĽĽ%ňůşŽS­V9qâ8ŠT*J|M&&&q]—ëׯsűv*lll˛śśN.—KX8ccŁ |Źú?F&Gsě!Ôť˙v\ŢqöŻŕůĽĄ˜ůÉ_Áţ÷¨–€áŁđďţ=œ~¤„łŻ ţú[PŤ†ŽWş7<Ő?„¸ Ë%^dž††9~üžŻxĺ•S­V9xđ ů|ž×_ŢŢ^lŰćÝwßĺßř˝ČŽ<Ô`řŢ÷žŸ„ƒƒƒüä'?ĺů矣VŤQŻ×1M“ńńńˆ]vœwŢy—\6NŸ>ÍŋŠVŤĚĚLóĂžBĽ\á_~ýkIkhÜZvůň:ČĆĆ K=ęÜ}Ÿ}@fgx>l4$B‹EŠ<ĚTŹ0|M L#ăMY1đ’ÂJĹ@L†T*C€Żt6}ć/­°žŃĄVoÓluÂÂV˘â7ˇď-]םnáÔ¤ MĽ\!𤆡¤Ź Čđś°,|Ö"Ÿł(—r^ŔÂrŐjƒfŤƒăy8śî+‘F‡&5„ $e˜_„­ >ŐŚF]Ó0›–`n6X\m1ˇTăĆÜ #ĂC ,Ţ|gŰ Âœ&Z?㖓¸ŕGě]Lčâ6ĆJĽ)č86š\~ŕ™N§Ń4 ×u"ÜCă˘?•J%NDšŚą°°@&“yŕĚG%ś‹+Ľkë HesQŢŁ0u•ÉQn68(ö{lÖ긞‡ˆ€ˆ°5Őíj?¸^čŚi2y\× ƒ|>GŽëbŰ6őz#ÔKęŘÉőu]Ďuń„Î)†ŠÓŰ׏Ži ť:fĎěu­ť[Ďśî IŹw HouôŠ. &Ô*Úfą­T”×*” ś41hłĆěÇ~ěÇ~üú@4o4áŚ28 “œ$`n!dŔ8ŹW†%›ľ€•ľ€Íşâ揿­eŠŻ7dĎx~˜ű„Â{wń °”’ĽĽ%JĹ"ét:qń<—#Gް¸¸@ľZŲ,´h#UJąşşJ­VĂśm Ă Óiă8.CCCId™&ËËŤœ8y"aihš†i˜ňŹ”…çzźűî{<öŘŁ\šrmx3™,2ŇÝ{óŰ躝bh˜ŚÁĘĘ JärYΟ?ĎÚÚ›››ô÷÷ߗqR<[GŮ&"0 ÝĘ7PxíĘźzĺ Ƥň膅…‡%|,<ŒŔĎĽ]ő%AÖ5”ô!p ‹  ďÔĽ‰Î嘘gxxˆ—_ţ.ƒÉľĎfsLMe8wîO=ő$8Ž8ɈmdqňäIzz*XVŠ|>O:śXdłYLÓâŇĽ‹<ôĐ ŢxăMX]]Ĺ0t|ßĂ4 ňů<ăăcŘśM*•BJÉüü?|Š7ß|“ˇŢ:ÇńăÇřîwżÇŠS§Bpűö,ĺr‰žžŢD“dvv6iujˇŰôôôűz;9Tôßůa‹×'aŇw0ľą+Ržě,Lc›ŻK÷A9($ŕwľ))ZôřAł-—é•Ϣ6=IĽ§‡ŃŃŃ0qNĽĐ´đgWV–I§ÓH)1-‹L&KĽRaii Ë {űĽ”ř~ŔO<ÁwžówüÎďüľZŠŠIŢ}÷]fff°m›‘‘˛ŮlÔ:‘IZBm§6­V‹ŠŠILÓLXKšŚ#蚎ëzčşAŤŐ˘Őj‘ĎçX\\d||œĹĹEŚŚŚ>ňÝ%a˜ŁŹ 4×#Ĺl t#d˘~ rýĐňÁvá…?@̜„t*¤ęJ „R!+&›Ă?pŒ´iîŇóé“âDüÍ7ߢZÝŕřńc‹%VWWyĺ•óŘcą˛˛Ę ŸÁm'ĺJÜž=Ë3Ď<Í­[ˇY\\btt„z˝ÎůóďÍf˜Ÿ_ˆ„\ ĘĺŐj•Ó§OńÚk?çâŋźőÖ9ňům[!: 50uÁj˝ÍÜĘo_ÜŔötęMßWX†…ř(?;€ľ%âű|-ËâË_ţň.ő¸Čď›Á­'NěpҒvęršœ´Ű<ˆƒq>ĺű>N‡\.aböL 5ôLŽL*ĂpŽČi‘âő×ßH4äś@ž­VŽđłG-FšŒr]'Í5T*íQ=ą%â­f‹ŽÝÁóB "ĽZbĆşjńď ßFˇč}Ź?N¤;´Ě$Âë"b¸~ ?ŘĄ‡”ńűŰ ŇÄkí>łűąűńkRH#€ŔB JEšĽJ!`r\cnÁ§XŒ …Éů@ŸFOYRoř> Łi[‚u…œ@Č­ç뺟čĎÜ)4MăĐÁƒ ENž<ɛožÉŠS1::ŠmŰ,..rňäqž|â1.]žÄšsç8qâĂĂĂ!`’ÉđÚĎ~ĆמöŐ$‘ń<ĹĹ%žôĽ—(äó”+%t]g` Ÿ?ů“?áw÷wI§ÓôöőÎ¤˘Ŕ€ÁĄAΟ?ĎńăÇą,‹bąˆe™<ţŘ#ĚĚLSŤŐ¸qăăcĄlĄPäÉ'žäěëg9věSS“8ŽĂľk×xâ‰Çčçňĺ+´Űí;ŠÓŢ+ ăÇ$đt¤çC`"°˘QmZŹ5<ěl ĽűčZÓ×Éx×őąé´ŃŠ˘5Â3PM=-T[ ÚJä¸Űé`*•bjj’ršŒŽë<óĚ3|ď{ßc żrĽ‚Śi\şt‰/~ńó”ËÖ××yůĺď144ș3§Ń4G=ĂääDb#yôč,+l‰¨TĘQ+KJĽ‡çž{–żňcFGG¤cŰ´Űmţđ˙€łgĎrôčŠĹЊűk_ű*ßýîˌŽŽ2::J§ccš&żńŸăŐW_%Ÿ/đŇK/°°°Č͛7yá…/&˘żq˛Űl6)>šľˇ’Œ2ˇő–+ a ž}şŔ‹ 7˜ě9…a€ăŠ”Ůč HYŠ™š> R YôĘ‹ž˛°’Äp/0ćŔ”Ëĺ„ýbš&şnP,–řĂ?ř}^ýÉŤ‘†L… đ9yňx˘ýó™Ď|†Ő•UJĽĎ?˙,?ýéĎp]—Ç ŰścbbœZ­ĆčČ0s.\˜çsŸű,##ٜ;wŽfłÉää$Ůl–t:d‡éşÎôô￁ĄĄA†řşEM¤Řě(„#CAT)ĐDŠrĆĂ25Ňé<=˝yňůľ–Κ÷¸97Oťă&Ŕş”:BH4ŠĄ˘Cą­înӈ—ŁřÔ>t¤!˙6@ăؘ†‰aşŽeé ôć9yl„“‡†č)§IĽ LCC×d ĂćŚÇúÚ&“#=ĚLVřÍĎáÇgońÓׯ˛žŃˆŠf°<űěo$'JÓÓSHM"…äŃGĺGŻüˆŃ‘Q„äó9rŮ,SSSf˜ŕ”K%‚ˆ’,ĽFŁ^§Z]硓á8.GĂ0ÍP˙¤ˇ—JĽ’$J)ĆĆF“k'B[oo/Ǐż/kĄ"<ˇršƒ'0—Ž˘ąšŒ¸ţxŹ jůüčۈ7˙š ę6|ýßŔđ8iÁĽw‹óŕűa‹RßúĚáíżkÍMÓ(‹dłY Cgp°ŸŮŮŰ\˝z•ááa666xď˝wčëëáŔi^}őU666$›Í`Y&}d2Ą&Ś…˘âš\Žz˝ÁkŻýË29rä0žďĄë}}Ňé˝˝&&&¸ző*?řÁ÷9qâNsöěYJĽ†a099‰RŠŃŃQžúŐŻ˛žžÎüü<Žk“JYźúęŤ<ńÄwiĹü€ĹmßÚzĎ9ˆpĎCJü Ŕs<¤ÔФ`ĽŽQm nŻ7)ÚvVÇŁÝqńźĽ4 tĹb‹}'„¤ťŐą›­aŰv˛Ç !$–1Őt‰ięä2•RšR1MOž‘Ą2ٔN6­ňŃd‹ůů†GɤňśáůĎĆffËŚŮ^ÄątĂŕá#eŽxœ‹WWšpe‘šĹ M!dhwí(4ś-I)Ń5 =• ?ƒá5ŇHXžë#E@ ‚¤ő))xťÖG]×ɤł]lĂűqŔłšóúWË<‹™ąţ‰‚Í͍d=‹EźcśqźĆĹ L7ÓÍ|ĄV;ĚĹ —pœ°ÝQÝ!3Š!5?Ç!œBn9Žç­”‚ Px~7ťE$SżcŰt:N¤Ó#ńîű„śíGÝö֚Žc˜)+…ŚëŃőą 7e|ßßƀš†čs‡šŸÓpŒŮý؏ýxŔ˜\F2<¨X­‚ď‡gHÍVŘăŇ=ĄŮRä˛+:öŁďY)A6€FSĄĄ€o@ť­w&)Ąż' X¸űéN\„ŰĄBjw>5’šĆsĎ?Ÿ|}xa\šř(UĘźřŇKÉ×O=őÔś _ŢŁo_űÚW’$dë3iŰŔ–ťzýRcĽ‹éŠAęéqňë‹HÝ'ôČ `lĽÎ_ĺď>ÍZÝ'ĐŰ8čŕ ´äƒMŽ˝Á€XAlHČ: T]Ř7‹,ŽÇ<ÜťŽSœ*hşĆnÁCš-•:třĐÖó5šű“iťSáäk-1{Úö=…ÚEݖRbYť…ď>iЎŚi-Móýĺłʋ@ÁˆĘĎ?Źüœ“gřú#łŢTœťíăx*aH9Kđ›Gu~űŒŽ˝ú˛óáľá q˜şé`ô#RcwtŰHŔÄčdOíHě3 TŃiyě̲sţÝmnî,şÓďZéŰĆćă´Ňž—ľP‰ŽřŸD˝űw× E{_ůÓ°ÂĘÂ埂–E}ő߂#á­7ŕ?ý˜: Ľ^Äwţ V—˘•tŽ&—ËoÓLÚ ěÓ4Ó§O'_ňĽ/˝´ígwÝGăăăÉż= Ŕɓ'8věčśç=ôĐÉm_ONNđÜsĎđšĎ}`Wť×ŕŕ ׎]K,ČłŮ,ßřĆ7"0>ËŘŘO<ńžďłśśśÇš¸˝ léRȨČsńŁÂ°ă(ZÉĘF#)Ă?ąthEQ+ąÖ}űŰŔÁx­ ‚Ę)ÓŔ˛L2)“bޢż7OO)CoŽJ)MĽœĹî4¨TĘlŹWi67 ­Ł ¤Ôk 6ÖŤäsyÖŤ,-Ż˘ëA” †‰SŤ(t*Íă§9z°Ÿ W–xóüm–Wktlç…íEń>Z*GşˆKő°ŕ–şŽÂVß÷đşÚƒâ{OÓ4D䎲îcŤë¤Rf˛V󁬛íßŮ[ ńɁ1ńŻbëëřýx^@ŤŐÚ҃érŠ™Č1č çvë˜ułeÇIÜ2ě1\Çĺúő‘fÜ˝źĎpf _l¸Ľ”]@˘Ř}PK­HۆHŤĎ­-4FtíĄ[Ěą t#şĄnƒmŰ8Ž˝ ŒŮ‹Łś(…ż2¸mŒŮý؏ýx"ŸÓ˜™Ô¸xŐ§ŮŇq]ĹOĎş¸>Œjčş V‡w/8™ŒŔĐžŻhˇś'Žęň ׅŮyŸ7Ďš8NX\šFŔ䘤TŇ>0IPř*ŔW7ISt%şÔЅ|ŔG*Ljҕ˟:DăOŽĎťh@x Ýőůtę ٌĎ­CÜô†iŤĺ2nŹrşt…“Ĺ díĘş‚M% üvŽÍŢI˛ĺĄč$u/§€­Ü! P O¨;Ś÷ˇ(“4)ф@> 'éĄ(¤äôŕ1 WłŹzöśŐWUťĆˇŢ˙+ţčDš˙ůكźzYç͛K5…!a˛WňäŒÁgy\_ů>'Ť˙Š:QVź5o&ž9–™ú€™Ž ]Iî6Z÷sŽJšĄçou2R">ŽoŚ‘n;'­ÎÁwţO8ň4âŮ?‚ƒO˘2e„őÜ×áý_Ŕßüň[˙7tÚQY¨@“¨ÓO"#Ü;ÝO;‹Œ?ˇ—đú‡+°~9€DÓ4FFF>$“RňŠmĎń IDATO}jßŢúc*Ž}?@ TМȄ…›Ý,ÎpQ1ď†BŔ !"-Ž-]hşÄ2MŠůăĂ9NŸbzźŸţž,íVNŤĂÂÂ"ÍFĺĹ6R‚mw˜%“ŁZÝŕĆÍYtCçý÷/ŃŰŰĂňJË2`n~žVłĂŔ@?N‡l6‹ď4›-fçćâŮgđŮ'rö7ůŢŤXŤś|•hr„axč!#„Iƅśďăů~biłe|ßO˜¤E+T[˝OcĽ"‹ůttMď˙úôńĎ7uÇßkĄC‘ă8‘ČłÚnm…Fƒ ]–i6›t:ňů|ć!xâ‰'ń<ŸŤWŻ&n^÷´6Ćďą p ­ö"۝bÇ"Áv6XéťěÚ ˘ľmw{iř9]×Bŕ-0ĆĆó\<ĎíjďŰ:ŒŮĽŻĽöޏ?ŠutŒŮý؏ýřŠ”ÎÁiĄóWojř>\źęąQSŒJÎčŘśâ÷˝ŁƒŽ ü\LFGŻ¸rÍçú-ŸĽ•ßOŽzĘ>GI2ăŽi\¤nzmĎĹ üŽäP$}ť[Śż{œ;ż§śýkłýč%uŠ‘Ő RŇ@"ďC¸ŚúŔßďßFʢđ…‡Xůˡ6jhŕ{H_qOčט˛VX1JŘBǔ=Ú&}f•tЁv¨ŞŹ ŻŁmTPŸĆĘW'­;Y:z* éŰ´}'DT„ n4V÷Ň}ż—@°şŰXE?/…$­dőP+GüŠî›*NÇ{FxŞňłđ#Ŕ{ĆŁď۞Åęţßóßâ ӟĺ+<Ƨ§¨ľš€ž|€ŚÍńňp¤őˇdS‹áçzřZ $žVÄÉ>C1Ó{‡b_á+EËwhxü@DsMjw‰Ý×]ÝÓv‡cJœfĄIq_[î÷xn%ú’Ôŕ$­žƒ[?GÜŹÝB)ȖÁH‡vĽRC+ČĽh5Áő ””¸ŮÚÉGš~Os'jľKKK8p i'q]šš9Š…Dí^A°´´D1:żÓë/..’ËĺÉf3Z{BJyOBÖBˆ(Rž/ţ{Ç9Ą|´ˆľ%„žąşn{ť…˘*jľˆĆSh ¨cDĚ´lƤż7Ď`_žJ–ţŢ…œ…!Ň)ßsČZ.şŚX[[…ŔÓý…~ڝ)Ëbyeĺ•U„ä YršLMOŕű=• śmS,ěŁVŤłşşŽi8ŽÍäȝN›LÖ˘XĚ#„OĄá3ONshŞ—|寽qŃa‘D…°łÍ źÝÎhčbŢŞ ¸B uŸŚŕŤDt1KÔďť Pwl>iP3ş.1›%“É$L—6ÎÝî}1ó%ÖPńźp-ět:4dL …BâĐ??ŸĎńđçđ}ŸŮŮYÜŽ÷p7Ŕh×ú˝cçŠßŽżĎ=ö6şX‹;GdGÎ[a‡“Gi)ŮśC,&íűžďmî_v1;5rş÷đbą¸ĆěÇ~ěÇ~üş2ş.™ˇ8zČavÁĹśM|Oą°äł˛pţ˝P ąÝQŃ)ب„ŞéŠżýMS8x^,vŚ0 ŸCÓ.‡0tyÇ#P5ˇCĂë0_[ĺőŮ÷)Y9=BÚ´şœ~šSáť=W)p;đ(‚Œ4HÎEüţ5]Łgj„Őß’Í˙XGT}˛ů6š)Ŕ“-ŔІ´ƒZ=/ J!ÝĄ4”+˛$Ž›ĂmW¨Ÿ>„yřz*u×ë hř5§Íz§ĆĎnžƒŻ>5ńĹt.ěÝ'jyšĂ•Tb‹™´˝$‹Şť€„­?9=…śe˙ńŔ„’Ź™ć_úÁőëýĚÎÎą^­Ňétvw[GďvDpŻkß6Ŕ¤+Q ¤DuÝgĄuv؊ĎÉđÚxQj[KŇ^ŸG×tĘĺ§NÚcöc?öc?~}Čd,žz´ĹŰ—Žš8NxÂáŕ¸;6)B‰¤ŘVž Ó ś9B†TgĹčĂgž’d2fdGšwţŇń=ęžÍŐľ9ţňr¸oœ…Ć/_=ËhĄŸ‡†płşFK}J¨Ć1ítžśJĆĚPJenĹĽŐŰôfKœ›żŔçŚ iË2t”đĎ÷xkáOŽmßĹúݲ$¤@ˇL&žô8W/-Ŕű^P#›m˘›RóŔ ZZ€AHQ’*´Ţ%ü;;ƒăőјÂ}üiz‡†‘w9ĹBŕůmßćÖć"˙őÜw9Ü?ŽĽüĂĺŸ3˜Ťđš™3\^˝‚Ą|OX ˆFîGýäśç˛ÜŹ2œďIlQ›N‹K+sT2yrfŠrŚ€Š* nˇXiTé˕)§ Ôź)Í@ }ËJúŞ35Mcr`œŻŽ?Ëšőn3¤$'ɘ ßełSçfm.iç S9|ib‚ć;'Eĺ I 4JŔ@ž!÷n#q†gÓôţ÷}‹ńr?=š"go˝ËÍl™Gǎ#…âěí÷9=rRG‹ĆH)EËíŕ+Ÿb*őé+j&Ővśk3U!ŸĘŕů^Ԗ$ą}‡×g/đŠÉSÝWR#Ľ™,hş0L䣿EűÇ˙ŠĆŇsślŽ×n¡˙Üž ˘€řoŠş=‹rě­é'^ވó•o˘§Rp‡{ig TŔ͛7™˜˜äúő븎ËßţíwĐ4IłŃdhxˆsç~Áëoœĺ駟ĄŮlRŤŐšví:WŽ\Ľ§§‡Ď}îłüŐ_ý%BÖwzź'đéxçć/slpŠÇǎqiĺwńg<öä1źŔçęÚ,›WŤsÔ;MĆJ”Źď,]cşw”ďź÷*e+ϋǞć —é˖¸şśŔ‰Ái^ž|–“3œ_¸‚Ž˜ä˝ĺ›4í&ď,^ĺĚČat]Çö=-ˆŘż’Ѹ§ńŇLě`…Á?x–Ľ ÷‡W°× 2ů–ĺbHŠű ¤ &×1°7s8v™ö‘ę/|ŠŃÓ'0-sĎÓÄîDËÜŔçőŰ868ÉéáĂ؞ß˝ý]&J(W×f‘Bňł[ďPNĺŠd dŒWŞsŒćű¨wšüčę9^<ö +­*)ÍdŹÜÇŮŮ÷˜é&k¤đý€M§ÉS'˜Ż­raů&nŕóôÄ ŠŠ\ŘŚ mńiPj;ŕ^“ąű}OI)I›/ű Ž7fůţŇYŐmßšEQ(lßI’˛´ řb‡ă‡´ O…Œ?‰Ťň,[żOďŘgRŰóţRJá>Nŕqöö;Œ—úřÔäĂ^ž|6ťD€íšüđę[¸ĎrcĄB‡{ÇyůňYz3Ešn›ëŐžxäI.-ßĆ \†s˝,5Şl´käSYŢ[źĆz{“ÉňšÔ¸¸z‹ŸÜx›§ĆO K/pƒ€”ä7ÍB uƒüč kżńo)˙đ?‘޸‚p~ů>Ź/ÁŸýPWĐaw9ŞJ‰›/˛ňĺoPúĚłMżçö ¸č€°daa§Ÿ~ŠÁÁAţüĎ˙!gΜćđáĂ|ç;G:beeÇqříßţ:ńÉĺËWHĽRź9œ]žüןňĘ+üń˙ťVŘܕßߌwWˆž‡çš ĎŁn­ŽpŢĘČéH’ĎYLö1>\ft°DOOš”Ľ“ś –——Ń‚oż}žŢ|ß§ˇŻB!—gldˆÁ>fçŽ^˝EĽRbnnžršBĘĘ`ŰÇqČfÁq]Jĺ"NĎ÷™žždu­Š•˛Đ5jľJ.—˘XĘóČŁa™:ş>‚ĘJŃé8¸ŽOłŮaiĽĆÍš*ł ŹŽ7ŮŹľiŰŽ#đ}‰aÂC ÷ZŢľö[–•XW{ž›XuKęă1Š4Ë |ĆÇý›ƒšŚ100@>ŸÇ˛,<Ďcxx˜N§C&ś DăŚ%‡Uív›ľľőÄ)-ŮËÜâćáXt°,‹N§“ˆvC(jŽëFrb›gß’Ö¤ŹhˇŰI{SąXLڑâü!ֈĐĺ0fĺřžmŰ!Śëř~@oo…Ď˙ćó8ŽĂĘĘ*++ŤÜźu‹z˝žĺźt‡}~'óDt+ Śűubéˇjî˛čî҅š“&•˛˜žšâŘąc ôaYĆ'˛Äěƒ1űąűążbŚ{3Ň4ÉĄ˝|ýKËüĂ÷ë\ž‘Ćqô¤)IV" &ëqâř Ú]ړbŇľŠN\ße˝eó×ď˝BĂnq¤‚÷—nđÔÄ Š†Ý˘nˇxzňţ‹—yţŕăÔí6ëÍMú˛eŽ Lsľ:˛(šUjŠ)”ÜŽ­đóš Œäűhšf7—ů⑧xíöťáŠ„%üJNî9qÍރ#ü<ŐÁöËqćÖ0¤ixh†‹.ýˆQ¨@#$žmâşiělö“#ˆőٟ=I&—ŮFíޙ4ěš3"dH|çâO¨wZ zY¨­mű™óóWřÚÉĎqłşšsč\ZšĹ“Çé_-cűŽçň꾡ůÓĎŕă>ď,]Ð:şŚóăosmmŽĎNŸáęúÜöŠ(ö Ֆ+Đ%Z{˘Ł —ů˝ăż…ë{źśvžş×LŇźmom ™aÜňyĄÜŚ×P(! ›FŇŚŸz拔gžiŚąĺ]÷XW÷VÓuČXž{ůu>RjT[ >Ěá™&G{Ég R–Fą&e,,ʞY[‡ŔÁó}††Đ5‰iĽ¸ukŽ‘áafgçČçsÔj rš<++k˜–AąXÂîŘQˌA§cÓŰ×C§Ýfh¨Ľ ŻŻ‚í8ŒŃj6IĽLňů…b6iQQJᚍŚMŤăRŤuX\ŮŕúíU––›ŹŹŐŠŐ;´:Ţ0rŤ‘RGH‰ŔŒ!i–Fź–ŠŽ4Bmč•!ĹŽ6ژ9ƒ ä}[Kňů<ů|ţŽűPŠ´{˘‹E*• JŠ„ĽňI„a´Űíd­‰[!BÝ(]ßX…@—Ol†łg„Ű4Źb°&fĆď)Ľ0 ß÷#ki•€8N'š~RJňů<…BÉÉ Ž9ĚüüˇnÝbm}=ŽlťďŽöĽ.á{§ö\v.ť~.^Tü˙îvĽŽö^]×Éd29r„cGR,â“ËYöÁ˜ý؏ý؏¨‘RbpâXŮĚ?úY‹w.lÖRřč˛8ÜQď RĄIE>ksä Ăgž28|°}łŤˆ^K—CÓ™Ş óó[ď˘i•L‘…ÍU>=y*,ŽdŘ3ľ2ôeK(iĂbľš.5ʙ77Ѥäfu‰B*CJ7Yin3ŇT[5Zn‡MťÁtĎšÔ¸ž>OÚ0‘BF-ÚRˆ/!f&ĹŕÉŒb–ŐCCŹ÷}̡çIŻśíđQˆČY@选“KŃ>TF<5E꼣  űÓĽ¸c"Óý¸”MH&Jƒübţ2vŕ‘6S؞ËLĎh˜ó ‰.5҆EoŚÄb}´arłşČrmƒĎĚ<Œ,Öךąž@ËľIéľN ?đńEËiâřS•!֛5ëk šI"łĺŇ#čÖxîÖ1ůUžB$`&džń‡ü ˛ďŚůţňYš^ ?*$şOĎ$đtÁćἇŃec­„NK ĐĘ˙™‘ŻÎ–ĂeE|[˘%$şĐ810şžő?*ôҰđ}ú{ĘšŽăščR#ge(T¸¸r‹”aá>׍ î§nwpý€+ks¸ĘŁ']Ŕń]<ĺłŢŽ“ŇM.­ÜŚ/[F×4–U4Š%śĄ2ú,˙tBęVe€Âg~›Ćŕ kŻţWJo˙ fł ŇGÄ~oB 4 /“cý‘OÁWżIćégIŠHMűP:ƒ?~!ŕÖ­ŰčşĆÂÂ"J){ě1†††›ŮG9ƒă8Ôj5 Ă`ii‰‡>ĹđđGM4NŸ>Mš\âʕŤw<Őݏw_Ö4 ŠéHAŕí9Ÿ¤P” ‡'rG˝Vgddˆz=ü[ʰđö× [ůň…ƒeĄ}ľçű8ŽO§nSo´Yßh2ť°ÁĽëËܸšĆňÚ&ŰĆÔM Ý@Óő­vÚěaőŽÂ —{ĺřj[QŻI‰fę]Ž9^"vœ0M„ŘJdîˆvG˘\w˘śOzž™Ś‰iš `r§ýż<îtB 8T˛Ůl" ěşî.'˘nMšř{ńšÔnˇq]—L&C.—CÓ4Z­N‡N§“čě‹z{{8zô0kkë\ť~ŮŰłlln`ŰvÄ8UŰôƒî6. Ŕtż†ÚMŹŮË )j…ŰÚÚŐŽźWČ0çŕĉ:x0ŇĐQZh}ŒŮý؏ýřg’ôʼn€aڧ*T*NiňÖů.^KQÝČĄ” ˘cn!CˇRśÎé6§ĘppŚ@ĽœFתBz{l¤ĽAÖ°898 ŽWçI/yŠáB/Á™‘#˜F“…T–ožyrşŔ×N~–Œ™B—uťEĆHńŘŘati K‰‡{GȚi÷M II%gŚg!Sĺ!,Ý ai„Îż˛qřŕqÚI˝ŐuŢą!˛_+QâľKs,_œĂż´Œ\Ş#œ%”Ň0ŃCúřĹCÔ&űɔr膾ë´đŽ›ˇ”XšÁ‰iLÍŕÂĘ-Ľ8Ô7Ę‘Ţ ‚GF L”*ôRLgńŸŁ}“ř ä*|ĺř§15ƒÇǎĐń&JCüîĂżIŃĚ⌅nŽçӛËstp’śă`j:•t]HŇŇH´}’ˇ,î$}R N7ĂBAĘ´81z„JśÄąË3|űňßs͞ÇW~wţ†&`Ę xžěSÔ4T p1ŠŞ3ČţŻ’ď?™.!w´'íül!uRšÁpĄ/˙4—VnaJÉdyˆăƒ3Xš.5žqú RYŇFŠ/͑ˇ2|ůřg04IÎĘĐr ŠńĐČ4 ČęéČÖÜ'­›í%H)¤4 @!¸ij†ÔîhăůaÖ¨ű>ëžÇ¤”XŮ<úɧé Ną:óÖ?ţ_”gßGĂ ç›Ô¨Žąń/ţˆÂżBjtÍJ…§ř÷˜T !0 ƒÓ§N~~z:Ô ŰF“Ô6çĽ33ÓQŃ)xä‘Gv]łžžžO4ÉߏűUŮoÍYM“‘ˆžżăŠzŁĂĹKł4uczrˆ“'Ńi{œ?žž^:• ÄÜěš|]7ąm›l.K ‚Đ]ÉĐčt:ŒpóÖ,éLšŃą!*•2Ę÷1M‹žŢ–e„śŇR˘i*ČDş/–‹ăv¨7lnέqĺĆ ó Ź­5i´l×Ç÷\?@Ó 2i#Kžëbj2d”mŐU×őpAyř4„0"Ąc/iɍ]rD$([š& ę@ ëa>Łş/¸řH Ë^BÚ˙d@čÔĽŮî  4›M ĂŰÄbçĹH8v’2lqp‡VŤ•0ebQ|Í2™L2VńkA@ŁŃŔ4Múúz)ň;z„ëׯSŤŐX^^aeuĎ Eţ÷bř~ ;fÇ>őÁ&;’TWňîVАÁXâȑ#a+Z6K§ÓŠŹžu4MKôzöÁ˜ý؏ý؏_È™Ţž ůœÉ™,Ë+-nĎŽ17°Y8ŽÂ4Ĺ, ꌎŚ$›ŐHYƞ…ýÝ6@MHzŒ R)=Ěáţq Š“6,´¨Ŕčɔś=ç@ĎXXddˇ,űłĺ¸ôŘQ˜†{â@nkk,Śr‰ţ†$Ł[d4ő˛ó 2Ýv˜[Ť;šÎě•či†Fś%•MSš ďé#¸ő6^ŁCŕ‡ŸĹH[šf>™2ĂDz§Ó„ř`FŽŚ$-…°ŕäŔ&ËC( gŚ#{kč̈́c҉đfÝ'}Óĺá]ŽĆtg”‘ )ÓIF3ČëÖŻLŮçn ™ŘăšĆNă˝#|-˙ENOœŕ•‹ŻńŁů7¸Ů^ Ř(˛ZŔç{ä ”0čy6üźŇłT†&•D7ĚˆŮ9fŰ' lçŒ4BHŽô3QŔő\҆…Ľ‡ ´3=#Ékä"'“b:ťuu?ŹćkND'ÚSÓ)4>Y ࣴ§Ĺ‰R ŠéŠ‘ÇüÜ׊eţo˙3ƒ?˙{¤ X=ńţ7˙z:…YěIœ“bśá/[}4ůOpç‰Öľť¸°ýÚă2jËŞ7d ÉfÓăęlÇuŠ×[T×k?>MА§T.ráÂzń\ŸÁˆQ%# ę9RÖëkëôéúúĘ,--sâÄ2) Â4uŇ醥'­‘10ÔîřŘśK˝ŃałŢćö|•›sëܘ]ĽşŃ Őöp=*b5Ć IÄHIÄý%¨Hä5lŢáŢ•śAŕGëŞB!…BGˆ4B¸ b!^ľ | éş ňHÄ×q쎢Y}äu'vśú8€äâN˲B%vŐ!˜%žç%mi1 É÷} ĂH!ËËËQ+Ľš‹QÓ˝Ć×4•J%Żíş.Őjçŕ¨ľľ5nÝşÍÚú:­f ×uCŤ÷ťhĚěÂ|˜=EípKŒ˜îC)%š\–ŃŃ1N:EŠT"e™[KĐétpÝhŠŤ}0f?öc?öăŸ×zGĄOq‡˘Ü˛t,K§RÎpř`O˘/„ˆýméŚUîi%y/'ĂQQŘkĺț)ÜTŰ'֊ѤD—:)atą•E¤Qüńôîîb1ěÁxů0,™­ MK…4ç• ‘Úă5ďFCţ °4Cfə)zRŮŽJńqJ´!0ĽŽ)4’Qwżś÷3!ŽŻáöÖ;ś%\{ŮÝßϧs>ÄáÁi~Żůn-ĚňîâenŐć‚&Oô–)˛hN$ٗ¤ IDAT“ŤĚĐ×?„aÄŔ‰LwG‰‚”ş™&mxŚżĺäpáĂÝ%ň/WX›BÇĐ5´OŘɀ[UߝÝîá^•š†™ÉS9ţ­‘Ü<óĘńčyôSôôô€Ś!ĽÖ5OÄ'ĘĆú§^ÜmÎű×kŻ}*œŰA°ĹňPŕ*¸Ž`nŐĄŢňk†ŔČzľÎĂbb|„|>Ëťç/âz.Ł#̌Œ01>Ęęj•TƲLR)‹TÚbrň87Žß„Ŕ'ŸË’ÉZĄö‡‚ŔŰńčt\Zm‡Z“Őő&s \žžÂŮu66[¨$7¨ ,ĘĽÖe-M(ń"ş–p …ş.žďă8n—NN|kčşŃĽőBŘž¤JYa‰Š„đ€ iąTä-I‹”÷O—%25ŘÖőĎéť1>öżUj{NfYŠÄĆ; …BjľN‡t:mŰ ‹*śľ‚€ŢŢި‰Ů3ń܎5ݚ3ń~ďŠńsMÓLZĽĘĺ2łűąűń §uݛÚ΍öŽ'ěÄ'Kâ.Ľ›řŔן—H,a`é÷Q´NÜĄĘd{ť‚čĘ3b&ŘůCcB´óąťŕ|@Oú@I°Dř(`E îXh˜łËĂ^CůaOÎw&Ĺi)¤ZwÝrĎűęÎ`ÎÖ)™Q08’Ér`r†@…:$zôšB„ZBČm- {ąÍvˇ(u#E!O"%tĐtÔ':Vâˇß  ę6Ňř0ë.@E„ĽoŚXaüł/„NVRn1•vrűŔ½EČ"¸łöѯ펾hhÉÜÚÔô=)5‚Íf@çśÍF# ăʰYëp`fˆc‡'řô§çćÍŰ\źx™‘ŃaŚŚÇ0-ƒt&Eš\¤ŻżL:m‘2Mž‰ŢƒÄvBG'Űv٨u¸~{• Wšvs…Z˝CÇvq˝PV7P EbŻ13B)… žç&,A!DĆ ŘĆJQ$,)š&ńýPŃťŸ+‰ "^ҎdG  X(ĄMT2 ¤‘u¸ Rh{,žżěús÷üçA™ßą‹Q7{Ľ›ábۥ圎똌šk] ™+!ŕƒ1(d€„ş/1SŻ×ŠŐj¤R)2™ ů|>ůÝ1˙žř54-l™KĽR8Ž“°ešÍ&AN§›˜-Łi›››!( œ1çť}0f?öc?öă+PŞŃm‘yOEȝKrî[˝„Ř*ăřȕăΡ§îüvťM^@äWQhřžiklÉÂuOěł˝×BfH4#Ԛ /l7KëWéäőŕďI[Žëştá]űŃuűJ!“yľsƂúšŚ¨ĺ‡f@G˛¸PoşlÔ͐%sâč$CCƒ”JEę&čap¨Ë4C‹ŰőétÂçmlśY]o0żźÉüÂs‹›llśiś:´;vHŠĐšYˆ b°ˆ$ÇPJ!…  K=B†m —Í"ś żn1!5@)RÉ­ľNtY'…´ źH¸Ţŕ˙gďMƒěČÎôźçäzˇşľU@a_Kw˝ws8C6ÉRĂ!ǚU ŽlK#…dKV„˙ů§#d‡Ăv8а#ËĄK#JĂ!9$5Ă­6{ďF/@فn4ÖÂV(ÔroÝ-ˇsü#óäÍ{Ť Kcé-?tUŢź™yNžsž÷źßű ĂĆ !$=V„!ĎííxQŃnˇ‘RâşnOٍžˇNÇ#ŠbQábąˆL@(€bą˜ˇr ZüVqy‘ ĂÄĄ­;ĆéďkľZ´Zqyfhh]˜l„aˆe™ËŔ ÍZŃ?×cńŘŘXjcÝjľRQ^ €čg¤Ů.ȉ˘X[Í÷}ĺr9ýŹpÂ0Lď­Z­Ś ŒfٌQʞuÇVÎ]>ËĚĺšó-š&N'-ŸZyĚV×`şÇĽ:q–ÉČčŰwîbűöm‹ĽäúşĎ§Óé`Ű6žď§@LŠTşŠňÖŒÉ#<ňřÄ,| LÓÂ÷CL3²ŒU“řO n=Á˝îYo÷Â\\űW=÷~1aâűÝéxńI˛ŁäcŰÖM-ČîZ,îLóÜô5¨;ßFzĄ*Ľ˘Ůlőě솁eYt:m,ËÇu›JĆď‹Bô/!UH#ÄGŢzwź˝:NşčÍ ”‡aH§ăQ(¸7üĚW>Nd´(ň¸ő1Đ\fٜÇĘósżŽ˜R1¨”D†%$R„‘¤íKęí€zÓca1döěŢĚĆ ëP"Í BIťĐiÔŽ.4¸tyéKó\¸Tçҕ:ľĽaĹş`I;™Ś“°8#”23ŔeŻxŠę+ŰB$ şLŚi¤îcËK>ăyQƒHFŠlúnKýCCCi›śZMöěŮCľZ˝Ľk‚€šš99wîĂĂĂLLL`QĽlŒBĄĐSúćyWŻ^ĺÜšsěßż?ľŘÎöÁ<énčsjqiÍŽŃ/ƒƒƒŘśś.WŇ@‹išéZ§{ţxęyN'vŮéůžlÉR?ťfhh(ţ.ßĂ <U|&śŹaŰÖ-xő€ůšŽ\™ĄVŤÓh4đ}ßRݟlI“R˛@ĚĚŚi`Y6ĺr‰RŠĚځ›'Ö0ž~NŠ€éŘȤd2)ŤŠ]ŠbŔĚuÝ[ŕr0&<ňČăc ĆtkoŰíXľÝ˛ĚU|˝?_é|}×âS´ Źâ›–âÎ҉ƒ ¤Ýn#„‘Šŕé?–eEF“RИÚAć‰ĘňŚw°Űé…XźË'÷ŮEŠNđmŰN“×unĘNsľd? ,ÜěůVť—[=ÇÇ9YŐ!Ľ˘ÝŽGŰvzŔ˝[ëyą`gĄŕŢ} 3t^‰˘0yŻb˝Ť\ggĽ1NĽ]V',NXŁŽMn˘'e`&Ú( ” —çj Éb#˘Ůňhw|îżośíŕ‡! ľ6ďp‰ŁÇ/qâôk­řˆŠ6̸f?`&bGEDa„”ъɤNŔu‚­x @F’HF‰ŽÔuDžEěDŁÇĺX{$JĆ`ýŽëąÓˆŸ‰Htw1B °‘Ş€!|PŃŒÖ‚˛1ĎHgCCĂH?žç111ÉĽK—’’›XP8Łn蜝%‚¤,gů¸ż CŻcÚHA‰ŐćŠÁsĂ ÓéĐjľ(—Ë Ç!‚´ÝLÓÄqœ”٢Ů2šÉR*•Ø1ÔnˇS§%ýY}oz˝”-“ ÐBĄĐŁcŁPDNÄ‹L˜kQmEłŃÄ‚M7°}ۖԆ˝Ńh #Éb­Ć­V )%ÍfƒĽĽQaš&kĆÇEŠT˘Z­211ă¸ $ď RbŃÜEüĽćĐQyťX"JJћÍf i€IŻs0&<ňČăSĆhM‹ XZZJęąÍä˙VÁŸ†݇$ŻRńÇśc{Đ~˝˝X /i+c٢éF“ëOsbŁ„@Üą~ť|ČÄÝòœ”nŢż3 ě´ZmÚív*:yˇŢ‹ĺťćIś{#6žŸ’ńMßrźkĽ‹ýţ÷JƒiqÂĐLDcVAwŒ=šfƅ*Ěs’ŠH† EOycܟľ¨iW¤ˆUœ\ĘeŇńӗ;4[!ĄşČ•EÉâ’ĎĽË‹ĚÎ7h4=:? C B`"a–\.1ŹŘş^[ňö‹ůëłgěTdć6E…H)zúB”VRőŒs1›BŻadâ6•°kč– aÄó„Éź[c+e!ĽM$ÍŰ^ľiY6;věHž‡ &'×R,–veüFF†B01ą6ĂxRˇ,ŕ*„ P(°cÇLÓdÝşu} ÜxHƒŐf†•ä8ĂĂÇďű醐:5iÇ%íČ$ A'ęĐŚMGľg ;˛ąK6Vb!­Ů; ÖÇđĐ śí066š˛‡âžkžçQ,)‹é=čgf¤Z0n BšŽƒoYŘÓČĐĂh/6k1ŔÓj3492ÂLôÇúKžr0&<ňČăS’¨dwô„ŚwŞbQËnţv+Éë'?AČ܋JőđoǙ3‹YeZŽ‘Şč÷/˛ťmUŔ˛l˘¨k÷šüZŻ}Ÿî\\Ý1ĺ!J˜ŚŘI÷'ŒŮňýwüNĹÚ2ýîwŁßö÷áOę—ö­šĽÂɉłG–Š.s,ć.ĚEÝ1Đ0L')OÉ˓Ž9+)c}Žút* Ő˙™$áÁœ…A$—ç|ćë—ŕ­Ëx~˜–]tKNLLË@Jłc$}ßŮđfôŠôĎłBŽq ’šÚ”˜é‰.L~§Z1(¤VŘýZ2úťĽŒľ T”‰]ŹĚw‰D¤?.ŤŠE~¤a!qn_GëřX֍*wÂ<' dôĎ–e÷8ý龥‚ôQo Ľ€XZk;f-Ź5h´xŻH4[E÷›Ź ’fšjś‰._ƒŽFÎJĽRŞą§™/Yh %Í Aƒ.#bKÄŔŻÖč ÐRŠ„”2e !hľš8Žƒë:Řś•ş@Ź]ť6˝f׍™MŮgĽŻ+ ĂŽËSĄł´TYŞâ-ŐĄYc°RĆh-5kĽ Ęv1MòîÚŹƒ1yä‘Gw`PË@= /[XĺqÇŰ ż-VÓęÉ.8 CŚ ›<î^ô'?ײŽÎ&”zљż[w7iŐÉŮj6ăŮ6ÔťÂy[ÝývZm ĚcĺçeZVŹt"ŐjůOÄe1É36ăÄUťŃ˜Ś™ş~Ĺ,’Źľxœlk ˆËˆÂ$YΖŁtż+ž“„!b‡"ÓŔT]7%]vąLKŠD4?ë„ÔeĹÄe5ËśąmŤ§Ü°g,NÎaÝ´2 C eŸJd4ß2ě–KĹ@ąöm¨wÉuAˆa8˙~eZË@ ”şŽŮƒ˜uKú̧ššŤ)366Fš\Ćq:Žă¤ýDƒZ¸Yný FłŮ¤^Ż399™–éňŞ0 Š×ëH)ŠT*=Ľ<ąp”`XWƒŤ4Ă› ›‰Čľv˛›'Đý]ŠTJE‹Űí6F#Őľ1 ƒŃŃŃ`)‹´Z­t]ŚŚBĄ@ŁŃŔuÝô~S›  ŮjašJCĂiů–)Ŕťzsö{tЍ[[ç‘Gy|ęż+-†óäîˇÁJÉýjm‘e^dkłó¸ťmw­dqU{éüýúHÚi5Ťř•šěkŢVwŒÉăúĄ’˙A ČÔöŮXÖżł,†6ʔžt™+ ĂP}şTNčݤ1LeˆXŰ%Vúݎ´3™č3iÓżK ˜&%”Z G[Wk`Hł1ôRĆ@GŚĚŚÇUŻk0… ›¤ÇeO SFvsŁdżm€Fفçٟg°^=.Ý˙4 ‘č<ĎĂ÷ý´ŻiŒÖžÉ2¤´[’‚z˝žö­5kÖ ĽL,ŮMŽÁÁÁԁ2Ť5S*•bń`"Ú˛'=lełš´ ˘Äj]u]Œ4+2Ť?”ŐkŃýO—ă8ŘśŠíęßeŃű’˛4ú<ív×uSĄŢHJDR˘çŽN Ç1d„ô:˜^#cňČ#<>u‹ş>G†¸”B—)ĺ‰ČOBŇĽ ‚yâ?y;ÝíÄQ/Ş˛”îkEˇüOő8Ÿ\żóç}Ťmľ’śŇj‰ż|ěڙfýŔłq˝˙^őŠnňsˇúűŰ}ž[˝˙ţc{˙—hćĺIׂ"éíŽI¤ťőýs{:×$šgYĐAł˛ŕH˙ř#26ÚÝľ‚JϕM^…ÖUKO"R†Ič0’’Ďn"i"¤.ΰx2 ťH.Fłf¤RˆLiJVtWeÜâ”č:ßÄÖŕZOĆXĆĚҟż=mŐxoU€÷ăÄhqĺŹzŠTNK­”uŇnˇSŚ,0—uéRłŮLĘKÝÔĐ`šţL–ɤA ţ!hśšH!i›m,Ű•.Őb•Ŕ böMŘu]r]—vť2Z˛÷ăű~ şh-™jľšęúéw.kîşî˛űÓ,Ý´ąÖ™Éęěğ5QÂ@ ۲Ý"śqwĆĹŒÉ#<ň¸ăLwBíZôÚŚiŚ“eŻśE˙żł éţcVúűV–2Ť}ÇJÇÜŠëYéó+]G˙˘EŹđßj…ăc Lť†š˘uŠvˈ˘0úuňý¤BRŞ”b˝˘ö˝ŽK–ebYö‡H2s4ćVŰ*ŚłG)~ľĐZ1Śi,ł#żýɌ¸‰cV;ţZçšŮď¸ŮăÔ*cއyÝqQJ•ó´Ž žĺÁ2KśôhYٗZ>Śd­Ľ5 “ýŹţł`LˇĚB¤6Šşl$Ë4IżMő2M´ó˘žë˘(ÖąM 'ŃnŇÇe™ ­U“€wF×!¨_‡F JŚżú÷†ˆő9Ó÷Ţ0Śčźnc|Źqż=:)$Ń`D­VKşußłm;ިT*ŠŘş.MŇ6ÖŮÍ*Í¤Ń J*r, 4Š…5TŒś[vńÚ^Úˇu{8Ž“.Y@N[L벊z˝žÚgAL˲ŇR&ĽN‡ĽĽ%Â0L‘bGŹŽŽŽçy´Z-FFFzúŹEłĺç˛, u—úPĆä‘GyÜy8&]ŘęÁ_–Ůďö.´oćߍý}+€ ×9§¸ ×#Žs˙׺îë}żŒtâ"ä÷ $Ć`MźŕČu>ĘE'XV,¨Eűľ~4¸ťNŹŽtíD+/Ať]IB…řž—ŠTfŰBƒŃŽc÷ěęćqˇŰIašž×;ćíąrôŰ ëŇŁ, Żg<Éěô3?4%+ޚ-݉Ř>(~‰ŇąĘ0ťě˛4ą…G ^v` ʤŒ‰äŽEŇăßgY7=ŕ]R•$2 Ekg"Ă00̄ý’\Ť˛%U¨ÄčzP'›gĽŒzXRQá8Nâ(h222’ęI)ŠŐjŠ›vlҌ“ŹŰ’E4¸Ą×CZ[&uU’>5oĂ6(eJ%,ÓBFńwúžO­Vc`` =§î[žďS(Ňs´Z-šÍ&Őjľ¤ÔbĂÚÉ) îčr:­Ól6{ŽŐśm†‡‡S@'[~ŐĘčçw7™ę9“Gyäq&Ě,ŽăfDűňřH ˛d‹Ýy„a„e‰ž<Ľ…‚{M-Œ<îlˆĚÎlźXŠ]˛ &Ľ$ž×Ą\.§Ž$Ůč›éy|řvę>sm›*‰˘°{iírĄ˜)=ËăδÄą%ŽĚă•@%€˘żŻęgśRéQ\śÓfVŢí+=ʖPŹôZ,â%6â÷OĄ˝ĽL);!jbaáQ’(RŠ`pé”Ht` ‘0fô;_Ťě"ÎzKőłMťk˘¸œI)…Œ˘´dęöÍú>oëĂÝwĆ˖ovíču˙ɎĄó<ݧDzbw;ĎóRW"Ă0R˝™ŹćŠ#4h˘ŽÁ(аl ‰¤#Ű\ńŻ0ęŒB p .Fâ¨'T*Őj•vťMťÝNmş=ĎK-°őćŠÖtKőd˛šbśm÷°cłPú÷RJZ­–e1;;KąXLmÁƒ HY?zý Á-ěşnęHĽ]Ľr0&<ňČăSô뿣(ÄqěL‚™ÇGˆ¤;<~ĐÓfRFéŇľ/•ößV˝{Ÿ7'’Ů[Ú/z!ď$ËŰĚu]fZĂŽÝ%lŰéÍVJ˛ďcżŘf6ůˆŻzŕŠqHŢ&×dôżăW™.ŹőÚ0śmćB˛“6ÓmĺűqŮŚi˜Ÿ~7ö›CˆDä“݌z‰,C&)žI˜1=âž}ÚJý%ĚýZ4+–*ó™2b ÔÄ0ťçîeş–2i€&dzp=üIĽşKĎoeŽ[ö|Ţ+[Ú÷_ˇčŠăÁíƒ.]’bŃ˝ĺJ⿏ýëÇ^ Ą0Œ¨×—’ţ`ôl>h†‹f~d[­•J%9Úí6­V+ՊénNuzú§>§ďűXśE,EK4Ł&“î:T¨p\§§TXƒĺr9=´ˆîââ"śmÓétBŕy^j=22–•"ú:4cFř˜ľqďŽLNNbŰvĘÎŃ,6mƒťnĹ`hôďƒ Hľhr0&<ňČăSČčIĘ4 ëűněRŻT×ţQFźˆéô$řńä.ŽßŽÉbT˘$íkě˘ő>_ľârďF&>ƒoBĐÓVaR,–WLîŻ%Ť˙Ž˘(q‰E*L#q˙0Ítˇ/Űrëöí, ź?˝ŮçדüfQłL#>í˛šł×Ç=,ˢh<äLĽĺó•PýVWŹźŃ㊡Ç#-źj,ŽÍ~> &Ç,%c#3˂ČţĚČŘ ëď73ʘ^š”ĽŁ1˙ě;ŮS6eˆ´Šß˝÷şx’*Bi—§ţ˛ˇ˜’RĆȆi×ԗú0ď ë:jœůhÇzJŢtëçż§fĘr‰A;ťÇ]Š_äVťiŔ%+š[ŠTR€Dƒ3žçaYVZB§Ů(RJ„)h„ –Â%Ęf‰qĆ1•‰á şş.Y;í´/&ç+‹‹ĹôښÍfʞ)‹éľérŠě9łýS˙;“ű~Qjń-„ P(P,Sç'€vť”’BĄ>ˇl˙Ń"Â9“Gyäń)c˛;^%ríkT};iŤ/˛@\sB Ao´h ôGŸ@ö×ýßPŊ’ °Ílç4mYgĐ\GŐÇ6m a"’éęß˝đ"2̌YÉ ę‚ůpł| †žRźŹĆĘJĎQJŐˆdNłŒ­ˇ8E2ľŤÎ‚<Ůž™ŤÓr˘d’ÂĐÁ`šÓSŚ•űß͞˛Š>íŐOCëĘdőń"š"“H(0„‰ś—!Œën|\*îŽ :Ą×@{FŘśŐóNjđB'â˝6ĺ eŻ…¸4#˖ź]ďžv€ŠŮžAŕ§cÜŔ@×u{˜0˝}D¤ě(­†ąPsąXH™Y€..Ĺ.†!ĺr ÇşÓé`˜^äá ?ôY[\Kŕ8vr>aڌ čf-ŕűmŚľ ŔÚľkRM¸ršÜ#Ź?Ł-¨ÉގA¤"˙ŽëŚŹf˝6ĐŒŻŹK”îZ#GŸ ň2Ľ<ňČ#OaRr=°%`mj78ë؅lQčóÔϟ“““ěÚľ3™üťťŰAôŘeNOO٤bó–M];ĚU˝× Ç/ůšŕ˜‚ű6ŘlˇąÍşl+ŽËžŃD1KC"ŸłĂný –(ĘjŒ1{+kíŒ¸ëqʆ0“?şn_s*Y'˛‹]'q}ŕL/,–QŘoz‡^%‹Đ.s)Âýřě’gË Ő™LŮă}?Ţ)<ňîqžóýŸńćáŁĚÍ/PŻ7čtźtfŰ6ĹbĄÁÖŽ]ӟ”Żő‹l˜ZăXX–yĂďÝâbĂoFĄ¸˙ţűpÝBşĂŮßN+•Qő?ƒc‚żR9ĹJťřŮÄďZ÷Ń˙™PE„2—ČgÎŤ1-!„`ب0ę R°]\ĂĆ&Ů$8CŻóŘ´žÍ[ožM§Óf×î]ŒŽŽŽXNŇßOž÷8ۡoť-ăóÝľ…r™™Aď ŹŕśˇŇxŰ3gt)eĽńy%0VU=ŔK?;%=ňi˛ÚQ/O„őÝI™h’íœd¤čúžS–a¤ ´ž~˝šMvłĎE˙éÚf‹DšŐÉĄ[^ŒAˆR’ŤWŻŚĚjľÚÜ7Kt:ĺr9eqč’Ę R`òL––H)Ŕql ĂÄuÝëźÓjůE^s ćĽÚ'J šÍfĘΈ݂{„uă{éŚňš%Ňjľčt:Š>‹BÂ0ě™s4°Ąď4€˘×}­v+ŹŹˆĹNR…{(Ëééżú™e™ĹÝpżG“F‘–(e„‹Ĺbę|”s …BzݐŃÂĎZH:‚”é˘Kœ˛@vHŇ ¸ˆéëń}ŸFŁ‘^ŻÎÁ˜<ňČ#ĎҢ/Ť-Ł$żƒTŰ´q-'ݕş‹{Ľ$ív›óoţ-_˙­żĹëŻbaá }ô‘tbťpá"?úáćŢűîĺ™gžĺË_~’ ç/F!ëÖOŚ“cś†WďÖ ‘‚ˇŚ}ţôĽĽDđĎŕ…S>˙ŕ‰űÖť˜âăÖ×_ăƒ#ÎÇ(ť™´IŹúNé?—gŽđŻţäßńďżóc:íhFT’¸čf˘–×džÖâÔôe^;ôßůŤŸđßüĂżËßúő/0ťršL˝^OďYż3śmsőęU,ËJ™;AP*•hˇŰÉóňR‘^×uiľZ=VŢY ' JúžŸÚdkWŚ(ŠXXX T*Ľöß9“GyäńYe€VŁÉ˙1˙# –Í”ă+Ă+W‘ š^„ʘ Ž%(ťćuiž×K´pŕÄÄľZ )%˙é?}‡ééi@qđŔźţú\›cúÜy~đƒrŕţ´Zm~úӟńŇK/ăş.üÇ̟ýٟŃnˇyôŃGxňÉ') „šî`…e ÖT f/ŸöŮťÎůD& E3¨3œÇW2^t E$bJł"ó4üW9źIŃŤ0˛´‰qk ŁÎFĘÎ Eيk–° aÄŠŁ’¤‚‘+EŤŐć駟ćĺ—_Ą\.ówţÎ299A˝^ÇqůŢ÷žĎ7żů[ Q.— ĂĎóŇ:jí¸P.—1-‹ R[ÎÓ÷łkşâŔQ iЙźdô`´¸Ž.cŃl p›ÂHÇNŃ­Ÿę‚&]K¤Ǩn‰TňŚŞ¸L(űőkĚôMY†Orĺę)ŐWIžËó<Ú­Nú|Pk,ńÁ†!Űwlgpp0óü$(AĄčŚŽR¨Őj\¸pJĽÂÄÄDĘÉśÝJqęÔiZÍ•Ęë§&S ćkEťÝfzzšz­ÁÖm[\VBĽŰ*臍Őj*¸›íWşäH—â螌 ^Hł˛}áÓňŰí"EQDIIaĐEJÉŇŇRř˘Y+şŸj—$]r5‹EƒEú:tYU@QJQ,iľZ §`ŽfŹĚĎĎ'˘ă~ę ĽË¤ŠĹbڌ+t˛fÄhëk Bi}mƒ3cňČ#<>‹ żdwËë´ůŻÔ#¨ ^`ŮA„Œ"$‚ŽÍsěRˆÇ2ŮžĆâ {‡pĺe 7ł /Ö"NŸ>MťÝâʕYNž<ÉýѡřÎwţ’óÎóŕƒš˙Ŕý<űĚł|ůË_âô™3,..pőęĆĆĆč´;œ>ÓőˇlŢBĄP$ (ĽbŽ e×`ӈE).ŤˆËő(-Čú¤ľ•’’Zgžšŕ Ąčj "ޛBĄ0…xtd“E1ĂéđUœN‰A1Á˜˝•1g#ö%k„˘UĹ6, ec°2ŤĽŐjqîÜyśmŰÎřř8N‡7Ţx“÷Ţ{ĄĄ!&ÖN°¸°ČK/žL<ţřăLOŸgff†ąŃQÖŹ]ĂË/żĚž=÷đŕƒR4-暒§ßó˜o†Ř†‰mŔá {×YTK&†)>mŇefhQáűŻź~„˙ĺ_ţ[^űmĎKz›ąbżÓ;ˇ†Xś‰e˜aˆI.Î,ň'ö}jľ˙ý?ý{Ź›Xƒe­.z*ĽäŕÁƒœ=sŽ_ţňEJĽ"{÷îÁqlN|ř0ĂĂà ިpúÔi‹‹5Ć׌Ţ0ó /06:NĄč28X]őŘŘ)¨“0€$ĽRŠÇâ9 îiĐ$Ű?űĹuĽ’(CєM:˛Ă3„-lT¨0m—0Œ zčR#힤K˘˛çÔĽIŞVŤiűč>Ż›ŹKR–ÍŁÁ Ś4T€ˇRФż×ŽHŮľ€fœjĄŢ,@Ł”ô56›MJĽRĘ>˝[,ĆŒÉ#<ňřX%1’ ÓĞ}…Bg„BaB´™Đه4 D%JÉÄ于đ‘Q@dX)ť%ž€ľú~ˇ~vőÉE¤Î žď†ĹbŃŃž{î9‚ `ëÖ-ź˙ţ ._žDe ĚĄ7ąaĂšÍ&ăăă,..26>ĆÔÔÖŻ_Çů ç €űŞ8–âŔ”ĂSÇCŽ6"^ě<ôŘVç#§îk]‰¸nŔA)ůăG>—ZçiKż›ĐĽ‚‹Zď"]ďŸŇŠ‘čŕ‹sĚ8ĺżDŮŚbŒ1`ŻaÄÚŔ”{ƒ…5˜†ľlq[*•¸÷Ţýœüŕ$ďjľÂwżű}žôĽ/1=}Ž+3łř~Ŕşőëxö™_Ňjv8{ö,•Ę|pŠG~ˆ>8ĹמöŐtńrŠá’ą˛ÁԐEÓS\ŞG\\”ě[÷ 2éęé÷Ŕ÷}Žź{‚˙ë˙ýK^{űA¨ÂZĺݤ|rÍďÝÁÖM“\‡ĹzƒcďáíwOŃęxü§ď?Cš\ćŸýŁ?d|lxŐ$D)8}ú4WŽ\Ą:XÁqރLOO366Ćěě,žďą{÷.Ξ=ËéÓ§A)lËÄś- ×up]Ë2?e.ˇ˘]ĽˆĹ•O5/ň˙Ě˙”Ÿú‡iŞ›Ą‹ÇçX¤ÉŸˇžg6\⟌|ŠŇšDŻéÚ×xńâEΜ9˛ĆjLOO37?ÇÎ];ٸq#'Nœ ŐjńđĂÓé´9u꣣cŠŽešTŤlÝşgžy†/}éI …BîPô b˛÷‹čöƒÁ]˝˜•ǨTˇ=Ň/PžZIR.[§ú.=ÖňÂ0S`9˝ĂŠőQ̸îůnC¤29Ů됪K̖ÂýĎ•ŽAúőq˛Ľ"Qa ŐW ű!ßqí1(ë&݉V˛’îm4˲˜˜˜`ëÖ­ Ýđ{„!ľĹ“““7üŰś™˜˜dćňöîÝłŞ0˝.łq'e‚˜ŚI˝^GAŠTJÁ ÍTрœ.CŇ%=–e€Čˆ˜ëĚ3RĄ¤ĘXI‘§éš‰Ë’”]ŃぁÔ‰) Cp]7ëtŸŸŸO-ŤłeLşźH—Đi†ŽIô÷hö‹f׆‘ş2AĚŞ×ë ô€9ŮĎęséçĄ5u´ĽöÂÂăăă)P“ulĘÁ˜<ňČ#Ď ِQˆĺ=ŢŔ jń‚GxKĺq<{Œc÷m°),ÇÂó%v ¤Ëěě vÓ2qlËśĆMęiűxŮ˙v›ţĎ˙Q$)—KlÝş•˝{÷2;;Ë<ŔÔÔzÖŻ_‚ýű÷ą¸Xcrr‚uë&)K,,ĚS(âá‡Â÷}FGG@° Áƒ›,ꛎD • öNÚÜŕް@ńÇŞ˝t˘çŰgńŁx!˜u‡†H˙ŰH3`ˆD˙C(B!dx4d“Yq+4)‰.ˇNđůń?°—'ŕapőę,–e1;;ËĺË38ŽĂŇŇAâ:.J‘ůľp\Űś(– ¸Ž‹0CCCLMMĽ‹Ňuƒ&eWF‚Ś3K–!Ř0lňÉkž.EyŠŃäĎţă_óÂkGńtC­˛ü(lÓdëŚ ţđˇżČ÷í¤T*ŕ‡EÇĺňĚUžzţ?üéË\ođçß}š-›ŚřÖď ÇąW\źY–ĹĂ?ÄŮłg˜šÚ€mŰlÝş…ÁÁ!6oތ”’7°uëVśmŰ Ŕć͛řŻ˙ţÉÔÔkÖŽĄT*2šn×u?cۍɈšˇÄż]|ŠűoÓTdvË{™Ľu& ËäŔ E]ľř˙MŠ‹˙Ôü:cćđuíŻ÷îݛ&iSSSüđMŠ\bűö­lذXĐ9|vďŢM„Ź_żŽbą„mYqů¨i$;Ž’uëÖąaĂĆˆůԁ3ąřm˛Ü#PtĆŽ {Šˆ•˙Ő@˜•ŽMő9’˛!#uř}nˆ*eËdÁC ÓL]ËA ˜ľ"QŞ×z[ëéâ˘Řɨ¸JE}ĹŞ::B„Ÿ%Ö ůp֊‚„•C”aĹĎCĘŘ5Ż^Żá8?ţRF %ŠĹbĆ!Š`ó<ŮŮxžýüç?mŰÔëu|ßghhhUŚK,,,°oď^!D `é~é8NZ2­Ů*Y—$ Śč>ŽďA)EťÝĆ4MŠĹbúy ÎA€ďű=#Ú)* éďÖÎUív›áááÔŇúzĺg9“Gyäńé„bđ[5Ź™×°‚V*Â'”Äi_ 5ó. …]é")Íęő:FľĘĹé ,ĚÍcŰ6nÁĹ-¨”Ë8‰PÚj@ŒŚ˜~îsŸëŠýaŰś­éqĂĂĂé$§[ˇnÝ2ˆ{ďÝżlQhX[5ůíű+xaźř+ŘąćÍ'1OQ(–:u.zÓ$"})ó%Ö B%€L˛ří)e")e XŁPH!KĆçäŰxž‡cz`J)Ęĺ2ű÷ďçȑwřÜçžŕ‘GᑇĺőCŻsŕţűŮ´i#SSSD2âמđk<řŕLOOsćôśnۚî¤eéč#eƒ'wů›wڜ[0<´Éfȅi|2¨ˇKÂ0â­7Ţç{˙ů-O/ŰYmĹ/„bhp€ü÷žÁΛyö…ˇxţ•#xa@šŕđ;_˙Užőť_% ŕ/˙úEć›üńs~ő‰lŮ´~Ĺ]LÔŻ[ˇŽçYˇn ůšJԛ6mLYťv-J)&&&PJą~ýú›˛đţ$ŇíĐçŻ_ă12a´Ŕ˛ęËÄtłö%s č(ŸŸtŢbŰâÇýbF°t{^Ă`hhˆÇ{4mƒ<ŔĐŕ;vnOuFF†{‘ńńąeÉrłŮ˘T*ńťżű;ŒŽŽäSÜ'ég4 #WdΈ>gŁ.¸Ńko–ěd4b˛Â¸Ý% 2Ź Î(ča§ô:8ĽÔ—ž‘Ż{Ţř˜řşc™XBĽ;_-ÓąŃVÖÉƃvĘ–P­T}ÜëBĽ@ĹöŰśebj†Mö™Ť÷ăkTąÜfźV[äíÇŠ 022BťÝN“ö}űöĽ ‹eŔpńÖ[obšƒƒƒ)ä^ŻóšĎ}nŐëń}ŸcǎQ,– ü€‘‘Î_˜fÆ)&''Wűęő:GĽŐjąvíZfggcŰśm+<ťĺemš]˘ŻS3IÂ0Ä÷}\×M•ʰ¤–(šE\UŔ6ŹDÂHâşNZň•uČҀŒŢpĐĎK‘ ‹E¤”Š›RŹŁÁ!}Y‹iýeŃíœuüY) …ťvíB%fJ•J?Ł\.]sÜfϞ==çqg™öP֚şX,% HזşŮlöŘZëқZ­Fř ŕa˛d.1bŽ"˝ˆŇ@1öGǢŮjS,şČ(Äfú ľđ­.őŃĺOÍf“Z-ÖŮŇZ2†a°´´Äěě,ĂĂĂ4dýjĽĽC`Ńş/şÄ* CJĽ333Š śJĽR śdĐrš[r'÷Ýh4˜ŸŸÇ˛,†‡‡YZZ²,ĂĂĂ)ƒŚŃhôô‡ťĹÉÁ˜<ňČ#I„a„Q;ƒŮ™C”ʐŃ7@AŮťBŐô¨âËńd˜DAKMÂ˙ý_1vî,VŃFTLßĎÂűË˙H#R ţíżîŠäÉÁíH"%'—NᇑJ˘ c$ÔC Т-I(Eʘ1’Ý<Ă “F$ßâlmiŢłť*R@ćZ ˜c:7u?†ÇŒUcçÜ.1{BJÉŃă§yíĐ{(‹_^óţ AÁuyěá{˜Ż3ˇ°Äo~ĺ1öîڌm[LŽ#R‚×ßú€ßţęălß:Ĺš Wi4;źřĘť|ý×…r9wž…v وW:'8^$ŒBÄšá˙tyşŽĐÎWJĄŒ^‘ć4Mś Ė ĆĂk0Gl¨ŔˆK$$gÂ+źŘ:ÎDq۸ńĺoŹcŢ40¸Ňű™Ç'/ ŽĹŚuÔ*YWĄ!_şÚ)ŞO‡D,Çr=L—´˜')J뚖>ń14Ů_ęů&!ĽÄ[*@i{ĘĚÂK )Ҍ—€Ú)!ůcÍ\Á:s&ůŒJ5Bľ:ňđQÂo|cŐ]ZMežž&늼^@ Y\\d` Ęâ⸎ËĚĚ ĽRŠGĚ-­V‹0Œ(—KŤ2>ě3ět:,--Q­VoťhfK… ™clPۘćhM"#H¨Ý ‹IscÖ8ľpĽpž–ąDhy(%eJCJ„ęŇŹĽ˜ĘfŞ´;@Ěă&ۉ˜2ýüËďĐń#„0Ż[ješŁCUvn"đB,Ăbdd0}gLĂdtdç‡ Vb;Ě0â셫źę<[7ŻÇdy›ÍĎĎS.—S[ńQą°°îŢČńsss˜Ś™Zu^ŤOˇŰmÂ0L)Űw}üSŠżÎńÎyꪍ2@ľ"”!;ވaQľEĺ$÷)đ"T3DÔ|˜óQ3m˘ż:‡|ć2ĆţaŒ/L"§fľ8Ú9˓Á}”­â5Ÿ[­VŁVŤ188Čŕŕ`úź•Rxž‡ďűŠž@ąXźíĎŤŃhP.—ŻkŮžL46ŰŐJßüÂ=lÜ4•lŠß}š˜_Ë%,[ŇŰ=nyin Ędě˘SŕĽßyiĺYqݚžnIŇjŇ,ËşPßqú;Žĺ}¸ěy$óœJ€"!ŒžóڎÍpľÄČ`‰BRFsł}YƒŸĹAˆÖP˜*Ţ…2o Ţ)„(pwG ÍČŸ÷r.S”…\őŒýĎ9WůŒJt´™”Š.;+ěŃ’ —Œ˙2ÂPVBŢ"RˆX˜9q„“JᇱӕďÇ@•ÔĚŞLTšĺdą “T2Â2 "ŻŚIÉdmˇšT*”BАČ3bfXŇůŁHkŃ@Šs˜c"݉Eć˛÷H*Eď1R1¨i™V˘C220”а… =Šś‚`%%aœ.š—@3žŒťĘä`Lyä‘ÇÇ!yLŠĆń4 ĹŹ †Á¸„‘(ž~… Q¤„0Š÷k•R­f,k˝źRˆ €N'ĽÚöşÎt'í0 ůůϟâž{îáâĹKlÝşĽGŁ˘á/„Ŕó<Žy‡}űöńŇK/ąqă&ö칇_ţňyyäaŞŐjęć”Ҥ•â… t:śmێë:Ër+ąw˛ G–ž]ř…aÄŠS§Š×ęěżwßcI%™k-0îL0RŁ5™óg™í\áJ8KŰlQ´Šř{†ö˛ŘY`ΟĺJç";g9§> 4˝Žă’ę.ZĽ€9Čäŕćaă~Ć(’= AVŸ§ß˝âzýŽW´ąWs ű|ľEfÍ~Ë ěoŰk}öfŢ#}ÍańÎńsHBX†ĘŹąEO"¸ŽĹ7~ă16m˜ŕę\ Ă0X\ląníJ ‚0b~ĄIŃu) ԛŘ•D(ćć—8a)C cšďáĂGءoo ŠŹDÎ>ë•Ú/ C^ýu>˙ůϧTę˜:ŻŇs•$;ŚÓĹ_yĺŐŘÍl` §>űĎÎÎŇh´|ŸFŁÁ˝÷í_öžŽTúpŰß)$WÂŁy˘$ýŰ0ţh[\Ž´ŚC˘lĽĚ< ć}˜i#Ď-ĄŢŤĄŢŤýň2ňއspŒŔŠ8]a6ŹąŽąűš”’ĽĽ%^|ń%*‚0dßž}ŒĽ‰ÍŐŤsĚÍÍQŠ”Ŕśíž11śŇU=Z4łżżw“kzŹ}—–âđ,˜œ=—î Ôją[KśOôÓ9PóáŁTtŘľu’]ť7á:NŇNę#š–>^ĚMÔęc÷l`šŚa`ĂřđnqZ‡Ä4MÜ($’RuYGꆴgşWŚ”ú„őÔŹžű]~›Ć őŚŢ~h~ˆkrV„°ÔľJ‰űş˙2-÷eÎX+3|+Ĺƒ?r0&<ňČăłÄ”ŔQÇä/  śEŠßlL Dj× IDAT„ŠC§}^<ŐáąmEîOf%Ő§\IL{Íčüޚ Ç5éŠZm‰ýű÷qôčť=ú.—.]bϞ=üâĎąk×.^|ńE …">ř›7oJ“ƒ'Nŕűď˝÷>ƒƒƒ´Űm.^źĚšsÓÔj5<Ďcbb’Í›7ńüóĎSŤŐŮ´i#ArâÄ8ŽĂúőë°mĎóX\\äžűîăđáÔËe.^źČ=÷ÜĂîÝťPJqäČ;œ&ś™Œx÷ÝŁŒ311ŃřËǎcçΝضÍÂÂŻžúľZŻ}íkT*好•v곌˘VŤĹôô4ăă㌌Œ¤Iëj ܇¤R´;Žĺ€JćRöî2'˙ď8&=¸‹o|ő1†˔J.ë'GůéłoE’‰ńŽ?Ă[GOóëżv€ĽF›sć C4; ľć˛çŚďe~nĎóÓú…^¤Óîpŕŕý=zŒ'Ÿü5.]šáâŋ4›MZ­…B‘ÇŒçŸĎÓÖ×çřÁ~ˆRŠ/|á œ9s†S§NłnÝ:ŚŚÖóÜsĎq˙ý÷sđŕ>ÂĄ×ß`óćM=zŒz˝Ćć͛q]—S§N˛uëVöěŮĂ{ďŕ­ˇŢfűśmœ8ń'>8ÁşuëظqGŽźCŁŃŕK_z’ŃŃŃ;Č(Ľˆ”d>\b.Zęv{×D<0 sÔÉ%xľ\đQ0ŽŤ+ˆáĆD ąšÇ0CŐ<8×Dž‡ 0ÉŐ¨N-lŽBjvŕĄC‡X3ž–-[7óĆoréâ%ž{î9JĽ2AŕłeËęő: ŒŽŽňóŸ?EĽRĄT*ąoß>Ţ|óMšÍ&kÖŹá‘GĆ0 ž{î—ÔjőTçŔu&&&°m›ŠŠőüô'?cßţ}źýöŰLLL „`ppĽĽ‡˝Áđđ0ÜϚ5ăĚĚĚđ‹_ü‚Je)%ďż˙>_ţň—yó͡˜˜XËÔÔo˝ő6k׎áŕÁƒ aš9óĄ!b‹yÇÁuěüÜî盔SÝа €Ú˜Ęú*y|źŢýŒÉ#<ňřl‚3ŔSśÁ–/`A(v˜㠂H2żđ‹÷aë¸Ë[ç=F̈R¨°ŐľŠľ×űVĽőZŸýěçt:[śláęŐ9<Ďgzú<6lŔu]Ö­›`ff† bÚöřř8/˝ô2{÷îáŘąă>|˜;vĐé´YZZ˘X,ą˙~žűÝďáű>kÖŹall Ľŕ…^ŕ›ßü&óós:ô&›6mâüůóÔjľDôÔbff†bąÄđđH*dxůňe Ădll”—^z…8ˆišźđ lذjľJŠTęQŽFÝDÖ@Űëpxţ;łDDœç9jžOŮ*2n˛Łź#ű,%‹C3.'+ظRČČ&"ŒŠÎ"FĚ !P†ÁúŇ6lcő’–  ‚€]ťvrĺĘ,gΜáÜši<ĎçěŮł\ž|™˝{÷röěYî˝w ˆ­_ż>ôŤ×ë>|$qm¸ĘěěUŽ}—G}„ 9věccŁH)ůöˇżÍˇžő-vîÜÉěěUÂ0äňĺÚí6•J)%ív›wŢyĽ÷Ýwďż˙>Š]gĆe6ۡoăęŐ9Ęĺ2 ‹œ9s† =z”ŠŠ)‚ äěŮł<řŕƒŒŽŽ|¨63ü˙ÝďđÔ/đłçsúÜe|?$LŘ$Šk‚M›ĆůťżóEÖMŒâ8Žëđ…_9€ăřÉ/ޢśÔdbl˜Ż=ů ›7Nđ§ń —f—PÂB˜ŠH)üP&ʈ€Ą„ŰwڌŻá7Ţä̙łœ9s6u蘙™Ą\.łgĎ~ň“Ÿ˛aĂzčD¤ĐŕŃGáäÉSźúęŤ\ž<(ž}öYžůÍoŕş6oŢ ŔúőëŮźy3Őę —.˝ÎO<ÎéÓgi6Œąyóf Ă Z`óć͔Ëe6l˜âŢűöóěłĎâű>|đRJ>žđk7Änş@ŚvhËNĚSąe.oĚŁţýId­ ‚Hv‰ Füž(Ë@š&Ɩ âńľˆűGáŔ(Ćţa„m Ěř#¨C+ňŽy333Üł{ĽR‘JšLÇó8ţż÷{żÇńăǙžžŚRФ"™.\ä÷˙÷8}ú4/žř".\ \.sôčQ|đA@ĐnwŘşu ó7?ć÷~ďw9věçΝctt”5kÖpćĚYÖNŹĄŐj3>>Îĺ˗iľZ<ýô3üöoÓ4qœXťbqq‘Ë—/ó+ż˛3u9)Š4›MöďßǏüS<ŻĂĽK—Ř´i#ƒƒŐԚřvľŐg*!KaÓ0nkImwŚ/fŮyäqk)cňČ#<>ł`LśNX?‚ďjňJPÇ)UůŁÇřwŻ´ů?QcËń) vďynö›×e׎ݟ˙ţűŹYł†ššŤ´ŰmîĂ.U’4^iĚqٟĂń˘ľ Áef9ךfŘ`rxr™%j‰ ›ýˆČbÁźJ€O(”Bŕ„%ÖƉ˛!Œ­úšŮśMťÝ˘\ހRąMăüü<őúoż}˜'ŢgíÚ5ź÷Ţ{ěŘą3] úžĎwżű]{ô ––,,Ô( LMMńWőC<€eŮ:ô&<ňĽR)ľäâľ×^gçΝ8ÉNq†źđ ˜ŚEłŮäůç_Ŕu]ž{îyî˝w?çÎMłcÇ&&&řяţšíۡqöě9Ž\šÂř˙áŰ<öŘŁœ>}†RŠÂ|ŔţýűřöˇżÍ?ů'˙řÁ1†ÁÖ͓lœZĂď˙öçxů“|˙ÇŻđîű¨7Úa„m›”ŠűëżÂƒvPtí”8362ČoýúŁüÖW#’’0đšşŘŕ?;ÄOž;BӏśJť*›Ť‚ĄŹjľZĚĚĚđć›o˛fÍ8Ží`&­V ˆKS*‰pllŸ\(EĄŕ244LľZĺęŐ9ŚŚŚŘľkgRc044˜:v‹Eʕ ŽăbY…BӌK¤(—Ë1Ľßu)‹ŘśÍŔ@…LÓ˘\.sđŕAŚŚŚRkć˜IŚŕ‰.šş-œ,ŁuâNŽR’jK+Á–2b]QpâgÝ Q—[ČęˆŮ6ňľŤ¨çg[*˜żłăńľP´Rš űJżS†a°}űvŽžű.űöíen~žőë×S*¤RŠPŻ×Ă0e9ŽĂčč(—.]ŚÓńŘ˝űvěŘA…Řś…”qťUŤąžVš\Jma}ß§^ŻŁ yŸ źöÚëX–•şY–…m[ŠŤÍÔÔżńżÁoźEEŹ]ťŰś(‹”J%FFFŘťw/Žă066’ŒÍ…Ô^b7˜Ď˘sׇOđÉË˝îôşG­ Yó1yňřŒžř9“GyäńŮ řu/˘aD4 Á–H˛; 1ĽäřĹ6Ż4: řß~Răü‚âĘUT↘ŐôXÇa÷îlßžÀ( (—Ë9r„ŃŃQ™˜XËđđPjkŰFąwď=Œq˙ý@Q.—ĄPpÄuśü˙ě˝y\×ućůť÷mš/ľď @a'@€ .")R$EQ‹ľŰ3w¸5á ťűw8䞞°{‰Ű=퉙é{l-ْmYś(QśľP)@ˆ ÂJlU(TjÍÚr{˝?^fVVĄ@¨÷EdTUVŽďź{ß=ß=çűş;ٸq#űöíĂó<:;;yüńÇŘżŚiňŔť!‘ˆ“L&9räŚirîÜY˛Ůşťť1MPŒŽŽ’ÉLŃŃŃÎ}÷ÝÇáÇB°{÷nlťˆiš;vŒ–––Ňk&( ´´´N§ßsÂxrö™b‘˘çˇŽ Ň-š(ĄČ ĐEˆ‚SD ­Ô†Stm&ěIšŰétť)äňL§S—˜QÓä˝őz#‰PMjW]#ĚÍÍ39ŮO__íím€/Â:44ÄÔÔ4­­-Ü˙ýźúę^ß ¨šiIź‹Ĺ" őŘvŠąą1z{×ĐŃŃΞ}o055ͅ CŒM †UIŢNž<Ĺ˝;îe``żřóżäˇţŐ˙ŔÂÂSD›0 ÇqIĽRœ??H}}]ĹV´LŐ×דH$ˆÇă(Ľhll˘X,’™žářą“444UlRod1.„Ŕ˛L,Ë䉇6s˙ö5œ:}‰WŢ<Áš‹—čhЧš1Í÷Ź%lYč†V|ô<_ƒčüđ'Î^bdlš‡ĎpřÄ ŮŹŇÍJy˝Ąë„ÂÖ×néš$Gösöl„žž°m‡x"ÎCďáľ×Ţ ‹ŃŇŇB"'‹ŃŮŮAOO7ĂĂůůĎÎşuëhiiÁ˛,RŠ$}}ë|]œţŁÔÖÖŇŐŐAccCĹĹ'ŃŇâ×śśV>B[[őőőÄăą )YWWËČČš.ihŹ' ÓŃŃF[[+ǏçȑĂ<üđĂž‹ĆÂX–E.—ŁŚŚ†ááavíÚőŢç=!k!a–ˆO :ˆ‡›Đś×˘t‰ĐKsœ[jí”e‡`"‡ŰŸAš@]Ěâž0ˆX—DÄ}ÂP ˆ ‹°f]1Q“R˛}űv^zé'ěÝű őôôt166Še™ÔÔ¤1 ßUÓôŇqďÄ0tjjҤRŰşH?ét’îî.„𨍍%ÓÝÝI$ĄąąX,Ι3g8~ü8ÝÝ]ĚĚĚrńâmm­„ĂajjŇ|üăĎłoß>jkkٲes%'Ož$‘ˆÓŮŮÉĄ_ŠÖÖÖB$aëÖ-9r„t:M*•ä•W~ĘSO=śožI[[žçŃÓÓ\hü"ć˝Üyçţ*îŻ22Ťü.Ť~–oeď?˝t3HÝťĺž}3™Lp´pW˘Z_@)…’Ď~áóüΗżL8˛:7 ˛Aą˜'‘H\&ŠŤ”˘X, ëŇk¨HŠq]c\ =Emą@v.ǗßŢÍK ÷˘Ě$!ËŔÔ%˘0ĎşwÂďůK’!‰5‘Q-f MÂĽœm÷ůżeY+ y1Vd2łX–…&u\ĎÁuB!ŤÔ"*+…b˙§˙oxyě Ž˛K–U …çŰR kŰŮTłžśHőá4 3F&?Ă×O˙ ç ƒ´XM´E[i 5'‚( Š^x$Άć ÄBą ŠPý|͘cǎÓŢŢNss…Bď|ç6lŘŔŔŔ †Ą“JĽŘ¸q#_ůƟ°gĎz{{Đu?,‹ěÝťË ałłsŹ_żŽŚŚFţţď˙ÖÖ6lťČääťwßÇOú =ö!Z[[9~üĂĂ#ŒŽŽ2==Ĺżü—żŽŚiœ8q‚éé ŽăĐÓÓĂůóçq‡h4ʉă'éěę@×ulŰƲ,tÝ`vv†x<Îää$}}}ŒÓŢŢÎńăljĹâhšdçÎ{—1J)ććć‘ŇŻ ňŤN˛ĽĘ*UŃ1˛m›LfŚ"‚Z9|J PĚĚů•(‡Ž 2:5Úöś­oÇ0üž–š…<‡Žň—ßÝÇޡNbŰžËĂrŐ@)ÉXˆßţOó/>ó!4]ŻT4c ˛ŮśíV„ş‹Ĺ"†ĄUâRž˙lĎáčěyţ`âŰě÷Ţ-e{0’E gaÎöoyǗ45ˆś a_äˇŕâ˝=…š. ?Ԍ¨ľ0ĐŘJ˙śáłěH­[q\-žcżxI˘çyĚÎÎů•TšÁjŒÜ\×%—çţŕůŰoţ ŞT…xľc{7]ď=ĽXŰŰÉúżÍŚ k—ˆÍŕƒÎ’hÉ5ť `EŔ)ÝÜŇÍŤşŠŞŸŐ&ZՋ†ËśLƒĘ˜¸Ż@˝§¨őTEdÔŇĎ+VƒN`š~Ņ˝ ŁGăčÇŐĺjňÁĄźŠp•ÇÄ C ădťâ†„PH„/Ä+AáđfćGfOSc$Š %Š3S¸žËéě9•ç´{óů‹čB'ĽÇH)ş"í<ďňEgŻ@Ā߂˛~ýzÂáPI`Ňŕ‰'ž@QŠşˆD" Q__O_ßz†††*-şŽóŕƒ266^ŕŐ‡CčşÎc}ˆP(Äěě,}}:étš§žz Ă𗠽˝kH$ôööTÚ4McýúőLNNâ8.„ĂĄŠśĆŮłçčîîFJICCŮl)ýD|ff†-[ś Ľ_ĽF ‡ĂĚĚdhllźĄ„Îo9Ń›š™Ł˝)ŽůăĽ<0jÓ \×cۆNÄŠ üŕăÔŐ$ioJ1>=Ď /żĂ‹?}‡ó§pŃA/íC)ľd}%uşú$­Í5>ŃI@Ŕܤ4é)Zľ¤+p…o…˘& ˆżDőOú‡?Ş# ¤Ŕ+ş¨yÇטI˜ČÎÜ[‹¸§ÖÁ”U ^­ž:-šš”|Ůl @€Ü|dL€ÜĄdLšüJřŽŐ;ŰĂhíʈŻ; ¤$; “CŹ\ #JiĹľi…ďžTÖz\Y˙îfÓ;eŰ'Qr}’TŰ5ßiđ<ůQĆó ]*mI˙w)@xŕ…-l°™*Îs.;ŒŽoßé ×okÂE!ŠĚ9Y.Ć):6ťęv\ӒV×uRŠĹ¤RÓ4ęëë–<Ćq”ňřČGž$ŇŐŐYŠňŃ4p8LGG{ĺX—w„H&“UäO¨ňťiš´ľľ^ö™LÓŹčĘTżŽiš<ţř‡¨ŤŤĂ0ŒË^ŻŚŚŚň{YtšśśŚ˘SrĂcH Ç叾ń ëťxâžőlčj"2ŃużÉ0­a‹X,̙Ńiż€‚˙ë[ݰďíłŒMΗxe$UÎÜRhtCŁłľžŢŽFßęz…Ń"*fgjŃjuY’/nĺdRŇcÜšŐpAÚJ°No&‘3#s(*˘Ă}uˆM)D… •Ú•„đە˛ęRut÷ÍqÄń ňŁmđL˘ĘE(á…Ůdu˛â•ö˛ŤÍnşMy‹ąšěöeî^ĺń´n @@Ć @€÷J”’9Ÿ°X$WĘ+uŻ’đ-O-÷ﯝEˆŇ+ĺœ"ónŰs/ŰVU÷ˆĚMŞó‹rÂ!¤Ä: =Œ!äť]tNĎ 3™Ëb{­Q"b¤đ!„,ýď&p=…‹ć‰’¤+?ž,}‘4Ň$Í$Rțbó™L&ń<ÄbąËÚ}źŞś‚rťHšíŚ-4tý†+\Ţ!hkmÄulţňoóˇ?ígko3żöŃűŘłľËԑĽďnšÉD”Ůůoô_ŕ‡ožĄ`;xUm ⲑU"â!vlꤚĄöŠ”ŠBQt]ćÜ<§ˆţyŁ*ŸtYkLéuÔ #L VźĽç ŔŇ ÂşIDW$!Ţo”?“Šě őňĂě;ô‹ ńqîŻCx %DI,Y,9śÂůĄf˜ÎŁ^E„%JAťVÇá>šɊžsŞ4§ °ńČÚň^W•çQľČŔ]Îu­j^\é~e˙?MhÄt‹°ô{ƒŞœÜ řî~Ş" ´ÔdL€¸sľEyМ_,_ő şŽgčx×ŇľQ࢘wňLç™-dY(äBE15MjĽýü+_¸ËŐŐ˙WJU%‡+ĚłĎ>[y-Ó4KvĚ:ŽăTt>Ž7Ń~?zR ˘‘0_xj;‡˙ěef {109Ďű7ľĚç ´ÔÄ1M‰Ě<Nňɇ6óˇ/˝ƒ-%žž4Ą_úŤ_]˘KAks-Ů˝‘e^vƖI–œk3]̒),0[˜őI3LÄaHßíÇ+‘+k˜¨JŇžt\ůçžD\^FQ"×\ĺRô”&Ş™%îȊ‹ň÷^›hçÉ™Í ¸cL Ç˙ĘşDů’ž—Í/(…ŇAYŠÂ§ťš¨T—hB’ň"Ѣ|2Śě´TzŒŹ$܋mM‰‚”Ľ1܀i\Ű&ŘśmΜ9ËŋCD"Qz{×°wďkÄb1Ůşu Žăŕ8.Ÿüä'§ż˙(ĄĹĽK٘ŚEwwcccě߀xúÜł ’ĎŻŽŤ8xđ ™L†X,Ćŕŕ kÖôpâÄI ä˝˝ţţŁ477Ł”â̙ł8ŽK8ftt”P(Ě_ýŐ7xâ‰ÇoČbúý&eążúô.Ćóű9pvWžűÖr śv5 €T2ĆĽŮ/žÜĎŹ'QVČ/iQËĆ!ţ`“†äšüŇŁ[|‚j…˘č9䜧&Î3š™ŕ[E)ĹţŁ d.ўn˘ŕůťĂ/ńhď˝ĚäćH…ă´$ęé=K܌s Ld3ÜÓ˛ŽĄĚ8 °a2>?M&ˇŔžŽ­\Z˜Ćő\Ňá8†Ś32;ÉOíç?<őëŇŔQ.śrą„qÇĆ |{éÚD _*<ƒ3鱗S䤍WLžIÍR’Z"ˆz!ö8kůRĂÓ4'ę翕fá)óvŃŮINŒçš  ExůĚ[ť4ŔŽÖő\œçěÔ0†Ś1Ăd 967­a 3‚Ť<˘f˜í嗷?ÍđĚŽrI†Ł9MWş‘ńšÖ7v06;Ms˛ŕÂĚX‰ŔŠĺ‰Ţ¸Ľó&¤Áe1@€ďeő‚§<”ňJ-Ë> …¢“íTŽWŽëĄ”_É"ĽBá–ZmÇY˛&RžByĘ[źPşŽ‹ÇőJ•Ą‹ŽĄĘóπŒ  @€;RJrů"˘čbz KĹ˝ĽtÁó”BVi}”ws=ákĘxB”Dp%ÂSDěGÍP°ĺ5íF•ň/ş“ŮYtŠńłło3™Ą1QÇÄB†îšVl×a|~š‹łăŹŤkçOžÁÎÖ>öăÁŽ­d˛sÄCa&ł %b…p<˘kcťƒÓŁüă‰× [š×0:7Éśćľdí<Žç—ązĘťs/šRŁ>‘ćÉčœ&Tš IDAT.öä6qivŠĄůIfĆ873ĘéšQ†í óp•ƒ‡đ+fĘäL•(gYcF0Đi°jŠÖŹrĄâ?ĆqźŠîN*&‹aYĄJ+’^iâĹu}{fÇqJ.H˛˛@“Râ8B\wńž\.G2™$—ËÝ}ôŚşĆÖŢ6~ő‰ćěw81‘#ç)žwx€ƒ“Ô'",䋌NgÉmjSHŠ]1nžňp•ËĐĚ˝őíźvîŽňЄ$ďp<OšĚsœ@“Ç.çÁîÍüŕä>ś4­!‰“+ć™+dy{ř$ă Óô5t6, ŽÍD6Ăw˙”úxÇsé­kÐ:yŰ'Šę‰âNW†őŰż4újťřMů1â?će÷=‡ˇ˜^\qT’¸cńaśđ+őąśśS3Ž:–ō=ĺ‘s ›Á™1Ţ=sĆXšáŮI<ĎoĽ,:6.ăĄîmź3rC7xkčńP˜Mk˜ĚÎPt‹œŕěôEś6ŻĹvŠŽĂL~ž—Ţ=Č\!G]4E&?ǎ–ő§¤Ó%/¸(ŕ=Ż+kŇ)’‰8ŚščŇ¸ąŻ—=rk×tHÄKkIC} éT˘˛~BLÄ1 Łâ¨ ëMu(ĽĐŤîŻI'‰DÂDJNžłĄ¤ľš)ĺ]łĄ1𠆲ĂM>ÚMfđűDBxN%őP(<4&œ-äě¤QŞt”mS˜ŸGzŇv P„ĐBÓđŇ5$śożF{‰@‰&%M‰ZNŽ ĐQÓD[ş‘Ÿž~‹=][ĐJ˘˛RHj" 67­á•s‡¨‹Ľčkędtn‚°iQIrtôÝ5-LĺfÉ;Yl×EĄJŐ4 65ő Eš0=JM$AŢ)VD)äo#˘iąhŒp8L{C3÷ÚšbžŮb–KÓź;>ÄáÉóź›cÜ] ˆŢń^ßQ „đФAW´…ˆYŐű'“ úúú8ţ<›7o"NÓסžX,JKK3†a i7öąyó&ćç#Ž088H{{;k×öbŰ6ŹYÓCGG;““tuuqúôiÇĄłł“ááa>űŮOóîť§ąmŤJÔöŽXŒ AIJxtëZL]ăżž|œwFłŘ\Ę9Œĺgń(!Q†ľHN.SÄöV1žßŘČŻ=ś•öŚ:4)Żrş tĄah›{řłßĺĂëv1WČ3šÁŇLtĄa+ ŠŇ™nb|aOyěîÚLśX`&ż@"çäŘyÖÖľ#Ľ o14Çsą=GšěîÚČĽŮiO‘ů-1‹Äƒ?Ćďt"ڞ@ŐtÖÖtđ[ćÇŮ<ÖÁßçöqÚ ‡oe­V b¤’˜JcmĄO…îçŃĆí4ĹęЄś*2Z&5bf˜°aááąžĄBąXj[Ź~ŇĽĆşÚv†gĆAŔúĆ.ÎN\ŔĂÂQł…Ző8ރíÚ\Cęlnî&Žńúů~’á(猪›’ $-x/đľ["%÷Âę9°wM=Ý— öG#á%•B`Y&Śi\śŠ–ÜŤ§Ôp8\rK\Ô&ó XŽ€Œ  @€;4Y”~u‚”’ô†‡™Lw‘ÉLBŮͨlł˘hz˜ˆnÔłÓÂÚąţë×ő[j”B”.˛ĄXŒĆŽŽ+ťä”ZgšAX3ŮŇŇËŘ|†Ÿ:Jńü–GčH5RtŚ›H…cX†IÔ óhĎ˝ÔFR LŇŰŘN:g˙`?{şˇrxř4›zˆY!r9>ąéQ !ŮÝľ…˘cłšą›ˆaqjlçúĐ:IX3ĐT•>Ζ$V˙.ĽÄB†E<ĄÎKљnd{çz>ZČ3>=ÉŠą ?ĂŃÜ—ÔśňwוP8€†‡iFX—hÇ4ŒĘNŇU/ŢşNWWg•5ľd÷îűBH$R˘”âţűďCÓ4âń8 ĽžđÎÎ4ÍONzhOĺ; !řČGžňŰDjk*çdssBvîź÷ŽߍnRB‘ˆ†ylűzšÓ1ţď—óĘp‚ăâxĽŽ$żđeюşź˜ kASDňš-üŇ›hŽI˘i˛2Ž*ç…*iœżŞM–0čH5ó܆‡řŰ#?F)ŘŮÚÇ=-ë04ßnüĄîm´&ëŠ 'ŘŐŢGwŞ•Ą™)Zq64tqběš˝“-=혆šÄ-bŠťĎĺC´ŕ9dě<ˇPq ¸â1_žŞ~ ‚Cj$aŠßöxfł9lŰ­TT‹E CťŚ3WľžŻy pńČ-d™˜šb4;ɸ;‹DPŤĹiŽÖQ“ND}B“Ľńšę÷VĺÁŸrJ-^ „ťd ,Žâe˝$)*Ď +ÄŠňY–˝–CÓIęai oŁ›’çyĚÎÎašşf°šÂ×uÉeçůŁ?řCţö›ƒ*ľĎŽ–üşÓŻ÷žRôööđď˙Óďłqă†Ň9ü‹@š,?koőßnOLo] V¸_]áńj•´Ă !áXj7l 8Ľ›[şyU7UőS]ť,AeL€ź}őďe˘çjšâßçJ•˗Fai YqňnqQł@á ßÂő“@`J4ЄD ßąŚÜŽđţ\ÂĹŞbWMŞ•ă¨-K°5)ŠMĽI&lę^Ë\.ËČĚçf.‘u‹ěné#^ć¤síŘ^ßYą<öWJ–îž$ęęçwő}š”ĢžÜš™ëć852Á‰ąy.Ě™.@Áő"š¤>,éJYliJÓÓROŘ2ąt!W™l–LÎLŠ‘6Â䤆­ÜŰzd Ą’†ÔޡĽËßV\ך*‘%Í%‰ GiS­xĽö.ż˝H–Ź[ĺő“„ň™)$5F”œ0(*§Džů{ż>łĘ¤F]×ńĎM! ISj‹Ň2łH ͈˘[qtË H€n*2&@€nsŇ¸źˆ¤œĚW™kíâŢ$čňÜČwţ ĄŇôĹ\Bąč$sŤĄ|!âËš[üćKŽť¨ŽXzÇ´Šœ€Ô4tM#d˜ÄÂQškęŮÁ†“Ôĺ,V:eŊ1źVŹ*šaHȤ­ž†G‡BĄ@ĄPŔu}]׹B–e!ĹŇ˙jÉž/’[՟ŻüäŰŚ~˙˜zŢr…T×Ô+šŠUt ¤źâöZÄóŐ™ňYĽ!‰!Vˇ |Ľ//.ęő̃ˇ9`~¨îôƁř`! cŕv%ÂĐôlĚ%âfŤMîoWbť$¸­â-%˝!üdDܞýaŰśKńŠN—ZA^OÂĄ˛<ĆŤx~€+'řŽëĄi‹ şŽkäóůŤśž\)šWJaşŽ‰D.ű5°š-ю)ľĄÜďGœÜ’EęŇvß­ku ˙Œ‡›7†ÄHńŢŢövWƔÔüů*˜gŕv cŕvĺBĽ…ŽŻ™ SvćXž *ĽnŮűßiip‹mxUÉ&źP(–ŽOuՃŹÄęŠâÇ×8ޡ*–ż¨đ<l6ˇÄ"Ów"ÓÉçs˜ŚyÝ-*Wľ;^ĄĘâzb*”/Ź~›N”ňINĎó0 } Šĺ8śmcĆűLśXœ %—ˇŕŘ ŔíBŕ› @€ˇ…c•ÖÇqYXČâ•ÄzWzÜ­¸Ý=ŮÁíIşĘIH6›Ĺu˝%B˝ĺXyž"›ÍâyjUU1nmҘËĺ|‚L7*„LŮ}JJšššRŐĹľÇâňvŁë!oŽJČ,7›P <ߞžZHřVßŢďXŮv‘l6‡Śi÷Žę˜ełYÇ Ë;€ˆńç@]7îžëE€ÜĹ*cŕ/WŇJĐ4 Ó4ąm›ůůLÓ¨¸1U™&]ç‚úňç\­ äJ_üœ7ţž7ó3ÝČ{Żţ~QŮ ö<…išKŞ-ŔßÁ/ÇjvvË2Ńuíş?Ďő;7ďř\ďšt+ĎŁkŸŤNçš‹E_Ŕu˝Ťdܢ´ąŞJI×uLsĺ6¤2y&„Ŕu] …" Îe:2nmŹĘ ˘ŽëX–qYÂXŽ›a•˜bŃ&—Ëăşn0Žn[ŹüÖ>)%†a`YĄ“űň¸˛, ×uq‡|~Ďó‚ąu‡ÍŕÖ" cŕ6/‚Áß–RâyĆÓZđ‹ƒęv•r –kˆ”cĽiZĽŹ?ŔíU9QźZ …RŞBř-f^0Žno´bĺX­łňă4MĂ0Œ%ą ô–îŒ90@€ÜZdL€Ü\ËÎrŠĺIG„ÜžddĽxT'őˉŸ<ó‚2ţۘ,^iě\O\ƒńtâUČQ¨%"°×rśŞXż ¨eBć´—˝s`@Č Ŕ­G@Ć ŔMLŻ”.&‹ Üĺ1ŤMƒEňőŁú؎䐳üďĺ;ÄŐ1 ’űŰłë!b–Ç(ˆ×mŠŞâFśÚŘVŃBPÉâuóŻMKçżŐ́ŕÖ# cŕ%ýWJ’>‚[őźRJs AS!DĐ&sCqY<ŽžđĺbâX.ŐŻ&`–—í;ŽSzN,ŢÎxA™ÄôŻnŠ&kĘăbąLQś2ZŒWÉÚhq4qíʋëyÎj^ď=ĽŐKž×Í{ě<÷ňǔǕR~l4MrE‚şż˛NĚňąTf܊ąÄ’8-Ćqĺ90@€ÜzdL€ÜôĹďʋYĄK…„Yꤤ‚ń[‹Ť%ŽëR,ÚK,wcĽJ žW‰U–Ű?ŽĘ?}ç—"JQą!ŻNŢ=ĎĹó< CŻú9ůŽçí„ç)ŠEĎsĐ4˝ƒĽd´ë:čş/ä[=&ƒXÝÎ1FÉŠĚŽˆ/מ¸}ßŕ&ăjŁžçťť†ž˘#Ě՞ŕĆbqĺhšÄ4u<Ď­8ď”ürőRŮŇ:Ëű3ŽŞE|-ËüJĽj˛Ćó<ÇŽ¸Ă,>w‘ˆQĽĘłj~Nš$ˇfq)–e 8Ž˝äŽëVˆĂ0.“n'|},Ó4*s`€¸×Ëŕ ŔMXŇŽ˘uE)…ëşhšDÓVˇ8-Ýú„żě–TmƒěďÜť•ňýŰuޏvź,ËÄq-ĆËmdž“’~x)J´ŒľtŒ]íŕúĄëzeŢ[ZmĆŇěFÇSŸ÷>žĘâ䚦áşnĽÝ/@€܆ëdpŕć,jŤîĺIFu’ŻëÚu%îŐ˝ü+˝v€Oć“FƒbąˆRz%NeWĽŐŠ’Žć˝‚ž÷qVnĽ¨NîÇ!‹ŹŘ꧔˘Ź¤UR;Y6ŽV3žŹ~L•ö?×u+•€ţ¸%Ľ{í•bśŇŘ âv Ž“ĎŢ3I @€Žcî A€ÜÜdq%ĘĹ\wU ÝĺŽKŐ¨vYÉăÎ^HŤ›BnÜŹX-&ŕşŢ’Ö—Ý^’4:6v!‹çRGGš†D{ĎUe›íEńÚE§”jAŰjビěŤ%6ăŐÉţŠq.v˘ę4ŹnQR,j:-}.Čk­wúńşÝŸw%"ş|.ú祋”úuÇüJYË-č—ĎĂ׳j‚ŻŹ_SÝFľü3]Ďą˝Ňçń<đJçž Iąô\˝M1óĹ͗ŽŤwď<šxłDřüz_Łüü÷Ő×0)eŠĘÎŤŒË˛ćލ'đ\!—^—o~äd€€Œ  @€ťŒšRRr˝‹řjw‹ędÄś …ŚiTtŽ•ÝD̝EČŹî3ßŘçUŔěđ)2/ţ{ŒáŸâę1ôOý9 vƒńŢ‘Žë2??O8Ć0 fff1M“bą@,Ç0tŠĹ" ¸ŽG$&}`49”ZNRŽĎěě,étÓ4ߗďQ,™™™AJt:MąXd||€x,F*•ňÇß ŽĽ<.‰DHĽ’Kž˙ÂB–|>O:•B7‚t9@@Ć Ŕ]ˇş’ŁŇjD‹–Żţâßq=ćr Nrćâg†&élNłŽ=I{s Ńp¨" źÜúwľÉÂÄÄ ŘśM6›%‹­j!6;;‹ă8$“ÉwŤ<Ľ˜Í{Lg=ň6ÔD$ЈÄĐňŽÍkŐ{ŠżëÚ,\x5v€˜˜AÉ,÷ý5Ý[‘şqՄőZ˜˜˜ŕ[ßú;w§‡?řƒ?äK_úůęWżĘ˙üo—x"ÎkŻ˝Î믿‚ľk×ňÜsωD>Ŕť|âŠD@ـy1ąW؎ËDÖćœͻ™çg.ĺ<˛žDâ’0$-uIIg2D{Ü 204y]ăĘu]&''ÉçóX–E}}=šŚĄ”"—Ë‘ÍfŠ­­˝%ąq=EÁö˜\Pd‹SR„L Ë棛EĐ܌שŢݡm›B>GĄÇó<4ЁˆRaů˝ŠĹ…b]×1M󲖛Ť}ŚrŹ^řÎ <řÍ--ôŽéáÂĐ>ýéO‹EÉfł„Ă8{ö<đ†Ą“Ďç‰ÇăX–E&“A)E:]ƒműÉd8ćâĹažő­ońťżűe4MĂSÉzüĂŰYŽŰŘüě´dĎ‹GzĂÄCÁn|€CĄPŕÍ7ß䥗^Ćq4ŠńkżöŤ´ˇˇűë))ŘŐd˘”˛2ŢŘťw/Ď?˙óRФ˙?)0M#8ÁdL€ÜńiáýŤŮYŻĽôŸçkńu~óˇ~“ŃŃQŽ=Ęý÷ßGCCĂ5‰‘‘ňů|)ٗ•Ş˛˝đ\Ţĺ‡Gsœźd“É)Ö5<ܢˇÁŔÔ?xI‡RŠb>Oqô$Úü"ä"5 ÷ü~˛™qĚh˘˘[r#‡ĂÄă Μ9Kfz†––6bŃů\žbŃfvvŽŸýl/Ď<ó4=zŒůůBĄ0š&îęqľrűŘ՝xTŐÍSŠů\žˇ.ĺyeŘćÍI›ą˘ŔöJç¸ň[T „ƒ%Ą3”ăŃ&“=-aúę"˜şŽ” ĘĐUŢ;ŸĎóÎ;‡9|ř„Đčë[Ďc}ˆP(„RЁAě“_ůďžxÍ*‹r+Ëňo§ÔJc\THݟäŮwÎáҜKsBcW§Ć˝ôeď÷^[çŽTx=sdőëyžG.—caaÇś‘R ůžRÉQnąńuh‰çšäó9 ĂŔ2-?ů\Ĺg*“Ţëׯç‰'ĂśmΝ;OĄPŕčŃcLMM‰Dă­ˇŃÔÔÄáÇIĽRtvv`š'Ož$›Írß}ť(mŽ9L"‘¤ŽśŽBž€mŰ˜Ś‰Ťŕ؈͉Q‡šź"b$pp Čş“x(h pcp]—ŠŠ)\×ĺ‰ÇŸŕ…^ŕő×÷ŃÜęëë ‡ĂLLL044ę3ghiiĄŽŽžŁGűŮ´içϝ§ŁŁƒů…yFFFxîšç8yň$gΜáąÇăđ;‡™œšdǎ=zÇqXˇnŚi200ČŚMŮťw/ är9fffhnnćž{îa~~×uyäŃGٿﯞú3ślŮÂđđ0˙îůwzëmžůo˛óޝ ŕwŢatt!uőuxŽG6›eóćÍ‹EŽ;†Śiôőő‹Ey÷ÝÓLLLpňä)š[š™ššâç‘ĎçXˇn“““ŒŒŒ0==ÍŠS§¸xń"mm­lÝś…p8´ňȘ¸Ű’H?‘\]YžçyţÎýÔ4??z–ˇ/8 ,$-4 [!T ˜ĆLśqÉčâĹÁ ޝĄăŘ ś5KîÝÔEc} ŚĄ!ĽśŞČq\:ĚÂÂSSSœ??HKK /żü ů|žőë×aŰ6gϞeÆ œ?žl6dž }‹EňůůꟴÄb1>ôĄGhhhŔqG/:źv:Oх!9;nŁIhNéws3´b*IäüsŽFŞůŠ"‡™8F+ăă$Zz*ůű$ŔĄPˆ5kÖđöĄwčď?ΓO>i™(%p]'—Ăó\Ňé4şnĐÝÝE(ú[/ŐY1.ž‡§2 źp.ËŤ#sPt=<Űg–żBAŔ†Ď;ź59Ë3E>Ô§&l"J€ŕĘäk(˘Żo=ǏÇ4,şťťŘż˙çΝ§łł)5N?ÉŔŔ ű÷ďÇó<xŕFGG9vě‰D‚††ććć¸té;wîäřńă8ŽËƍ}Œ ’ËĺČdfhjn˘PČóŔťijjĄ1•őřÁń<“sŚcs/rékQ“Ü,nîfşŽ•ÇĐÂÂ< (Ď­"[ Ÿj-Œj{lQJ”ťˆë¸D"Q–ëŻüy}bëâŋé?J}}=žç'ˇýýGÉç ärYZ[Zhnj!•J100ČČČ…B‘‰‰ fgg‘RŇß Ă08sćů|Ý÷ß_ŃĽ*Ďą9Dž MQS02ë‘Éz,˝ŕ˘ŕ=ĂĐur9Ÿ”ô<—W_}•ááaîšg?Űť—‰‰ ršťvíŕĐĄCÔÖÖňłWĆÇ?ńqöíŰO<–ŕŻ˙úŻŠŤŻ#ŸËóä“Oň˝żÇůóœ9s†śÖV¤ÔˆD"8Ž‹m;üŕ? žžď˝ř"‘p„wO˝Ët&ƒ”’üŕ‡|ěcăŕÁƒ444đÝď~72“É008ŔÇ>ö16oÚL}}ŸúÔ/ńÂw^ŕÜšs|îsŸ+9ćtvtâŘŻżţłłł(Ľ8đćö˝ąx<^úŽ÷páÂ~řaΞ=‹eYŘśÍoźÁž={řîwżKSS™L†…ů,ßüć_ł߁ŇF–ĆG>ňJ)†‡‡ůă?ţcÖ­[ÇŮłgI$Źí]‹iim}2&@€îÖÔq1ÇęŠéĚ,?ţŮ>޸ dÜ$„k!d˘<—ěôťŒüęv|ŠXű=ˆD;Ă^g'8ś0Ç˧˛ŤÉĺ™GwRS“B_…Нçy yžň•?annË ąďœx;LĘó˜Ë™JmCkÝBA‚í)2Ó6Ůy›.×}OŽ%şŽÓŃŃÁž}űšték{× ëůBŽ#ýG*;œ˙üĎ˙Lss ccc|á ŸçîŃęššđ”‡ă).ÍdůóăóüdÄaÖ. §^}Aí.`ťŠˇmÉć(:.ĎŽIľ 4 ÚUâ¨ë:őő $“)BĄšŚóă˝DŃś9tčO<ńa …Żżţ:,Œb IDATţźdÓ­ąwď^žzę)Ξ=ËÄÄ$ăcôöŽÁ4MršgΜarr’Lf†Í›7qâä)tĂOžNž>ÁŃţŁěŢ}?çć GÂ)Éç DŁQ"‘ĂĂĂhš$‰ř9–Ĺšsg‰D"äó„ds9ćçýöO!íi¨%™^PĹԂGkN*¤ Ŕ{ĹŋÉç ôôtsßý÷1>1Acc#<ňöŐ?Ł­ľD"AoďZÚŰÚůÚמĆÔä46l •L#…FĄP¤X,ŇŃŢI4Ľąą‘Úš:Nž8EWWýýý¤Ói>óŮĎ …FG{mmm|ó›M!_ŕĄçćG?üO?íˇýéŸţ)ŽăáŘ.ů\ÇvQhšAWW{öěÁ4-ŚŚŚş0Ć ™˜˜ä•W^a׎](ĺ‘Í.0==M>Ÿ/iD tÍż&nÝş•ţđ‡|ń‹_äk_űĂĂ9wî_úҗ˜ŸŸçßřMMM´´´đěłĎrřđaÇadd„ŚŚ&ŸÄޚ‰=ö'Nœ ›Í291IO÷šťKú.@@Ć @€+-ţ/żšŰŽĂ˙úG˙Gë>ŹíŁD)Ż0ĎÄńď3źďŤhŃ(VSz8‰Đ ”^Ď,u,ĐÁéóďňłŸüGţĎ˙ýC†B—ľ-­Ó4ůҗ~sçÎóĆ˜›Ÿ§Ł˝ƒÇŒŃŃQ.ŃÔԈŽD"aÚŰŰyĺ•W‰Ĺ|†™™ZZš—}GhNI_„!00ĺŃQc`hĚՌë)ŚgPŃzźt’˘8ŽÂsژĎÉfłÄăń~})%--Í<ôĐ6oÚLm]-JÁƒ>ŔŘĽ1"‘0Ÿ˙üç8~üóóó<˙üÇHĽ’Ť:>h¤gŮ%ibžŔ_œœăÇĂ6sEO­~_łźîś=¸˜Uü§ Äe†'zkьë!}-!Ă4ŮóĐC˜ŚŽ*šéär9ÖŻ_Çúő}$“I^|ńEşťť˜˜˜ X( [ŹYÓĂŠ“§9}ú őőňy”R´ľľRS“ŚŽŽŽŮŮYrš\ĹŇť-­Ą A*,ątÉů)M´Ľľ;2^e͊ٙi4J9SňĂĺVĽe„L™dÓ¤FĄGÓ5LÓźj ŠŚilٲ )%­­-€ŕŃG! óËżüćććYż~=­­-œ={Ó4řđ‡?Ěŕŕ}}}466rčĐ[är9}ôQzzş¸paĂ0ظqRňůŹ˙^B°ąŮŕĈÉ;CEf ɰ`g‡IC< cÜ8¤”˜ŚIWWŸ˙ü¨­­ÁS.ąh”D"Imm-=Ý=ŘśaĢ1şşş0M“LfšO|âă(ĺë[ĽÓiÚÚÚIĽRäóyRŠ4<ň0˙ôO˙Äşuë$ ÓŐéoÔD"üq~˙÷ţ?ţ8ú60|q˜ţţ~,ËdŰśm´´´Ďçxő՟áş.áp×uŃ ­$JŻ“Ëfůя„ŽéLMMQ__O,CJɋ/~ŸńńqvîÜIMŻÍdY&ńx‚T*E2™¤śś†h4J:fŰś­ô÷÷S,Ůšs'Űśmăűß˙>DA"‘ ‘H000€ahšFmm ŽăÉd°m›m÷lŁ˙H?ž§‚Ľ @€ôäqa!G.eŁkH^Ą<—Ba”ńƒßĆ)d™8üO¤ś”pl˝oŤ$.ŕ*Ł`n~ĽVWňnY&-­Äb1Ňé ľŹ_ßÇK/˝Ä‹ß˙ۡo§žž–T*ɖ-[8~ü8őWĹ}÷íÂ4- …<Ÿů̧ůťżű6ľľižřĹ/úɐlmŐ98`0:ç ýĹB‚­m1ëF(łžXt˜œ˜"âIĄI<ĎÁ°BäóĆ'ڈFŁ•6‹!ń Ă`׎¸Ž‡ač(Ľřâ?_YŒ !hllŹhyü˘- +•fJ‘+ŘěšĺÇ ĚÎGŸŤ00UđJ7!ăó‚˙v2Çúş9şjâ+Ú/YléÉdÓ4ijjf˖MźńĆklذ]ťvŽX466rôčQ8Ŕ3Ď<ÍGžzš?ýżJ<gMo7u–I"™Ŕ´Lރ“›EMJŐcY1” ‰*Űâ …Śů$ˆŽë•ńą’–”’mŰś.3÷ďŢu™u<@Gg{…ôŮśm šŚĄi=öJ)4McÓŚMôőőUĆăłĎ>ƒe÷'ˆ˜’OďŒđh_ˆÁI—ľ éˆôí­¸AhšFoo/ ´´6ĹXČ.°k׎RĽ^Ďüc:t]×éí]C$ćŮgŸ!›ËŇťś—|.ĎGž~Š5kÖđŤżúßóîéwYÓŰCWW'őőuDcQ:;;‰Ĺ˘$’ ë‘R :–"‰pßýťhkkáŸü8ű÷íÇSĎ}ě9jŇ5<ýĚÓ\ş4Ć'?őIš››*äąišHMŇŢŢΓO>Éť§NŃŢŃƞ÷ËĺxöŁĎây÷゚{wěŔ ™ĄŘžc;słsÔŐŐńĚłO‰DxřᇈĹb44ÔsđŕĎŃu{śßC<ÇuFFGyţăĎłĄŻŽÎöî݋çyôŽéĽśśŠI˘Ń>řƒ<˙ńqĎömč†ćkŠp Vqż¨úťüťŹúYžiĽ›^ş™€¤îÝrĎž™L&8Ú¸Ť“şŠÍ´”|ö ŸçwžüeÂ%›ŇŐź†ëşäóy’Éře‰[ő{m‡Żüٟó§L;?‡’‹źšrŠä/˝Ë‰˙ňKgưęťXűëB¤c+šfR–¤J1˙Îwyžö˙ć_ý–i-j.\ç÷^ŢFUžďJí—˝‡ňâĄi‡c#“ .šuÖ7šDLyG$„ž§˜™™Ĺ˛ŹŠŁ„ë:„B֪ۉ”ňK-Ďcrrœ7źEcc“ŸkÇq™›Ÿgzr’†ş4[7o" ÝT’än˛]~/ßqnnĄ˘PyM§“—ŤJ)ŠŽÇšÉyţóÁI^WŤ&'ýsšdŁ˝äźV†„Ovjüë]Í$Ă&r•„×j4‰ŠE›×_ŠŠi2™ ›7obǎí2a兛(Պ,~v˙ý “ó8Ÿcf&㻗T‹B€r S#d†Ž‘›ş„r|ˇĄéÄęۨíŢJü˙gď̓+;ĎôžßŮďžß ŕbkFďŮĹ7Q”8˘=#qFÎ,.k*•ńÄIUœe*ŠT%•x*ą'NĽ§Ęů#v*qEilIcí”H‰âŢdď+ş4öĺ¸űzÖüqî= 4ť›MŠ’¨Ń}ŤPž¸g˙žď|ďó=ďóô!Š2öVKlŰƲmüţŕś>÷Ię+N›~%ü űUŠTFU~Ěł,‹F˝Ę_üăÂ×˙Í×pî˛˙u‹śi9ăťĆůG˙ó?fßţ}hšöks []Š$IÂśl,Ű] QĹŤ6Lđ,Ú;ŽG>gw܉\W&Iňśíźď,Űu@’e×Éqm-Ç˙ţĎţ9™t†żóű_&“Iťă°Ž{@‘ ž=|¸ěôɨ鎃:ŚiB¤q‡VŤŐ¸eďź;ó+ÇvŸ™( (˛‚a8Žƒ,ËŰܜ@Ŕ˛Lďř6LŤĽ#.›N”Dďďóí0ŽźwăoV¨Ş|( fűÇj˙Ř[~œ-˙:wfŔۖvŢ7č2cşŃntăŰ­¨áŔŢÝŻ~[vpDgű(ŽiHÁ”rH0ŽŚbËŕ*qŢůŽą1ÍĄ'ryŃ>§ó˙d‰dc2˝Q7I’DYţĆ Ę:Žc蔦Ď\|ŸşŮîEPüśI°ź†ž:C+ 5ԋϗýŘŰQ7ś‡aŰźť\ćJŃĆś°śX[ú— ¸vë˛(ôËěŠk †Žl´¸˛ŮŔ°ÇÁpŕ'ŤŸ[+ql8 ÂÁaóŒdYćȑĂĚÍÍ …č÷’˜w5កRÄ'qjÔç•[IŸŕž§ë:VŰFwۏăP__`sć"‹3Ő<‚cš`™(QĘoŇjTésLÂ=;$¨Ű ”†ŚiŸHвŰuťńqžTUÝö™(‰ˆŇvëŽÍs'|>ß’RuŰś÷‹p8Ěů_ýŕ8CAŻ˙Ţ˝ďË[y÷uÜ}Νë˝×9mÝÖď÷ßuü÷/˘ţ}ŽÝčĆĎÝV֍ntŁŸ¸ŒF†ń×Ö°Gźă âŕŕř$äp‚qĐT,ŮÁ‘lĎFp,”ę2ăŁ_tnĹő^ÂÂ|Číî ܀|Güáűš{ۇýě“Ć8˜z“üŮďÓ;÷M• š?‰¨Şˆ˛Ő( -Ř´łÔ#’Î~¤kéhkt&şö]+ҝďle7=H+ă^ĎđAĎő^ŹŽ­żß­ŰqŻc]úÇ Ýäg‹uŞ:86.{ĚqÚü–;\Apiž˛é€ĚŠţ ÇűěIúč ČüŤËyŽmÔq,GÇ(4L^]ŹsdŔB¤´Řk•$‘X,F,űXî$ň‰/}ŮŞcŰś>uî™Ń¨P]ťÍęÜMŠ+‹(Š„Ď§á86­F‹bąŒn™řĂq´`5’~ŸĂ™ˇ˘˙€sčh uJ’:ŸmeÓÜŤ_܏IxżżyLËm}e;HvŻ6s÷>>¨wŁżĚüď5şŃntÁ˜ntŁÝřÄ& wO˘EQ  3ÖgŞ´Œ˜DčŘS ś*!E“îwƒŸ‚-Ů8˛cťş2N-OÜG,nOî?ŽéĐů;ç´ľüęƒ&úD§łBľU e{ŇńÁűŘĘčЏ;4ćÎůuÎéÔřܝüü04ÇŚQ)Ó¸öâR˙Ć>AD’DŸ€í˜´ę"ků"őŐYě=ÇÚ÷äÕMlnnréŇ%OŕŰßţ6$“IĆĆƁ7ŢxƒŮŮYAŕôéÓ oKˇębthŘʸ{ßmΞ=ËŔ@?çΝăšçžó(ďmíĄőN,ËâÇ?ţ1­V‹ááaz{{Ńužž>˜Ů:Ůß lLOOsţüdYćäÉž=¤ TŤUVWW= “”nݏišŹŽŽríÚ5FGG`zzšĽĽ%öěŮCOO–eńîťď˘ë:GÝĆč”$Ü}~ßkľ:ëôőő˝˛üq$’ŕę‘lL]BŽ-"F,Űşƒƒ™‚ŕ rcƒĘŇMôF_0‚ ÝœťW¸Z) ‹†N4ĽVŤá÷ű1M“ĽĽ%ŞŐ*Ÿýěgąm›k׎1<<ŒŽܸ1ÉŇŇ"cccŹŹ,388Čŕŕ .\ P(pęÔ)šÍ&׎]gfć6ąXŒp8J˝^çúľëH˛ÄŢ˝{ …Bض͙3ďŇh4čď T* h4œ={żßO,#‰Ç9ţ<\ž|…H$Ž;¸ys’z˝ÎO<ńąƒc–eąźQ˘č¨Xś8ś[Ě# ˛ŕŠĽîŠk|yO‚Óƒ!ü˛ˆaۜ]Ť3Qٓôc9óĺŚea;‚#`aă °aŮ(VúďOń?{ö,Ůl–T*Ĺúú:ŞŞ’H$îÁ4şSj¸•1ŃIěˇYîßÜ+Ý ŽmeL8ŽĂĎ~ö3vîÜÉŕŕŕ'>QßĆô`Ë˝qŔnŐŠUËŞŸ‰g˙.;÷Bőůq, ŁŐäć•ý\ů/Š” ÍÚś{°.} 3ĆśmJĽKKKŹŽŽąžžÎúú:–e˛°°Č͛“LLěĆq666Čçóœ>ý8F“K—.’Éô0::ÂÜÜžúŐĂ /ź@  R)“Íff~~žŠŠivX,‹ĹštéĂĂĂÄăńîK´ÝčF7ş`L7şŃnt㣂1šŞq`ßnôwĺŕ§é,j;‚€ŁŞˆą …˘8>GpÄś‹ˆeÓ\ŸaüČ 'Hű0aWŽ\ĺţčštéׯ_§Ż/K4ŁŃhxâ}˛,ăói”Ëe"‘˛,łšéZO ‚$9h˛Meú"ő|Ő@řŽJ~żŸh4ĘÚÚš\ŽÇ;Ĺôô´W˛”Ëĺčďď'#Š"Ÿţô§h6›źőÖ[|ţóŸăŤ_ý*Ď?˙yŚŚŚšvíŞŞFůÚמĆŕŕ‘HÓ4iľtΞ=ËČČjuW\UUU8€mŰźńƛ<÷ÜsÜşu‹jľÂřřN–——ąm‡ŐŐU–——Ń4]ť&¸téRŰ*Ôdnv۲ůń^á?ţ˙ă Úĺ&Ť5Ű´°mŤ]˜š żĚá/N$x´7ˆOh˜ˇň žvŁČţ”§‡]f™íŔ|šĺ2cŔą=ŘÄĐ[2ƒśÓöa~Ű8ţ/˝ôň'ÂÜÜ<Á +üm&šŚšŚb˛,cÁ`Y–iľZ”Je$I" ’ĎçŰ}ĐOłŮD’DŻšŚIĽRA×u|>ÓÓ3ĚÍÍqäȑ_‹ąĎŐvikřlł’pK5eÍÇÄ_bϑcȲ‚(I ËČŞĚžGNՙ3÷ebŮ%Ţ,0<<ĚĽK— üîqD‘‹/‘L&y÷Ý÷ED"I(ćÇ?~™ąą1dYáňĺ+ &'oňřăŸâ§?}•ÁÁAÇ& ńýďŸçŸŢľZßŘ`~~žÝťwłgĎÇĄX, gϞă‰'>M4#›Íňć›oąoß^Μ9C(âęŐkÄă Ţzë"‘ďźóŠT’ýű÷w_ ÝđXSpżĂŹz˜1v+‹ëƒúęVŘ}ĎżŽaY–'&źľŹś3׹mۛ+H’´ýÚŮ˙GŐnŮşŻę\xżýŢďzžąďî2Ę­ÂĆŢ<Ł}ß; ä5śr6ŚmŰ躎,Ëú~ß]6ý RĘÎâۇ}Žşç?/óôaŰ|ŒéF7şŃß Ś^Œ ˘VżB KVď$˜š„ƒB$Šăo ř 6 ŕˆ&Bi…ąĄýŢ$ěƒ^ڝ—ŠŽ”JeADnłŮlđĘ+?Á˛L˘ŃĄP;wňŇK/ńđnh˜ä7 är9ü~_űÚ_ąk×.t]'“ɰžžĂ0t.^źD:fllŒ;†˝cW*52™0M Ă09wî<_ţň—‰Ĺ˘ŹŹŹRŻ7(—Ť:t˜bąH ¤ŐjĄŞkkëźöÚkX–Ĺđđ0ů|MSY_ßŕsŸ{Ž—_~Ľíaâ|̎”ŢÄŃr¨×lVôĆzĽŽhśÝÚÎ<š„R4 TmśmÄŠ#I‰D‚ľľśm{ŕ’Žë†A4eyy™L&ă%č{öěA‰Á`xĆĘƊˇŸ{}=G6ŰĐvěSJô\`ÜçóšÎ—ż‚rŢ.ӍntŁŸŔE‘p(Ŕ@TeŠž‰ÓÎAcq׼(r5cD71 ťV%)$"Ą‡~u˘ŐjąşşJ8&OP­V)Kd2 àѨÓlś¸rĺ ýýýHmwŁ=1[_ß ŻŻp8rä0WŻ^ĽPČcYWŻ^cϞ=ěÜ9ć: l DQÄ0 Z­KKËD"aüţÍfAˆup(—ĽĐ.%X[[# …ŘÜÜddd„őőuVWWéÉdŘ`?ů—_ŁVŤáói3::J.—ŁŮl277G*•B–e˘Ńˆ×WÂá0{öL03s›JĽB$ĄP(`Íf“D"AĄP •JÇť`Ěo@ŘśMąX¤ŻŻfłÉ¨ŞĘđđ0׎]#‰´`—đűýěÜš“[ˇnŃh4P…ąą1677š|ů2šŚ122Âľk×q›S§Naš&/˝ôýýý†$Id2.żąąA<gϞ=ž ÷…B4›M˛Ů,WŻ^ĹśmNžů$łłłô÷÷322BĄP`qq‘jľęŸ}}}ܸqQéííevvI’@Ó\ůP(D0äʕ+ř|>nܸ,ËX–Ĺ… hľZœ:u UU9sć ˘(2??Ďúú:Á`]×)•JŒŽŽ˛źźěé썍ąZŐľq IDATąąÁĘĘ {÷îĺęŐŤ>|˜Ë—/“JĽŘ˝{7@˲˜™™áľ×^#°źźŒßď2/-ˢżżŸJĽB˝^Gt]çȑ#ř|>Ţzë-oLíééA×Ýů@˝Ţ`bbĹb‘÷Ţ{cǎ133CĽRa||œŮŮYŽ;FľZĺöí۔ËeĆĆĆČĺrÔëuYYYÁ0 BĄßýîw9}ú4>ŸJĽB&“ĄŃpÁqUŐxă×ůíßţm2™ gΜ!›ÍRŻ×i6›d2FFFh4\ż~Ó4b~~UŐƒƒA.^źˆŽëěŢ˝››7o>Đ]Ź ĆtŁÝčĆßŔŘ*dŠŕŕÓTĆłićóËٝo("„Łˆ B0ˆ­JžŽ‚#8ŘŐuă~B퐇ľŰ•$‰h4ĘŁ>Š,Klnćyýő7đů4Ž]ťF*•" Óߟĺ•W~—żü{w„%ŰŤEĽR‰bąHŁá–ĂX–E6›eccƒńńq.\¸Čęę##;Đ4žž ŞŞŇӓfjꯞúFƒąąQRŠŻżţ&>ŸÖfôpŕŔ~üăÇ‰Ĺ˘‚Ŕúú:kkk(í$JnO˛dYĆď÷SŤŐ¸xń˘Guý8@Œą-SGośX\\Dö‡0٧)$ tDł…$"čŽHՐ)×Měb™Ľĺeî݅„ƒŹ(’„(>€Śi>ú’ä–fíÚľ‹t:í=Çcǎ‘ĎçQ…d2閿iG& đř㏠…ńűý(ŠBš\A×[¤Ói,Ë$“I#n Ěg>ót ‹!"ŃhÄ[ĺJĽRŒ‰DĐ4bąč­p*Š‚išœ={ŽcÇ%đłsçX;Š”CœKłŮ$śÁˇôřqWDťRŠz@Ëőë7Čĺ։ĹbŒŁë:­V‹t:…$I„ĂaĆĆv˘Ş*˘(˘i*O<ńšŚRŻ7Eh4Ć3ĎőŠO‘ĎçŠT*źýöŰ:tˆ\î´Z-âńxť¤Vâ…ó bY–eąąąÁíۡ9pŕ 4 †††řéOJOO`éşŢ^ÔťŠ(ŠÜşu‹;w‰D˜™™Áq‰śm“N§ńů|ĚĎĎ3<¤t6+Ć-Qp*ë ĹCž{Zß÷… ËüŃýĄ—ĽÓ)žzę dYĄż?‹$I¨ŞĘúú:CCÄă1ö{äčaFFGĐ4•@ H0čçčŃŁ¨ŞŠßďDzĚ6 #î‘?nÝşE,EÓ4bą§O?NĽRAUUbą‚ ´iţápˆH$B(t”bą„mۄBAÂá0śmsęÔIŞŐŞ›´)2ŞŞá÷űxńĹ/ ůěgŸmŰĺĘŰX?cc[&ÍľiŒëß'_n˛śBMôƒŹá¨AtEi'yR;ą3ąšMŁ‚Ź4Ů\_çć7˙ORQŃá]„÷?ĺ%’ uÄ: ŮĘ ‚÷јeI"L$pUUÚĎ;šĺ›Ę6:p§Mt>síŇdIćo˙­ˆDŁ(˛ [’č@ŔĽ 7›-NžiiCĂvLL`­bąViy7K•Š-°ądÁ[LËáĆf ŰvÚĽNw4™ŃaH3ˆ„‚đ*xęŠ'P5•d2ÁWžň÷…ÜťFŁŮś‚ đˇţöeĂ0ˆDž†ÂŘŘńxź ˛EřÝßý]4MăđáCLLŒ{“Oˇ=Äxúiwňߚߝúü_‡D\E Ý@×[m†ĘvŒ(ŠSYĹOyî"ůé÷(*`c›&’Ş‘ُëAÜĘŚIš\A| Ť[ĐęO4EEęĚ%–——=‹išłT*Q.—=`DÓ´mŰšs…‰‰ .^źHĄP  šŒ9]GĘ岡€UŻ×˝ůŤŰU" aYáp˜@ ŕąsćçç=4ˇ&wžR.—ÉĺrŢ8 šs™H$Âőë×B–]-žÎ>:Z:ńż#„/I>Ÿ@ €ßď§Z­z/A}EQPU•T*E­Vă;ßů{÷î%`ŚirâÄ nßží•ČvžUçš"‘Á`˲¨VŤ(ŠB,CÓ4Z­†ax:@Š˘PŠTźë ‡ĂŹŻŻŁë-oALUUZ­.\  {÷Ő0 OŤĽRŠn9UąX"p¸ápQ‰ÇăŘśÍŔŔápŘ[d …B„B!‰Ífł˝HŁ^ŻP*•ź÷H0¤żżŸ÷Ţ{l6KŤŐ˘P(xÚ<ýýýŒłcǎ6#ŹËŒéF7şŃßěɔ(˛#@›źFS˛plŰŇl[‘{°| şUC$ÉeVPÍ3Ú'ŕ{x‘ÚŽ˜Z:ň’śŁÂq"7É×ušš9{ě14íNrF˝Ő'€“'OŇŰŰóž2ŠŢ^_Ű٨Ćřř¸ˇĘ%I’çşłuż§§g›kSgŇ9çN’‰„ …‚Ű@ AHĽ’ídDۖpýźá2blŹf•úť˙Ţř笗bŘŁ˙R˛QpË'ÇÄöżímmÉŃÓԙüÖżÄŇ X{!F2Ä&NxǸ/X×Čëü<¤ÎÇ%—ă8˘ ˆxš÷C#4͝ţ˛ťmł}ŠĚŁ˝~ćçLtóţw eÂ?}{™×ĘüO2÷ŁÉ"–ăp}­†eŰXöíEQâxOŔ+ם_DcŃ-TîLť-‰Çď<ăT*ĺUŞm˝O~żžž^ďłNb­iŃhÄkӝ‰ąťç×Îć¸3řü~VW—éííń4Sî”3ʄb‰ĎĐŹhVň.Œ c8‚„ƒkižŒŠŐjŹol0<<ňĐşŽ€ŤŃőaúă˛ ’éÔ–Ł  ;÷…ę¸Ówœ÷wTI’Ţ7.vŁ UUŮż?ÍfAŁŮl"Š˘ěÚľ‹`0HĽRi—žE9}ú4ŽăxŕĹáÇ=1ţx<îiůý~dYćĉ´Z-ü~?~żŸ§Ÿ~UUŃuÝc\†Ăa:ä[ŇŠŃŃŃmžąůžžžśXyČsP”e™D"á1SŠŕtúóĐĐńxœĹĹE@ ˇˇÇ+]ĘfłŢ9'“IŽ?N @×uqńöŰo“N§Éd2T*’É$Ď<ó ápŘÓmé€7Á`'\F§˘(ť§sŞŞ˛cÇ"‘Ńh”t:͉'źů”ĎçŁ^Żł¸¸Č‹/žˆŚš šD"A(â+_ů étY–ŠVŤŢBˆ$ILLLĐ4JĽâiNućEfK:&ó{ż÷{p&îťbxx˜‘‘řý*• ńxUUyńĹI$Ž9B˝^ÇśmvîÜI(Âď÷ ůÓ?ýSâń8˛,óůĎžÍîťSr•Ďç˝űć–hşL×çŸ˲čéé!‘H ( }}}„ĂaLÓ$ Ňl61M“‘‘Ţ{Žs>÷œeYŕÜi{Đ) ŤVŤÄăqLÓôî—$IŒŒŒÍf ‡ĂÔj5Ea``ŔÓáH$=z´­ÓŐcşŃntă72: C*#ىL•7@‘Šü‹˙ [×ăI¤á1—ޤţÚwLˆüg˙=’ éčôF2ȲôĄiŰ6•JEq™w'>Ÿ#GŽźOš~Ť˛żă8=zôžŔ‡ă8hš†aŢĘFge⃎{%—Ďî•dýB“QÇƨ°ç^Ăl4hnäwPÓä šh Jŕ¸Ě, Áj!5|™Ĺ7h•rčacc†ÖâeĚąG% AČ؎éŘ4mݲ\A|ٙŸ’PD M”‘ńĄ<żxPŕţ–Ĺ>Eć™1~˛œŁ˘ť öý˘a[źľPâ?úv‹˙đh§‡cÔM‹É\Ó˛=f €, ű žK =Dť˝űH’đĐýň~B§AUUřüU0wƒav rŮ]KKKŒŒŒ´ËkśťĄ˘ˆ?–ĆIşŕ‹eťâŘÜqÝč1­V‹ůůy,Óňž—XśMÓ1ŃMĂs`Újˇýńö[ڄ â”vŠ˘đ‹Ăşń72$I"™LbY–÷ˆ˘H,óúÁVFbż'xÝaYôöö"śßEčÎ{){,VÇqČfłX–ľmĚęˆĆwÚq§dvŤăÎV×#EQčééńÚ}ş$Ëü˛mŰc”J%O÷f~~żß‡m۞hq4őƅŽ(îVÇŚVŤĹ‘#‡Ű%şű÷ď÷ĘfA ‰ls€ęA€wŽŚsM– @$yßŘ\ŠTxüńÇ ‡ĂžŤĎçó€Î~\ĺÎv6ŹŚiŢ÷îŽXܓ  †<öOgMEĆĆĆźď¸`t›{S‡ĺ˛wď^ďœßćóyĆÇÇÚĆĘŰÚÖ:çî˛}ü^™ďÖűى*î\cç™nVś:=ŠŞJooݎÝVqäÎ9uúI‡mÚcşŃntă78DQ$JŇÔ¸žšŒŕ÷cŹÎaUËHľ ęĐćň<ćÚ2‚¤a–Öąý!’˘AO&…źe2ô°Ąë:Żýěuú˛>|ř#%ÖúŽ+¤i2==Íüü˘(˛sç;věřőK:›fîJń&-,Ă śřq Ąt )ťAK h!DYÁv,0먕uœÍyŒ[ďQ™žÁŞŠƒčŕTs˜Ť70š5¤@x[Úw7(ă8-ۢlś¨ču–J€Co$‰*)H?Ô:˙ýBADd"ŠUTřd<š;Œ¨­€€*KČ&x˘7ĎW§›śđŔ=4l‹ëUţŃĎZ<6PÄr&Śĺ2.Üc€& üÁxˆţdQ%íײ,–—–éíí% ~2žÂGźçĹˆĹâlnŽŁiZ{Őҡ}lŮúcŰ.Mi ˇU'fvv–••†††Ű`Œto­ěví™e[ŁAŽZ¤aśH˘„4˙/ü ÔDˆâ# *ېš.(Ӎˆvn$I$ ąşşŠă8Çˇą[;Ŕe.—óŘkkk8ŽC<î:Ŕéşî%čŐj•X,ć%­ĎÖÖ֐e™l6‹Žëř|>O/DQŠĹ˘ČttÖ××iľZ °ąąAĄP ’ɸ,ÂÎ˙EÁqt]gaaĂ0Čfł^ ‘išŢuuJž;,ŸNŠb"‘Ŕ˛,Ďq,—Ë‘L&äöíŰDŁQ†‡‡ˇŮ.;ŽĂňň˛wŢŽN“rßűß1î|żŃhl[܁ţţ~˛Ůěűě­caąX$ y×ýQÇâűmë‚ŰÇλǚÎ}‹FŁ^yRGŤęîc‚€ßďçäɓŢ5Üë؝mlŰŚŃh ëúűʔď~Đľ¸çj`ŰŰAΖO§Ô÷ƒîUąX¤T*188řKłşî‚1ÝčF7şń ŒÎĘR<g@2Ńß~ísżƒ˙+˙‰ťú[ؤő“˘~vDzâQô×~LşšAOćŮý"鸹LMM#ˆťšpá‚ xV@€L&Ăââ˘W nY&ssó8ŽĂřřNnßvÝúúú0 \nÝŤSÖ4×Igii™;w˘ë:33ˇńűÜşu EQdrň&Ą`]ץ­§Ešqă:ŽăŠŐ5 –——=Ęí/ĺĹŮq=rŔ2uœš—‘Š#J Ęśí •çńßZF]ü‚EP‚Hš ˘ä4 UÄŽ×( Á"¤9„Ă š(͛ؕߎ$şöĺw­" ‚€éŘTĚ&ËŐMޜ˝„i[ȢÄR%G*g"=Čz­ˆ€@ÔtKŠĄ}ę`Ú65˝AHóť`MłĹF­„_ŃPe… âóŔphš:ŐV€ę'¤ř‡„&#sgâôŤJˇ–÷l˝_’(Šřya"Ăľü"óMóƒ÷WlüpjÓłCś;Z1AUŕł}2ŸŰ?„"‹ˆ˘đ@ň˝÷ŢĂ4MšÍ–— ôôô0??OłŮ¤żż_ăöíY"‘ŠT’™™ŰH’ä9YlllÉdH&“\šrAŔŤ“W5WöąXĚ+kšŸŸÇ4,dEćȑĂ?ˇ ň/ŔéˆL Q(X_Ď!Š™L†PčÎ n‡Ĺçl)#rÚş>śgç>;;Ëââ"Á`;v´¨N;ˇ1śăP1[l6+\[ťÍÔć"ŞŹ %8Ú?AË4hš:a-€,J€(ˆíň(Ëś¨´ęÄüa\m%Ă4ب—ń)*śm“ Ć<0Čm[ĽV HŁT&Š*´Î.ӍşŽsůňŻEŁŽpőÔÔ§OŸć•W^áńǧ§§g[Ň=99ééŁ8p˲X[[ŁżżŸ—^z‰S§Nxűíˇ‰Ĺbœ?žçŸŢ+3™™™ńsßzë-‚Á {÷îE’$^~ůe&&&Čĺr?~UUą,›ŰˇołźźL8ćöíŰäóyY\\l— ťâžÇ÷Ę| …“““9r„ršĚĘĘ étšď}ď{ xăĂčč¨ÇŞ(—ËźýöŰ<űěł4›Mڧ§Éĺr ş L‡I355E>żÉž}ű˝’˜FŁÁůóço[  ‚ž6eY˜ŚéM­V‹—^z‰çž{Î+‡Ú:öú|>Tę°6ς^EZ­çΝă‘G!‰xĺ;šáVfeY“i띯#ÚÝъ錙šŚyâ˝>ŸĎ3m ˜Îś—/_fdd„ŠŠ)Ž=JľZE]ąrEQźëߪ)ÓŃ+s]tÝmƒšŞĄjŽmSoԙ›ciy‰Ó§O#‰†éęČhކn8Ž"+¨šę†ž>˘ă.HtX5ĺrŮ˝ďëó@° .]şÄńăÇńi>Ő=ßÎÜʲm4MEÓ4KKK‚Ŕ~ô#Oç¨ ĆtŁÝčĆohtÄ$ dÉüőż'gę¨ç+ąƅ÷0oŁF^@zä´ęßüÚĎ~ŔÁßý2™ôŇńˇc î Օ+W™˜˜@–%–——¸qăűöíçüůó;vœĺĺ$IŚ^ŻsëÖëëœ8qŒÍÍMAŕüů‹D"TUâÜšóDŁLÓ¤^o°¸¸ČŽĂ‹Ĺś“R—/_öěKĽ33î¤čęŐkœ>}š÷Ξeßž},,.půĘÖÖV‘ۡg‰Çă věöh´żčdÓiŻśŘŽEŤYCZ{AÖ „z“P*‚ä˜Čś‰Ül!V H€Ź€(;  ˜&¨‚@@‘ŹCvH@ €(LáTŚą“ŁˆŽzߒ#ÓśhÚgŽSmŐ8Úż‡ďÝx‹ĂűqäFnERPD7QLb„ľS› dBIňľ"WnńÄčQ6ëeRÁ’(ňúěcbţ˛ QÓěÝIąYĺęÚ MŁĹžŢQüŃZމĺŘH‚ř+bî%Xłő\4UáĐ`Šż[¨đ\,rłda9NWť78週寂# Š  đФÄ͒ˆĽnw7oŢddd„łgĎňŘcŸbee…Š)ˇ˙H’ÄĽK—9~ü7n¸ ĆĆĆ&çϟ÷]w­ĆggçÚËiŞŐJێ\$ růŇž~ćIffnˇű#ř|.]źĚś­ôţâ°JgۊćG)S’$×~˝żżŸ……9677ą,‹dŇ ! ‚ס–8ŘśeŮčz‹ľľ5fffXĎ­#J"ű÷ď'™J~ŕń­6ł^+p~ů&GúwÖź2u–T(ƁŢ1ÖŞy–Jë5""é!ć Ťčś Ŕ&ßăKŸ˘Ą7i-bç—n’&Šśęěëcž°Ępź—€ŹńŢŇ$şeő‡HŁčŽEË6QEĽű"ěĆG7EŚ\.ÓÓÓC<÷,Ť]Çľ†aÜsÎŃąŽD"´Z-QŠT<@ Z­ †\Áíö~ś˛Ei[Ť8Žß$rýúu&&&ś6ׯ_çȑ#Äb1ž˙ýďS,IĽRTŤUt]÷\p:ĺ#Ł^Ż{`FŁŃđܗzzzřŢ÷žG:ćŔŰŔŚFŁá zw\ŸąXŒ\.ÇŔŔąXŒo|ăěÝťĎcÔ\ž|™ţţ~Ν;Ǒ#G¸ukŠĹĹEO<śRАĎçG}”ůůy^}őUÉd2‹%rš5z{{9pŕ†apćĚršœW^%Š"}}}Ź­­‰DŘÜÜô,ęϝ;GłŮD×uyěąÇږЉ8–ey, ‘‘677éëë#N355ĹÚÚĽR‰Z­ĆłĎ>ËŮłg‘e™ńńqVVVđűýžłÖ§>ő)†‡‡] @–‰ĹbÜźy˲¸|ů˛'ş[,yîšç8ţźç|tĺĘęő:‰D‚ÍÍ<›y‰o˝ý‡fǎavMLPŠTyç3ŹŽŽ˘Ş*˙÷żúřô§OSŤŐY]]!s˜\aăÄ0 Ν;ĎęĘ*ťwďŚT.Q.•‰D#ňydYahhˆtއRŠČ“TŤ ů˙ú˙ý˙xôŃGŰý˘‚ϧ177ĎŘŘ(ÁPˆ]ťĆQU…ááaڧ§i4źűîť]0ŚÝčF7~Ó'T˛,óԓOŇ2LţŮ˙ő/Yř'ˇ˙ዐN˘~áˇa ‹Q\Ăü˙ńéküÉď˙>ż÷Ĺßń„q?L†ÁoźN:Ýă: ČŽ{R6ۇŚiô÷gŃőWŻ^% ˛{÷nnÝşE˝îNň>ĚťďžGOOżßĎÔÔ4étŠd2I˝^§VŤny.—ŁX,’NgxůĺWđůü8ۄňúűűÜUţ•ĺ ů§N=F8ěґUUáÖ­i._žâ‰ţýRbl só&~ë6NŔBQĄ×ń˜Cł ś ‚ĺx✶ ‚‚- KK@"ă Eä ;HŇ őňUó1ĹďšÂÜ}].#ŔŚÜŹQ×u.­ÎŻ—q›BÍu%¨ľš(˛ÁOgÎóÄčQfó+Tő}Ą-Ă 'œ ięÔô†eňď.˝Âg'NŻ—ˆúĚl,óE°›…Â˕M&ŇCäjEĆMÓ$ľ çWTŚó°ýČqÂ~ĎEd†zvšš€n;(ÚÚ^Ň% âžě‘ř§Ř;F‘DWčőÂçóŃ×ׇ˘¨mË+++ěÝť—ÁÁjľşg%>99ÉÁƒxć™Ď099ÉkŻ˝ŽŞŞŢ îĆĆGŽfss“ŐŐŐö) „#aúűűÉĺrT*UˆĹâ\ż~ý—~Ż`Ž3îu˜s…ü&ľZŰ^§RŠ ńű}hšIą,Ă0h4äóy/ńĐuMÓŘ˝s7;wîDĽ‹b#`;îjs]o˛^-°RŮäjnŰą™+Ź`96-S§ÔŹđćě%>=z„sK7(7ŤLĺ—Ů™$ŠPÔkř$™Šň:œĘźq IDATŤ•M‚Z€błJÔ`ĽźÉzľHPół\Ú`Мă`vœ››ó쟌gÚv÷%؍–ÜÉ2ƒƒƒŹŽŽ’Ëĺ°,‹h4ęiłm]€é0ú$I"“É`Ű6SSSžžRç˝jů|ž`0č$###žvĘÖ2@ ŔţýűYYYńtśvîÜÉŤŻžĘČȈ§AÓĺď0<: jš\ŚŮl’ĎçiľZŢ÷ˇ–¨ÔëuÖ×]űřZ­ć•2†á‰ĐvŔšÎut´ęŞŐ*>ŸĎcŕ¸,œ;eS—F×YYYŮŚŠ×)Cęďď§X,z×÷ío›˝{÷śměÓ˙šĎ¸Kx÷a“˘BĄŔĐĐ_ü♟Ÿg}}AŰVŠATUm;$YXX —[ÇçÓ¸qăׯßŔ4-öďßÇO~ň|>űöíĹq\'#Űv$IôĆď~÷ť4›-žţyLÓŕúőkí—ŕnż§˘ďóih>•“§NňÖ[o!Ї˘X,rëÖMvďžřĽ1ŽřŤƒm5!÷ ˛Śťśâ6(Ś€Ş„€–śî`›îf˘, k˛O@PIŔj˜p3‚¨:Rő=lý÷°üIÄť’ÇN˛+Š"‚㶏Ţp‚KkS8śÍńĄýŹW íďvRLŠf(7ŞěíáFnŽŮÍ%ţŢŁ_@‘d–ĘëLm.˛ZɡKr, *Ťĺ<~YcgfˆbłÂŽx/5˝á‰‹ŢA§~őń áXA%ˆT~ëčNúƒ"˙ë™U.”%†ĺÚ];wyŢ´•E„¸&ň…~‰?>6ĚHŸrÇvůƒÚ^G˜1 ŕóšýčŕÁƒÜş5ō7<גóçω¸ Ĺůóďb:ťwď&—ËqóćMdYć‰'žŕ[ßúkDQdttŸOCUe­MˇVI$â\ž|Ó´PŮŁq˙˛Çąş­›8ůŘż?׎]ŁZŠśŠđÍfË2(‹mú˝EŁŃ$żšÉćfÓ4Đ4ŞŞđ%™+—ŻâóűČöÉdŢĎreA%‰¨?DľŐ`ž°Ćç'NńW_Ć-ćÜ2EÇb(ÖĂĚ暪‘ 'xíö9ž°űSh˘HÓ283Óą™H #8n‘[Ëҙ-lĐ| G{XŻMd)5*ۀ!QčNŃťńŃÂśmršďžű.˘(211áiśtţţĘ+Ż022J6ë˛'‚Á ››œ={Çq…‚TŤxŰ(ŠÂĚĚ ’$‡Ůż_›ĄWőt`‚Á ;wîô€Ô×_ééi:D:&rŮ4׎]cppp8Ěž}űxőŐWŠŐj<őÔSź÷Ţ{,..ĄŞnYô;ŚiŘśÍää$řý~8xđ …BÁ+ăL$LNNrúôi–——Y\\äöíŰ=z”h4ĘŘŘ_˙ú×Q…çž{Ž3g\f† důáˆ(Š<ýôÓĚÎÎ200€a$“I>Ěęę*‹‹KLMM1<<Ěää$CCC„B!|>Ÿgý­( ›››źţúë|úӟF–e>űŮçxíľ×Čfł<ţřă,//“Ďçéďď÷ŠÇáńÇç[ßú€WśÔƒƒAlŰf~~ŢsŹ ȲěšužŮV§ŁÎů…Ăa˙ößţŸűÜç°, EQxä‘G˜ĺŮg?Í7ř˙Ůťďř6ęűŕ/ÝiK˛,ďŰąă8‹$Í ‰Ca„MYmĄ-Ľ”QĘ(-#-e–/Ľe ”Ť@ ”„‘&„ěá8Î÷ŢZ֖î÷Çé>–źb;‰HÂűůŔÄÖ¸;ÝçNşĎ[ŸĎűŸŸĎđj4 ¤§§ă“O>Abb"–,Y‚ýë_ÄDžjľuuuزe 233ŃÚڊ`0š\ňň28XŽp( V‹`0‡ÓżßĽR šœ'“ÁçőÂëóAŽPŔçƒO:–]{y˝„‚!¨Ôb0^&är~ż^˜LF8N„l6źľçMźţúk˜tťěđ‡ý8ˇx>9°MşÝôx\¸tÚb|źg=Ć'gĂáëE0D×‰…㌣ÁގC °č0/g*2ŒIPq XT(ă8MI8˝,‰˘4LÝl6ĆTúč|°i- …ŃŐcǚ˛j|VďEĽ#€NwŢ €  6…‚t ŠZ9&™8\XhÁœ˘\čő‘;ƒä¨Íq>Ô’ţŰÜ˙žśśv466Âăń@ĽRböěŮŢ+Z[[ŃÝ݃žBĄ ćϟwLrĆî˝Ün‚ÁËA 柒CŁQťŸ¤éGҰüîînđź *Ľ‚ Žćóű}đů|ŹL­Ďçcy ¤iáp­“'OCQQۖţB‚€ž€;6TďBeWŹz3ŞşšpIÉ"äXRŃâčDƒ­ UÝM8wÂ<ěl:“Ö€ęÎ&ôź8-o:ž¨ÜŒŠi…ŘŐ\ ¤”|Ôuˇ˘$=[ę÷bbň8Tt6 Řš™ŒCYŰ!¨ĺJ”¤äaVÖDČe<,JT|ü’c ‚ř¨TŞF|Ź„B!xÜ.<ţčcxďíw!DF÷äăáó>,_8xäQ”L*‰Ix{źc¤sA}"ĺ4‘Ę%K#FöíۇI“&AŤŐÂëő"đC&ăXB\qʓ‡ƒuÚe2JĽ<ĎŁŤŤ ápVŤ^Ż …ršœ•”…BPŠTlj‹BĄŔęŐŤą`Áčt:śRÎi*Žôţ.Mâ8Žu’Ł÷•§;ýý“ĎnŰś ‹/ř|>ôöö˛ęsRi›ĽĺĘd2ěۡÓŚMĎóđů|,ˇŠÇ㍌Čó´H× Ňô'éúAÚҲCĄŤnĽŃhŘc¤ü*Ňg™´,ŸĎš\Î!ĽiaŇň¤`™Ävš\(//Ç´iÓXéoiZ–4ÚGŞŽX rń˝ÚÍî—öżt}+•š–ö‡BĄ€RŠd éË:Šý”J%ÖŻ_wŢyáp(˛l>ň9-N+•ŞTIŁ—ÂáPä6@Îó0$$ˆšîB!bĺHi_÷ťapĎśYʓĂqâzŻžú”––" ÁçóbăĆM˜?´Z]ä3EŹ0%ĺż ƒ°XĚsŘř#?ĄČO8ęGˆúWˆúZ'úƒ\ ` !„Á˜Ă•pŹó …ŕóűQ[W˙÷ö;Řź};ŚL,Ć/ż&AĽR !B8Ž~0&,„Đ]_ŮŚAáo†Lô]ÂâÇľ,4Lېńâ'§L%ƒ ú>e9‚29ü“_AbÁ™ŕĺ|$č C€'@ˇĎ…ŐÝM aŒˇdAI, ‡YY^ö:#Ł?Ą˝bÂQ–ÔW&ćżbűRő 9ÇC€€PXĚ#çx¨xŒ 5TźJLŕ‹ř$đ=\0&:H0X`C:CĄ0ź :z¨nˇĄŞÇ‹Ž^?zƒap2Œ*)zŠľČIľŔ¨Ó@!çÁs˛H ńřw8Ľjd‡UB€ÜÜ6M ú1^Ż đűý?~<ű†ôťxďôxźc ĆD—ž ƒ°Űí°Űíb‡G&v|‚ ?Á ‚Á@¤âGěJ­Áĉ“ŘţŹÝÂŕaó÷ÂîsŁŚ§='Ć%Ś!YgfI°ĂBaA`%ÍĽŽť „Ye-éś0ÄŰ8ČbŽÂe1Wę}ç™FŽ„ŽWAĎŤ[2‚1Œ9Ň×čršŘ¨Šą,G œHď/ýlˆšFßż#^§ô~]nűp()đ áóůźGľé5Hď7 l}RđE:ŽŁ_óńÄĺrÁívǔˇévF6BĄPĚ´śąXšňcź÷Ţ{c~~ ŕgŁ;yţč|™p饗₠–Áď÷ĂápŔlNĎsCž#*•â˜ch $!„Ä‘4uäđ“ ČpZÂń¸ĺڟciM ˛˛2‘–š:č ČľdýşKšĘˆNăՀßBÉ"ľr1°"cŽnx–ßCü/rAĚFˈ ŒšŹaˇƒ ZN ™ĘƒBƒ4˝%2Œ7ú€‰îöőď ƒžŽ¨ $„Ôˇ~^ĆAÍ+ á‘dŞń=ޢGĽ יlŠ—t›\ÎC/çĄS%!75 Ăaƒ„BáČýrČĺ|ßT¤¨“ďsL&“AŠT`âĉĂ>FŁŃ °°đ;ďđ >ęçđç^ôsĽ!úIII0™LpťÝđzÄŃ6áp(Ňi#ƒ!B86ąŻ @* X,IĂv.8Č âä0+uPóJX4 , ꌃ†W@ĹÉÁƒŁ7crLÎK)KJJ ôzýĺwR*•,ŻJWWŠ‹‹ĄP(ŕńxXÂބ„„˜çHš=F" ˛2ŃŇTáÔ××C§Ó!)) <ĎłjJĂéčč€Z­fů\A€ĂáˆŮÎîîněßż'Caaz{ÝČĘƌßéQě/ľZÍFŐŐŐ űyˆ‘ňá8Řl6¤ŚŚĆT܊~Ź4Šg¨÷Óľk×Q č›fĺóůĄŃȏř¸x÷ÝwĄ×ë1qbIäzAôőů|>¨Tʸ´c!$žÝ)6ÝfäA~‡¤$ Ěfűćb¨iI#™F@bă%}űq¨@ƒ% Šy×# ‚}ˇ=lŸMč‘ há8¨4zpüŔQ1ŃadĐp ¨9yä[y!NűI LđŇą&‡ ^íÎDlÜŠ˙ôşÁFÂDŸÎ ŽŻ#ĚóŞ!ĎÁž<9'îˇţßEÇoŕq9ş`tô~–ňUHßtyĚ 3s2¸|Ó+ƒ NšLŽ0 ŽÁ1Đ)űNĘY BüÎarl…B!ttt žž<ĎC§ÓÁăń@ŠT˘  íííhhh`Óo1ďG{{;Ün7233ŃŃŃŸĎFš\ŽŽŽ.X,äĺĺ!ŕĐĄCPŤŐذafϞP(„ććf:tľľľpš\HMMEBBęęę V‹š ‚Á ***ŘtĄŢŢ^dggĂfëß€N§ƒĎçƒËĺB €ĎçCss3T*ŇŇŇĐŇ҂äädÔ××CŻ×#==ŐŐŐhllÄÔŠSaąX°cÇ8ËĺHKK‡Ëĺ„Óé„Á ŽPvš\pš\ČĚĚÄŽ]ť`0ŽŽ.¤§§ÇŠ‹‹Áó<***ŃÖ֊ŒŒ ř|>ôôô !!MçQŤUP(”čîî† ČÍÍEmm-AŔôéÓ‡ąk×.¨Őj–Hš¨¨p:HNNfÉl5 t:Kü›ŽŽÔŐŐEŞW*ŃŢŢ­V‹˛˛2dff"#77¨Š+ěIŐ´œN'T*ĐĐЀÔÔTdff˛jXN§mmm‡Ăhhh€ŐjEkkŤ˜}„B!”——#;;ľľľP(ČĚĚÄÖ­[aąX`6›ń׿>Κ„„Říbő?žçŔq<äržUů ‡…Č—,bŽťÝžçĄ×ëřaˇŰĄT*ĄŃ¨Áq<\.'‚Á’““#ďéü~19ł´ĎÄiJĄ¨)m„Ă!üß˙ýnżýX,TUUçyäć梟źƒYYYŘ˝{÷€)ŔŒ!„“¤Ă …Ŕq˛1wćÄůŻňA‡řRql‚Áŕ€Ŕ‡x7xGŒW(Ą•+VqāŽ‘ó—œ &ëté˙Bt×:žŁb‚Á ú.°¤ę9ý;ôÏĆ\Ąóld¤ŽP˙ăYʝ0Ň},[ŃS!Ćz~¤ý¸Čč5NdÜ÷c„J(¤cű$ Ćx˝^47ˇŕŔý())ANNşşşšš ŸĎŚŚ&ÔŐŐaΜ9ččč@vv6:ŽăP__ŚŚ&¨Őj˜ÍfTUUĄ˛˛‹2™ 999,“BĄ@CCBĄ ŹV+1ÉŹ8EŃ­V‹ŽŽ|űíˇƒčîîFaa!ÚÚÚ`ľZąyófhľZ477#11VŤ{öěĎçÄ ŕvťńůçŸ:;;ątéRx<lٲ]]]đx<˜2e2x^ÎrEŔîÝťQXX—Ë…ŹŹ,ěÚľfł:„ĂáŔ̙3YŁÎÎôöşą|ůňHrđ !Mý1›ÍčîîÇq0XˇnJJJĐŘ؈––˜L&ŁĽĽŔěŮłQWW—Ë…úúz´´´ ¨¨°yóf̙3]]]ČËËCSS\.jjjP]]ńăǃçyěŢ˝vť3g΄×ëEff&PQQYłfa˙ţýhiiN§ƒĂa‡R™ÇŚwÖŐŐÁl§X~ńĹČËËCII l6l6ŞŞŞ˜˜ČF´ˇˇ#`Æ ˜;w.śoߎîîn$$‘””ƒÁ˝^‡ĂÁ86› ›6mÂňĺËńĆŻŁ˝˝ĺžéŤ„äD(Br˛~ż<݆Űílj9ž’’,čęę†Ůl‚Ăá@b˘vť€€ŽŽdddŔďŔnď„Á`@WW;’’,‘<;@8‚ĎçCWW',–¤H OœÚÖÝÝľZ Žă`łŮđŸ˙ügu6n܈ÜÜ\ƒAěÚľ ĽĽĽŘľk׈FaQ0†BNČ`ŒŘi”Ś?I‡‚:G)¸5ď=zjřý~(ň!§ť Öa<™‘?řť)f$‹tVAˆ­Ş$;ömĺőú “őĺ&J!{˝^v5ňœ‡O2MFŚ‹=‚Á AˆÉA"“É ‰ %Gš›¤˙h§#­Ö4ˆŁ85Mˆďö]źg‹&˙¨ž“ă;SSSĂ:˘rš‹…uЁžj&“ áp‰‰‰8pŕ’““ŃŢŢ…BÁ§z˝ĹĹĹ0›Í‘Ęˆ6‚çůČč=KŕËq\äŰ4-- ÍÍÍHMMĎóŹDľ ČĚĚD}}=A@QQ’““‘œœ ĐjľŹm¤|;RŽŹŹ jľšĺŕß×ÄŠÁâžV! ŁĽĽ•%ːKŁYĽă8ÉáŠT…RŠ•)#íŹ=9ŽCoŻ›ľÔţ'ƒFŁ…Íf™–´˙>̝;™™™˜:u*ŇÓÓąoß>Fttt !!!nU)C!GůBz°‹÷č„oĄP>Ÿ?R˛pôoöńîœĚ¤ŞbU%ť; VéA*/śÓ2ă|L ĚF' źăě—@ Ż×ÇÚJ œ‰nˇęHÉËÁˇ–Ë;qô’×ëgŠ˝ÄŠax˝>¨Ő2ČĺüČ×pÇűűgźˇOze*b‚ŇäĤP(PTT‡Ăźź<6u$ş|ň”)SPPP€ääd˜L&hľZ̜9“uÚóňňPWWÇ>˙Î>űlřý~Fđ<ĚĚĚH`5“É„‚‚h4šHŽ' ‘äädFäĺ女ł“MyŇh4(((€N§ƒZ­†×ë…Ůœ“ÉľZYłfą€nzz:ŚM›†îîn¨Őj˜L&ƒAäć梾ľ•ĺ”jllDjj*R#yôN=u,–D„B!h4L›v Ťb”’’ @żß‚‚Ftvv˛é;ůůů1ՊÎ=÷\477ƒçy¤ŚŚ˛ÉâŋĄŃhŕóů‘‘˝Ţ‹ĹÂö…TUIj)ÇqX˛d ŇÓӑœœŒ„„””L‚ÇăF(BJJ ’““!“É0wî\řý455B­VłXNN˛˛˛ ×ëYđ§´´N§‰‰‰ŕ8sç΅ŐjE8ƒ%KŕőzŮô'łŮ •JƒÁFĂ*™Íf‚ĽR —Ë•Jł҈l“ÉÄ5Ëĺr$%%aéŇĽ8xđ ´Z-Ôj5‚ÁäňžŇ艉řâyq?H_lů|>pÇrý(•J( čt:„BA(•*¨TbŇ÷ÄÄD8N6"6Âd2AŻ×G*O‰ąôľř“˜˜žçYu/ž—ĂçóańâĹ,(šhŃ"¤¤¤@§ÓEŞEŠâöÉy¸ŰК!ä{m$ՔF’›EJ*) ËJß S‡1~FąƒG*˛D†"÷ĆH߸~pĽR“K&}&ę!rÁ××Vb[ÄǤjeҡbINŽÎŤďŕÜ;P!ömĺáÚJŠ”ƒăx œĹíóŹ/‘źô ÁóŠQc¨šŇÉ!şźp´ŞŞ*Ô××#??ŠŠŠGäC4 đrě⅀ŒuFd2DžAá\LqÇŚQ„B!HňŘ蜢F;ÖüžaÎ2(ʘ ý“ťJĂߌĆѨÔNÇţü’ąó 諄1Xç*ş­ü~ńÚVz$ńjŤžéâ{ œŚ)}Otwwł%’üü|äĺĺQ #šßď‡ßďg…p8 ÇĂ~¤R҇+E}]ĺ÷űáőzĄÓéĆTž[ š¨Őę!Ă­ßăńŔëőú|ŁŃˆ9sfł\%#át:ŮČ!)KVVf͚ĹÚa°Ńs‚ Ŕívł@ˇĹb°Nš\Žääd,^źxŘ6 ƒ(//G~~>ŒFă ÷ű|>čőú÷566şL)Ŕ]Y+úóŔh4˛QzR%Ăp8´ľľĄšš™%ľZ­hjjbšOĘËËqÎ9ç šš™MéęęBkk+ŚL™Â:Ɂ@ůůůĐh4IHÜĚŚ^Ůl6´ˇˇ#33ÝÝÝHKKCuu5ŹV+ŒF#***——Çr€Ô××#77@ HOO‡ÉdÂĄC‡`łŮP\\ ľZöövÔ×ף  MMM‘)M)°X,¨­­…Z­Frr2ššš “É`2™PQQŚŚ&̙3:fłĐétŘ´iňóóYNi›ü~?ŞŞA.W 55•-O•"ĺliiiBĄ@]]-ŇÓ3 ŃhŔóŸjľééé0 ,pYY+ •Ň6›ÍƒŘż?ňó °˙>pÇŚ—) h4čt:Lž<7nD{{;ěv; Ň`ŁBşťťĐޞ§Ó‰¤¤$pŤŐ ‹Ĺ­V ‡ĂĆĆF 8NdffBŻ×C§ÓĄŁŁ€8ĹMŻ×ą Qâ ÇɠՊŻWÚG€”ŘÝ)oŸŘĆaBß^ršfł‡Rn+™LŻ×ÇŞ ‚řĽ‹˜`Y€×ë‰Éí§Ó‰”BĄ0d21˜'k:‚ ŔĺrÁăń°–TÖŰçóyÚc!ä8é<öÎD'M†|ˇúÚ‹Ę m1šRČtŽ_¤‘€Ô6„;<Ď#-- :&“ ÄâŋĄVŤQQQ’’$&&˘ŞŞ >Ÿ‰‰‰ŹŠŒÉd‚JĽ‚Z­Ć¸q㐛›‹ĘĘJLœ82™ ČĎχÇăaů=*++Y5%Š’PNNŒF#RSSŧ\ÎF†äääŔď÷cîÜš0™LlŞ˘N§Ç´iÓĐŢގžž6˘äĚ3τ^ŻGnn.:::P\\ ¨ŤŤĂŇĽKŃÚڊńăÇŁąą%%%HKKƒZ­fS!SSS!—Ë‘™™‰ôôt$$$ ¨¨3gÎDMM Ěf3Ěf3t:ů3}út444 ššăǏGb˘X•é?řŇÓÓQWW‡@ ŤŐ …Bžžôöö‚ă8œ~úéläsNN:;;‘œœ ›Í†ÂÂBđ<ŒŒ ôôô° LSSşşşœœ FƒÂÂBčt:h4$&&˘şş“&M‚ŐjĹŚM›››N‹şş:¤§§CĄP`„ 8tčP¤’™3g";;rš‰‰fhľZâČŠŽŽ,^|: *++QXXˆÄÄÄHa fΜ‰ŒŒ TVV"-- ÉÉÉ¨ŽŽ†Ů,.G Y­V¨T*(•J̛7Ÿ}ößČ(ŸDVZZĄĂíö )) ƒ8őHĽę+}  “qlĸ4Ĺ-55M[R*•p8Ä ’LƁçĹQ4N§:&“™ĺ#âyąÝ55k‡p؅p8Œ„#?0ôX¸p!L&xžGaa!ŞŞŞP\\ ŸĎŸ>Ăn§jJ„ęŒcřjJ„BČ÷ US:~_C(by¤˛ÄŇh)爔/٤¤VŤuŔ4j@Éŕ÷űĄVŤYÂ\•JĹĹz<8NäääÄL7ěŸOZž4Ęa° FŃŐ ĽDěRđGÚviJtżFŁaUÁ‚Á ”J%Ëń&Mƒ lČĺň˜Š‘RU7ŠrôXĽR‰Ď?˙Ó§O IŁ<¤˛ŰR’)nYY&Ož ŁŃ“FZż”Ř\Ú~iôEt%Šh@t•&)żŠBĄ@  ˇĽe(ŠČş‚„p¤LuĄP˝i_żúꍸđÂeHH0Ć´…´°uDˇMtűIšŚBĄË÷â÷űń“Ÿü2™TľMs<ˆÇ‡PH,8$`d21áűĺ—_ŽůóçĂd2 {|Űl6Ź_żďžű.ü~?Ű>1ź4‹y)Ví"ˇKăđňËgŻ›çy6=LĄP@&45US"„“5ŔCß B!äh’‚ R°C§ÓąŽŠ8­HNNFrrň€Î¸TMÂlę‹ôAŘT#Š"š^݇Őj°ţč¤ĐCU˙‘ CŃh4ŹúŽL&ƒRŠdÓ]¤őKËč?Ľ$:řpA4)'$şüôŮgŸ=ě~î_ŞZŠTbÁ‚śc°ő‹ƒ†î†÷ż/úďčőFß.ŽŤď>…B…bŕ:n¸á†ĂC# ř˗/‡FŁÇqđx)^;Ľ­'„1đűý‡GdĄ*<„BNFRN’ž<Ú'ÇC›tuu˘ąą[ślÝngՀA@oo/ęëëąeË–sCddd ĄĄ---hmmŎ;PSS˝^łŮ §Ó‰ 6 11ťĆv'Áó<ź^/”J%ŒF#öîÝ˒ڶľľÁĺrAĄP žžľľľHL4łmĽ/ŹH‡+Vüa@ ćdDÁBőuuđů|ÂtA!äűG đůüh¨Ż‡˜—2şćůÎÚ%RŚ9##:*• ăƍCgg'BĄ+é,%™ĺyjľľľľP(hmmEJJ2 0›ÍhkkĂŢ˝{a0pîšçb÷îÝđú|čęęFggT*ŒF#T*ěv;ŞŤŤQXXˆîîn6ÂĆd2A§ÓA­VĂăń°mikkƒÓé¤F#1žzę)ÜvŰ­())9é_+MS"„Ă‘EŽ3!ƒ,rÁYuč**ŕłfA,$G „BžG~¨¨8€ŞCUěóQýšy’6„pƒA9~;wr9 ĐŐŐ…ŹŹ,˜Íf´ˇˇcîÜšŹěľL&C~~>T*Âá0–,Y‚p8Œźź<¨T*tuu!'' ĐëőĐëőP*•HOO‡×ë…ÝîŔţ}ű‘€’’$%Y P( ×ëÁqŃŮŮÉňÔHIv­V+ƏˇŰÍE'J•*­­­8pŕ ž~ú/¸íś[ńôÓÁž}űbsĹWž4Ż—‚1„râ%ŚĐ“—Ó‰W_~ůůůHJ˛BŠ6@!„œě‚Á şşşđżż—Ó)Ö˛í÷šy‚~ŕłA>2A,ńkˇ;"ĺxO <Ď#11‰‰‰ě6ŁŃČ~×jľČËˋyNVVVĚßRŁţύžÍh4BĄPŔhL`NÇ“M' 5ijŇž}űđôÓÁľ×^ƒ{îš÷¤}˝Œ!„Q] ÉA@0Äö­ŰđˇgžÁ/oý,+dAĆŃB!''!,@€€ŽŽN<ű—g°mËVA1ôr$ň•ž|Aäő8”ď-Ăô™ÓĄŐjéˆĐétĐj´bЊrâ‘#ÔÓÓłŮŒ ŠpŕŔAvűž}űpĎ=÷Âd2aüř‚Ľ§ý~?*+Áfł°Ż‚1„2Š 4!˜ńů|XőŃJ475㆟ý&CŠTE.Nއ+Rńë=ŠŹv˙ňÚqݒëböĎńźmÇCŰ}§[ÂśAÚ/ßĺţ9Üqs/O†Ď|@@ŻËĎWŻĆÂE‹ RŠĄŃhč‚‘Â<aČŃąnÝ:\xá…xđÁcn—Ś# ĀRŠDAAśmŰFÁBůDd!˜‘‰ßz˝lův3ö—ďCţřäää@ĄTޏ“!´˘VĐ˙âť˙…řX.Ěű/Ga˛,ŹˆëęŰOŇďc˝€ě[ÎŔ}1ś}+vęp˜ĺ­ý>üž=üžî5 G¸/Đ/`ƒ~űftÇtôkřşúíŰŘĺ ×>Ăď÷ŃƒGsß›cşď5 ˇoßváŰȏéĂ/#z?Š>ű~ű1=˛};Ö÷éѷݑÓ#o7żĎşş:T:‡Ă‰` Ŕž ‹ę¤Ÿ,ŸőÁ`••řóăOŕÎťďBVv6”J%8ŽŁ!„ôm:ß{ďý áp .„Ĺb°<…BpXŔ7ß|óźyóćEîŰzc*Á xoĎůMÁBńő™ ‚LˆdÄ P‚zzşąmËVlßşULř' Ş3*öÍ^zĚh?Ôc˘ďíßGşÎąlăh_ɲ_N´śKŰĐ1MÇ4Óߏcšă˘‚ŤR^•˜€ÎÉœč +ţ Řşů[Üw÷Ý8ëœsP2i2 d‘€Lt SÚ‚Đ7kKú[ t‰Ë “ Ů šá‚býď‹^ŽpŘŕšôűPĎ?\ yŕýŃí/ xîČśC܆ţű)z;űŻ7zű[÷pϸžčŕíŔöëߖѷIĎíżýƒ˝Ţţ÷÷ßC%‰~9Ű/vű†~~ôžďüîř‹9["ϗÉŘíöaCíÅâ_|ń%źřâKîÇ °Űí1kęv łžčű÷ď+püIűH.—ÇéýćđˇG׊“~ç˘ţ•~řȏ<ňŁ `š1yÚˇöx.!„ô'HŁčKę;ŕoB!ä$Á/˛S‘NĆQ"R J Ě(” hľZÄÄľŇk>\°#ş+z¸ŕB˙N_@l`gťÇš° 6 &c‹Á:ŮC *äţĂ˝ŚĄ.CÝ}ŹI÷žŢŘűcbťĺCÝ?řśŽý†ş4í×[‡ 0 vżôü‘nűŔíŠ=~÷ź˛}{‡ˆžDoĐ ~żœ}Î9ШՃF/Ü˝nŹ^˝zđ(Ě`˜¨uN)™4dűęő|¸ň?sŘř#?ĄČO8ęGˆúWˆÚ a¸ˆŒ!„1^”ĆŒ’‰ž0áŢv !„ćĂn`0Śßý2œœÓud‘ŃݞČčżßżĎž˘ż€!„ˆ\Nç1Yî†uë0cć̘j]ĐŰۋíŰśy˝•+†źĎd2ĹeŸQ0†BĆ|*`„~e˛č+XšRN!ääűĘC!'ŘĹ€ž’˜ô!„“烎ďóîűřň#Łd;–ďőű„ě„;ŻÇrßŃDÁB9Ş×Ť4"†B9)?ßé‹BČQDÁB!„B!ú⅐Á΋l{‡ý§‘16„B!„B+Žăh[GťtŘB!„B!dŹäźœśu”(C!„B!„1S*´­ŁDÁB!„B!„Œ™JŠ˘m% ĆB!„B!dĚä<ľJ}Üo§ZĽ†œç‹mĄ` !„B!„BŽˆNŁĽm ĆB!„B!äˆČy :Ăqť} :Ăq3* ` !„B!„BŽZ ˝VwÜm—^ŤƒF}|MŁ˘` !„B!„BŽ F{\IĐŽË)Tr:T!„B!„r´hÔj( ôzÜđúźßÉ6¨Ujč4ÚăjjR4 ĆB!„B!䨒ó<ŒzqTŠĎďƒ?@0D8>&ëă8r^ĽB•RuÜaŘţĄC„B!„B!ǂœç!×hĄÓĐžˆF9c!„B!„B∂1„B!„B!qDÁB!„B!„8˘` !„B!„BHQ0†B!„B!$Ž(C!„B!„GŒ!„B!„B‰#yű ;vě„ŰíĆÓO˙ĄPˆv!'¸üău466Ąłł/źđRÜÖ{Í5WăWżú%~őŤ_bţüyÇĹ6B!„ď'9íoŻ˝öţđ‡‡ÉÉV\qĹĺřĺ/žça2ąbŃřŮĎ~°Ůě¸ôŇ+h§rŮ˝{.\LŰD!„Bžˇhd ůNľˇwŕ™gţ†gŸ}žÝśxń"6:ćňË/É;=MiîÜ9xá…gąiÓ×8x°ťvmĂ{mŤŻžjĐéLx䑇ąnÝWŘżż ;vlĹß˙ţ"fϞ5čś-X0/˝ô<6múű÷—aÆľxňÉÇb|._~QĚöMœ81f×\óØ9VkqŠÖx%>řŕ=ěÜšĺĺťńé§+qË-7C§ÓĹ,căĆőlW]u%~üăëąyó7¨Ş:•J5䞝7ďTźřâóزe#؋˙ýďK<÷Ü_źŢč}üé§+ĄT*q÷ÝżÁ×_˙ĺĺťńÁ若t഍ÜÜüőŻÁöí[PVśO?ýg˜LڎýSO=ÉÖű›ßüůxíľWP^žëׯż—^ ČĘĘÄ3Ďüvě؊˛˛řÇ?ţŽźźq1ËâyW\q9Ţ}÷-ěÚľ {÷îÂę՟bŊ‘››3äzxŕwHMMźŽÍŘľk^|ńůĎ€qărńČ#cýúľŘżż ß~ű Ţz럸č˘eËĆľç̙ˇŢú'ĘĘvaëÖM¸ăŽŰ —ËcŽ— /ź ć9ĽĽ đĘ+/aóćopŕŔ^Ź[÷ţřLJ••5˘}:Ň6Ţ˙řÇ+ČĘĘÂŤŻžŒňňÝŘśí[<őԓHKKň8üůĎŠSO‹O>ůěņ kqçw {<ľţ÷Ţ{;ć>“Ɉ;}ś eeťPVś ~ř/,_~Ń çőH^ó’%g Şę`ĚqsĂ ?FUŐAÜqÇm‡Ý&Ł1ˇß.mÓNěÜš˙ţ÷ű¸îşk´}ô~:ëŹ31}ú)x÷ݡPVś›7ƒř=›z}ü^~ůĽxë­bűö-8x°[ślÄË/ż€ŇŇôAA!„r˘‘1ä¸đÖ[oă–[n†L&Çq8í´…x÷Ý ůř+ޏ?ź"ć6ƒÁ€3ŚcÌéX¸°?ýéMpƧă/y jľš=^ŠTbѢӰhŃixůĺWđ裏łű~ýëŰ$ńLOOÇE]ˆóÎ[Šťďž}´ŤWŻÁŠ@Ł“Ÿ~ú"ěۡ/&°Ô×IۄŽŽN(•JźňĘK8őÔš1Ë/**DQQ!.¸ŕ|\qĹŃŐŐ5HÇs.Î>űŹĂîĎoź÷Üó›˜Ű˛˛2‘••‰łÎ:Ď>űžzę/ž§P(đ§?ý]t!ťmÚ´Šx啗qÝu?Ćƍ›ˆÉY?üđ} ěqçŸ˛łłÇ”×'++ožů Ved¤ă‘GFO +V<3u­´tŢ~űMœuÖRŘl6p‡çŸ˙N?}qżŕ[> ňqŮe—ŕç?ż˙űßşë5đú믢  ŸÝvĆ‹1}ú4œsÎůčěě̞= Żźňkg°Z“`ľ&aöěY¸ä’‹qíľ?bÓčÎ8c1ž{îol_hľÜ|óMHL4šî¸ă6Ü|óM1ˇeffŕĘ+ŻŔœ˙řFlŰśý¨ˇšŃ˜€ˇßţ' ž¨Őj,[v>N=u.–-ťmmížsĘ)Ópǡą×—žžŽ›núŚO?W_}Âáđ˜ŢrssđĎž†ôôô˜Ű§N‚ŠS§ŕňË/Ĺ5×\żßDŻy4rrÄmĘȈ݌)S&cʔÉ8˙üĽ¸îşَˇwŔsKJ&âG?şž%'×jľ¸öÚŤQTTˆţđZöţôç??ŽóĎ?/ćš‹‹/ÂâŋđčŁOŕĺ—˙N„B!'CŽ čěěŠ | yĐrîžűNö÷Ž;ńűß?ˆgžůë¤IHIIÁŸ˙ü8 Ä8NŹZő 8Ցý fΜÁžˆŠŤŤĂʕŤĐÝݰř#rssĐŰۋ/żüŠ=6:  Ńhbž˙裏#î[Y Ćăńŕő×ßŔ믿ŽąăŸ—7nČ*DgŸ}‚Á öî-Guu ëĚőďŒţć7w°ż×Źů<ň ¤Ŕ/~q˛˛2í _pÁůŘźyKLP‰ă8üęWżdß˙}1˜ŠŠJŹ[ˇ%%QX8~ÔíżtéšHL4ŁĽĽ…Ý&“Éđâ‹Ď!%%mmíŹmąÜůœXśě|śßŢxăŸxěą'PWWÇÚ롇t˝Ë–šdűm IDAT´´TŹ_˙5š››Ů퉉‰¸ćš˛íxôчY Śźź>úDL°pΜٸđÂel}üăb‚R[ślŎ;q啃Oš;í´…1˜UŤ>ÁóϿȎQN‡§Ÿţ3”JĺÁŹąśůÔŠS P(đÚko`ýúŻc‚Mwß}× ë;ăŒÓQQQ‰W^ů***ŮíłgĎb#šĆâ駟bç~(—_~…ožŮČîŸ9snźń†QżćššZźřâŔjl/žř2śnÝ6ě6ýĺ/Oą@L(Â_|…Í›ˇÄŚ~÷ťßúܛnúœNţ÷żupš\1űiΜّ€MIL 棏VâŢ{ďĂ|ČnťóÎŰG5ęŒB!„˙hd 9n¸\.62b¸Ž‡^ŻGBBBTÇőSźő–8­`çΝĐh´¨­­Em­Řżä’ĺĐëőŹ3uéĽW˘˛˛<Ďăý÷ßŔ)“‡QZşŰśmÇő×_˖]__óÎ[ˇŰƒŒŒtŹ^ý)4 Ôj5ŽşęJüéOâŁVâźó–&M*Ar˛íí˜7ďT6mĂăń`őęĎĄVŤc:ä÷ß˙>üđ߀ˇß~Ÿ}ś pÖYK`4&ŔnwÄźvťÝŤŻžűöír˙ôôŘpőŐ×!== Z­Ží›UŤ>Ĺ7ߏc†ââb444tÝwßýxçwĎ>ű ‰3eĘdÖ6ŃŐfžüň+üěgż€ (-]€ücôßŕű|>,[v1*++Œvxňɧđüó/bܸ\ŹZő ŞĺççG]wݏ‘žž†ŽŽnkooǟ˙üq„É`űS\|ńĺ¨ŹŹ„VŤÁę՟˛`Ŕ”)SŘ>šíś_#== iiix˙ýápˆË™;w6˛łł#ęb|đ8}N:ŽŁˇîšç.ÜxăOźţýč:öű|ˆťîş7˛˙ŸÇš5â6ĽĽĽĄ´t>žř⍣ÚćĄPW]u ŞŞŞ/źđ,–,9pć™g@­VHś][[‡K.š^ŻZ­ŸţRSS\pţ°ŁÚ†2cĆtLž<)ćܐŽĂßţöüä'?,X0Ď>űܨ^óš5ŸăńǟĒ%g°ŠJ˙űŤxüń'GľM<°ożýŕÁďgť‹.Z†Ç{6›-ćůuuőXśl9z{{1aBV­úˆUlš:u 6múééąÓÁ^zée8pď˝÷>žýv :;;Q[[ǎ9B!„BÁBŽ*)`"v.{†|œĂá@UU5ëŒß˙}¸öÚŤąwď^ěÝťß|ó Ź`Ÿ>ýöűÁƒQYYÉ:Ążţőo T*QSS ŸĎ7ŕń_|ńÜn ŠŠ;věÄźy§˛ŽŹ[ˇ===0›ÍÉdXźxŢy罘)JŸţÜn7ŚL™ó:ŸxâQ<ńÄŁ^#Ďó(,,đ­ýʕŤ† ÄHA­-[śÂd2aÌéřéOo@zzú€ź!C˛řď˙Ë~_ˇn= ƨT*(•JŒ7.fÔLJţ‡ĐYż~jkëÍš2œĘĘCŹ]žúꍘ`Ě'ŸˆŰSSS‹C‡Ş0iRIĚöˇľľŁ­­ŮŮ٘2e2nšĺfdddŕ´ÓöőFŻ×íö`˖m,‹ÁĐŔŰ˝{öď?€3Śă —!##ĹĹX &zůŃ9…ŕ˝÷Ţgż˙óŸoŒ‘Ž%¸řâĺ¸řâĺƒî§ & Œ9’6/+ŰË1âąú% Ćh4dd¤ÇÜŤWŻaˇŰƒ7aůň‹ fĘ×hLŸ>=ćďUŤ>ażżđÂKřď?CUU5 Jéq~¤Ű´rĺ*ŒQ(˜2e2ÖŻßóřőë׳éKD[[ Z @yů>( ŔÇ˙ű÷@yů>ěŮS†C‡ŞbFmB!„ ĆrÔX­IHJ˛°żŁ§Ť ćöŰďÄßţö4ë çćć 77'2Bĺ7Ř´é[Ü|ó-°Ű0›űňt47ˇĆ,§şş&ćoľZ“¤˙vD˙mą$˛ÎúŞUŸ˛ŽŮ˘E§áwŢĂi§•˛Çţç?âĽčmMpJbˇŰGôÜ[o˝?ýé 19rFĘĺęË}=5GDOO÷ilGąŤŤkÔÁ)Á`lůňčmƒžŤŃhđÔSO`ɒ3بƒ‘ęŸç#z]ŃËZ˛ä üáŌxŠŮÜ7ŞËăńÄäţinx\÷?ćF{Li›÷qŃŢ›#Ćh4ö8ŒÎ+3Öé4Ńůt\.WĚ´žîîn6MđhçcŮ&§Óő^ű^"˝ u. u|577ăž{~‹+„N§Ďó˜4Š“&•ŕňË/E8ĆoźÉ*ĐB!„ ĆrÔ\uՕŹs‡Mś­źźK–œƒü`&ć̙‰‹qĘ)ÓX°cîÜ9¸ăŽŰńŔŌ˛IOOYNQQ!ôz=jjjŃÝÝ Ż× ÇĂ:Çý+ĘD˙ÝŐŐ×9ü裕,3kÖPP””œřúëo`Ŕ4†éÓ0`ę̑şč˘e,żK8Ćżţő6oތňň}X˝úÓ#^~˙Î{FF:öě)cG‰‡ř=ÎRÝÝ}çŠ^ŻŮoVkŠŠŠP]]ƒ––‚p̏óÁśÉ`0°€LZZě{IôűÁhýç?ă‹/žÂ‚ó0cĆ LœXŒŠS§@­Vƒă8\ýľŘž};>ýô3ú° „B9IP_ňJJJÂ/ů‹˜äĽk×ţoĐ .’””\sÍqď˝wăŠ+.Ă_˙ú,nźńç˜3g>víÚÍ7~|1Áo_đĽăNj fyžÇŁţ ď˝÷6śn݄ß˙ţž?ýôEŹ“œžžÓńŢž}ű}çΝ¨ŻŻ$$$ÄäYľęVe§˛˛’M{€sÎ9›ýn4&ŕx×_-N=uŔźyób‚DżýíďđŃG+áóůJ›UWWł×ˆĺ˝Ľ@Ú˘E§hôČŃ4ţŠě÷GyO=ő4ÖŹůjľę¨,ÖŹ™,ÓŇ҂ëŻ˙ Ţyç]ěŮSĆnŃjjjcţ^´č4öűyç;č:˘ƒYýŤeÝyçřĹ/~Ž3ÎX<`TŇŃhóÜÜ6ľG.—ÇTŇrť=hllđœ%KN‡Ĺ"ŽdKMM)}.%ôíŸ\úpӅvěŘówtRŰoźŻżţ*6lX‹•+˙3ć×˝M#)ĂÝ›–.=7Ş-—˛ß@LŽFII nźń'¸÷ŢťP\\Œ?ţńO¸ęŞkPZş8fĘôžE!„BN42†ÄÝő×_‹‹/žrš|Ŕô ťÝß˙ţÁaŸĎó<~÷ťßB._ŤŐŠO>ůFŁ‘`1ź˙ţ‡řéOo€^ŻĎóx÷ݡ°ví˙PX8'łÇKŁ^{í –&''üoěŢ˝ ĚgŰëóůXÂĐčá-ˇÜ 1IzĽ)JRçöý÷?Ŕľ×^ xčĄP\\Œžž,]z.K.Z[[‡3Î8kLű×ăqłßç̙…ĽKρRŠPŞ{Źl6;6lřšĺdYźx>űlZ[ŰX…˜xŠn]tхčęęFnnnťíWG}ůÉÉɸöÚkĐÖֆË.ťd@šc@ĚłăvťĄŐj#˘?bÖŹ™ŕy9–/żpĐuźńƛ, ˛lŮůĐé´Řłg/ć̙Ĺ*o…B!œ~ú™ƒŽ¤:Ň6ýőWąiÓfäćfnjrY˝zuL@@bąXđŮgŤ°gOŚM›ĆňŸHçtvv@¨ťëŽ;aľ&ĹäЉś}ű”•íe szč~”–·Z­Fié‚çéX^sGGË5ľlŮů0›MXšň|ńŗ#ÚŚ+@ié|čt:̟ß ú÷ż?󈠟źq¸çžťbŽą]ťvٍ¨0&`T^^N„B!'Cžƒa@ ŚśśW^ůC´ľľ űÜććf<üđŁě[îŮłgaŊńë_ߝN@üvţšç^´ľľá׿ž‹%5pá…Äb^}ő5VŽöŤŻÖ˛çJĽ‹.şII∏@ €{oUkęë„~<`[kjj|cţřăO˛Ń7ršW_}nšĺfˆq:¸óÎť-[=ŤV}Šp8 @œVőĚ3OăÉ'C8B{{ÇQiż+†ÍÖ7}Ľ  óçĎCEEELIěxřřă•ě÷Ůłgáĺ—_Ŕ}÷݋ݻ÷•ĺoŘđ5ëhó<řž{5kvîÜ5ŕń.—+&ż‡FŁÁUW]‰Ë/ż+WފU$ů˙ěÝy\OŮ˙ŔńŮ÷]Ö0b„QHىa"{˛Ý˜ŒąQ˛L˛'!!ŠěR ­ •ĽČh0ŁbQhńűƒ>ú´~2MłüŢĎÇă>ú,çŢ{îšçž{?ďî9÷̙ł8::)Ţ÷ěŮCéčďßżgůň•Yž„Tűüć͛|„G“œœĚ˗/šté2cÌÇŇrľŇň×­[ϸqßrá‚ńńOINNć×_ĹÍíƒUü÷?ŻŔ‹ťűą,钒’9r4˗[rýú ^źxIrr2>d˙ţôë7 ŰůŞ bÚ´ܸƛ7ořă?8uę ăĆMä͛¤Ůw111ĺÔŠ3<ţ‚¤¤$Μ9Ëřń“x÷.šP둽ýVÖŽľá矐œœĚożýƎ;Y´hi,˙ĺ˗Œ1š źHHH 11ńă#Đ'p÷î˝lç9tȕ)SŚqíÚ5“říˇßpttbɒ˙)ĽKNţ4 ńŠ–L™2 _ž>}JJJ OŸ>ĺ̙ł >Š}űœ˙’}ţćÍ[LMÇáí}Q1ďąc <4Ç ĆÝť÷3f<ˇoß!99™Çe˖m|űídE€ŔÜ|.nnLj%%%…ňĺËç:Čňƒ1ôďoÄćÍ[¸wIźyó†›7o˛`Á"FŒ0QÜŠó9ŰźoŸ3ŤVY}Ÿˇoߒ˜˜¤¸Ă.ˇşŢż˙@6ośWt3LHH ,,œ+,1Â$Ë@Đůńţý{f͚…Ĺ|ƒxţüŠŠŠüţűďřú^fÖ,sfϞ+' !„Bˆ˙˜"*|^$Ăűô×E3üMŸÔ>NĹ>N%€â@ĽÖ­u2ţ]!ţëJ”(A­Zľˆ‰ůtU­Zľ¸|ů˘âý!#¸víZĄçÍÖֆűşâ 62Ďyüü|cälŢź[Ű ˛“…B!ÄNĽJ ÖžÉŔ; ĺă”úqJË0˝Ďđ7˝{CĆ×dz Ș1BQ J•*Ĺńăn4l؀˘E‹âî~œŕ૔*U’áÇ)Ň=zô˜°°0)0!„B!ţ’`ŒB 7oŢpčĐa~üńŒŒ`d4@)Mbb"ććsł?F!„Bńß'Á!„(`;w:ÁčŃ&´n­MŐŞU?Ž­ň˜K—ްs§CžU !„B!ţťdĚ!„B!„B oĚyš’B!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`Œ(Tjjj„„qďŢʔ)ŁŇ3ŢęžŢU {÷n¸şşpëVçΝŚS§ŽJŰ˜ĺ¸‹ŽŽ¤L™2¨ŠŠáęęÂΝŰßkjjrçN}úôβţš5kpďŢ:thŻřlńâ…DGGR˝ú§vâŔ}Ź\ů?Ľ<ŤŤŤIľjŐXľj%ŃёJőŻ}űöœ!$#ÄÇ ßŠáí탟_Ż^˝Ś_żž9ڎ´\M׎̝kž~Gâââ4Ȉĺ˗áě|€ţýXˇn=ß}7CĂ~Š _‡řűĐŁGofΜ͸qc0ŔÓ§Ď2j”)ǏâŰo'eťîĽKcd4€ĺËWĐżżŢŢ>ŘŮm¤víڊ45jT§_żžLœ8…)_ž<––+ß÷ëׇիWrđŕ!ŒŒŒ9|ř˖-ÉłœÚˇ×çáĂGôěŮ'§ýŘÚZcnn†šš˝x÷î––Ëé;w˝gΜgĐ !XY­aěŘŃ,X0_‘fɒE b̲eË16Ćłgż3iҡJë57ŸĹ”)“XšrFFƒ9ޓ;ś*ýp­QŁ::ubʔé,]ú)ß|óáÇő€ƒ™6í;z÷îŷߎĎvűÔÔÔŘłg7ęę5™2e:C‡Ž %%{űŸ2˜zPˇn]úőŔŕÁCŠ\š;”.äTI“Q÷îÝXźx!66ëéھۜí䧟6PŻ^],-Włi“ŠŠŠčëwÄÎΞ"EаcÇVžúŞ%łf™3b„ ńńń¸¸ěĎR2–Kú|͛k1eĘtFŽ4!))‰C‡\˛ >}}ýŽ<~ü+‡š˘Żß‘Ó§ĎR˝z5ÜOBB#GŽfúô™4nÜGGĽ‹őŢ˝żćůóç 27ˇcv̚›ĎÂŇr ˝ŕ§Ÿ6Pşti•ćMMMeîÜĐ×ף_ż>)R++KΞ=ÇéÓgł¤ăćÍ[téňŠžuęԑäädĹĹvٲeiÝZ‡ ź•ć‹‹C_˙C[ۍčëwäíۡŠďgÍúŽbčĐÄÄÄ`gˇ1Ç1Ťňj_˛[ďŃŁnüňË/čëwÄŇrľJő&óž53›Ă—_6eǎm*ďŸÜÚşě¨ZŸňs<ŤÚžä'ßy•M^ĺ{÷î]ÂÂÂłŒ1p`ÜÜÜIMMĽS§ŽlŮb‡ťűq ÄÚľ6˜™ÍdöěYJóLšô-+WŽbĐ !9nόS9sć,=z|͖-ŰřńÇhÝúC ¨hѢěÜš &OžĆřńŃ××S :fŚĄĄÁž}{ˆŠŠbذ‘LŸ>==]~řá{•×ŤŚŚ†ŁŁľk×fҤŠ|űíd:wîL›6­óŐäU6oţ‰%J`ddĚ ACiĐ@ƒůóČń˜ĚĎńĽŞźÎĹÝşueÝşľ¸şaŕŔÁĂŻżţĘŻżţJˇn=HHHŕéÓ§Še>ţ"Űu/\¸„ *đűďż`ggĎÔŠ“iŐŞ%żţúŤâ"{ţüź~ý€­[ˇakkC‘"Ex˙ţ=&ŒÇÝýۡď 22Šš5k`a17×rzüř1ŽŽGŘľË ‹9¸ššsďŢ=\\)cŚOŸĘ‰§ŘźŮ^ąž÷ďßłaƒ-?ýdGJJ*Æ aáÂ%œ:uF‘Śe˖4hđá›2eJ3aÂxfÍ2ÇËË[QŽ_}ՒѣM¸té˛b›ż˙~ž˘,ÓÝ˝{?\ţöŰo;ćAűöúŘŰoÍöGú ACHII&11 €Ýť÷°wŻ#•+Wć?ţŕÝťw,^ź”ÔÔTž˙ţ._žˆž^;üýTN“Q˝zőxńâ^^Ţ$%%áâr“'O)ś'>ţ)OŸ~ŞkúúzčęśĹŔ 111XXĚçÔ)Ǝ5eőę5ٖ‹ž^;žúŞ%;wWÔĄšsçáççËŔýqppTĘ×ۡo‰K||üÇéĂúMLŚđúu"ććsŰ8eĘ4Ž\ńĽk×.Š}uď^4k×Úř1ťnÝE—ŠUŤŹ02@óćZ*wӈ‰‰aÍk,˜O•*U¨]ťvŽPOĎ |óMoŹŹŹŠYł&uęÔfǎ]tęÔ 7ˇctě؁äädüüü•ćKKKSěť§O?•_şůópţź'‹-ÁĎď-[ś 00(Kňj_˛[oĆIŐzcb2*Ëž6í;´ľ[ĄŚŚŚř,ŻĄšľu™eˇÎěęS~ŽçrĺĘĺŮžä7ßy•ŽnŰ<Ë÷đá#̙cÊ–¤¤¤Đźys7nĚ´iß)ÚÍÝť÷°k×nĹ~VWŻÉěŮflŘđi0T[||rçăčQwNž<Ŕž=NŒ5‚öíŰpx7 IDATz ]Ýśhkˇ˘[ˇž<|řđăď9\žě“ëqÓĽ‹ąąąŠĎ<ŁGáíŰw9“ů9žTţŻbçâɓ'rüř śmŰĄ¨ŸŐŤWSܝ’“jŐŞ) Ř °i“˘<ň{^Ë|~IÄţý úŽ\Ž­íz“T:_´hчŹ[ˇ—ƒ9n—ŞűŔÉiWŽřpäČQtuŰ2qâ<=/¨”&żí“ŞůĘíź4räž={Š…Ĺ¤ĽĽ)Ž%]]?ż MMM4ĐŕË/›r˙ţĎDEÝĺěŮs¸¸ěçĘ?ƒ8sć\ŽŮy˙ţ=::Ú´k§KŁF ŃÔlŒšššŇíŮ Š“ĺ‡ Ď3Š+F‰%xűö-Mš4áđaWĽĺćšîŒŕiii¤ŚŚňâĹ Ľî%J”Pş;vĚCiÁÁ!+VŒŚM›’˜˜HńâŠɔ—ŏĽFQştivěŘŞTNĺ˗WŇˇ9ťrüíˇß”Ţ?{öŒćÍľr-ß>}ú ­ýŠŰt3–ď;‘JżýöńńOiÚ´‰"ТJšŒNž<…ŠŠ /zâë{ ˙@ΝËů‰R-Z4'..^qᔞ÷ŤWŻŇ˛e‹ËĽeË”*U /ŻsJË+_ž<őęŐSš6oŽEhh¨Ň6ĆÇ?ĺÁƒZ´hŽřńüčŃŁżä¸Í¸_Ÿ={ö1pW&_ËطϙqăƲlŮ&Nœ’cŕÂ/fϞEŐéÜšĄĄ×¸|ů 7~x T—.¸rĹOéŽUƒBŸŽŻÜe˖ýŹöEŞÔ›ěöí“'O8sć‰ĘëÉo[§j}ĘĎńܰaƒ<ۗüć;ݞQĽ|=“–-[ĐĽKgzô0ŔÂb.3gšáééĽŇ:śmł§iÓ&ĹŘx0M›6AGG‡-[ěňýŸă]ťčׯ/Ó§OĽIM 2ÂČh`—ď–-[0ŔiÓŚĐ´ižůŚ7˖-a˙~gž?Áëׯqq9Äüůôíű M›6aΜŮJ ‰‰‰888˛bĹ2 űѤ‰&#GŽ`÷k׎@ó{˙ţĎ¨ŠŠ1z´ _|ш= ”N—’’̆ ëhٲúúzlܸž°°p‚ƒŻć+MF#F gß>GşwďFŁF 11Iĺʕ‰Šş |ľJ•*hkˇ˘jŐŞĘćÍŃ××CKK +ŤUÔŠS'§˝9nc``ׯß`űö­tčĐ-­f,Z´;ťMTŽ\Yĺ˛rv>@šrĺXˇn-͛7§];]śnľăΝ;\źč“ď˛/_žZZ͔ŚĎ}šHhč5ŇŇŇXľj%ZZZöcňäIY~›˜Œbɒeœ?ďI@@ ÖÖVšţ‡đÂ/úôů0ŕoú1{ń˘ăǏĺƍ0ŘOى‹‹Ľukžř˘Ńg×ĎźÚU¨Ro2îŰ-šŁ§×;ť 6”wďŢĨQ#éÝťÚÚ­°ąYŤ4e^mÝ_]Ÿ•Ú—ĚňĘw^eŁęqČłgĎX´h§NRŒW`oż…QŁF2uędš6m‚Awvîܖç‡ňëŇĽËÜ˝{;ť05ÇĆfMŽAîű÷٘ž={ШQCÌ1eČă|­÷Ęnݺ͌McX­_o˛7IśmeʔÁŃq'˖-ASS“Ö­učßßPŠţe>&ó:žŇť°hkˇRtKHH iÓŚÔŹůyA›]ťv3dČ`ƍƒŚŚ&ýúőĹÔÔäOoĆ|Šr^Ë|~I§ĽŐ ss3š6m‚Ąa?,,ćâěěBRR’ĘçËô˘-ĄĄ×ŘşusŽw"ŞÚĆ >#Ł4i˘ÉôéSéۡbŒ%UŇäˇ}*ˆś÷Ŕ*WŽ„ÍZ´´´čÔŠ# Ě'))éłŰ|UŽ%UŇ|îőDf˗/ĹÎnÚÚ­hÚ´ cǎ!11‰‡˙šîĘB ƈšţýű‘”””í ˆ7n„ńË/żdyęEn,XăءĎGÇ]“ž}żÁÍ͕… çłoß~,-­iVŽ\…łó–-[ÂŃŁ‡ŠZľj–؞}'sçÎĆĂÝ)S&ňż˙­Čń‰ Ÿ+22ŠYłfcjjÂącG™8qBśƒĎ_Ĺß?GÇ]lßž…˜˜_˜8qŠŇ%ޤÉČŢ~+..‡Xşt§Ny`j:šE‹–(~ˆ^źčÉ'Ůťwß?‡´´4žýv2ˇ°łŰČÁƒÎÔŽ]‹#L˛í֔îÓ|Ź_oĂŃŁ‡iÝZ‡QŁL•ú‹ç%..žáĂGQąb%\\öąe‹?˙ü€1cĆÖďťt鄇‡ťŇôÝwŸ×E 66sóš´n­ŤŤ C‡łjŐ§:WŽ\9ÖŽ]ÍŽ]ť űđˆú%K–ĄĽĽĹ„ ăr\ŽżĽK—ÂÇçSx_*T¨ Ó$'––V´mۖ“'gy´mAľ/ŞPĽŢdܡěcóćMÜť̈́ ËYˇn=ţţŹ[ˇ{{;Ž^ áÚľë*ˇuu}ĘOű’9X™[žó*UË÷ďßăęz„ƍżŕđá#YÚÍŠSgĐťw/ÜÜ\Yłf§OŸQzJ\AHIIaěŘ <{ö ‡89}8˛<:Ýž}Î89íc͚ոşB[ťŰśmĎ×zSSS™0a"<`ǎ­ěŢ˝“Ë—/T`ۖ€‰É6lŔáĂppŘAllÓ§ĎĚń˜Ěëřzńâ%ŽŽN,]şX0Ůśmß|Ókë5Ÿ•O,^ź”ącMńđpcěXS,-W˙éíϘ/UÎk™Ď/éśoßI͚59zô0‹/ŔĹĺ kÖXçë|™qż›™™SŹX1lm­ł |ŤÚĆ-[ś‚#†sü¸Ćƃ™7o>.xМ&żíSA´˝=f̘ńÔŞĽŽŤŤ ˗/ĹĘj-/_žüě6_•cI•4Ÿ{=‘ŮŹYć<|řˆ­[íqssESł1ăĆMP<,ŕ‡,đńńBńďPD…Ď‹dxŸţşh†żé“ÚÇŠŘÇŠP¨Ôşľn@nƒ6 !DFÖÖV”)S†3fýŠ4Bńw+^ź¸âɀéöďwâÖ­ŰůßíÚérŕŔ>ZľjĂŤWŻţś|ůúzłsç.œœöýcĘŞnÝ:řřxѧĄâŽŃĎI#ţŰśm!>>ŽE‹–Jań'TŞT‘ĐĐ`}ŕ9 źR>NЧ´ Óű ÓťSd|MŚ×€Ü#„Bń—Nœpgůňe4i˘IŁF ™:u2şşm•,ţ:ƒ ÄÓó,_ݓzőꢯŻÇ…?řˇb„ř+|ńE#|}/KAń/!OSB!„ř $''3gÎźÝb(WŽ÷îÝcöě9švUÇĂă$ľk×ĆÂb.uëÖáŐŤW\źčĂęŐkĽpÄŠššľk×RéŃíBˆéŚ$„B!„BtSB!„B!„řO’`ŒB!„B!D!’`ŒB!„B!D!’`ŒřĎ)]ş4^^ç˜9sF-ÓŘx0!!˙ˆĺ”(Q‚UŤVríZ0üýĂœ4é[˘Ł#łŕĂ#0ŁŁ#iŇDół×QˀĂŢźy“$B!„Bˆż•‹‹C_ż#GşńË/ż ŻßKËŐJw÷côécČýű?Óšs'ěíí8sć<ƒ ÁĘj cǎfÁ‚ůJËmß^Ÿ‡ŃłgoœœöckkššććôâÝťwXZ./°z ĄĄÁž}{ˆŠŠbذ‘LŸ>==]~řáC—¤ÜöéŹYßąqăO :‚˜˜ěě6f ´äEOŻíÚé2nܡLž<úőëâః˘EĽ9B!„BéŚ$ M``ű÷ (čwlllYšr9śśëILLbĐ !¤¤$“˜˜ŔîÝ{ػבʕ+óÇpď^4k×Ú(-÷éÓ§¤¤¤˙4Űőš˜ŒâőëDĚÍç*ÓŚ}‡śvŤ,wŸ¨ĘÍÍ???bc㈎ž‰ÉHÚśmÉ'élllńńńÍq9‡aîÜŮ,_ž’””žúŞ%_|ш)SŚeI›––F|üSĽ)Ł#GÜ8tČUń~úôМ8qŠÍ›íˆŒŒâýű÷lŘ`ËO?Ůńüů ?~ŒŤëvírŔÂbnnîÜťw—CycŞUŤŚ°7ÝŚMvlÜřS–´111téb@llŹâ3ôęő5üńGŽűtţüœ?ď Ŕ˘EKđóťD˖- Ryß)R„Ůłçňöí[fÎ4ÇËëzzí˛ ć !„B!DA“`Œ(47•Ţ߸FŠRĽĐĐĐŕöí;ź˙ž>}ú ­ý4kö%%K–TĚóčŃŁ|ݎys-BCC•î4yňä gÎ<ůSŰŁŽŽÎđáĂĐÔÔ¤A žü˛)÷ď˙Ź”&Żüzxœ`áÂůtëÖOĎ 4ŤWCřůçůÎĎăǏ•ޡhќcÇ<”> ĄXąb4mÚTŔČIKK#55•/^(>{űö-%J”ČuÝŮ ŕŸcúâŋ1aÂ8´´šQż~}š7×"...ĎmŒ‰‰QźN„•-[6_ĺtëÖmE &}™Ďž=ŁiÓ&ŒB!„B ƈlŊĺřžJ•*¸ššÇɓ§ńöö!%%…Ýťwţéő)R¤Ŕç™4i"ffßqđŕaźźźřůç̘1-ßëIHHŕěŮó ÄŰű"††ýXłĆć/ŰďßżWú[Pň3€oťvş88ěŔËË?żŽuGGG‡!CřöfˇUýL!„B!ţ˛ßÇR˘°ččh+˝oÓŚ III|+VâŔ}lŢź‰{÷˘™0a˘"™™9ďŢ%łwŻ#‹-ŔÎÎ^)(réŇeBBBqu=ˆśv+,XăءĎGÇ]ÖŹYŤë!´ľ[ąmŰö|íÓěÄĆĆan>—Ö­ľquuačPcV­Ęş­WŽřáďˆŁă.śoßBLĚ/Lœ8…´´4ʕ+GőęՕĆ*B!„Bˆ‚TD…Ď‹dxŸţşh†żé“ÚÇŠŘÇŠP¨Ôşľn@aţ'^üóřúzłsç.œœöIadcÌi ä믿‘ÂB!„BˆżIĽJ ÖžÉŔ; ĺă”úqJË0˝Ďđ7}ź…ŒŻÉô1c„ř[ŐŹY“ŚM›0vŹ)śś¤@„B!„â˙ Ćń7š9s:††ýpw?ÎĄCŽR B!„Bń˙€tSB!„B!„ đş)ÉžB!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1B!„B!„…H‚1â?AKK‹­[7sőjaaĄ<čLϞ=ţ_—IÝşuˆŽŽ¤IÍÓlÚ´'§ÝşĚźäwkk+6oޔăűŠńăÇâí}^ĺíř§ř§ć+łV­žÂß˙2;w’FT!„B* ƈ˝Î;áęęBńâĹYşô̙ó=wďŢeË;ŚL™$ôѨQ#ńóóUúěĘ?.^ô)Ô|ô:łŰ.!TńäI,çĎ{ňË/Ľ0„B!DĄ*&E ţÍJ—.ÍÚľV¸ťgÁ‚EŠĎ==˝ˆˆ¸ÉňĺËđöžHTÔ])ŹlOdäMź˝Ďóő×=sÝŽşuë`kkCp°?×Ů˝{ššŞw­*Y˛$K—."(ȏ;w"8tč@Žó—)SššsÍńőőćöíp<<ÜyLŻ{žžŢ|óMoźźÎqëVÎÎ{Š[ˇŽ"MąbŘ?߂  ?""Žcišœâŋçëxhß^ŸˆˆëŠ}V¤H&Ožˆáá×qu=Hˇn]óľ˙Ň뙭­ 7oŢ 0đ sQSSË3?ăǏ%$$°°Pěě6QľjUĽĺΘ1 gç˝DEÝBKŤŮÇü4Vä'$$ľkWSŠRE čĎíŰá”.]Ząœ3gNpáÂ9ĹűRĽJqëV††ý¨S§6ŰśŮ~đđkŘÚÚ(ś/óńlmm…ľľff3 ö'<ük׎ŚdɒŠĺŤŠŠ1gŽW¸yók׎ĆÔÔ$×îdB!„z-. IDATBH0Füă•,Y’#†3iŇDjÖŹ‘kÚ-Zpűöž?‘í÷ţţ´lŮBĺuwęԑ-[ěpw?΀ƒXťÖ3ł™Ěž=KĺeTŤV —ý<{ö”!C†3sćltu۲cÇś<H?|řˆž={ăä´[[kĚÍÍ07ˇŔŔ ďŢ˝ĂŇrůg•ŠĽĺj6m˛#55}ýŽŘŮŮç˜vٲ%Ź_ż‰ş°eË6ŹŹ,sçsˇ53sóYXZŽÁŔ ááüôÓĹîîÝťąxńBllÖÓľkśmŰÉO?m ^˝şŮn—šš{öěF]˝&SŚLgčФ¤$co˙S>ňc†S§ÎŔŔ wďŢcËťK—.ĆČhË—Ż #ź˝}°łŰHíÚľijÔ¨Nż~}™8q Sž|y,-W(ž_˛dC†łlŮrŒ‡ńěŮďLšô­ĘynÝZ‡íۡ°rĺjÜÜÜĺ:eĘ$VŽ\…‘Ń`Ο÷dǎ­Š1RTÝff3 Ąsçî̜9#ŁŮý2:ŰľÓeܸo™†Üż˙3ŐŤWăŕÁý$$$0rähŚOŸIăƍqtt@MM‹}PSSCOŻUŤVĽQŁFÔŤW—Zľj)Ö[ŹX1|}/°yóO”(Q##c Jƒ̟ŸsŢżůŚ÷ÇŔĎ`ŚMűŽŢ˝{ńíˇăß[XĚÁÄd˗ŻŔŘxąąqLŸ>Mn!„B‘/ŇMIüălÝş™.]:`jj‚‘‘1ż˙ţ{śi+VŹČü‘ă˛^źxAŊU^÷ôéSŮ˝{ťv}`6:ú>ęę5™=ی TÔÄd$żüňyó~$-- €9sžçôéhiiqëÖ­lç{üř1ŽŽGŘľË ‹9¸ššsďŢ=ŕÝ>ŸŒyőęńńOyúô)ńńOsMë䴏+Wü8rä(şşm™8qžž l[3[ˇn׎]`Ő*+ŒŒĐźšW݆PŻ^=^źx——7III¸¸ääÉS$$$dť]ƒ !%%™ÄÄ$vďŢĂŢ˝ŽTŽ\9×ú’Ž~ýzDEEzíc d%K– 555Űô .ĄB… ŠzjggĎÔŠ“iŐŞ%żţú+E‹eţüź~ýúc=߆­­ EŠĄlٲ 6„… —pęÔ"#Łhٲ% ÔĎ3ż-Z4ÇÁaëÖ­ÇĹĺ đán Ć3k–9^^ފúüŐW-=ڄK—.Ťź˙ƒŘż˙AAżcccËʕ˱ľ]Ż(ă̊)ÂěŮsyűö-3gšăĺu=˝vřű|Ź_n:䪘gęÔÉź~ˆšů\EYO™2+W|éÚľ ^^Ţ_ĽK—N\źčCçÎ BMMÎ;rč+]ťv&((˜—/_PŻ^=Nœ8Itô}FĂۡďr,Ëťwďąqă‡ŔÝożýĆąc´oŻ˝ýVJ—.ÍčŃ&üď+űéΝHZ´hNƒŇx !„B ƈ§zőę*1𡋁AwE"ť`K‹Ís\^Ŋyńâ…Ęë×Ók‡ž^;†ŞřŹ|ůňT¨PAĽe´hќV­ž"44Hé‡iúüœąąąŠ×iii¤ŚŚ*ĺýíۡ”(Qâ/ßJďoÜŁwďŻ t[3űíˇßݟ={ö1˜đĄëŘɓ§055áâEO|}/áďČšsšw y˙ţ=}úôA[ű+444hÖěKĽî&šqttbűö-œ={Š+WŽpéŇŝ9­OGG›vítiÔ¨!ššQSSSZ_BB‚"đôé3Š+F‰%hذŋ'$$Dišycš5ű’cǎ‹ŁŁ“âóFQştivěŘŞ\Ľ×çôŸŞű/"âf–:QŞT)444¸}űNśůşuëś"ĂłgĎhÚ´‰"óřńcĽyš7×"44T)č˙”bhѢ9^^Ţxz^`Ô¨‘Ŕ‡;ŮQSSŁS§Á˜Î;ăě|@1˙ćÍö̟?=  ĆÓóáá*ŐĹôúŘźš–R™†„„*Ľńó `ŒB!„`Œř÷zöěw•Ćpyřđaށƒ‰'PŠREž?AĽJ11Ĺńă<|řˆöíő¸x1ç'í¤˙đĚđ°ľÝŔ™3gł¤MHH \š˛y.ŕüyOVŽ\•ĺóœîđ)(Ůĺ%ż2SRźxîÍÄ_˝­Ďž=ŁOC:thO‡úL™2 ‹š :œGgI_ĽJÜÜ\‰ăäÉÓx{ű’’ÂîÝ;U^gPP0]şĐ­[WôôtYťv5ŃŃ÷=z,)))YŇoŰfOÓŚM8xđ0nnîDFFqäČĄ|ďˇĚűO•ýŠĄĄťűqěOďŢ˝8{öœŇ÷ćůóçJŸ%'§äk˙+Ś\2żWľ.ćľ=š}˙ţý{<=/°hŃjÖŹI‡íŮťw?đáŠZęęę4jÔOO/Ĺ|Žœ={ƒî´k׎C‡&âŕŕˆľőş|×E5ľ]ŹRR”ďJMM‘Ć[!„B䋌#ţQ™6í;~űí7^˝z…••5A9Ś÷ööá÷ß˙`Ţ< ž?AíھٴiŚŚ&4lؐŁGÝ>.ű5ĺ˗§TŠR~Č*ßuN:ľyôčąb*]ş •+W&55•ׯ¨QăÓX6ՅwÔ­[—ǏU,ăŐŤW4jԈwď’ °Ź^S˝zőOsѢԍW7ĎłyŃÖnĽôžM›ÖšŢýđWok͚5hذ!žž—°˛˛Śoßţ-Z„ž}űdť]zzşÔŞĽŽŠéxvďރ——wžÂmܸ1ĽK—âřq.\‚‰ÉtuŰ*îČ¨rĺĘtďލ… cggĎŠSgˆŞPĚKtô}’““ißž˝ŇçíŰëç9ďůóžĚkÁŽť°ąYCăƍ¸˙gŢźyC:u”ęs:u(VL-_űOGG;ShCRRÄ䘯f͚)ÝÔ°aŞTŠ’c]‚wŕččč(ÍS­Z54ĐŕÖ­Ű<|řˆťwď2t¨1%J” <<‚đđÔԊ2lŘîÝť§ŕŞŠŠĄŁŁC\\<{÷îgćL3VŻ^øqc>Ť.>xCJJ ::ĘLjŽn[iź…B!DžČ1âçňĺ+tęÔMĽ´III̛÷ŰśmĄFę=ꆟŸ?#F ㍯Zbm˝ŽČČ(BCŻ‘––ĆŞU+ٚӁF2yň$ĽĺŮŰoaǎmÄĆĆáí}‘:uę°tébřá‡üńÇDEÝ凞ç͛7”(Q‚)S”—ąż3ŁGÂÚz NN{)VŹććf¨ŤŤÓ§a•S@@ŁF$"â&ąąąŒcŞô”™ôŽ)ÚÚ­xň$–¸¸8ŞTŠ‚śv+>|¤č”ŮđáC‰ĺÖ­Űôěكž}ű0uęŒl—YŰ:bÄpFÁüů ‰‰‰ĄS§ŽTŽ\Yń¸ňĚŰu˙ţĎ¨ŠŠ1z´ ^^^4hЀ ć+-3!!/żü’ 4xđ &Ëűĺ˗Rźxq,-W“””Ę1Ś$&&ńđáŁ,ů{ůň%OŸ>ĹŘx0ąąq”)S–ďż7W9řđúők\\1žϟ˙Atô}úőëKăĆ_đîÝť\çMďŇccc‹–V3śnÝĚ ACHHHŔÁÁ‘+–Qźxq˘˘˘hÓŚ ‹/`áÂ%¸ššŤź˙´´šannĆŠS§ŃÔÔÄÂb.ÎÎ.$%%嘯ˇoß°qŁ-›7oĄlٲ,\ř#aaá_Íqg瘚ŽfÝşľěŘá@ٲe˜7o.wîÜáâEE:OO/&LĎŋ>Šąn|}/3~üXœ]éʔ)ƒŁăNNœ8…ŁŁĺ˗ŁCE›_/_žÄŐőóç˙@bb111ôěكśmŰđęŐ+iź…B!„ĘäÎńŻçë{™aĂF’––ĆŠ˙ĂĘĘRńĂ(ăŘąąq˜›ĎĽukm\]]:ԘUŤŹ˛,kęÔôîÝ 77WÖŹYĹéÓgXşôÓŔšffćź{—ĚŢ˝Ž,Z´;;{ĽALăââ6l$+V`ď^GöěŮÍŤWŻ05—m—ĎľnÝzüýXˇn-ööv\˝Âľk×ßżxńGG'–.]üqĚNœ8ÉŢ˝{řţű99.wٲŒ1œăÇÝ06ĚźyóšpÁ+ŰeĆśÚŰoĹĹĺK—.âÔ)LMGłhŃŏóĚŰĹŹYł155áŘąŁLœ8ľkm”–éârˆ˛eËŕááNńâĹłźŸ5˜‡ąuŤ=nnŽhj6fܸ Ův˝JMMe̘ń4hĐw÷#XYYâč蔥kP^VŽ\…łó–-[ÂŃŁ‡ŠZľ*öö[Už?5533sŠ+†­­5EŠÁÖvۡďdîÜŮxx¸3eĘDţ÷żЧ-Šş˙śoßI͚59zô0‹/ŔĹĺ kÖX皟+Wüđ÷ÄŃqۡo!&ć&Nœ˘žd'..žáĂGQąb%\\öąe‹?˙ü€1cĆ+#ăéyŠ+ŕëűŠ âŋ>T¨PAQWӃn&&chذ‡ŔÁaÇǧÍüěú¸lŮ </’á}úë˘ţŚOj§b§@q RëÖş9=zXˆżĘ˜1Ł™>}ýú Čń.ńIÝşuđńń˘OCĹ]'Břúzłsç.œœöIađa\555Ľ`Ő̙3čŐŤ'ýű’B!„ř—ŤTŠ"ĄĄÁúŔs x¤|œR?NiŚ÷ţŚßŸń5™^rgŒřsrڇž~G Ä! ĚŞU+qrÚMëÖ:ÔŻ_Ÿ~ýú0nÜΝó”ÂB!„*“1c„B­[ˇž9sfłqŁ-ŐŤWçɓ'8::ąyó)!„BĄ2éŚ$„B!„BtSB!„B!„řO’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒB!„B!D!’`ŒřWkٲŃёŮNÝ d›6­ÇÉi7uëÖ!::’&M4˙’í)]ş4˙×Ţ}GEu´a–Ľ#{%š{ďXP“XŠ6ťbEąb76EcÁ.` @P,ˆŠHł€(č’5*ňJ)űýĄlXvE‘óüΚgďÎΝ;wî\<ű:3ëďďƒ9sfń斳qăĚpőjŞUŤVĄĘ"""""˘Ż2›€žÓ§ĎŸţ)•öřń“2)űúő`hii•ËudeeÁÇÇwîÜĺM-g11÷áë뇴´´ U}}ŒĄŻB||‡Ë—}$ďŐŐŐsC‡‘Ű>őë×ĂÖ­[vŃѡáät͚5“şţ͛m1sćtDD„âîÝHěÚľCj Ž"y Sô˜ţýőŕĺĺ{÷îŔĎď&N%Ľż˙t`ÖŹpq9Џ¸´hńŁd:ـýáćvQQˇącÇ6hkkcíÚ5 ťđđLŸ>MRŽąą""nJŢ׍WűöíFTÔ-DEÝÂÖ­[Pšň7’Ďťví‚Ó§]q˙~BCƒ1gÎ,I˝ —%`a1—sçΝÁ A?K]ç‡űnŽ;ˇ#*ę6BBŽcʔI ÷S"""""b0†č“ŠŠŠaôčQ˜:u jŐŞůŮĺ­^˝Ăąví: f€€€+Řľk;ęÖ­ čׯ/VŽ\Ž-[śĄOŸţءď vîü Ô/śÜÜÜ\xzzÂŔ@_*ÝĐPˇoßÁŁGdŽquuGÝQŁFuIڀzPQQÁŮłçdň 8°-[ś€…ĹLŒ3™™™8uęŞUŤ†ŔŔ+ …čÚľ  ZľjhҤ 4¨:uęH‚ĘĘĘ ş*7 tř°j׎ ‹™1b4rr˛ą{÷NŠ|ôGýúő1dČp@•*:pt< Q$Oa%ÓŤWOěŮł žžg1|¸!ěěś`îÜ9˜7ĎRŞœ‰ÇĂÓó  Šřř?$é&&F°˛ZˆáĂ Đźysxzş#!!ţ‚UŤÖ`Á+tęÔQnÝvBUUĆ04FÂÚz  J•*pt<€7BĐż˙Ϙ3g&LáÇĘ-ËĘj.,,ŚÁŢ~ MpćĚYlßžM&˜2kÖtx{_B˙ţągĎ>,]ş:´˙Ź~JDDDDD§)Q…łwŻz÷Ö˜›…1ţúëŻbńńš(őţíۡh׎`ůňUřć›o$eěÚľÓ§OCŰś­ńěŮ34hĐŻ_ż†ż233qâÄIœ?oßž-ąŽ§NšaęÔ)hٲ%îÝť <vv[äćżzőRRR0lŘP8::ôő‡ĂÇÇoŢź‘É߼Kg´iÓşşý$ő_°`1‚ƒƒ Ż? ŽŽÎ GďŢ˝xşş=qóf(„B!tu{âÔ)7ô飋ĐĐ0šĺçććÂĐĐ99ŮČČČ89ĆѣΨRĽ ^˝zx˙ţ=VŽ\ÜÜ\Ŕ…KpíZ şví‚7BÎSXIÇ̜9NN‡qčЇ”E˘xÔŽ] óćÍĹożí@^^ŔÝݧNšÉ”ďârOž|X;ČËëÌ-)ëÂoXYÍC›6­ĺN)jĐ Ν;/™ţff6YYď5kրşş:.^ôĆłgĎđěŮ3ôíŰ_nŸŃÔÔŔ¤I°nÝxy}¸ĹĆĆĄ^˝z˜={&|}ý$yOŸöÄů󇁊éhtďŢ‘‘ˇ>ŤŸƒ1DEjĐ ž$|˜*˘§×nnîĹWxßü/÷ ‹Ńž};téŇMš4FłfM! ĄŚŚ8ţĚÍÇ"0ĐAAWqăĆMřřř*Tßřř?pëÖ-ęăŢ˝{ĐÓëUUœ;w^nţÜÜ\œ>í ƒáptt†ŽŽúôéI“ŚĘÍßşu+¨ŤŤĂßßG*][[ 4řů]†ŠéF’„„Ü„P(DŻ^‚1şşşpq9^ä5ˆĹb 4íÚľAÆ ńăÍ@Ň>đŕAŹT›>ţÉÉ)řá‡ď%EňVŇ1]ťvA׎]0jÔŠk€ožůŠŠŠ łxsž/%űŮŮŮxóćľÔçYYYPUU•{ʃĂnX[/F˙ţz ƒŸßeDEEâââŇ%œ8ń;Ž_Ć͛Ąđöö‘iҤ 444&•SÓŃPRR’•ž?.•çĺ˗ĐŇŇüě~JDDDDD ĆéĺËż‘‘MMMIZţȆâƒ"E/ŕťoßnüđĂ÷8yŇžˆƒťű)Š/źƒ EÝŃŁG7XXLŢE 0bÄ(<}úg‰çvuu‡•Ő<ŘŘl‚ĄĄ>ź˝/ű+:ŽŽî˜>}žűŽ şuëŠÄÄ$ß(2rr LLFʤ§ĽĽK‚1+V,C­ZľĐŁGw=ú;ŔÔt j׎&MĂĎĎ_nŮUŤV…‡‡’““pţüE\ANNœœJĺSQQ‘9VEEšÔyd?/ţ˜ŹŹ,lÝúź˝/ÉäűŇ#Bqé’ôôúĄK—.8uj ąył=Äb1fΜƒÖ­[Ąwo]ô﯇E‹`Μš2m-ĘčŮřź~JDDDDD׌Ą %##3fĚĆóçϑ––[Ű͸y3ô“ËŤRĽ úőë‹ĺËWb׎ݸpÁÉÉ)RÁžZľj˘qăĆ ş [ŰÍĈĆPUUETT4˘˘˘!*aäHkëĹČČČÄÇŃŤWO˜šŽ†ĽĽ•Âu*M?%"""""cˆž¸˝{dŇ,XOĎł7n"ěěláééŽÇŸ`˖­’Ÿ†ţđ…/”””°ző ÔŽ]Ož<ŊŤxEŚĚׯßŔŮůVŻ^‰5jŔÁa€ ůÂŢ~[‘Ł\ şxń"ěěl^쓟ź}–.]‚ÔÔ×8sć,śnýMnyööې––†Ĺ‹˘f͉â1oŢ|\şäŁpJÓO‰ˆˆˆˆ¨b(.(đ>_ŠŔkţ&ü¸)ÜT¨ĐéĐĄsHjękś6}ľ:vě€ăǏAWˇżŞk۟ٚšš˜5Ëňłň”Ĺ1DDDDDD_’ŽNeDF†u Ŕ{9ˇÜ[^M\ŕ5˙ć îŁĐ>ŽŒ!ú,ZZZhŢüX[/Ćůóžş@ •=.ŕKôú÷×ĂŃŁÎHOOÇúő6l""""""*§)ĄüŚ)qd Q9b0†ˆˆˆˆˆˆˆ¨1CDDDDDDDTŽŒ!"""""""*G Ć•#cˆˆˆˆˆˆˆˆĘƒ1DDDDDDDDĺˆÁú׍QŁ:lm7"44÷ďGÁŰűLMÇH>oŰś nܸ]Ý^_Źđ÷÷Áœ9łţńö8xpD˘X™ÍĹĺ( ~ýz‰bńý÷Í>ůeQ`Ü8ł ×§*Ňýü\'ŽG@€/˙PT@ŞŞŞŘ¸q=nÝ ĂńăÇţŃşŒg†ŤWP­Z5Ţ"""˘r Ě& ű—™ăÇGzz:V­úIIIčŇĽ3VŽ\†J•´°˙Aźx‘__?<~üä‹Ő#++ >>~¸sçî'—ńÝwMŕăszz?!!!áłęt ›7o‘JKOĎřäňvě؆œœ\̟żđżçŚŚc0{ö ôčŃťBßO˘’Œ5C‡ĆěŮsńäɓ´.11÷áë뇴´´ ÷Ě}ŒĄľ^˝z˘aĂoŃącWźyóy ŮŮŮčŮłöď?ˆÄÄDŹZľć‹Ö#//śśvŚ]Ţž}ƒ˜˜űě _Éý¤ŻSíÚľ‡  Ť˙x]ÂĂ#Á›BDDDTN8M‰ţŐrrr ¤¤„ŞUŤHĽ:ä„I“ڐ?ĽfذĄđőőƃŃ8yŇÝťwƒH‹Úľk6ośĹćÍś˜;wÂÂn *ęěěl ŚŚVd] NšÉ?gż~}áćv11wáăs˝ző”{ʁÁpřř\řűűŔÝý@ ŔÂb*/#&ć.Ν;ƒAƒ~.óvěÜš~˙ýîލDDÄMŘÚn„śś6 ŔC† †žţ0ˆDąčÝ[Wr\÷îÝqţüYÜżŸ‹RSÁŒqSę<]ťvH MMMIšŞŞ*6mڈ{÷îŕćÍëX´h„BĄÜzÚŘlŔşukPŤV-ˆDąXźxá'ľ“ƒĂ8;’JSSSÝ;033•šŸĐ´éňş ; IDATwpr:„¨¨[ÂęŐ+Qšň7€áÇáţý(hhhHň{{ŸĂĺË>’÷ęęꈉš‹ĄC‡Č­Sýúő°uë„…Ý@tôm89Błf÷YEú¤˛˛2Ź­!44ŃѡąaĂZ¨¨¨{0eĘ$ěŘńîލ„‡‡ęŐŤ‹qăĚxŃѡąu먍Ť+Ô_ţn;sěÜšQQˇrSŚLR¸Ď€P(Äüůsr÷î݁ ĚÍÇJMš˜6m Ž\ńGTÔm¸šDßž}JußŐŐŐĽîťśś66n\đđDEÝĆáÎřńÇćĽę×AA˜5k\\Ž"..-Zü(„‰b1}ú4´oß"Q,ll6”Řƍ3ĂíŰá2‡vÄΝŰzň˙6Ŕ×ב‘a2×UÔ3_Ü3˙ ­^˝ĄĄÁxđ §N—ęĂDDDDÄ` U`jjj=zŚN‚Zľj›78řnßžOOw,X`…víÚBIŠřnݡoŘŰŰÁÍÍúúF8yŇëׯ•É÷Ë/?ü˘m„3făçŸÂäÉKu-VV–ذaôô~BTT4vîüMę {ž‹/ÁÔÔ0j”)&Ožúńř𰰘{űm044Á™3gą}ű6 8 ĚÚťaÆ8vě0âââ0rä̜9]ťvƒ%FF#qóf(‚ƒo [ˇž¸q#DrŹĽĺllßž#FŒFBBvíÚ.hQ„…ĹT<ţFF#°vízŒ=K—.‘›wĂěŘą ššščÖ­'víÚýIíäęęŽ=şŁFę’´ô ˘˘‚łgĎÉäŻ^˝:Nœř/_ŚŔÄdć̙‡Î;áŔ}€ŔŔ+ …čÚľ  ZľjhҤ 4¨:uęHž°+++Ë! qř°j׎ ‹™1b4rr˛ą{÷ÎRőÉUŤVŔÄÄkÖŹ…ąńHź|ůŚN\â=022ÄáĂGЧOüůç39âŒöíŰbÔ¨19r şwď†É“')Ô_ň͚5Ţޗп˙@ěŮłK—.A‡í.cѢů;Ök׎ƒąńH$&&aćĚ2ϗ…ĹTŹ_żFđőőÁ{‹\*˙ž×ŹYŁŔ}ď/šďěE›6­aii…ŃŁÇ"99'NüŽşu떪_Oœ8žžg0hĐPÄÇ˙!őYRRşuë‰Ó§=đřńctëÖ6ؔŘΜ9 555ôďßORVŐŃ˝{7¸şş•ęY˜:u2ÖŻßCC9ýAö™/éČ?ˇžžŚOŸ=˝Ÿđđá#ěŮłŤČŕ*ѧ)Q…łw݃äbÍÍÇÂŔŔýő—Üź9993Ć ăƙÁČČ3gNGbbœœĂŃŃ ššš2ÇL›6gϞþ}ąąq¨QŁşd”Ež‡aűö_‚ž?Ž3gźĐ˝{7ěŢ˝Wákąˇ˙ ˇnÝlÜh ƒáhٲ…Ět€ŹŹ,¤¤¤’“Sšúšš˜4iÖ­Ű/Żs’şÖŤWłgĎ„ŻŻ_‘ç2d0† ,•fjjŽ›7Ceň&$$ wo=$&&JŇźźÎ᧟^˝z…””äää"99EęXkëe’zŹXą ÁÁWŃşu+šç)ʝ;wńŰo;$×WŠR%ŹZľ[ˇnCFFŚTŢ´´4$'§ %%ER—Oi§ŤWŻ!%%Æ …ŁŁ3@_8|||%ÓÝ ;v ?~‚Ĺ‹—"//0ţB\źx-Z´@LL ÂÂÂŃťw/^ŽnOÜź ĄP]ݞ8uĘ }úč"44Lnůššš044ANNśäšœăčQgTŠRŻ^˝*ąOVŞT #Gš`ůňU¸pÁ[Ň­[ˇFŁFß{ 8rä(Ž?†É“§"11 ‰‰I¸|ů2Ú´i­PÉwú´'Οż8|řLMGŁ{÷źUb03‹_]'š–bŃŞUK4jÔ°Ŕ}ŸKK+řűD˘x´iÓffcqőęľbďűĄCNCC}É}ďÖ­+:wî$ľnÓ˘EÖ¸pÁ ăǛĂĆf“ÂýÚÝݧNšÉý,//ÉÉ)R[ž’úŻŻôőő%í2|ř0$''ăÚľëĽzślي+W‚äÖOŢ3ŻČ3đíˇ ‡ČČ[ƒƒk ŚŚ*÷ď0ƒ1DHƒőĽŚÁÔŤWzzýŕćć^ä1ďßżÇÁƒŽ8xĐ 4ŔđáĂ`i95Äňĺ+eňˇjŐ^^çĽŇ ŽöČ÷üůsŠ÷/_žD˖-Ju=ËxůňĺÇ/‘ŠiҤ 444&•SÓŃPRR’|)*LŢž˙ű_ыŤ¨(cҤ hŃâG|űíˇhٲ’’’JŹcÁ…†?ä×ŇŇ*UÝşuGę}DD$ÔŐŐѰaCÜż˙ŕ‹´Snn.NŸö„Áp8::CGG}úô–Lm“×gÚśmƒČČżƒLđíˇ ?żË’_ńęŐŤ'BBnB(˘WŻÁ]]]¸¸/ň:Äb1 „víÚ aƒŠ1§¤×'7nDDHúBBBJ Ć Šdgg^ż~S XřŞŞŞĽę/ňꪼĽŠPů÷4?@”/88DŒÉĎsŕŔ^ź}űV’G[[=’{ßw}:ä„jŐŞAWˇ&L˜,šĎIIÉRýZ,#<<­[ˇ*UżţóĎ??éo`IýŔŐŐNe¤Śž†Áp¸ť{ //OĄg!ßÓ§OKU/Ežgç#Řż.]ş€ëׯăęŐëb=""""cˆJđňĺ_ČČȐ X”ćWFžú÷×ß>“äŃŃŠŒ6mÚŕŋŁJžˇŒ˙ý/999hßž-?~,÷9˙ďŢ˝C˝ző}Ż@[v)vÔGBBÂÂÂńóĎŃŤWOŠűš5k AƒR÷Şcǎ¸vízŠúő§P¤äĺĺáôiO ü ŞUŤŠĐĐ0I•ĺߌÂς"Ď@ÓŚMńöíœ=녳g˝přđQ\źx-[śŕĎÄ1CÝľk×ŃŤW_…ňşššcěŘ1pr:ˆcÇ\žžŽ.]:ĂÂb*Žs‘ťVÁĄCN°ˇˇC\\Ž_żďżosóą˙řu''§ //={ö@vv6ž={gç#°ś^ŒŒŒL<|ř˝ző„ŠéhŠ/ąĽ•?ĽŁ]ťśxń"ńńń04Ôǀý^˝zÁÄÄŻ_˙=Ú 11 ={ö@ÓŚßáŮłç '2ňňňň°qăz<čˆ&McÚ4Ůi@͛˙+Ťš¸pá"š5k†Ĺ‹ÂĹĺ„äËhaIII¨Zľ*Úľk‹'Ožâĺ˗ŸÜNŽŽî˜9s:ęׯ‡%K–™ď÷ß]`ffŠÍ›7áȑŁPVV†•Ő\ÔŽ]ƒ •äóóóǤIxEňĹ7(č&N—E–˙„B!ĚĚĆÂßߍ5²eÖĽşŻééé8q⏭!5őD˘x 2M›~‡÷ďߗY?U¤ż|noŢź››;Ź­— ## 0 ?:uꈴ´´A‘ 8::cÝş5PQQA\\:v숕+—aůňUđđđ,öžĎž=uëÖł‹$饥aˆˆˆ„ƒĂvlܸ oޟŸqf¨WŻ.Ž9ZŞ~ýimŤX?psű0ŞŤN:’EŹ?´If™ýÍ(üĚ+ň Ź]ť***ذÁ™™™7Ιxňä)˙a#"""*„żŚD˙jqqajjŽź<16ośĹĄCű1hĐϰˇß[[;šÇxyĂʕŤ1~ź9źź<0~ź96l°ůÇŻĺíۡXˇn#ćϟ‹ß? °ˇß†ańâ…8sć4ŒŒ 1oŢ|\şäóÉçyýú œ`őę•07‹cÇ\päČ1lÚd7ˇSh׎-öíŰ_(€ĺˆ´´4xyyâçŸ*üeÎĘj:th7ˇ1Â7ÚĘäŰšs7jŐŞ…Ó§]ąrĺ2œ8q›6m.˛ÜŔŔ+8wî<Ž=Œ… çV;]źx5Ä­[ˇńôiŃk|$%%cäČ1¨\ů=ęŒĂ‡––só RŁŻüü.Łrĺo$Ußožů—/űY~ll,-çÁÜ|,Μ9)S&ÁÎnKŠďíúőáârkÖŹÂéÓŽ¨V­ZŠœV„"ýĽ,ĘXłfźźÎaăĆuđđpCăƍ°żô´­­[Ăţýą`Á_ŠŔkţ&ü¸)ÜT¨ĐéĐĄsHjękś6U***’…JkX?~ mŰţý?ďDôţă$@(Jťć̙…Ÿ~€aĂ>o=#uuuÜźy˗ŻÂšsçŮŘDDDD$ĄŁS‘‘aݤČđ@ÎÇ-÷ă–W`x͟ë]p…öpd ýęĂĎď€ ęŁ[ˇŽXž|)BBn2CTAlܸGŽ8ĄC‡öřöŰo1dČ L˜0>>~ŸUn›6­ąbĹRźz•úY#̈ˆˆˆˆ>׌Ą˙/Żó¨[ˇ.-Z€úőë!-- W`ccÇĆ!Ş ěíˇaţüyŘž}+jÔ¨/^ŔŮůö|r™uęÔÁɓ.HHH€Ľĺ<ŠŃqDDDDDĺ‰Ó”ˆˆˆˆˆˆˆˆŔiJDDDDDDDD_%cˆˆˆˆˆˆˆˆĘƒ1DDDDDDDDĺˆÁ"""""""˘rÄ` Q9b0†ˆˆˆˆˆˆˆ¨1CDDDDDDDTŽŒĄ˝5ŞĂÖv#BCƒq˙~ź˝ĎÁÔtL…¨ŰćÍśppŘńŐś}‹?B$ŠEíÚľ;vlÑ#Nĺ^úőëA$ŠĹ÷ß7űŹr&L‡ŕŕ Üş†Ę•żŠm‡‰b1}ú4IZTÔmˆDą2ŰŇĽKŠźNXZÎF@€/<ˆĆľk°ś^ MM2}žŒqłČ÷DDDDDĺA™M@˙fŞŞŞ8~üw¤§§cŐŞ_‘””„.]:cĺĘe¨TI ű÷d#•Łë׃ĄĽĽőĹĎłcÇ6äääbţü…eVfłfͰrĺrŹ]ťxýúÍ?ޞóçĎĂôéÓpěŘďpp؃ʕ+cҤń8ţ, ŒńäÉŠüsçÎÁĽKžHHH(śÜŮłgÂŇr6~˙Ý{÷†FŽ4›ŰIL™béŕDŐŞUŃŤWO\š$•ŽŁSýűë!77Wć{ŕí}I*íĺ˗EÖÉĆf=z÷ÖĹÖ­ż!.î!7n ++K|˙}3Lš4•}UŒĄľ^˝z˘aĂoŃącWźyóáËsdä-dggŁgĎ Ɣł“']˙ľuŻS§ŔĹĺ8˛łł˙ńú´mŰ3gNÇ…‹áéyV’~ń˘7\]OŔÖvƎ'IúôOhh¨ĂĆf=ƎąX,ˇÜV­ZbîÜ9X´h‰TšçĎ_€˝ýflٲ ýú ”jƒŤWŻaÄ™`ĚđáĂđôéŸrĎóâE"bbî+t­ZZZ00Ї…ĹL\žě/yŽ?~ŒuëÖ zőęHIIáFDDDD_ NS˘ľœœ())ĄjŐ*Ré‡9IýozĽJ•°aĂ:„‡‡ 22 űöíFÓŚßI3b„1.\đBLĚ]\šâ™3§K>˟chh__oDF†,,Ś"0đ2îÝťƒ3gNcŕŔR媊Šaýú_†¨¨[°łłššZ‘×¤ŠŠ Ź€ű÷Łŕĺĺ!UŚąą‚‚Сo^FLĚ]¸şž@ŰśmJ•GMM ŤWŻ@hh0<ˆĆŠSÇŃŹYńÓ|LLŒqů˛îߏ‚‹ËQÔŹYSęó‚ÓHŠkłiÓŚŕĘDE݆›ŰIôíŰGŞœŚM›ÂÉ颢n!4466$ӆ|1dČ`čëƒH‹Ţ˝uĽŽ … šŽ3,¤Ň;vě‘(M›6•šŽ€_89}zŮÖĆĆFˆ‰‰‘ ˜Ŕťwď°eËV¨ŠŠB[[[’ž——‹­[ˇŁk×.5jD‘ĺŽa‚ű÷ď˔+‹acc‹ZľjAWˇ—Ôgžž~0@:::RéFF†đöžeĺϋë‹Ĺy‹Ĺ¨^˝šTzXX8~ůe¨T ڤçI‘gˆˆˆˆˆÁ˘BÔÔÔ0zô(L:ľjŐ,6opđ Üž}žžîX°Ŕ íÚľ…’’tˇ8p`/Zśl ‹™3f,233qęÔ TŤöá˟ĄĄÖŽ]—ă6ĚööŰ0{öL :DŞŹŠS'cýú044XYͅ…Ĺ4ŘŰoƒąńH\¸pťvmGďŢ™íׯ/`üř‰Xąb$wm|ŤWŻ„ÁpŹ]ťÆ ŕ víڎşuëJňTŻ^ ÓŚMÁ´iÓŃŻßÜ˝…ŁGQ§N…óXYͅžžŚOŸ=˝Ÿđđá#ěŮłŤČľA† ›ő8yň ŒáęęŽ5kV•x?eŰĚSą~ýFÁ××ě•jÔ¨Ž“'Çۡo1fŒć͏ćÍŔű>FâćÍPß@ˇn=qăFˆÔůrssáéé }ŠtCC}Üž}=’ŠŁ‘ŃH,^źĐłg”|öóĎ‘šš “Qđđ8#Sż™3ç iÓŚpvv”j;míoĐž};Â̙s0wîěŢ˝ÎÎG ŤŰ>>~Řąc444äś[ŤV-qă†üľLŽ\ ‚‰Éhź}űśŔsŁŽS§\qűöX[/.ňŮ)ŽÜääˆD"´jŐR*ýÚľ`ź{÷úúĂ%i͚5CëÖ­pöŹ—Ě3WZ™pv>‚őë×bÓŚčÓ§7ÔŐŐĺć-îyRäY'""""b0†HŽ˝{°aĂZX[/‚ŤëIT­ZľČź9993Ć ťvíF˙ţzpw?…k׎`ęÔ)’/Ć]ştF›6­1iŇTDDD"66 ,Fvö{čëxxx˘oßţ8vĚ"Q<ΞőBTT4:uę(už-[śâʕ $$$@SS“&MŔŚMvđň:‡bąoß̚5Ož<•s˙ţŹXąQQŃ8sĆ gÎxĄ{÷nE^Óň占Żo ??|ëÖm€‡ÇÜž}GfqÚÂD"233eŚ2 2-Z´ř¤ëŻRĽ úőë‹ĺËWb׎ݸpÁÉÉ)RÁŠü JëÖ­¤/mŰśÁýűÎÓ´iShh¨ăěY/,_ž cǎCçΝвĽüşÇĆƢGééUĹMˇ’'>ţź{÷őęՓşőęՃ˛˛P,hßž˝Ôú+ľk×ĆčŃ#ĄŞŞŞpĐăÜš ĐŇŇBϞ=Đťˇn‘S”>%HR¸~ŐŤWGŁF ?9ř ťűi´hц†Ż}óřńcÄĹ=D›6­‘žžŽ¸¸8šÇfggcéŇĺ¨QŁ:ĚĚLĽ>suuÏ?ţƒáRéK—Z#11ąČŔ‡ŤŤ~úi~úi |}/ËAó) 菘˜ťRë"€śv%@ffŚBĺ(ňŹUCÎľk×ŃŤW_…ňşššcěŘ1pr:ˆcÇ\žžŽ.]:ĂÂb*ŽsAnn.nŢ ĹíŰw°˙^lŢlÔÔTÂĚĚ?˙<oŢźH~ýúÂĎĎééi?ŢMš4.öËuţ˘ŁÖ֋‘‘‘‰GAWˇ-Z ‹™ˆ‰)ýľżyó)))066Bbb45ľ°pĄ•Lđáýű÷Xąb)śmہÔÔ×°°˜mmmœ8qJá}ŠŚM›bΜYˆŽž‡ČČ[ ľ™"ĎúۡoQŠR%´jŐąąq2ď+ÂϚƒ1DZ\ÜC˜ššcŢźšŘźŮjjjxüř1ěíˇÁÉé0 //“'OÒ% ąmŰTŽ\11÷ajj.Ybٲ°ąŮ€cǜńúők?~%žßŢ~ŇŇҰxńBÔ¨Q"‘––VŸüĽ<77ăĆM„-<=ÝńřńlٲUć§y322°yóVŘÚn@­Zľsó HLLT8ĽĽ–-łĆŢ˝ťńÍ7ڈŽž‡ &᯿ţ’[ˇ‹/ań⼘5k:,-g#2ňVŹX…ăǏ•ęˇný Ż_żĆ‚k}ţü9~ýu<<<IIÉ5Ę˗/Ĺńăǐ••??ŘÚn’ ľmŰ^^žXśl<<ÎŔŮůVŻ^‰5jŔÁáĂZ&§NšÁČČööŰĘl QÁú8q ďßż‡ż6l°)rńăOeoż qq1~ź9Œ ‘——‡{÷b`a1S˛6Mq6ośÇ€z2#NvěŘ‘('އ‰‰ ŢżĎBXX8FŒ]l255>>~čÔŠ#Ž_.öÜłf͐™ęwę”–.].“7++ cƘaÁ+,Y˛:::HIIˇ÷%lßžCáQ-Š<ëWŻ^CDD$ÜÜNÂÜ|‚Ěű°°pţa%"""˘/N @ş Ŕűü}ĽŻů›đăŚüqS @§C‡Î!e5œčżÎŘŘ˖-Aǎ]?+ĎAǎpüř1čęö“ TÉŁŁS‘‘aݤČđ@ÎÇ-÷ă–W`xÍ˙ŕ‚ű(´€#cˆč+¤ĽĽ…ćÍ€ľőbœ?"""""ŞP¸€/}uú÷×ĂŃŁÎHOOÇúő6l"""""ŞP8M‰ˆˆˆˆˆˆˆĺ7M‰#cˆˆˆˆˆˆˆˆĘƒ1DDDDDDDDĺˆÁ"""""""˘rÄ` Q9b0†ˆˆˆˆˆˆˆ¨1CDDDDDDDTŽ ƈŮTDDDDDDDDĹR(~‘1DDDDDDDDĺˆÁ"""""""˘rÄ` Q9b0†ˆˆˆˆˆˆˆ¨1CDDDDDDDTŽĘ*Ă_["""""""˘Ż]™Ä?”ĘŕäⲏQ$/ţńIąĽ/T1"""""""˘ŻE™Ć;”ž@e!""""""˘ŻE™Ç>”ž`E9}‰ˆˆˆˆˆˆˆţm Ć3žHLCŠ *WÜç ÄŃż"1OŽy(•q%‹ŞHď#UpEĹ/JŠ{”JYcÄĹTP O,Ć+@Ŕ[JDDDDDDD’@ €XŒWř)Ű(čł2Šc ˙dSI?áTxnUŽ@ ~ʤ¤Ä;KDDDDDDD’’’ńcš(y-ÜŇĆJ¤ĎUDziçEIFÁzČÍÎΚ§ŹŹĚ;KDDDDDDD’˛˛2˛łsîA:#/ÎQĐ'­+Sšá*EP\Ěçbšďßżc0†ˆˆˆˆˆˆˆ**eeeź˙> ˛#cň)QČçÎ*<%)?Z”żĺȎšĄŹŹüR(ňîQ…" ĄŹŹü266ć€l|ˆgŒo^?ćłÖůÔ`Œ¸˜ýÂĂxrdeggŸTUUĺ&""""""˘ EUUŮŮŮ'dáď@LQӓJľ>Œ<ŠcäH\Ä~Á çcŢ'$ˆN¨ŞŞrt UBĄŞŞŞ/D'ź‡ô¨˜üřPt¤ÔÁ™â‚1âRŚŹ ĚTĽˇoßžz÷.k›††ď4Ux÷.kŰۡo_Aţ%ŕďŔ Púx‰Œ’†Šäě JČ#(b_œ’’řżš5kURQQi“Í;NDDDDDDD˙MMMâc÷îÝq çă–?¸$1ßÂӕ Ż!S*Ľ Ć|/€t°(>(#‘”ô"źnÝúu„Bá ČŃ?ASSĘĘĘgďލ´Á‡@Ě{Hb /ŕ (ö+K%RdEFÇČKČyŔ‹ώתU[KMM­Mnn.Äb1{}qBĄZZZÄÇ bňî-¸őkJŠŒŠ)6ĐQÚ`LÁ÷Č!SřqĄ÷yr“’^„UŤV㉦Śf;%%%MąXĚ  }BĄęęęĐĐĐx™˝áŢ˝;‡¤ăď19ř„É#/SŘ'ýÔľŕňÉńRxS*°/üř^šŔžĘÇ} mmí* ~7FEEeTNNNľœœäää //Á"""""""ú$JJJPVVÎß^fggŸLH˙¸Xo&>ţčţžšTpšR~ڍ‘1Ŕ'ţ˘’ 4×!g_рŒŇÇM(gS @ĺ‡Z誊ŠuRVś‹ß ¨Ĺ~›ˆˆˆˆˆˆˆňÄbźďsrrŁł˛˛ÂcccŽâCŕĺţţŐ¤˘Ś&}ą@ đéÁ˜‚ďĺý‚RqA™ü Œź2>g”ĺ[Ňt("""""""únÁ-?’ƒÁ—üiH…/ß+„S‡)—ň"ĺ­“"A'̓t %˙˘ň1ů^pMţhĽé€ü€ ýˇ äRň źĎ+”^ř“Š Ŕ”i (]0&żŕâ2%É+?+pQ*P~á5(ž""""""˘˙Ś‚ąˆźBűG¸ŇA˜‚ű%`™š$ď}ą>5˜ĄČĎX7uФľe çUPš‰ˆˆˆˆˆˆčżĄ¨`HÁŃ1…_™†¤ČH˜Ď ğČł//Sř˝źŔ j’ ˜z3 CDDDDDDôßP\0¤p0%OΞ"ÁyÁŕ땧,‚Ÿ:JFŢgňֆQ’sÁş"""""""޸Ä%¤ST`FŃL™†)¨,ŠŽ’‘—&oż¸éI‚r¸"""""""Ş8Ä ¤5]Џ`‹źŔK™†)¨ŹƒŠŒ’É(GŢkIőf@†ˆˆˆˆˆˆčë"Vđ3ń'ź–”G‘:”Ę—\ˇž‹ŕ3_KŞ71DDDDDDD_'ą‚éâĎ|-ŽĚ2ń%ƒ‚ö ҡ_^×ADDDDDDDGiŚ+Ü+đYqűećK1J3JFŃýňŞ;UlŠ.č[Ô~š†)¨<‚Rź˙œŸŻfp†ˆˆˆˆˆˆčë&.ĺ犎x)ˇ@ P~ EFś>á"""""""" äQ2Šź/*­L ËąQJłŢ ƒ.DDDDDDDTâR¤‹KYF™*ŕ |FDDDDDDD”Oü>+S˙TŁź×a0‡ˆˆˆˆˆˆčßA\Îĺ‰Ëű˙é …ŕ_TW"""""""ŞŘÄ_(o™Ş(Zˆˆˆˆˆˆˆ¨<ˆ˙é TÄ 3DDDDDDDT–ÄŠ2˙†Ŕƒ3DDDDDDDTb6ŃżĚ˙ Ľ s^nHIENDŽB`‚bazaar-org-bazaar-43ce9f7/screenshots/bazaar-light.png000066400000000000000000006475431520414637400230670ustar00rootroot00000000000000‰PNG  IHDRcśLůZsRGBŮÉ,gAMAą üa cHRMz&€„ú€ču0ę`:˜pœşQ<bKGDTTT3cÁő pHYs  šœtIMEę0!Č´ IDATxÚěÝy˜U˝7đďŠęęmöL&3Ů'űž°%@ ěŤl˘÷ŞWEŻđŕĘ"ňÜűžzEP.ˆ^ß+ú *("B @€„„ě!űžÍ>ÓÓ[UóţQŐ=Ý=ÝłeŚgÉ÷ó›ŤňĽ×ŤdzĆô´&W“ú8ąĂ2ďťŰ̗ˆˆˆˆˆˆˆ†ŚÎšöĘ,÷ŠaŒDÇÁLŽďL aDŽméTO‚ŒŽ1] a7‘ńhŇ eůńl? ~Š!ˆĚxœş ĺąĚxœ+”ÉÔôʰĽîVĆtÄtuRjđ˘#{ “Z“Ť— ˝7LjULś Ɔ“1džż+ߕ9LŠ[ÖşĆô4ˆÉŹpёÂč)7Ă˝Ďüʇ(‘#[uJę-˛XL÷ŢNših eěŒuČß'2÷(9ޞ1ٚövÔ FĎr3ř˗ŻX2{öŒS‚ÁÂŮ^Żgœ”Ş é҈ˆˆˆˆˆˆˆ:#5M4ÄăÖžp8´qăĆ-Ť—.]˛N(uď!L"ť°ŃV5Ł!{(“ŮŔˇG|EŢו1ŠAL˘ ƓňŘp–.]Zö䓿˙lUUĺőRŞrž/DDDDDDDÔŰ4MÔ9rôéoźáË—/oŔ˜hŤąRwĽŮoś2†3] c:žÔYsŢÔ ĆƒśĄHÁuëÖ]:kÖŹo1„!""""""˘|Đ4QˇiÓŚ‡ć͛÷7a´ aJ cJ2]mň tłĄow؎Şb˛ő†ÉÄřjjjžURRz#O"""""""ĘˇŚŚĆ'+**‚S!Eö@&1t)W• Ѓę˜Î˜îTĹd›))Â$îý‚MMM˙ŻŕĄ'""""""˘ţ‰„˙ZRRňŸp*dŒôfż™31wuLwšăfkڛxžúZj(“Zcđ×ÔÔ|‹A őˇ@ xEMM͡ŕN,'żHÍ3Rs ă™žť<ăsOg*ƜjşŁž1ÉŞ˜ľk×^ĆĄIDDDDDDD4P”””޸víÚËŕ2Š“%n™™˛<ÂŃÍe"e}™aŒqöŮg—Í™3ç›<ĚDDDDDDD4Ě™3ç›gŸ}vÚfNÍ5€öŐ1™şşŹăťqŻČؐl•0:ÚĘ{ź 8xóˆ#ţ‡˜ˆˆˆˆˆˆˆšcǎ=6fĚč˙Đ §oŒ‰ö˝c2úš{ÇdíÓÓ0&WăŢÔŚ˝‰>1>%–e˝Â)ʉˆˆˆˆˆˆh Ň4Qçńx.Đ †öS^§ÎŹÔŐFžYĂí8ˇ5××iC”–/_ąˆA  TRŞň+V,BöĄJŮzĆô˜§ďíŹ[pŽY–ôYłŚŸĘĂJDDDDDDDÝeŰ6bąLӄmېҤit]‡ađů|Đuý¸żkúôé§XŽÎgMR)÷ČXŢŠ\aLg OŽŕ%sÚ'@/((šĹӇˆˆˆˆˆˆˆşĘśm„ĂaÄbąŹŻK)!Ľ„iš‡Ăđů|ƒÇĘ͂S“-çčI“őőŽTĆdöŽ9^Ë\– cź^Ď8)Ď$"""""""ęT4E(ęÖgbąbą á÷ű{ô˝gŇĂ wöĄ2^WY^ËJë…}”ŤJ&™"IŠĘx*QgÂápˇƒ˜TĄPáp¸GŸuó‹Ě1š†+ő˜ÖKű*×öö÷эF{¤¤ ‡ĂˆFŁ=ůhŽü˘łÜŁWž¤+şŇWFäă`Ő××ăóŸ˙nžůßyć BśmWELŚP(Űś{úńŽd=Î<úŞbĽ×Ś{ęL}}=nšĺŘşu+âq“g/Ń Ô1˝´ÎĚ^¸˝îxĂŃĹe}˘ĄĄˇŢúMěÚľ ăǏÇü˜g/Ń “˜žşˇĹbąăŠŽIčő죡+cňÄÜrË7°sçNŒ?=öß(//çLDDDDDD4ČtÄ\tŃeřöˇď@SSSrYss3nżý.\tŃeÇľî.ęŐźC녍ČËp¤T bˆˆˆˆˆˆˆ†Óě¸íČřńă°iÓ&ÜqÇÝhjjBss3îźóűXż~Ǝs\ëî†lů‡8žu´vśi° o~óťŘšs'&Nœˆ_üâ1DDDDDDDƒ\GA >÷ß/F‰={ö`÷îÝ1˘÷Ý×qӕu÷‡AĆ!x–`<ź^_ňša0 Ď üY]óĐC÷cҤIŘľkžöľ[Q[[Ë3’ˆˆˆˆˆˆhÓ´Žă‰††ÜqÇ÷°gĎŒ;cǎÁÁƒ‡pçwŁĄĄá¸ÖÝ/?ď`;@eeexôџaҤIŘťw/žţőŰČ bşŽwřú÷ż˙ŸŘťwƎƒűďż÷ß/Ǝƒýűŕîť˙ă¸ÖÝ´ÁxČ †atřz˘wěý÷ߋ˛˛2”••áţűďĹĉąk׎ăZwčęlJ™3*őŰlJŠ2gVúůĎĆđáĂy "śmw:ܨ§ĘĘĘşUsœł)!ă10fSĘÜĄ<ňSLœ8{÷îĹwż{Ď`""""""˘AF×uř|ž^_ŻĎçă0Ľž0lŘ0<účĎ0cĆ x˝Ď`""""""˘A( Šuö†A=L‰ˆˆˆˆˆˆˆ†Žh4ŠP(Ô+ë*,,„ßďďöç8L‰ˆˆˆˆˆˆˆN~żżWŞY‚Á`‚˜|aCDDDDDDDF0Daaa?_XX8`‡'%xx˜‰ˆˆˆˆˆˆh ńűý0 ápąXŹKŸńů|ƒ˛ao&†1DDDDDDD4ŕ躎˘˘"ƒAÄb1˜Ś Űś!Ľhš]×aƀ5)†1DDDDDDD4`éş>ŕ‡u{ĆĺĂ"""""""˘ŃQĂ^ŰśqdËF”?ýřęŽrg Rşe"pô G"śn_˙ETMŸ]×ŮЗˆˆˆˆˆ¨wőľD0Ł”‚R G@ůӏ3ˆB|ľG1ěŠÇqěĐÁäqN=öDDDDDDԆa őşŽ.ŔĂá0ŒކŻîwÔăŻ; Ďű+‡{tn(ĆPŸĘʐˆD"đ­_Í3DůÖŻB$Éz쉈ˆˆˆˆČÁ0†ňF)˲hŞç΢u°,› QĆPŻĘ6}uę2)%<śĹ5Dyl RĘĎ"""""˘Ă"Ę+3DDDDDt˘ăÔÖÄ pęłcŢWSY?đŔOńĚ3Ďć|]Ó4”–– ˛˛ §Ÿ~*ŽźňrŒ9’…ˆˆˆˆˆVĆѐ#ĽD}}ślقßţö \ý xîšçšcˆˆˆˆˆh@`CyĂęëţÇq˙ýbĺĘ÷ypˆˆˆˆˆ¨ßq˜ĺő˘œĚ‰yĚűj¸RŞšsç$×ÖÖáĐĄCíśă‰'žÄ˘E yˆˆˆˆˆ¨_1Œ!˘AOÓ4üęWżH[śbĹ;¸óÎťaŰvrŮ'ŸlăÎ"""""˘~Ç0†ú+`(Ű9‘ ™„%KcÁ‚“°jŐGž—[ślĹ /źˆ>Zƒşş:˜Ś‰’’bL:˖-ĂE]]×Ó>óĚ3Ďâ~ÚĺíůĆ7nĹg>s}Ú˛X,†çŸ+Vź‹ÝťwŁŠŠ^ŻŁFÂ)§œŒŤŻžăƍ˹Ξl÷ü<˙ü ÉçłfÍÂŻ~őţß˙ű5^~ůÔÔÔâĆoŔ׿ţUž´DDDDD}„a  Y­­‘´çóćÍI{Ž”ÂĂ?ЧŸţSť Śśśľľuxď˝÷ńôÓƃއŠŠŠ^Űś;wá[ßúŽ=–śÜ˛,ěŘą;věŔ3Ď<‹Űnť×]wmŸn÷#<†§žzš' Qž°/ )J):t=ô06oޜ\îőzńկޜöŢ'žxO=őt§•\ŰśmĂíˇRĘ^ŮƖ–Üzëm킘L–eáÁ†+ŢéłíŽŻŻÇ_ţňO""""˘^zélÝş5ůږ-[°jŐjœ~úi€QŁFᏳgݖwß]™”ƒAœqƢäó?ýéÔ×7$Ÿkš†Ë/ż łfÍŔîÝ{ńç??˲’Ż?ńēX˛dqŻlwŚĂ‡t]Ǹq㠔‚ßďăIEDDDDԇĆѐ6qâD\ýľ˜6mjÚňĆĆF\zé%hh¨G}}BĄVüüçُ¸°lŮš¸ä’+ŇB•-[ś&C3ÎX”°$<ňČcxç÷ҖÝu×i˝_**†ă˛Ë.E]]-ęëqŢyçছnLžnš&žyćŮäó­[?IöÜ9ŢíÎfҤIxŕcäȑommő#G`šfť÷ž}ö@AAAÚňwß}|đ!&L¨ĆśmŰńӟţw‡ßyäČQÜsĎ´ V”R¸űî{Ú˝ţü“đéO_‡Â‚vŻýć7Oŕ†>ۖxîšÚUΤ:Ţí&""""˘ţÇ0†ˆ†„­[ˇvúžE‹NÇŠ§ž8唓ńÚkŻ'_ŤŤŤÇmˇ}+íýÁ`0g•É˙ř4›Ú-˙řăuYßďó9rGŞŞJ9r4ůÚsĎ=çž{žKß{źŰMDDDDDýĂ”ˆč„pĆ ńĂţßäó‹.ş°Ý LŠnşéFLž<)çëŠ}[şőGWÓđíoš–ýĎoii žő­Űr~ţxˇ›ˆˆˆˆˆú+cˆhHňűý(++ĂěŮ3qÁçˇk¨ëőzńČ#?ĂSOý ˙řÇ?qŕŔ†cǎĂu×]ƒ /<7ßüď}˛mK–,ĆŻý+üîwOâă×ĄĽ%„ŠŠ ,X0_ůĘżaďŢ}9?۟ŰMDDDDD˝CtašHyžxŹĽÜ'nş{ó¸7/@iYż%loo€1űdý1Ÿ-‡öĂĐôžY4ŒŇ GáU}˜†McĆKÔ]‰gÖD°éóˇeö(×, 4Ŕß'"""˘Ąˆa 卹& QŘÔÜ'ßѢ)„0ŹrdŸŹ? ž˛”DűdýÍ%…IĂú(Œ 56@ Ăű(Œ‰ĄëŤaˆşŔ’ ďěˆcÓaűęm4EdňľU{ăŘv̸a:f4pćd/<݈ˆˆˆ† †1”B(ĽŕńxĐRZŇgaL&Ž=ÜgaLŤF– äP߄1uĺ%[1 óxűdýľGaę6†ËžůŻí‘ŇRézň˜÷…őM<öV(çë“*<řîůEXš+Žg×FđŔ5%˝úýˇýŠ1K%ŸřćŒňâş~řgCSDâĺQŹ;`"l*Tj8s’gMéżŕÍm1źś9Šť.*Bą_Ă÷^hĆů3|8gŞoHüM´¤ÂŁË[ąőˆŮáqŮpPbĂAk˜¸ui!tĘ c¨W%B—\ź^/§MÁˆ˝űűäűˇxM˜?¤Y údýD| Ş1öŁ˝}łý3&"iÁ$QŸŹۆŐđ{-L3žš¨Ÿ>Ă}žNϑă1e„w_\œ|ţŔ?ZpÎ4NçX~ŁďÃKfű1Źó}ő­6žYÁoߗřúمƒîwś!,qßß[đ—Í  $ °żÁĆK"ŘYcáK‹ Л{ôßi…Ś_<Ł Ă÷-Ó1ʁ@/Ď۟kÂsX<ÉŰŻűýÝńƒ˜L[˜xgg gOaщŽ˙úLâ˘;őâŰď÷C-\ŐUŔfĂÄśWAJŮëëW؏ě8u dT HMÆY“ąĽ5ŮA Őăí—Ű×­ÂfÂěƒă-…€Zx|)aLśsŕx ąezňŚi@I@K>Ż(ěű?kĽ)ß7oŒ×.`ăA1S şßÓ?Ž ŁĐ'pç…ĹX<ً9Ł \2ۏoœ[„5űăŘpĐě—íš\áÁ§OÂЇćМ͇ťż_ˇś@DDDDC+c(ż'œÇƒĘŮ3°wÚToÝÖŤëţĐG“Ś€†ZŹ_ůN:óź^]˙vQ‡LČa…زt&f˝ąŠW×˙ţisĐPT7ąśĽ'—őęúמű:Zë Xí‹ă´XďVě1 #ç̆Ç3°ţŹźńI ˙ŘEKLabšŽ]T€ň‚śŔfĂA]ÁŃf‰Ň ŔŮSü8wšÝɏ4! i@jďâ÷vĆńĎO˘8Ö"QěX<ه‹g9Ľ÷Ö۸÷ŐöCőƔęřţ%NŐĎöc^ÚÁŢzM`îhŽ[DŔëlX]ŤÄ ë"ŘrÄBĚR˜RáÁ5 Uâ űíĘ0¤RđęŔ‡{M\97€eÓÓŤ*š#™ř÷ł áó¤˙Ŕă†éřÜŠéU1‡›$žYƎ †.0g´×Î$‡g­ÜNj˘¸nYAcDaBĘ>żçŻM¨ 9Qŕ‡{â¸ui!ŞJtÜýB>ż(ˆW6:ÇéĄkKł3łlŕ‰÷[ązŻ żWŕŒ‰^\>'ş“m(ÓCݎ`|šŽeÓý¸óš&Ŕ“´âÉZńČőĽ0tőMź¸>‚#ÍE~ ‹'yqŃ,?™kŽ}ší¨…ż|ƁF‰ !pÖ.íďôÜiŒH슡;ţ[ЧU{ąrW‰ˆow…ĆˆdS_"""˘!€˙Žň&QQQQşK/†eôŢP™¨PřG –|žâŧEzmý&lŹG ¤€’ď]wâţŢ 3˘>^=ďLŘJ@* ˙ŹŤEŹŤ{bŃ0Vźôtňů?QÄDďUq˜†úK/FyyyÚąîoĄ˜ÄÚýq|aQn9ť‰'ŢoMžžů°‰_źÂéŐ>|ďâb\=?€—6Fđ↮Ÿ;‡›$ţňq§W{“UďďŽáŤĂ8k˛w_\ŒOÍ ŕĺQŹŢTiřÎůEÉŰĄ `áD'D¨ IüěŒ*ŐńÝó‹đ•ĹŘ~Ěšđ[żŃ‚ĆˆÄW—ŕöó‹ kŔ˙źŢKçăý& |§Oh˙űśżÁ†RŔÔŮ´%nĽ ŕô/yđőř oŸçlÓá&˙ýfśL xlŹÚk▥E¸ë˘"DL…'?tśűŽ ‹0u„ÓŤ ÜwU ŚUľ}ď?śÄpÝÉAÜuQqÎ}ýږ(†h¸ăÂ"\rďěˆ'÷IgJüîťĘ vޘŔ}W•ŔĐ66ńˡC˜?֋;/,ÂľóýXž-†gք;ܗĄ˜ÄŁËC˜^eŕ—ăKgŕÍmQ|¸7Öéś<ł&’ÖŹ7›+ćpĹź@ZŔבxvM„˙˜ ʌĄ> ]}cS—y<Ě^şŤ>ن…{â8‡ä(w)‹ Ľ€R@ƒeá‡ŕ_G…vœÁ†R/<ţ0BM mušÂď Ăř|KÁq'˛JŹ9˙\œt֙Đu=í<Č fňŇÜź¤…nĺĆĺsřÍĘVHhxuSËŚűpŢ 'Š*ö˘aŽÂ‹ë#¸|N g…ĂSŤĂřӚ , T—ë¸r^ ůú >̨2PâV0T{ńÖövÔX8eź>C`r…óç×´ţôQsG{qž[šRQ¨áżŽ,IŤ€8ľÚ‹ľű0G׀;/'ÚĚ IDAT,†Ž!YŃrî4~öFĄ˜LţźU%Ž:)s˙„ă  đuĄ/ˊ1x=_<Ł Y‰ňľł q×óMŘtŘÄ\7´‘ ř—ÓƒÉŢ=Íňăń÷ZĄú4űľäвÄo\9/€ŮŁ:hŤËu\6ÇůyF—ęˆ˜ŔŸV‡qĹÜ@ťĘžlçBI@Cą{K|˙+›˘8eź—Ěö'× üúÝV\:ť­)sćž<Řh#n+,ëEYPCYPĂ//IV.u$1}u.ÓŤ ,›îÇ#ËӃ.ŘtŘä?2DDDD cˆzԔ””`§ŻĆú†Ě}ďƒ2J F°ŮŰţeÇŚľxýĎżÁůŸţ„čYä  °JĆ^´@)%‹M%v̙ˆ7nXŠeż_!{şýšň\ʟ>J HJR›CaźxôލŃăC)‰üéql_żŞÝk[ /#¸"@O‹d”XwĆéwý5())é—ŔĽ#^-LΟT€i)ř mÇ,l;f᝝ńä{"qgg´ĆeÚgS]2ۏSĆ;ÁI(&ńâú~ôj žqŠüÎgÂ+vÄp¨I˘ŚĹƁF•ĹZÖ`'WřćšÁ´ĺś^ßÁ5!űëm”R‚-kö™Ř]gĄŚEâ@Ł3ěĹJšx//čxŠô WŔ’@ĚT2űęmLާÍćSĐ0˘HĂžz+Ć˝ZZĺ"Ÿ[–­:ě˙2ź ˝~&”§˙“5šÂƒ¸­PÓ"1ŚŹgÓÁqZuúđ­ÉĂ=°%p°QbjĽ–u_Ž*ŐqŇX/x˝3*=˜RiŕäqF—Â˜ĚŽČšţĎĺ%xfÓ4ů ‹‚řçÖhˇüâŹLfĹLuu5˘˙z#Ţ/.ŠŻ/‡ÇěޅGT(üą ‚-Ţܟ[őćßĐT_ƒ+żxźž@ˇÖoÂĆŰÚ~ěG ”tBç& ÜĐdŐy PW^‚Ť~ů2źŃx÷śßďĂď>{6̘ěŹ)ß'˜yŤž5Ś…1ŹŰŰ‹†ńü݆Vç|Ďťţ8t…φđŠî…(Śa`Ő˛s0ęę+0a„Ź0)˜ÉĆĐޘŔ‚qF– "w8Pě×P• V4|}i!ž÷|3Vď3qÎT^ŰĹKŁX<ɋyŁ=QäĂ+›˘íÖłrWě1qűůEińۏYxdysG˜Ve`áťjmŹÜĺ i‰Jüřď-( h8yœłGĐđČňPˇ~ţąe:„śł’Ă‘R­ŘGi@`ÎhŞ;éBÉĚlťŇčşG9ŁHœÇżĺŤK °ˇŢĆŚC&6Œăůu|eqA2˜ĘeÖH#9dÍů9€ˇśEńĺĹAl”hŠ(üu}$çg‰ˆˆˆhđcĎ곌+ŻMŸ> Ó?ŢúâMŘ1{&d.ޕÖxăřII¨Ă &aŰşń󻿆Uoţ Ş }X”’Ř%đźž űT ¤„{NO÷š­[ |2o2ţűÇ_ĆË@vaH”ŇVŸ< ?ü~ĆdŘĘš“nEŒTÂYć~ÇúŚPˇˇĂűËńË˙¸ľĂ &ała⾒źëwi–%%öNž„_¸3žp#ŚOŸÖíă>PT—ë¨Ű(/Вˇ˜ĽŠ)tgÂ,C0t$gSZš;†s§ůđ铃8}‚†{ИŃ#ä@ƒ?Ž ăÓ 7,˝ęâŁ}qŒ.ŐńĽĹX2ًéUÂńśĎoŻąĐ–řĆš…X6݇šŁ ô¤8Ť8 aÎ(/Ź‹ fĽŻ`ƒ?Źj…tăŒńĂt쪾Ҟ§9"qŹEbü°nTĽÇi°§>}6Ą56źEÎďĎŁĐœ˛Ÿ•jC˛ĂŻ7LǎšĚőZĐ5`TIîß稊°ťÖÂřa:.™íÇ7—aÎ(ooďźgĚľ )Ă´Żoáů#^¨áń÷BiN % ×,€ˆˆˆˆ?VĆPŢ™lŐ1J)TUUaŮ5WaűÜ9xuĺ˜ąţ5”‰Ŕąŕ‹8Ią€ą UAü~ďngÖ¤n‡šńÚÓżĆĘż?Š'†ÉsNAYů—9 g›ęĐX{Ű7|„më>Dńýˇ9C’¤Hö‰I JVݏý]”B…üí3çâí NĂôľ;0uĂN ŤmFIŁ3cNci1ęĘK°yĆ$ʟ5 EĹΐ$ŮśnĽÚ†)ĽUá¨îoKc]ˇöOHSx!ÁrŸWÝáţß4{ŞO9ç̜żßß.h,U1€ÓĎ乡B(ńk˜3Ú@]ŤÄӍØVéÁż,,ČůšĆˆÄţgXP$ްrw M‰šcœŞ…Şb6tú¨ř 7?‰âhłÄXw(M$Žđ?+BUŞaL™rÎŹLŐĺ:*‹u|°;Žuă¨*ň`óaď튣Ŕ­žŠ,Ň!°|[ sÇxQÓbăĎkÂ=ÚŸ=5ˆűţނ˙˝ËŚPŘß`ăő­QĚăĹÜŃNŁę%“}xs[ żyŻçĎđ#f)<÷qcĘtĚěFľFi@`Ë Gš%ĘÝ;Gö×ŰxqC Ćzq¸ÉĆs‡qÖd/źnż˜i•ŢŢĂřa:JŢ܃igťjLLŽđ ŞXĂEłüřůňŞŠ5ĚmŕX‹§VGpö_˛_L6űęmüô\r3ŞœĎíŞľ°p‚ˇ ű@Cő0ëĘvĚŸÄrk†{8“âŽ0˝&„€ĎçĂŹY3QPP€}Ą•8:ą(çz›ö÷źanKc>Zţ >ZţJ‡ď+TŠ!I[“č#ÝŚ-¨q*fKŠđîŮóńΒůîçDĘçÚŢŰn*eËR‹aşşý=Ő¤)XÔáţŸţy¨Ž!D—›óÔ`fÖH_]RˆżmŒŕoŁđ '¸|nÇŐ/oŒâĺÎ°#ŸG`tŠŽŻŸ]˜œVúĆӃřÝaüěŸ!˝Î´ÖsFľ}~Ó5!‰šp˙k-Éĺ>Ŕß.ĹŇ)>4G$žx? Ľ€ŮŁ \8ӏwv8UŁKu|yqž]ë ‡?LÇŐ'đË­ÝŢeA w]T„—6DđŇúÂq…Š" Ď `é4o˛’¤$ á;çă™5a<řz ]`ö(×-đ§ő‘éĚů3üŘS׊žŇŒ›N `ňˆŽ9—Î `w­‰űţŢżW`ÉdŽH9VWÎ  9˘đřĘ0†ŔĽłýˆ˜é/Žēśâכđ./ÁŹ‘n>Ť/­wŽiĄOŕŹÉ>\ě6ôÍejĽ_<ŁŻnŠâŮľ˝§U¸|ŽżK?ËĚQÖl_Ů×Q…ÓĚ*ţ“MDDD4dŽ—ť°\¤qĽ2‰ÇJŠv•R8rä(ś=uO‡ëűËŰëű|›Ť~ůƒś E"˝Š%ĺyÎŔ%QQăžÇ–)KF0“ e}cRžÄűÇqń›úČŇʐ˙™úMfĺĚ@şhˇe[pb§(@zđ‘Ľz&=ˆI.ËV “¸8OJ`÷5{`ťŽžQÇ<šŔ­K ńÎÎ6ś°§ÎBSF_Ą’€†ęrfôŕĚI>1DDDDCé˙rP>.Ü3űÄd.sHS°- Ľinő‹H†#mł*e.)ÁŒĚn”Ę\¸´Í˘$Ú"U[̊cj8ˆęłF‰1^€-Bf Ńc8ڇążn ˘ńŚź×ÎzĹ0¤!ĘM׀ł§řpö#ĎŽ‰`ăa§RfÎ(WϰG ŃĹ0†úUG}eňŧ \{R f\Š@Ľ°Z7ý[Í*ź:űD5#Łyoz'dĎ3†/!ŁBé2ŠM‚§Ć qAëĚśŠ )gö(Œ(‡˛$”%Ą[%z)‚ŢbTMÂÔŞĽˆI{j?ÂĆý/ śykޏ!ŸŇ€†;ł€;‚ˆˆˆčÁ0†ňvÁޕĐ%ßöc =¸őKăP01č ˛T\˘ŘŻpŞyÓ7˙ży)Ž”U¤IJ #BFŕgşëś*˜” ˆśeПw_n{ńŮđXĚąK]8żî›•­ tĽ HM@7%`J:KMÇřá§ ŞüděŤ[ƒw>ŽpôXŸËŢ|щ†a ĺ]śĄJÝšxŸ4˛´WśC_şn‚3 œÄÄtS]8÷(,ţíŕßđ“ŕç6üiU-iÍw3zĂ´ =Jé!Łr/;-Z†›˘ăđx á´ČvWŽ,• b4á„:şRđ¸ÓaKŘB@WŔčaó1Źř~¨ý=ZBŤúěf{Άˆˆˆˆˆ¨sŒNB\Ä_2ۇ‚ş47ü‰MB@((•řÔş@JĺN5- Íwá!Ň Xdrˆ’Óř×N,SďKůÜáJ|96AŻͧ;ˇ€ÍŻCó{ |ŸáŐĄy5Cƒfh !ŕşpÂ%]<ş#+žˆ˛˛+‡Ô1#""""" XC'¤ 0ńÜ2HKA(ĄœjĽTj“BsK˘bŰ>(¨LŸŠZfLE-÷˘­ąob™iϕŽ4ĆŕS…ŁĄůtŻÍĐ! Ѕ[ÓVŁ„ô ŔVş‚Đ%4KAšrď…‚ŚœűҒ aĘ8BMŻđ  ʌĄźÉUIŃœZx`*¨¸‚ŒK(S9=clg:ié†3 š&ńŮÚN5Œ¤íޤHžm™Τ?b8Ž Œ…đçfh^ "Yăćó8A[ #<ŠäIšiB@ƒS“¸wF99NIéĽđOňǔˆˆˆˆˆh°`C'œiEĂçqÄ%sn*.Ą,'í4ȅŐ6uő¸ňN9˛%%pq;-„I]l) m‘ÂH.ý¸É7Áĺބî.šĄšC”ôô F× 4'Œš€ĐœĐCCr„•sŸzsC™ÂaŸć)çÁ'"""""ĆЉuÂ+%§Aš1*&[Ü˝Ĺ$`9U2Ęvƒ7œ‘śÂUćj[eTÂdŻ|I†0vj5ÎÜ _ӒI2II3Í bÁKjş÷1ÜĎ y—|’Y—˘ ?|Ľ×ň """""׌Üt"9s¤Ž@•0ĽS“¨¸Ěś WśtC6PäăŠ}ďf„0n…ŒĚ ]ڂ;ąLSd!fk%ił.%ŸČÄěI2f;SZKĺžÉ>6Pî˙¤>MPĎÝ×=ţYžI< ˆˆˆˆˆˆúĂ:ač łć‰1qéÜÇĄŒ‚Œ;30%¤%éŽ3ŞdÎń|‚ŇHKÖáG‰Ę—vËRúČ\$‡gNĂä0śtBSBFm糥Lgš˛ĽĚ$oh›jmyN"ˆI]ćÁ•ÂĚášSŁ @”ć„R ŠŁ”œ@&ŃT× ^$œ>-‰jˇŒ˛$Ž €ˇKć "ź)}bRzȤ…2@‰đŔR Â%eÄe[cŤäTÖÉiʕӍ7ůÝvJ#SÂĽÜÖ6)•2iÁŒ‚ ˇzF”ńÄ """""ęĎkUîĘćę&|†'Ů´ş€“„´Ň]8SH §űm˛wŒ;öÇéc+KAşLąƧ÷/ÇoF_ŕĚ\”ŹŒ)ĄL[…Œć0•D˘IŒŕ1%4;QŁAhÎv%¨älKNuŒí†0Ůn‰*'QÉĄK‰Ç &|Cţ¸Ťp Ç "q nAٲmZpę! t đz ^ čƒöÍ9k1 ™ˆ‡MX1ŇRN@:¨v—ó{îńéđ ř řŠ žGDDDD”†a Y…Ra\™púŔ耰áIФVŸŔţٝZ)ČśćšBRJ n…ŠÓ;FXÎëçE7ŕ•Ö“qĐWžŹ†IočŰÖŕ×R q((H'°śđ(ÝЄ4‘šĹ¸ëSnuK˘úĹLš7ej…LJĽL"˜Üţ2ÎýŐÔ ŮĐ 3ů Đ[”‚˛lŔ˛ŤŽÂg@++J zĺ+ÂőQ„j"0ŁöŘ] śŠ`›ą‰–c€á×QX@p˜Ÿç`CCŘ|Ä ŰRiÎ Jœ-Ń/Ć wi8aŒmՔ2Lȝ†€%!Ý2†máóű^Ă&~.mHRbĽÔ•šĽ ]îĚFÎŞA‰&„3ɓŠwHé÷’%hI WŠçŞ”Iš9ALlčĺŃ8TMłPßďď˜ űH#Ds˘˘ÂďíŃzâa ͇[ íđ̌ÚhŘB¸!†â‘đůO/щŽ˙†¤JÓDEPAĹĄ;C””ćOŇ܆-îK"qď&$*q/Ű÷ށíöŒ‘îĚJn3ߓěݸ}ŰOq$Řńpáů6âĆ8HáßŘЅ‚%t7Jľcŕ2Š=`ĄL[ř"ł„0)}dŕ<Öíú!uŹesęH#‡!őŽA퍅¨*…VěÖgĂ 14î şaHÇ#2QťŁ Ľc ,óń"""":1ŒĄ!G@až‡ŠťC’tĺöŠArN٘dƒÄP%áŽ1J„1pžŰÎěJ‰ ™Äsa;ua3c­8(q†Bĺ5C÷ŒuŚ›†€ ] č b47ˆI­QNÍŽŰśŚ­L˘2ĆĘŹˆ‘Ů+d÷>ylČkن:ÜŔ“ž?)u¸čr nˆĄa_Ë şťTňgg CDDDtâbCCÎäP şâncÙĘZsŞbT˘AŽ›ť¤ŢC)ĺ4ň…t†( w¸’ł°e˛Ąo˘ŠoT7Dą{X çśĹâ;`řOq‚•č)Ź +M8Ś4 9˓B˘•J|}ŰěH*G˙˜Œ!KVZľ Pť‡ĆEm4îTÄĐŔ8GĄźžN‡,ĹĂ÷‡NřýŐ¸?ä6ůĺ?ĂDDDD'"ţż@RźśÄäx JP tĺVÄ87¤5îuzĆ$s7˜ITÄ´UǨDĽŒ-Ű˝XŇ­Ž‘Î L­iĹţ,]Ëş}f| ˘Ň†!tŘBAw+c4Ą %结Ő:p§Ç†3Ô(u¸RćP¤v3,I™öÜVŠímCă⿌™C“ÔQP5Íc‡wřśćĂ­Ýš$-…Í/ďƁľľˆˇfď-ă x0z~f^Z ÝĐÉîRh>܊á“JxĆЀc+˝ƒĄ>BÓ ¤ĚúÚ̆0ź–„Ň„Ó´× c„&œenó^@´őŒsď\!9•JśUȤ”Ľ8}c¤3D vʰ%KÁ°f aøâW`-ˆÇ7CzgÁVş4ˇ2F@ľMň„”YžR†)I¨´áJ‰ŚźÚWÇdW˛”BPnƒpÎ}Ťi˘ă ăű=ďšZŮŹw  áĐԚs–Ľp}´ŰÍzˇźşťŢ9Üá{â ťß; Ľć^5iĐěŻXČD¸>ĘY–ˆˆˆˆN@ chŔąMş7÷Šé÷ˆDŰ_ˆE-Œi‰9Ðô””4ĽIw:k7lM|ś2ˇ EÉÄLJp†'ŠDă.ˇĘ˜´{ {¤ť+‚˛˙ Vd9lĎLŘn5Œ.´DăΤ$ĐV9Đ6ó’jČXÕŹ,ÓR‡,°ßëpßű˝1ąŹĆȆÖîć`ěwˇ@i^čÓÇB_4€€˝j;䌽PĄ8DE1´?ŽÁÜOMrdŠJ*ěYy{>8†ÖÚ0<^SË0óâń¸ý[^úŢ{VöʝiçĹ´óÇ9ŰľŚ;ß>ˆPMހUłË1ă˘qđřť÷Ďj¨&Â0†ˆˆˆˆa Q˙‹[6ź„1%EˆĹă2ý‚iÎáÓ ]”-Ý!J‰ć˝Ęé#ÜaKnϘśÚ“Ä՚H4iq–şC”œqBnÓ^ˇBFş3*9}dTr†%a3ˇŐăĂyŮ/慵fl3,ď §qŻÎ*ˇ:&ši‰MRí™ÔFžNeLű@&sŘRľĹj_ÎýŞiJK ;<61Ëę÷óC…cPąîUWȃu0Ÿ]é 3€Pöęíjœs"Ľ °:Öóů`|ęôNkĺ'°ß˙Ä9ŽE([BíŻ…¸‘†ŽnmŔčyĂqÖ­sÓ>×ZÁ?Y  jN9â [_uBÍy×LĆřÓ+mŽá­‡×Łé@űVĂřÓ*ťľmąĂ""""†1DýŹ9A•*íđâĐŁk^šŇřr$°nÖŔú9|ĆvřŽŸ÷Íčń§€–Öh˙ç‘x÷?s´ŠűŸŠi¤„“čeyÝ´ˇ‚BxÝ ičKf@›7ÂýœőćŘď†>"´Ńĺ˝vŒr5Ĺí”čĺ÷h>ԊýCkmÁ2 ‡űĄˆv,?eKTÎ( ÝŻ IDATC‰ŰłĆŠ:ÇU÷ĽéK<ˇzЧÇű†ˆˆˆˆ-†14 YśşŚPJg]ęO Í!Xś´ŰďY4 ÚřŽ÷oŃĆ ‡çĚ靿1ŕƒqńřnžĆe§@Ÿ9Đ5g˜Đ›şŸ;”$ŤQ´áĹ%A€ŞkIżđŸXĺźßđ$.U×ŐZ }ę(ç=>´jg،:RŸžžŠ#{ˇWLŸHl ęĽ÷S΃Ëď]„Ĺ_›;ncĂ_wcÇ[éAUŹ%Ž˝L=ˇmŔabś$;ٚ%ńÜă×ůƒˆˆˆˆ:żćŕ. ~šź_Fă&ZŁ1îŹ~ŠDéÂěE]9Ś˝rîč=řłĽk0Ž<ÝŠbéěâä‘đ\šĐ™˝ŞžöG;`oŢř hSFÁsá|ÎČ]G2>ňXćś2ŤÁďËŘľ*ő󉐬Kű?ă=š–ˇc¤yú7ő1#6ęw7ŁaoKr‡M(ƨšNőĎŃ­ iďßůöAHKbř”R”o›Rťh„3”Ťůp8­šŚéPŤűz°ű˙{˙Н`ĆЀ‰Ĺ‰›`‰L˙ˆĆMDcŹš¨ˇ‡}Çu ĆE  /œ–ű-ó'¸ěOţ4Ć,Xoo†őÚ:ČCnʼn¤;C“0Üíô8÷ňH˝Ž(šçXÖUŞĆÖä4Űň`T‹Ű;Šź8í}rË÷$;ąŽň"ˆ"?Pŕ4龡93Џ•ü>QUÖńĎäfĘV˝~Œ<žžUŒ$2&•š_)´Ƙő}ŠçrsďübVü|=jv8ĂžŹ¸Đ@ ¸­ŻP(Ľ Ľ„eźĆ˘"ŕ… ÷°bJ8C–DŔ€ľ|S[%ŠôÓ§ÁłhZ×W5˛ ÚŘ Čý50Ÿ~˘0eŮ@ԙíI_0  {őv¨#ˆ?ţ˙Ůťďđ(Ş5 ŕď̖l6!R …Ţ{ U @š  ˘˘^ô‚í"J 辢RźRDAĽI ˝ƒ ¨iŇK¤%„„ôms˙Ř찛şi› yĎ3ϖ™rÎŮ33ߜ9łÇIP*ó bčցčď év b/Äj@ƃm6D_†éj¤ä4sÇ˝Žj(Öʎ `Ř}†§aş )9RJowˆjźMnć€LFôŤ…˘]]ˆľü‹•Gš6MŤ*ńă­őéÜ:•€ŤżÜ‚.À 6~¨­ˇKĄż­âďŠęÍ|qëTŽ|sî~dŢ×AŸa„B%˘n÷A—ˇn˜e„O-řÖöĚąJ4ěŠ3›ŻâÄşK¸rč2’ł`Č2ÂłşBŰý‰ej-kMDDDTŮ0Cĺ{b-vwÔk’$ddę!I”˘…(BTŠP Д„Q’`2˜`”L0M.*e‘ňĐĄ´.@Ž>TŠJѲ6„*Zčˇ$ Ş>-!6(z'żĘÁí`üăLoAJN7?Î:ŔŠ5ÍýÇCŞAŮľ1 їL=ÄzCý ßv,×üDW(Úօá×sćĎőŞCŢ<×tŞGŰŔpđoH™zŐ} ęŃL~lľ˘YM*% Ç.Át3P)Ąh e×&@!ů*TŃ@ńHS˙źÓ­{ďŢŠŒ6wpÄĹ]…”;ĹŤ#ŕŘOçqçě=˜ŹZí\Úw—÷߄_Coů–!Š€Vt­Ÿję7q#úŇâ3ĄtQ °Š/ô†G`v˝Y\űí6 AxާŻÓľ:ÔŽJ\>t ińPš*ÔŞő -Ömt.î Ć1CTŽDQ„ ć_,%IĘžuF‡,™:}…îXÖ)*…ZZ54ęN *ˆbůŢÝ(h] ¸¨ •đö)ąNTCĂŁ1¤jńÖEĽ„˛SC SÁý*Úօ˘m]Űđ†yˇRA]Hß6˘Ÿ'ÔOwË|!óPę‘yhUĘVľ‹Ÿ?.*ycި Ň( /âӆ¤ěX_ěéD˘€€&žíŕ…JDĚŃ8Ü>¸ł:& ˆíŠJőÃP?<˙´Qş(Ńďý°B×+¸­‚Űú•¸<Ť4 ¸Ta0†ˆˆˆ¨Ň‡1 ČY‚Q ¸hcÄ ‰jW(˘ă[Ăä\o7łűf)Ń|Šůčf*8oňă^Í÷Žýé5‚ÚřĄVX\­nIŞZÇúŒ:¸u2W~˝…”Řô —^îŐ\Yhˆˆˆˆ*!cČ)XnWR*•PşzŠ Ć8#•Ö …BÎłrăéá~FńűŽĄ˛ůk]Ďüƒ1Z ŇďeŠď˜öŁ˘j]Ď|˛ĘUĐţmďř+ÉĹ{ÚV9qqWAëŁaÁ!"""Ş„Œ!ǞŹŇGŒZ­F•ŔşHťÇÄrBŐëÁĹĹĽĐ|´5•ëÉHΓwFƒĆ<§–œ)ÇܸM0&Ż>Ţ9–ńpŚiÎäLLź‡ęąťóLKzĽeémžŢ­jÖ ľÉźŢçĚ3""""""˛ƒ1TŽň źäg9ї$ ŽŽŽ0 ˜ƒ’…S(Ôᅦž%G^-ââîŕĚĘ}EJ/WWW9}ěiĂ@ QŃ0CN%ggž92*•• ťk×ü´>~PŤUý­5ÖidýY­V9˝T*eˇ%1řBDDDDDT2 ĆPš+¨ELΧ,šşşB¨ZRš}Á…Fí Őj $TôŕBÎ@Œľ˘ŚWhcszĺLöCDDDDDTzD&9ƒÂú"ą´ÔpssCP‹n0h| §[Ő tčů¨9 ‘ŁĽ‡ő`˝ŹŠ4äˇŢÖßiľZÔhލéŒ=űËÁŤÂZÂ0CDDDDDT< ƐÓČŻ’œAĆĂľqoľŐň—śj0Ú÷…ƍç PXżĎ+¸Q‘ŇŤ @Œĺ˝9˝" IŻ´ď˙,7nœgšôžˆˆˆˆˆˆŠ†ˇ)‘ÓĘŤs_A P(ĐŁW~Żâ…›çţb/AH˝Q4BăYžőQˇeGtčĐJĽ˛ŔÂĂÔgL~ŰŁT*Ń=ź7~w÷Ä­óć™^őZuD‡ P( ÄQ Ďwíř^°úly/Z˝ZEö ĚÔTźt:ý&55°×gË{Ëk\ÜÜźyŠŠŠwwwÔ¨Qţţ~ůöŔBAéWXzŮˆa`†ˆˆˆˆˆfjľ* @=̏§50f&ŤA˛zľœ|YżGŽ÷ćóŞ|–Í` 9m@Ą q *㣭 ›Ś°ta †ˆˆˆˆˆ*Gcx›9Ľüž°d(č֜‚‚k@Ą t)NZ1CDDDDDT6Œ!§•W@°/°ßüJ2ŢŮäŐĘ%Żt*ęśUŚQy`0†œZ΀Œĺ; ˙`D^Óu\EIkůĽSIӊ"""""˘ŇĹ` 9˝ź2–ď‹;ż‡50­ˆˆˆˆˆˆœœČ$ Š 4‚‚ TŠŕBim'1DDDDDDeƒ-c¨Â(ĘíIyýŽéĹô""""""r ĆP…Ă`Ӌˆˆˆˆˆ¨"ămJDDDDDDDDÄ` ‘1CDDDDDDDä@ Ć9ƒ1DDDDDDDDÄ` ‘1CDDDDDDDä@ Ć9ƒ1DDDDDDDDÄ` ‘1CDDDDDDDä@ Ć9ƒ1DDDDDDDDÄ` ‘1CDDDDDDDä@ Ć9ƒ1DDDDDDDDÄ` ‘1CDDDDDDDä@ Ć9’I@T8I’ Óé ×ëa0`4!I’C×A( (•J¨T*¨Őj‚ŔĚaů`9ŠLF˜Ră!e$CĘL…¤ĎL‡•AQ AĽ q‡ŕę Ń˝* *˜7•¤n`ĂňĹüełî r˛˙…ß VŸ-ďEŤWË Č”Ůƒ€ €—N§?Â¤ŚŠČ`0 33™™™Nš~J%ăŞ,,'Ny •SŇM˜’cîZˆž˝j@pqcfUÂşu Ëó—yĚşƒ(ojľ* @=Cö`ĚLVƒdőj9ŕł~ďÍÇbůŁĺxĎ` U:iiiČČȨëęęę 77žLą|°œ8ăÝ+0&^ŻëŞđ †˘ZmfZ%­Xǰ|1™ÇŹ;ˆl9"Ă0$QƒŠŠŠ0 f322 ×ëáîîÎŤ ,,'ĺLĘJƒ1öXNʉ”‘ Ăő*caĘLáú HÉĚČJX7°Žaůbţ2Yśˆ‹Á"ŤŔýű÷+t犒$áţýű–-ű[ˇnƒ čŐŤž{nT‰ňĆh4bäČga4š°|ůwpuŐ°œ”)+­XOMʸy Gś"őâqîÝDjŸ¸×k Ÿ°GĄ ¨YŽŰeLźŃßúV˛}÷E,_Ě_ć1Ë‘c°tSĽ—™™Y¤é“’’ńóĎëqôč¸sçT*BBBĐłgwôéÓ …ŠśÍÝݝ™ěŔň‘Ÿ;wÉÍnׯßI^|ń_v˙Ţd2!==÷îÝÕ+W°mۤĽĽ&OŽÄŕÁƒPż~=x{{ĂÝݍĺāLI7‹6˝^‡[ëç#ń÷í@ŽŚé™ą×{ żl€O灨>če ežó‰ŰśIÇ÷@?Ńfœ[hcÔ|q:Ú*%Ţ6…}frÔ ‰‰‰Đét6ßůúúBĽR9dýĄ×ëěšÖŰŰ...Ü9qůş˙>Ö­[ŁGG\ܨŐjÔŹŠž}ű {÷nÇ•,ÓŇҰfÍ:üúëo¸{7îînhҤ FŒ†:ujŰľĚ .bíÚu8wîRSSQ­Z5tíÚC† śyő‘#GńŃGŸŢxă?čŐŤ§ÍvNš‰+WŽƎ} ôgŮ" Řń˝`őŮň^´zľ ŠěA™=¨¨xétú#LjrF’$!!!ĄHŻo˝5 ńńńyŽo׎-ţűßiezĐSTžžžNľ>sůĚWşVŹX‰˝{÷zöěgžy ÷î݃Á`D||<"#߆§§~řa™]ó|ë­I8ţB‘ÖŁaƘ=űS–“2ÄĄżôŤÝ÷ű› z\ýz2ŇŽœx4í]ü-dĆ^“§Qş{Á˜v’d‚{˝V¨őŇ'ydnmřń‡~ÎwYŽAuQ{ĚŹdA€Şng@T0ŻKX7X¤¤¤âÝwßDž sSŠ”xůĺ1ˆˆčgÝrĺĘU¤§§ş ­V‹ÚľkĺyEůüů ˜5ë3ÄĆĆٽ΢(˘oߌűoˆbńîpgSvĺ+.î&Mš‚„„Ä<ÇŘcĆźÄcJ”Ç÷îÝÔ)Ópóć­\Ó* L™2;†¸Ě#GŽâÓOgĺyUhh(ŚO˙^^žcL&ŚO˙Gţ2d0F~e‹*ľZ €€€!{0f&ŤA˛zľZżGŽ÷ćc>&3Uf9ŻJćçŸ×ˁ˜'ž†ž}ű == ~ƒS§Nă?ţÄńăĄuëVNľ%š˘ÉňQ4+VŹÄÚľN×Ž]xţůgwďŢ-ň<-WĘÝÜÜŕéé‰Ŕ@tîÜ óć-L˜đ&8ˆ[ˇn!))iiiPŠ”,'ŽˆĹ¤ĆŠăĹŰëż@ڕ“P¸ş#ä١ĄtóŔŐE‘松ˇ?ôIwQwÜȸ~×W}†Ô‹ÇqkăBÔúZŽyÝ;ś ÔˇÚŕ­WôÉ ¸ňŐdܸ„3ď ą-KžŐŕÓž/ü"ž`G€E’$˜Ră!zř3łKX7XlŢ… .˘mŰÖ8qâ”ü׆ "66_}ľ=ztˇi!“žžÉ“§âęŐŤv/§V­Z˜1c:´Z­Í÷łf}†řřtíÚŮćĘvANŸ>ƒ­[ˇŁAƒúďÉ}‘“•ŻeË~@BB"DQēOŽ@›6­‘’’Šďž[†k׎!*j+ěęŐŤçúíŠS§qęÔi˘GGxŹńäń‚ qóć-‚€~ýú iÓ&ˆ‹‹Ăڵ둖–†yó mŰ6ůśÄKIIÁœ9óa0 ŃhđÜsĎ 88ťwďÁţýƒ%KžĹ[o/p˝—,Y*b:wî„ýëy–-"cˆ˛OZôE{ňIrr˛ůŁTbäȧä[’† ŒS§NîßOqşmäNĚ1ĺ€Ü"föěO!I&NŒÄŢ˝űđüóĎâňĺ+xűíw˝z…Ű=ĎO?Ž\ xęŠň÷–`L÷îÝĐ˝{7Čs:–“˛#e$Ű=mćí+H8ş‚ "ôů÷ŕ^ˇ%’˘÷– —jÁ¨÷ÖBœžŇwŹĘŤŞu{qťW ńˇMđí4 W2Ćts]siÎ+öçsň]ÄíZ(Dř÷~Öţmd0ŚÄuƒĹ;ć€ěŘącƒłgĎÁĹEƒ~ýúŕťďžÇîÝ{‘ˆ€€iž˙\˝z:t@ppB—qăĆM9rűö@˙ţýäď‡NÂ0yňDť×9&&Żž:˙}śŘÁÖ1eWž6ʇ€€jđóóGŸ>ZUĽĽĽbÖŹ˙A’$Ü˝Ÿo0fĺʟкuŤc˜żÎ“ǡnÝ‘#GC‡Á /Œ’§oٲĽÔÍĘŇĺŒŮ˝{Ÿ|kőżţő<}´/ E‹ćˆĂšsçą˙AŒý/šuŒ…ĽËÖ­Űąqăćěőoˆ ĆŤ… Ë1Cô*jö]ştĆţýa0°aĂFôë×éééŘşuŔÝÝ­Zľ(đ`đÍ7 ĺqgϞĹĉćŤăĄĄ!X°`˘˘ś`áÂoäiT*%jŐŞ…_ü7nTfŰHĽ“vƒQîÄrěáĺĺ…zőę˘YłŚxö٧‹4żĂ‡Űdąw:–“R ĆdÚ˙řÍÄŁŰI‚W›^pŻŰYq1HüÝ\wčďÝÁí¨EPşy˘ĆcŻÉ…&+á&’˘÷"ń÷m¨>čĺ\óUj4ýtŤÝëzń8Ž,œˆ{ě˛?“ÉGŒ–Ő˙ĽC‡öčĐĄ˝őiLžÓ%%%€ć͛:ßÓ§ĎŕȑŁňďŹë%puu-ŇzşşjKĄNdSVi5pŕ›Ď&“ 111Řźy ŔÇÇőęŐŤ˙ ćqÉóřŘąhyş^˝zbőę58pŕŒaÆ ,ŹCË;~ü¸y#ŠčŃŁťU E@Ϟ=pîÜyH’„żţ:!_ ’÷K˘§OŸÁ×_“}Ěˆ˙ţwjąűĂbŮ"cˆRFŁąHӇ…uŔĉăąrĺj,]ş K—>čóŁUŤ–xńĹÁÓÓłĐůÜž‹sçÎŁaĂ€AĽRBŻĎ˝ĂiŢźęÔŠŘŘX>||đž˙ţ[ťŻuŠdi׍W8VŻ^ƒ)SŚÉßőîmnăëëƒĎ>›Yäy&&&ĘWÓáăăS˘éXNJ1َżƔ ÇŢí"`ŇëpiÁ›0Ś™[֘ YČź}ő'.~˝ŕÓž’˘÷"őüąRY_mÍ&ćƒŰűńe˛ŹˆiVži5cĆl:ô sß ÝşuèQ#ĄŐ>ŔĹÇ'Čˈ‹‹Ë~˝ƒ¸¸;ň4UŤúéĚ_çÉăë×oȁ“•+’§€sçÎᣏ>Á믿jÓÂ&§;wĚeĄZľŞšžÖXłf¨ŐtšűžJKKšß~'oă´i“áááÁşƒˆÁ˘'Ečë0GçOœ8-źXťté2ΜůĄĄ!ÎŁiÓ&8}ú öď?ˆ† Ŕd2á—_~EŁFpňäŠ\ÓwčĐƒL˜0çΝGbâ=”É6RÉŇnäČ' PˆŘłgŻœ1b`âÄ)8{öT*7nŒ˙ű_ -tžŃŃÇŃŞUK˘Ł˙˛yJAqŚc9)E&űŻŘé“́2SV.Í}UÄX¸×keo›ď,ˇ&éîÝŠŰČş˜fΓVFŁgΘűłłnYńÖ[su{óćMŒýoůó’%‹ŕďďÇü­€yœšš./#:ú8Ţ~;-[śŔéÓăÓOg"33‹‹îÝťĺ{aĎň´F&w+:F“k:k‹-Éd’?ďŘącƟȺƒ("“€Č~‹-ĆΝť`4ńÂ Ł°fÍOřţűoŃž};¤¤¤ŕË/âŔÎĂÇÇ5jÔŔĄC‡`4qüř $%%ŁYłŚyNo0葑‘‰sçÎáúő¨]ť–M_ä\”J%ž~ú)|űí7řöŰo0rä“ňM,÷Jëőzœ8qoź1111…ÎóĎ?ŁŃśmk´iÓǎ+ńtT^Ěůoȸ}Rî–)ú{ąňŁŽ~݄żß†sŸŒb˛‘Ý&Ož€×aţüĎŃŹYS$$$âëŻËý™ŃßÇ*ՃM#F CXXh4´mŰŁF™o‘ÎČČŔߟÍwnnć[ł˛rˇŒ´~$ˇe:k&“ žžžr_2QQ[ňźŘHD ĆPe?5*BGbŠŠiŘž}' M›ÖxüńĄpuŐŔ×ד&˝%?˝făƨçc2ÖÉÉ÷qúôš6mZç9ýŇĽË0|ř“˜0a ´ZWźöÚ+EZo>Đ1ĺŽ]‹Á´i˙Ő!Ă1`Ŕc0ŕ1 2ÓŚ˝‹˜˜̜ů ˘˘6`ŐŞĐťw/čőz,Zôm!ĺń'N˘UŤ–hÓŚŽ?‘g“]{§c9)í˝¨ý LU^Ő.žŐŃpę˛\ŤN<ş ąŰż`~R’!5 ŚŹ €ÚŰŻBl#ë'/Ž˘y˝‹Úěßd2–xťYÇ8.­ jŐŞ…)StŇź˙ƒ Eß˙-˘˘6 *jFŽ|Đşu+ůť¨¨ EjĂüuŽ<öö~p‹r:ľm~gÝzŰŇAo^ŞU3ďŻîÜšk|€˜˜ŹŚËťœ|ôŃűřčŁ÷ĄT*!Ić̙‡ôô ÖD ĆŮîĚ앞ž.7ťĚů;…BA0˙RR îěR’Lx䑮€'Náĉ“ ApppžÓ83g~‚ˇßŽ„ŤŤ+ŚL™†K—.—É6RńÓîÚľŒ?~üŽ” IDAT'Nœ´yJB^­`ÜÜÜ0zô €ż˙ţťŔůŽ[ˇZ­+T*5”J\]]ą~ýŚbOÇrRĘÔ*ÝÓVŠß˝ m*uŽiô١#™tY6ßť7hS!ś‘uƒsóńńVŤĹącÇąqăflßžÓŽáűď—‚ƒƒ*]š9˙ąIFŽ…§žzłg˙/×8 ëŰFřŸx¸ó¸qă†ňwgϞł™ţ̙­aüýóoeÝşu+yžűö°:†•°gĎ>9HҲeó\żíׯ‚ƒƒPłfMů6í;wîbńâoYśˆrŕĺ.ŞÜĽŇî^ÚŤVőE@€?bcăđÇ"*j zôčŽôôt,]ş:ТEáOş¨]ťBB‚qřđaÜž+7ÍK@€żüô¤ŰˇcądÉRüţű¨[ˇŽÝŰHe_>-Z ˝^ˆˆŢ=úy¸ššŇŇҰxńRěÚľ‹}‹éÓß7Ÿ\ťťÉÁš‚üřă*čt:<őÔ3ňw+WţˆaÆk:–“RTh܁Lűgďö(~ـÄߡÁ'ŹžÓ$ŸţŚeYȌ˝ú`‚ߏ–ď6Rąëg"Š"ţýďј?˙K|ó͒"ýśV­Zčׯo‰ŇŒJż|iľŽđDž ą˙A¸¸¸Č­oW­Z-OgîOŹlיœ#Ű´iŔŔÜž‹Ÿ~Z OOO4oŢ ýu?ýdžžF¨WŻ.`˙ţƒ˜;wjŐŞ…O>ů...ďUŤV#55 K–,…^ŻCPPöěُsçĚžŽ]ťÂŰŰ;×ú6hĐ@~?bÄ0>|WŻ^ĹΝťĐąc´kזe‹ˆÁ"@ĽRĺj~YĐAěřńăđŢ{ ## ~cóčiŔÜĂü¨QĎŘ5żnÝşaŊ˛ßwÍwşŁGG||<ŇÓÓńË/żÉÁœ˘l#•}ů°\}˛ÄZÁěÚľ;W+˜ĆÚü62rÖŹY‹k×ţ$™›?ńİbOÇrRʁ WO éś]Ójj§ó@$ü˛זL šqŚŹ $Ÿ8hóo—ÁpńĎÝŃłB[ÌTdÜź×ö=ś6ýÚs~{řmŠŘuC~ňę”R’ĚWśsÖ íۡƒ‚‚jŘ5ďęŐńÚkŻäşE0w*ޤIœ;wYYYvÍĎßß͚5-ŃI똲+_Żżţ "#ßFjjvě؅;vٌoѢ ço›5kŠ‘#ŸD```‰×™œ# &LxďźóŇÓÓńĺ— sw´˜0aź\ĎěÝťz˝.\ĕ+WѨQCxxx`ܸ×1cĆldffbŃ"Űŕmpp^zéť)ăÇ˙ož9ƒóç‰ ćĄJw–-"c¨˛SŤŐEšžI“ĆřňËůXťögDG˙…řřx(•JŐ@—.0pŕťçŮ˝{WŹXń4¨€€ddä˝S>yňNž<QQ­ZU<ńÄp„…u(łm¤âĽĽ…‹u Ć"żV03g~Rč|Űľkk×U${§c9)]˘{U‚`÷ÓŞzYq˙ őâqťŚwŻ×Çä9ÎťmâŽĂĹ˙˝\äőöj×Çž@Œ @tŻĘŒ.Ĺ˙KHˆů–ÔéÓ?———͸óçĎĂÍÍ žžć>ââî`ţüňř_~ůľH˲L˙úëŻÚô€ŔŔ¤§g`ٲĺ¸qăfž'@ýű÷CŰśmĘ=ÍXž VŤV-,X0kÖŹĂącÇľÚ!!ÁčŮłúôé Qó Ćä÷ćoĹÍă ęcîÜĎđÓOŤqüř ÜżžžhÝş5žxb<‘łOŸœ?uęÔśiuÝącfÎük׎Ăٳ瑚š ?żjčÜš3†}L>ś)LíÚľ0|řăřńÇUHLLė_.ÄäÉXśˆ`y´CÁß VŸ-ďEŤWË Č”Ůƒ€ €—N§?¤&g•ššZâ+œÎJŁŃŔݝˇ8˘|Lš A0cĆÇĹoˇŢš„óç/8MÆ 1{ö§,'dŒťŁ­c@2pkăB$ţśIn ‘;"¡Ë`“ŤŁ_ “^‡¸mKq/z )‰v-[ĺY>íűÁ/âbá÷á+źĄđŻĎL.Ĺ}‡N§ĂçŸĎÑ#GshýýýđňËcäˆ$Iřâ‹/ągĎžbÝĽT*ŃłgźţzŢżŻ\ůVŽü)ßßť¸¸`ĺĘeů>ţ–u M˜ż<ţd٢‡•Z­ @@Ŕ=ł“Ő Y˝ZŽĐYżGŽ÷ Ć€Á`@RRŇCšm^^^ź×ö!*SŚLĂéÓg œŚYłŚř䓏XNHĘJƒţڟEţ]fě5$ţž ŠçAw/Îźă÷ö‡{ƒśđíĐ/Ď[“MUł-7fr%Űwp_ÄňĹüełlQeÇ` ‘ƒ¤ĽĽ!##ăĄÚ&WW×n´ă{vŕK•REęTœą|°œ8ŸŠÔŠ/;ë­Üuë–/ć/ó˜u‘->M‰¨œ dff"33Ó)×OŁŃ@ŁŃđj,Ëˉ“’˛Ň`Jş Sr,$IrŞu˘gDŻź-Š’Ö ŹcXž˜żĚcÖDyc0†ČYN¨$ :z˝ƒFŁŃá'V‚ @ĄP@ŠTBĽRA­Vóţb––“ŠÂd„)5RF2¤ĚTHúLŔdpX9•TwŽžÝŤ˘‚ySIęÖ1,_Ě_ć1ë"cˆˆˆˆˆˆˆˆœ’#‚1ěŔ—ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆĘŃącŃXž|$I*÷ušuë.\„¤¤$fĚCŽyMDĽ)++ Ýşőđ#G™Dvb0†*Ľľk×!,Ź‹}ľ)k–áΝ;L'9 aa]đĆoć—˜˜ˆŽť",Ź víÚS*˙Ç#G~dž ›Ą×ëśm–Ąw8q2Ž_ż¸té26mڌ۷c ×čŃcđŢ{°ŔÁ´iď ,Ź ćÎý˘ĐicbţAXX>|¤T–}řđüôÓ*ůsQňšçÚľ„…uA§NÝrĘ>‚°°.¸qăFžŸółnÝĎ ë‚çžÍćqc™7FG‡ hÝşŽ\š*§ŐéÓgrMűůçóÖ#FŒ,ľő]ż~8(^°`!† ĆÂK Ć9ŤŮłgŕ믿DdädxzzŕÍ7'bƍL*U˝°téb›ÁÇÇ'×t&“‰‰ĺ$||źqôč¸yóŚÍ÷[ślEŐŞžĽşŹW_‹uëVA­V;dۂƒƒĺr8uj$.]ş‚ńă'Âd2Ą[ˇŽŘşu35jČBPĘîßżC‡~EXX{lŰśÍ!Á7kGŽüŽUŤÖȟ™×ÎiÓŚ(ÔŻ_žžŘž}GŠĚsóć­ kóçĎă…‹Ld7–‰ß~;‚6mZŮěË||źńóĎëmŚÓétŘśmŞUŤZŞË˙ůç8xđ3‚*c¨RkѢ9Z´hŽ=şcúô1hĐ@̛ˇĚWÁßyç]ôęŐáሌœ&ˇhřţűĺčÖ­'233{÷îGXXDEmčőzôčŃ_ý|ăÇÂŘąŻ˘[ˇžxęŠgqćĚßůŽŰśm;đä“Ď [ˇž>ü)lܸÉfüşu?cĈ‘ňř-[śÉăŇÓÓńá‡ÓŃłgúöí/Ż•oo4jÔĐfP*•X°`!FŒ‰šsż@÷î˝°mŰv |őŐ×0`0ÂĂ#đć›äV OĽŁNÚŔúőţw’$aÆÍčÜšłÍ´…ĺIa˙Ç bĐ !ňžŇýá‡Óńüó/ڌ߱c† {˝zőÁš5kqřđ<ńÄÓčÖ­'ŚL™*×ayŃh4r9ěŃă<ýô“¸qăââîäZţíۡ1aÂ$DDôC˙ţƒđńÇ3žžžkžééé=z ž}öÜżŸ(ۡď€(Š?ţ $%%ăŕÁ_lĆ˙óĎ?xĺ•×Ń­[OŒ12×ţáÖ­[˜2e*""úĄgĎLž‰{÷îÉ'7aa]°|ů Œű*şv큧žzVžj˙á‡ÓąjŐjÜž‹°°.ŘťwżM^/Z´ÝşőDZZšźź-[ś!,Ź Ž]‹lÝşO<ń4y$Ď=7šˇ"”ŁŃˆíۡă‘Gş˘sçÎظ1ŞÄóź|ů Ν;‡çž…ęŐŤcăFۖ˜>ýS„‡G "˘6l؈Çóć-§9sćoŒó şwCGয়VɡUfdd`ÖŹ˙aĐ !čŐŤƍ˙Pď“*ëqŁ=ů|řđtěfó]—.]°{÷^›ýÂŽ]{ ×Đşu+›i JťÂŇcȐa¸xń˘\oYˇ*Űž}'| ={F`öěĎyዌ!rVÆ Ezz:ţúë$IÂřńqîÜ̚5ŸţŽ^Áţó& şw:ǎEŽýđűďNœ8‰ŒŒ <ňH7yţkÖüŒŃŁ_Ŕ7ß,„(ŠřŕƒéyŽÇÁƒ‡đţű"<ź–.]Œţýűá“Ofbűö€łgĎaɒĽxúé'ąrĺ2ôéÓ}ô1.^ź˜5ë3ěÚľ‘‘“ńůçŸaďŢ}HNć ’3şqăŇŇŇđĹsŃŠSG̛ˇ6lÄÔŠS°hŃBH’„ąc_•O€ OĽĂ`0˘OŸŢˆŠŠ‚N§“˙Ű7oŢDϞÝmŚ-,OĘâ˙řÇbΜŮ=ú̝űVŽü3f|ŒO?Ž_=Œ5kÖŮ5ŸťwďbϞ}pwwƒŻoîÖZÓŚ˝‹ääűřúëŻ0gÎ˙pćĚßءożÍ4YYYxë­IHKKĂźy˙ƒ‡‡ P6oފŽ; 44Mš4ÁŚM›lzoź1wďĆcîÜ˙aҤˇđý÷Ëm~˙Í7K’’ŠůóçbÁ‚y¸xń2fΜm3Íňĺ?ŕůçGaőęQŻ^L™2 7oŢĸqŻŁGG Š"6mú;w´ůÝŔ`0lňvűöíhŢźjÖ ĹţýđŃGăńÇòeKŃącźůćÄO Šč~ůĺW$&ŢCÝŢWŻ^ĹŠS§K4ĎM›˘ŕăă-š#<ź'vîÜ‰ŹŹ,yügŸÍÁöí;0qâ̝ű98ˆťwďĘăccăđúëoČ-ę^~y ,Xˆü °dÉwŘľkŢ˙],_ţ=Ôj5VŽ\ĹăƇ츱°|žyó&nܸ‘G0ŚA° îlذÝşuRŠ’ż+,í KĹ‹ż†§§ÚľkƒM›~–÷Cqqwpüř_řŕƒ÷0|řăXťvöěŮÇʆŒ!rF–Ű’’’qęÔiœ?ož9­ZľDóćÍ0q⛸víţüóBCC‚#GěLŸ|ň üńǟ$ ż˙ţüýýаayţ=6íÚľEƒő1tč`ÄÄÄČ'zÖÖŹY‹&MšŕĽ—FŁNÚxţůQhŐŞ%ÖŽ5Ÿ`5jÔ[ˇnĆŔ TŞPŁF H’„ŤWŻA§Óa÷î˝1b8z÷GŁF ńîťďŔh42ƒËÉŞUŤmî5Œœ&Óh4˜2e"š6m‚*UŞ`ÓŚÍxá…çĐŠSGÔŠS‘‘“‘ˆß~;ƒÁPŕx*=&“ ƒDrň}ůŔmýú hѢ9‚ƒƒlN˘ ʓ˛ú?>ńÄpaȐÇ`0Ţ5k†˘S§ŽĆ?˙äeúâŋrY8pŽ˙ ~ř~žˇII’„ÔÔ4¤ŚŚ˘fÍPüđĂ÷čß˙Qyź^ŻÇ”)Sƒůó?‡ˇˇ7 OΟż€‹/""˘7 oßŢřăcr-'OžÂ­[ˇäýMŰśm0věżmćńîťď`Á‚y Ş•J?\ştĹfšAƒ!,Ź9ƒťv큇‡üüüáďď???¸¸¸Řü.00íÚľÁśm;ä ÝącÇ1xđ@ć+ę;wĈĂ‚ąc˙ęŐŤŰ\Y§’‹ŠÚ‚:uę víZhßž||źsľd) ˝^;v <<˘(˘oߤ¤¤bďŢýňř;waذÇѡo5jˆwޙfs\˛}ű("ŚNŒZľj˘wďpôë×›6mą Čꐒ’*˜5k&OžŔăƇ𸱠|>|ř‚‚‚dóWWWôęŽŸŢI’péŇeœ:uôđ ÓúÂŇŽ°ôđőő…ŸŸ?üüĚuœ(šOqU*&N|­ZľÄË/§§.^ä­zä<”L˘îލx{{!66PłfMy|:ľqqćqÝşuĹĄCżŕúőë¸{÷.ž{îlܸ —.]ĆŃŁ k׎6ó÷ňň´9 ˇœĚ)•śĹŘŘ;hŢź™ÍwuęÔÁńńń˜9s6ţü3žžž 1ďüŒF#’““Ą×ëQłfˆü[OOO›e“cőéÓĎ<ó´üŮÝÝÍć˝ĺ !)) ™™™˜3g>–-[a3¸¸ŘBÇSé‘$ čĐĄ6oŽBXX{:ô+Ţ~{ŞÍt…ĺIYý]]Íő‡ő§…BĄ€$ĺß [­VcɒEHIIÁ+ŻźŽđđšŽfZź˙ţ;řň˅7Î|u˛]ť6xă˙ 88ä@U@€?1X˝ÚÜWKdäŰEQn&ľ/˝4ZŢ÷„†>('5k†ÚĚcÓŚÍřţűHKKEPPŇŇŇs5ˇ ôˇ9 ŞZŐWžwaŒiÓŢA\\öěŮ WW ÂĂ{fđ.!))>:Pž>1ńBCƒ™šĽ$!!‡ý čÔÉÜ2Âd2!*j Ţ|s´Zm‘çyđŕ/HJJÚ5kąnÝĎV˙ëŃŻ_$%%A§ÓĄNZň8›ú)66))Š0`°MŢ[‚ˇĎ?˙,2331cĆ,Üť—„úőëc̘ó­SxÜX1 Ëçß~;œož2[ślĹ_Ŕž}PŁF ´mŰĆŚO${ŇŽ ôČŻĎ5OO›´Ňjľ0xq’Œ!rJëÖ­‡VŤE˖-pţüŔľk׸zőŔßß|ŔűČ#]ąbĹŘšs7Zľjooo´mŰÂŋńÚk/k=ücóݕ+Wäĺ.^ź—.]ÁĎ?݆——ůŕ×_—w jľWŽ\“{ďŢ=$%%3ƒË‰——7ęŐŤ[čtžžžÇĂsĎ=c3NŤŐBŠT8žJߐ!!2ňmlٲnnZ„‡÷@BB‚ÝyŚP(Šô´4fddĘßĹÇǗę6…††Ęĺńĺ—Ç`áÂE¸pá"ęׯ—kÚ   |đÁ{P*•¸pá""#§aćĚ٘?. $$ďź3Żžú̙3&ŒgĄÉA§ÓáŔƒhŢźŚL™$?yňTDEmÁčŃ/ŔĎŻZv=ŐŤW—ß[Ÿ¨üń źńĆëxňÉ'}ô Ž˙ËfY—/?řMrr2âăěî$ł[ˇ.đňňÄž}űą{÷>DDDČ';ľk×Ćýű)˜;÷3›ßXŠdśn5ˇ2š3ç3řůůeççźóΝؾk7TäyFEEAĄP`ůňďŹƒkąaĂF\ż~ţţţP(¸qăAG劊Š6ˇ§XĘćwß-BĄżŕîîŽ×^{&ŒÇíۡ1kÖgˆŒ|ťwoĎ0ŕqcĹ=n,(ŸM&˘Ł˙°açšnM›6A˝ző°oß8pÆ •ˏ…żż_ĄiGô0âmJTŠ8qRŽÔGFNĂŚM›ńĆŻCŁŃ YłŚ¨WŻţ÷żšˆŽ>ŽăÇ˙Â̙Ÿ!44mŰś‘w0UŤúâÇBç͝;wÂŞUŤáîs˛ü(•Jˆ˘ˆóç/"99?>§OŸÁ˘E‹qńâ%|÷Ý2DGÇ㏵:ŔĎ­[ˇqéŇe̛7_ţ^­VŁwďpŹ]ť;wîĆŮłçđá‡Óö¤*>•J…ÇŠmŰś!:ú/¤¤¤b˖mx饗‘’’Rčx*}]ťvAŐŞžř⋯зoß\˙ŁÂň¤¨˙ÇZľjBE|ůĺWˆŽ>Ž+~Ŕߟ-łí{â‰áđńńƗ_~•kœŃhÄŕÁC9 WŻ^Ëî°S€ťťťŠÍ›ˇâěŮłxěą'˙ÇĂĺ˗ľÉÉ÷qňä)źřâXœ[ťsçŽý/˝4ÚŚÜ˝üňżĄRаqcÔj5ÂĂ{`ŐŞ58xđŽ^˝†?ţTnqýúőVŤĹ‚_áΝť¸qă&&OžŠľkÍ-mŚM{O=ő,Nž<%?!LŤuľ™+ţqcAů|üř_0™LŽűĐĄƒąző$$$ÚÜęjaOÚĆÝÝ /^ĆůóŘI/UlC•Ú„ “Uаa̙óÂÂ:07˙Ÿ3g6ć̙‡I“Ś@’$´k×ăǏ“Żö‚€.]ş`ƍňNľS§ŽřôÓYčׯÍU¤‚ˆ˘ˆ#†cýú Đh4xýőWđß˙žeËV`Ŋ•đ÷÷ǔ)ŃŻ_Ŕ˜1/"!!Żż>žxéĽŃň=ŕđÖ[ă˜1c&ŞTŠ‚1cţ˜>q§"7î5¸şşbŢźů¸?!!!xíľWä+Ľ…§Ň%Š" ˆĹ‹żĹ!ƒ‹•gEů?V­ZS§NĆ×_ƒˇŢš„Ţ˝{!""˘Ě:JŐh4xá…ç0{ö爎>n3NĄP`ćĚO1oŢx鼹P(D„…uŔřńărÍgŔ€ţ8}úo|úéLÔŠS Ôgá‘O˛7Łzőęšn!čÔŠ#||źąiÓftě†Ď?Ÿ…O>™‰ńă' $$Żź2'NTŤV oż=ß~ű֯߀víÚ wďŢrǟŁF=‹;w⯿N" 3f|,÷á0hĐ>|Ż˝6&ŒĎłÎůd<<Ş }űv6Ÿťví"˙nëÖí$ }úDŘĚĎÓÓ]ştÂÖ­[1věK˜4i Ţ{ďC(• źňĘXœ={Nž>00óć}Ž/žřcÇž 77-ÂÂ:`řps+ˆńăÇaîÜů˜2e*RSÓФIc|öŮŹ‡6SY ĘçǏ˘uë–rKşźôéyó cÇđńńÉs{ JťźúÉÉiôčđńÇ3đâ‹c°bĹ÷ŹX¨Běř^°úly/Z˝ZEö ĚÔTźt:={–$"""*:ÝşőÄÔŠ“1hĐ@&IÎ>HúôyC‡Á˜1/1q¨P#FŒÄĐĄƒĺ[(‰jľ* @=Cö`ĚLVƒdőjéÚú=rźŔ–1DDDDD•Ň7ß,ÁŢ˝ű1qâ›đÇ֭ۑœ|ßî[CˆVŻ^ÉD *&cˆˆˆˆˆ*ĄÇ‚ۡoăż˙}ÉÉ÷„wޙ†6mZ3qˆˆĘoS""""""""ĘćˆŰ”ř4%""""""""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""ă™äu IDAT""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆH鈅Ä^ű&Ł‘ŠMDDDDDDDNKT(˛‡c‚ƒŞ’‰šJDDDDDDDÎKpĚ DźM‰ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""""b0†ˆˆˆˆˆˆˆČŒ!"""""""r cˆˆˆˆˆˆˆˆˆÁ""""""""b0†ˆ¨$Ib"Q‘0CDT‚ 0ˆˆˆˆˆ¨H”L"""""˘ÂąE,QĽř§;d) Ć•Ó興ČŮĺ×´2ś ľŢoŰłç~ž¨˘V|ŽY ƒ1DDeppfďX~Ó ‚`3.ççž/îˇe^ö./żß”t˝J:ßŇ\{Ňť e”U•´”U™˛w{QŚ‹ł˝Ž(Óe•wŽúŻ9K}ä¨˙Zi–éň¨ěY˙źće śH’T`ŕĺaĘX§‹Éd˛ůž°źĚk4ďn&b0†Á"˘R Ŕä ÂŘwĹŹ ƒlÉŽ Miž´ÚsĹ/ç÷ůýڤëUŇů–ćş”4Ę*JZĘŞLŮť˝Ž(ÓĹYž#ĘtY坣ţkÎR9ężVšeş<ę#{Ö?ŻyYaň ČX‚8k@&çţÝŒ1™$ťö÷ůˈȚĺ</+ Ćó8Ż4I‚Őű˛mÂ\Ú-ŹŞ ›oÎi {-î:”džĽľNĽ‘îeľe‘.ewÎVyËtIćW™ËtqÖą´Ëki–éœÁAäďA€( •"¨` ÄXöń–Œů˝ &Éţ}=U°`Œ¨`0†ˆČ™Î 2ň+$›é‰ˆˆ*"Q! ˘”1™›@Ž(ŠňűŠ ÉyK’$I0M00šŒ00™¤ěW÷ńDm˝Ç` ‘Ó¤Y_%“$Čd&É$_-3mŻ–ń@ˆˆ*îI‰(ˇˆEQΈ˘…BI2ĘA™‡ĽľŒÜúĹ$AŻ×Ă`4Ŕ`0Â`4ďűMä}˝őSW$ÉÜ'̃WKËŁœßçÝwŒőáB^Ó[ĆçümÎĂ Ëxëő„|—ß|óZ'{Çç\炶ɞ×Âć›ßřœărĘoźŁÖаüËů}^ËÎoźőňěYw{׍ ßVf‹“VymS~e2żß5JŢŚDDä˜ź‚1FcvŕĹd„Á`>Hłźéő†2ë#€ˆˆČ‘,…BQ T*ĄPX1 Eö Ižž"er^p1MĐôĐéôČĘŇÁ.ZO¨5ZBž'vö§iÁ'˜Ĺ™OqćQż/(ĐQ”u(îoK˛ě’ÎŁ4ňŻ$éç ů˙°–?GŐa ĆŮq€Ř6Y6 0 Đë ĐéôĐLPšh (\ &ä솽ŕŽ-{ÁęłPč8ű;M,h~v§BżÉoţŠ×˝”} +eďh…|Ö!˙ůžŢB!énĎ| [§œiŤíŠ‘îśó3ŔEĚŤ‚ŇJ*0-Š6G”iäł,ű:-<ďŹË`é”é˘ý— .×y˙Žđ2]´´Í?ďr˙?Q†eşheđÁ|¤ŚEQŇV*Ăt/n=-˜EIoQ4XŒF=˛Ňł RŠPŠ”0ŠLPš”P*•D&ˆ˘čđšŇŢç›L ó>>##P¨ŕăQáQ!ň" 1CDTÖd9Ÿ¤` Äč zčődfé (Ôđ „ÚĹ‚|ď|IOŢJe ň=A-ŮÉIé­[ÎN$Ë+Ÿmץ<ÓV'“N–lƒ9ƒČă$ލßĺ?Ϝĺ9ďćőË´ÍIťsˇ%8ó ‘3ŹÓ§xËf}TŔú)Dh´UP­ş+âŽ#++Uî+FĽTe×R… ÄŘޢôŕvdƒŃ›'J9CDTZŒ!"˛ó@íA1Fčtz@Tg7[VŮœÄ źdFĹ`4ł›Ĺë+TxK FŠTf÷%Qœ–­nôF ŠY F ZŽ*˘ đJ4‘Jřúăî­+ČĘŇe÷'cîÔ×d’ä€L…ÝßKćV°D¸h´DV@DTúŒ!"˛çŔĚdŐtŮ`€Ţ`DŐęš1DĹa2™™™‰ŹŹ,˜Lڊyr&ŠpqqVŤ-úI˜dž Bg0áĎ=ţŒÉBşÎ„OşÔŃ v5%ŒĆ•űžĐňߢB O_Äßş˝^oîÔWTTČۓňŞ“-aPH‹˜´´4ÄĹĹĄf͚6ýĺ9w—™™ ]–’$ĄŠGšSn˝^掻•*%á⢍&Ł pѸČzSń0CDT„ƒ3s§~F¨\\ĄRť2Q¨T deeUčN!M&˛˛˛ RŠ VŤ‹öcA‚Ţ !úşˏŚÁÍE@€‡OdâĆ=F…ięŤbA!*C–Űtôz= L&sgź–VoyTj ”j FóSŚ ČŤŸ8ëĎyMŻÓéË—/#$$„ÁŞ@űl#n\ż‰ľk×B­VcôčŃĐjľ0¸qăţůç´k×Z­;wîBÝşu‘––†Ö­[#==ŃŃŃhööŢěIŽëž÷üœsrŠ­÷F/@ŁMp§D˘D‰Z,YeZ˛hËö˝Łšz˜˜ëˆyđźÎÓüq}ďÓ8ěq„^Y–­…&EҒ¸I$A7lĽŃŢťkÍĚsć!ŤŞŤFƒŘß'"ťŞł2ł˛NžĚüoţ–ýűŠEUśoß&^áŸcA6hœ9\ói™6iŽšůWŁĹqźŽŃiSę5ł2d§Qvśń4ş1ľöÍŐ9]Zëĺ{ilkŁŒ´´{„ďűÍďÝČůĽŤpđtĉé˜l yp$¤[Ţ=Sĺýs>[ťLs_[Űęf+ŁŰ¸F´śs#|c­ĺű˙I~C뱖k‘\Gšç…ÇĘóc#ç°ľ–RŠDE+<ô´ÖřžO.—[†˜n[Ł­EÍűäBEźú꫌ńőŻ]„ác,ó ólŢź™caa‘ƒ255…çyŒ111Áž}űpÎ133ĂÁƒ9zô(wß}7KKK<÷Üsd˛!ň'L>Ÿ—űˆ1‚ W׸]Ëصւu ¸ĺ]ą…›k ľäŻ˙ßż!—ËńÇň,‡biąČ—žüE6oÄó<’$ĄZ­R­V›Oł‚ hžo„ŰYkI’c Aƒ¨FŘT&“Ůđ@c-1h˝ÁLExžGœh˘$M^ĹĽ°JՈJĹ!ZkΜ9COOOsßżíf8ŽĽR‰ý×套^B)ĹžđžřĹ/ŇŮŮšbšršLľZ%‚ Ŕ÷ýËž–4<Â0ü„šz„Űi`U*•¨Ő"l˛,ô/ ĚfłëžĂËë×ÖüŹVKC …Bs;Î-ß/ćUr;ߝsüöˇżĺĄ‡" Cé„­wÝHŚŚŚřřăxřáGxçwxóÍ7ůÁ~Ŕɓ'Ů´i‡âȑ#<ţřăřžçyüâż@kÍŢ˝{)•‹7Í=XÄA„;@˜ŮČŔYŽ6ŻţúuΞÇó<^{őu˘(âľ×^g||œ˙ýżţottt033ĂsĎ=ÇŮłgiooçŔźńĆüŕ? \.“$ arđŕAjľJ)Nœ8Á׿ţu2™LsŕeŒ!Š"ţéŸţ‰;wr÷ÝwÓŃŃAWmpŐđú‹żř žň寰gß~zTHw&¤ż3ŕätLOŢ0ŘŽů荟cNeřňWž„ďűüěg?góćANž<Éמö5zzzPJ5äď"ŇŇŇƤž5ŮlśůÝů|ţŞ>ÍvÎńӟţ”cǎń—ů—TŤU~ň“ŸđÎ;ďđřă7 օ…~ôŁńîťďŇŐŐĹ÷ż˙}ÚÚښâL†ÍBŮlkÓd˘žď7˝˛Ů,/žř"Ĺb‘ÇœŢŢ^Â0qřćĹ_äĺ—_!‰šĚ<_óŐŻ~•/|á ëŽŰö a§ŚŚČçó‹Ĺfßj$_-<ŹőŕâN@)ĹSO=śožÉÝwßM>Ÿ—N(ÜRý7B|ßÇCš\Âóźf˜ńŔŔ[ˇnerr˛žl@ĽRářńătwwSŠTŘźy3ǎ•Ć1FAnovíÚÉącÇń}Ÿ;w019Éčč>>őŠGČd2MŻ­BĄŔg?űYöěŮĂůóçI’„šš9>üđCڧ§Ůąc/żü2Q1::ĘŘŘ?ýéOŮącžďł°°Ŕ–-[8yň$łł3|řaÂńăÇ偸ŞqS,–8uú ?ýŮó|ţ‹_á‘î휩ő2[ĘsßVŸ/î 9ô+¨ÖjÍźMJAĽRallŒçŸžÁÁAxóÍßp÷Ý{0ĆpćĚÚÚÚŘ˝{7?ţńŮ˝{7Ĺb‘ŃŃQڧ§8pŕŔU-xűíˇůţ÷żĎĐĐÖZxŕΟ?OąX¤˝˝çóóóĚÎÎr˙ý÷“ÉdXXXŕwżűlÚ´‰˝{÷rřđaćććčěě$ CN:ĹΝ;9qâžç100Ŕââbó¸îßżŸČĘ;x`ő裏˛gĎŹ]CŒŃMąňRçb#tnaaçžűŸtt´ł°°Ŕˇżýmúűű›Ë]Ě dĽgĚíßćžď3::Šľ–—^z‰oűŰŞ$Ü2cŘśm„8~ k-aňĚ3ĎđĚ3Ď077Çđđ0ÝÝÝär9îż˙~zzzŔZ˖-[˜žžŚżżŸŽîNy@)bŒ ÂľCî1ÂÍŔć-›ÚBŒlapófîeëđp3G‹sŽjľÚ°çóyŹľ,,,pôčQΝ;GŠT˘ŁŁƒ$IČfłd2|ßçđáĂô÷÷sţüy˛Ů,cccÔjAĐÖÖĆË/żĚƒ>x•OŽĺ°Š¨Q).0Ř~’.}–'<ĹŚÎ Y_q¸YÉ,Aë„÷ć‘GÁ3>m…vţýß_ŕŤ_ý*§ĆNqŕŃ>r˜S§NqüŘqţËäĉ“<ő…/räČŽyŸˇŢz‹?ýޟ˘ŐŐ8ĺr9&''¤VŤ1;;{AΎBĄŔŢ˝{ăôéÓôőőńŁýˆÁÁAΟ?O!_ŕđ{G°ÎńÖoßćž{îĄR­˛´Xä݃żăŰßţ6ľ¨N‘Ëĺ üW^ů%ĺf||œ>řgÓĚ-i5Řď~zzz.qŸ[RÂ0¤§§›_|‘Ď}îsMŻ9ń ]‰R ß÷Ůťw/›7o!F¸ĺúo[{÷ݡëFktýaK咽f.ş\. „ž.”Ö( Łł˝žíÍí "Ć‚ ÂmÉá÷säČ´ÖěŢ˝›ÁÁAĆÇϑÍćČĺśŇd2úűűŮľk333”J%Ξ=Ëôô4žçELNžÇ9Goo/###:tĎó8yň$Zk*• JAŠTÄZŰ|ޞ9ˆBŁP e†Îś_`v&WŠTąÖŃŮŃĹČČ6<Ďç˙ńŠU#FFśĄW9áčSO=ĹřCN:EĽRáľ×^ăÉ'Ÿ\Ṳ´´Äää$š\Ž“'O˛}űözööv&&&™Ÿ_ ťť›Z-"I,ýƒlŮ2DľZc~~……@ąyó6męĺÔŠÓr’Üá ÓŮم[ν‹6ĐŃŃąĄYƒRŠÄää$O=őMWEŻM6›%›•ęŠÂ­'ĆxžďBo×ĽŞĽlľˆ1‚ ‚p§łT,˛´TŹç@)R,™›ŁX,‚shm( ŒŽŽ˛iÓ&úúúčîîćŃGeÓŚM<řŕƒXkéééĄŻŻƒŇŰŰKoo/Üu×]Íź2…Bb1MĚ733מôĽŤţ›´ŃÍőF’၁Â0drr˛™ƒa÷V+œ9s†ŢŢ^ž|ňIFFFšŐ{ě12™ A000Ŕý÷ßOąXdhhˆÁÁÁfâÁĄĄ-8çxâ‰'ŇÜ2×Ŕ¸}ŕčďďç˝÷Ţ#—ËńÝď~—7Ţxƒßýîw<üđĂh­éďďg˙ţý|üńÇ|ë[ß⡇âîťďćčŃŁlŰśţžŒńhkkcŰśm R(ŘącĎ>ű,ЎLĽBœD yœEžĚßÁ8çx饗xá…HâĺJJÚŔÓO?ÍżřĹu…Ďó0Ć`­Ľťť›ď}ď{„aH­VŁ­­-=_ëU•A„Ťd7l`žjůżń^ˇź6&SŸźú>ĐéJç_[!Ó ‚ Ü4âç“$­:Ĺ•J•RЌňômَÖFž W<ˆ*•J”Ëĺu—;řÎA~ýë×ŃZń{ż÷e:::Y\\¤łł‹\>MTťşäsŁ7ĘÔŽŐW×*‹˝z˙ybËŽG&“!—Ë]ň)zRUăg?ű9ýLOOłeËúűű™žžŚŻŻžŢ´ŇÄqL’ÄÍrňJĽáƒŤË:7ŇߜÔç§Ë'‰ĺůçŸçđáĂüٟý˝˝˝éSAĺŽÉľ#Žă澝>}š8Ž›0–*O’dEűˇp`EĄV”/O’¤y,Ň㕀r( ڈç|żŞVŤÄq‚M×ĐZáůŢ%“;[k)‹ÍŞI ę <[“^§yŞ"&ϜŔEe˛Ů ařĆŒŃşfÜ,×áĆľ2ŽjQRŠL-ś´÷ ‘+´ĄľT,„;‰ đ怨q}Ję“m™\Ëkă"ÚúÖpĹ1FAÄáĘĺ2ĽRiÝĺĺ¨üVĄAĄšwęFXZń˙ú\(\|šK}Ţc6˛|ăkÝçVaĽńţrĘäŽ÷[ZĹŚk9HźXu™ŐżérhăÖm­Ţ†\‹îěëHëÔÚVç,ZďSŠT¨Ő“e7śÓđˆÉfł+x‹#‚ˆ1W&ĆH˜’ ‚ Ü`<Ďkzt\ŒtpséÁŔęĎFBWcŔÔư‘ím4ŹćrsU\lŮë5(ÜČ1ř¤ű˛z-ŸäYKŒ0ƐËĺđ}Ÿ(ŠšbŒçyřž/ap‚ WŰţ“&A„;ˆň<L&CĽRYWšŮG†xž'" ܂ç/¤i+rĂČů,‚pm1FAn §ĎŮlśYíčrÂrn†ý×Z_đôüVŮAVžĎ Œ Âő@ÄAA¸´&Ţő}˙–ŤV˛V>Ě ‚ ‚ Źˆ1‚ ‚pYďIôzI^o6ąŁ5ĄŹ1‚ ‚ ë#bŒ ‚ ܤÜ*˘Fk$AAáŇHZtAA>1"Ŕ‚ ‚ \>"Ć‚ ‚ ‚ ‚ \GDŒAáŞ!ž2‚ ‚ —FrĆ‚ ‚pŐX/é° ˇSSSchkËIc‚ |BDŒAAaĂDQD’$8—•ĆAř„H˜’ ‚ ‚ ‚ ÂuD…Źćr]SœsŸX<‰K%˛œ›pÖŃUđčĚyx&ío"Ęw""Ć‚ \›×ᒄd~žđܸ1wĘq—&áfEĹĄœCŸ;G2?ééA#ăŰÉöppfŚĘ˙|§Ěą)Kŕ9~4äÓŰł žŃhqƤňL-śř°Ž¨M°IšŰÎřʤ“gցSŕiE’¤ůš| @J)< Ő(fąbůĺ‡%~uސ3ăE綅̗bNÎ8Ř2>WćÜBĚ›}ĆĎ̲8vŽ źH[băaňyŠí˝ôvł­?Ëťg"úŰ›ÚŢ9Ue{ˇŚőxkŹĘŢ~ƒďi~;ޘ;ąc K”Ŕ/Őxt¤Äž­m}é!ŠskíŠ>ęœCk1fÍĺ“Öş)0ŽŢ¤^9şîÖş^ë|A¸ˆ#‚p=q’#FA¸ŮîMN„˜Űî.Ď$Žp֐$kÓ°é¨GXCľZ!ށK4ĹŮYć?:ÇŠˇĎ`§ć‰ŹfIÔLḦ́D&Âúe’b‰žÂVĘĽ*6ëăŹ&ŞVq‰!‰Q­†KЕ÷j/ĄŚŘ<ö;‚ŁÇ°1D: Ö!5OQQ†šö¨Z$֔Î,Q ćŘżŤž,ŮĐă3weń}Ď(žÜ AŕM{J‘f|~žwĎąVqOoĚPOO]DIŤ;­GEźđ‹źô‹—PZ“ÍfÁÁמö5úűúĐZăHCŤ–řŤżúŒîŰÇ7žůtŕëyÄq‡~Äöí1ĺr…úÇâĎ˙Ó"fÉd3X똝™ăý÷?`dxłłó9r„ťîÚĹ˝÷îÇó<ń–Ž"Ć‚ ‚ ‚ ÜŚěěĎňgZ>>=C_WžĄžůŒ‡Ö8pqLś˛ČŇK˙ÇÇČڀ’—%ҊDy$Ę#Ö5íĽŢ1Ú'ś§•XPYžîRhĽhËgšßŮ^ČÖß): Y Öň‡t˛÷Ä4ÎZśoî˘#ďŁŐ˛R ĽÔš^ZI’P)WŠŐbž÷˝?aűöm(Ľčěěä7żů-qłgĎĆĆNqţü$[ślĄ¸Tb~~ˇßz‡ đŮ7:ŠB12źöśŞ•‹‹KĚĎÍó˙ńKśmŰĆĐĐš|žťvíŚRŠňŇOÎ믿ƽ÷î§ťť‹ááac„Ť†ˆ1‚ ‚ ‚ ˇÎ9’$!ŽkTbˑůş:"’¨DąXF) qŒž&úŮżÁŮI°Îř8ŔĄpJa•&Q†XyDʧŞŞ* ě<^ü0Ą”,ň­{= Ąc9oŤˇ‹‰uœ)†DVąĂՈ"ŁĂ9_Ö—sDQ“'ORŤŐČĺ˛d2Yřëżţkžxâ Ţ}÷]î˝÷^śnÝJľZĺľ×^㭡ޢR­ňЃňo|ƒ_üâÜ}÷݌ŒŒP,ů›żů´V”Ëž~úiňůó™ĎđGßý.ů|žçžűašC'ŽÉfł<đŔd2Yîťď>öěŮłf˛`Ař¤ˆgŒ ‚ ‚ ÂmFÇ‹K8hÇ`Á˜Ô[ĹY‡ŞUČţ ţŃ÷qą‡2ĽÓ<3 ęţ-.eŹR$ZkŞóŠY¨Ô?űHh͗ďŠČ7ćƒ>ŔZťâ;<Ďgűöí ŃÖÖÎŮłă$őDĂAĐÝÝM„ä ršœ„( WcA᪣–mGç.´HoĆ=VJ› \ăkŠQĽ \sśîé2S6üljĂúňĎĹdÎ~Dfě0ĘVŃ4E‚vvŤH'C;‡rŕ”BG]U Ő~ň‘Ą’ŔˇöEdý֐Ľëŕ­s>ŐXq`kß@œDX㜾ä}Č9¨ŐŞüć7żalě$÷ÜłŸ0 yńĹ_p×]w1;;Ë /źŔččhë Žšţr=÷”RŠČO~ňSúűű8}ú;věŔó<”Jď‹a’$1G?>ĘŘŘ[ˇn%éZÂUAÄAA¸šŚoŞŔԇ[Ž9ěşŮĽke€(WĘZçůrľ˜ăBA¸F÷ ×|mÍżŇZ WčĘ:4WÉ}SÇŠíŒK0¸ôľů‚ç @gg'ç˝g/Oó›źüĘ+|đáűÜ˝wÝ=ôôvS(čéíbűöz{{čî餯˝˝=ô÷022ĚGČ}÷ßË7żůMڧ§číífÓŚFFFx睘˜œdrr’ááaédÂ5˝gŹžŻZţoź×-ŻÉÔ'Ż>€tşŇů×ŘŔI&‚ps Nm=ů%I˘8˘RŠR*•ŃAžž-ŰŃÚlČŁŔ9G\ŠPýŕ} ÷˙Ą*iŕŰVˆIˇĽĹ ţ¤Ű“&„[ĺěoFX¨şŮœÍŞ.žÔç*uˇŔMą÷Ů,‹Ďţ1™=wăe2—źŻŁľŚťťƒŠń1\T&›Í†`ŒÁÖú–đşkäWą6 ŠE5JĽ2ľŘŇŢ3DŽĐVŁšuÄk-Őj…ééI–(Ĺš˘8BW#?ůŻ?ÓU’%ERö)ë,E?OÉËSôó˝ÖŚóŒ1dłi‚`k-AÉd$oĚBxs@Ԁ¸>%őÉśLŽĺŐľ˜qn=łN%§ůńŸĽŞâî‰ýTąMŚaJ WĚĆĂx=Ď#Ÿ÷Čç˛+ÖXë<ĘçóĚ Ă\.ˇRěq­ů_ěšn J)ÚŰŰWü/W cAáŠ` GZÂ:G‚%vŽ(IęOIÓ;tu…ŠK›Ą ÄEFnľA°RčşŕbœÂ<­0ZĄĐhĘŠ›?~Q¸uűŕŠ; tf-_ÜU"çCPš#¨M <‡ó ]ą˜8ĆKb<፞öńm•81„JcŃŘXÁtLrZÓŽTŚ.úÚ)”s”‚€*Š_ž4~owDG& YÚߥpő0%…rju—uÎ+š‚ç'=/WÎpkśŘ%ׄŤ„ˆ1‚ ‚p…Żs8Kâ,U Ş nËÁΘB[*ş4lšúÓóey=ŇЇeÓłáasąŠŤçŻ•ąfŁëގěŐ\÷bűy9ßw=żë2žŻĺX_~ű’c×úů•üÎkݞŹń]i—‹ œntŸ^{~ĎŻ°‹‹TŽ~Œ'Lœąx¤ 3´¨1Â5Ĺ­¸kŠŒ:YÄŘE”— |P8|›ťßÖ𭇟xڐX$ŃX ŽcOX2 !.ČŐ3şî…ŁRQĘxŤšŸä‘ ŕ‰‘ˆÎŹŁ+ŹSäü¤š{ňźA1FA„Ë7uëIgŠ9Kفžw?_˙&^gx~*Ś(ˇœTŚąîĆaâs †%­"ÉjÁär˙_C€‘§¨´tą(Ś63ĹÂżü Ľß˝GŢZ”†şďŒ„+ ׅůŠć×cŠĐacĐ*p¨ŔĄHBQ‚ŐŹGl=ëaƒU&­§TM¨.cć=BݖFöXWcş.ʀCŤ,%Ľ(:ĹßóŠĹđôh#SľDńřpB ]ęYzƒÎ×ř#Nj BÄAA¸"cÎ5óÄDh’-Ct?ýx=˝`Œ Ěo0śžĚ1Ž"Ź˝°˜€sňOÚřź> 7ZaŚ}@Š Ä8ávźV‡iv…ö|ÍtţÁr~z–ęéÓÔ˘ü1N„<áҕKřý=%ăpĹSBÍ8|•Ç™œM'lžT/&ŁHC•´m„,9*aHľć(Ő !Mš;ؖp9WÚÄÁ[§"zňšŽŹŚ–XÚ=–jŽB Kh4ÖA.PŤĐ–QXóeKgN‘ R˜Jäxţýż9Q#ąŽ™’âô\Â> šk“ް¤růĂĽ$aDŒAa㶕ru1ŹVx˝ÝŠÓBľZebb‚ááa´ÖŇn×qÝŻçu0==ÍŠS§H’„ŽŽvîÜI’$TŤUŒIKŸćóů —ąoĐ(•ťŢ˛gΜáwŢáӟţ4}}}c(•JĚĎĎÓŢގsŽśś69˜7rÇ=z”Z­†sŽÎÎN‚ Ů'BLš\n.§”j–Âő=e|Lw5>ÉwÍŢ"ÇמŚá๐\P%›+PÜô8ŮŏQŃ<*v$¨HŁ…‰ARĽV‹¨LĚQ[ŔV<Œ.ŕLŒuiiiĺL]XtmA§Ž_ŠHc-~ʈ8žŕ‘8ĹŚ|‚Öé9°Q "ôRѤTłtdĎD´eLXśőhŽOĹôˇćJŠÔ9[n8$:Žˇ<śÓGkÇŮů„Łçc*1ä|Ĺ]›<Ţ>sf.a×&u-ĎɋňĘ]đ @1FA„u­ŞĺušNÄ4--k-Őj•ŠŠ)^ýuÚŰŰÉçó„a(Mw„˜Ő&M›ˇe]­V9yň$ (Ľ˜Ľłł“Z­ĆĄC‡čîîĆZKWWJ)2™LӋfóćÍdłŮ5ˇ˝Z˜Yk˙Ęĺ2‡ćď˙ţďéčč ­­|žŔ[o˝Ĺââ"]]]ĚḚ̌gĎ´Ö”Ëe‚ –––Ð8ŽéěědÓŚMkzkWŽľ–ůůyŠĹbÓ3fÓŚM,EľZ?ţ˜ršŒçyěÝťĎóđŒhP:ő5á:ӝůý=qZĹHŞŮ-œů#ÚÇ~ˆoOŁŹOb"[Ľć–ćËĚĎ,P›ŃNă'ĘŚž0‡FĄë‚bł„śsMQfľçLG’Ą=cx¤PĂhšŐ”6Ś”Ş*ŽOo řŐÇU|m˜XpléĐź?žĐ›W̗#ݐX81cęĎ> í]ĎÓFYŒvtdك†#ç’t?”Â][)f]íUŽß"Ć‚ ‚đ $™ĺiy•$ 'OžäŕÁƒ:tˆl6Ë˝÷ŢËśmۤюś}Ť–¸†řŹíţíęůd˘(bhhˆ ˜ššbjj ­5“““?~œööv&''éíí% CΟ?OĄPŕ›ßü&Ůlö‹EgϞĺÔŠSTŤUN:Ĺđđ0;väŃZsţüyfff˜™™Ą\ŽPŠ”I’„l6ËÄÄI’4­[ˇŇÝÝ-^W×ęüvŽééi–––pΆáаˇĆ2I’`­%IţůŸ˙™ĎţóŠ×œ­{fáhsˆ#\oŞąć؏ǜΈBNűDůíĚm~‚0ů;´>E˘b"SIjžEeÁ^bp.AU.NŕPŘşłÜł•réüşŁz´!hĆ ą…‘Îď2ç­čÍňfßfkatPąTuܝŧ;Ż)„0St ´kz 'ŽÎœfŠjiËčf¤č@ťf×&wOW9|.&N`¨Ócs‡?5AÄAA¸•E™ćMÖóŘšs'íííDQÄç?˙y2™Œ4ÔufVŠ2kçÎUJQ(PJ155EWWccc<ůä“,--ąwď^Ξ=K&“ÁC?ZkœsdłŮ溟tűűűikk㊧ž˘łł“žžžŚ7UEtuu‘ÉdčëŰÄšsçXZZb÷îݜ9s†]ťv‘Éd(—ËÄq,ý 1J)<Ď#œsřžÁqWJ5=“˘(â™gž!Š"´%áĆSŠ4O{ôćbržĂ(…ÓYâŽIL˙č˙…ł3$Ö˘ŹÂ$>ƒS§h‹šĘ¤×U…kzŹhgAY픳i…%…‚bď– FĂř’Ą+†:bŒÚxˆ’oťú|Œ†˝Ö-ËěŞqGąšÓĄ•˘+—Š/FA”Œ^Nە 4_ŢŇÂťgbú šOďđŮÚĽë~1W)ď: 7’}ËľAÄAAŽ‚łÖ€Ű÷}şşşxä‘G6œwD¸ňÁójaćb‚ˆçyěßżŸcǎ177ÇOžŸ–ˇwˇ‘?Lw‹ŃKÔźQÂ)@gq…Qâí˙'ćÔèPZ§ĺ׾C)zť(ƒRQZş*˛(› \‚‘VRj„(.ýăím>[ˇřhĺxh°–Š$ZĽáM>SaE‘ŽŤW­ëęŠIU˘ôľž^°ęK´†|hřÜî,ŸŮ•.ăkĐZ­[I ÇĆJŃ_Bąq¸? "Ć‚ ‚pČd2ěŢ˝[ Żk,ÂŹ6naJ­!Lk‘Ďçšçž{Z uÝ„Ż%đlDčil§áIłÖňZkşşşřÖˇžľb_Ă0löWç i|~šű"\ąěy 7A#lu›cČĺrÔj5Źľčzyó4_Ě#ą[y`ßÝ]ÁŻŹ[…RMsäźĎîŢíĄ[”!iśü/űWh5†§âş cŇtGŞ.D(P @ÉBbë2Ł—ÔËş7ňŤ˘‡ŻŁö“oÓŕŕĜGdawO„w™—-ľJœšŕ3ľöÂk-k˜+ف+X~EkŐz]بÚ#ˆ#‚ ÂĆě11ŽŽ› łş­=Ď#“ÉEŃuKšÚU‚ ¸¤ÇĘZy^.VÎZúэccůxRo)Ďóš}QĽąˇ]’Őâu ÜÔÍTQ3ŇŠp᪊4˜3}…uoĽő×´"]ž˝Zř%–Ú÷aËăÄŐ%l˘ˆmöâĺ{éÉç 3™aI+´SEĹ{ăŠFёŃěęś4łÔ^Ę.‰b¨Tq.-Šu¸éEěŰÇpóĽÔCG)ěŘáwŁ TŞšÂěތ[,cĎLهząă3i˜S%B>zŰ&⷏Łrfç nĄDrv˝Š<YJ÷áĚ ŢWîG˛Í]vq‚ŤĹ(ߐX˜):lŇę˙Ś(Ő÷ ůlîô8ż˜pä\„u…aژđŤŁUœsd<ĹRĹr~)as‡Ć7ŠlTŠAbŠ˙/ˆ#‚ ÜÎJ Î9˘Z ;5 Ĺ2ju¸PëëM°żËáJ•XÜô<ĺlˆßՉ2Śń‘¤ŔAîŹ[:đÁ”ćß>ĚЖóůÍxB”TůĘî„(Qäü´ uŠŚČç•H‘ ,Ö)Ş1ä|EMľQ w“Ém%ŠZ Y_QsĆóĐžf!Ňx ĆQŠ4žvĆQŒ4‹řńűĹ$Ŕß˝ń_łôlt4ęRFŐC¨•V¨ś,Şť ˇTkQyĚ˝#Š0c>şż“řđiô@ŽŁ{;ps%¨F˜Řó ¸š*ą(ß'9|”ĂŰÖO|řô´avôCš–&ë ź m‰ş â€Zâ6üsâÄňޙ˜ž|xŢŃjJak‚™ĺc(>u"Ć‚ wˆá†ƒjš†­F˜ŐyY|• ! Á˜ Eg/T=ZóȬ梟9Ňr Ť?kQUŹĹ-.AĽ˛l 9PIB2_ÄvśƒÓőoJ´AáÎA)Š#”fKWH #ŚK5Î-NÎú<2TfĄŞ91ës˙`…óEĂdŃăށ cs†b¤Ýql.Ŕ(ŘŐíqlĆŁ#ăȅ N ľÇhcyw"`wOLč9޸ˇ?˘ĂoĎúteÎ,hö{TcĹábÂBUѓßŕYkđ .NŇęM¤bŒ÷ĐNbŁq %ĚţĚöţÔFP. CŇ:őpq¤áE3‹ÍMÚĽşíŕ›ÔSŚTEőśAšŠ]BwĺqžĄŸć„qsÍbHiűÖ'­›ćLÖW,TVŞ'ą…só–šrD9rDIZEɢčmӜsh•Ś÷}Eŕą"§ĎF’. "Ć‚ ˇ‘$Ł­˝0ŽçĄˇŕýçďĄďŮŢeŢFV?đšđĐeí#Ľ2ńßýÉóżŔ--AŇx~äę>r$/ťUëÖęfŢxď¤AAnrý%-݌RXIbŮŐ ',ÇĎW™\Hxpś´Çôb˛ž%ç[ş2 ß1ÔŃWH•í]1ąUžcwO„uŕÇh_ŒRŠĚ˝5ŒrřŹá‡QđŠÍUB/}`ŤcĄ}ĹŃÉt›6q‚ú˝|ˇĺ\&DUpI*śÚҍßSŔ.UНůÔsĽn`¨Bśőa¨ĐOc}âŐ×AňţhϢˇtƒÖ¨ĐÇěقęʧůc˘$MŹUşŽľ˜Ý[PĆÔKr×ËR{xižŁ ;Ż9żdIZŘńţDĚžAĂŠYKhJ)|ُokŔţ!˜/[˛~*ÜŔrb€l 0k-bŒ ‚přč;đţä;˜ďßżąĄJCźď}2’ýˇ¸¸QťNh_lŁ* ľž ŢżńšÖZLáĄVŤr~jŠ]]Ý<łĎňŢdĚž8°5"ď/çS¤ÂJăĘÖßűžŤkĎsMżTĎŻżW÷]sů !ćC›^~ߎ˛žâG#Ţ”ˆň4tćšŢąő›*ą˜=›Ą#ň X‡Ů?‚ę)ŕ<ƒ W`S˙ƒƒ[ĐÚ[Q¨ńbz‘# ÝqÚ ˛:-&°˝P×⌮—äžŘˇ+­ńôÖú=î’{֚´7őF•>};"bŒ ‚pIX‹‹ă´˘Ŕ&ŮĺWc]ľržľ$X+áI—‹Öß÷ńƒĎóXZZ˘łł“ršĚĚĚ4CCCřžĎŘŠ1ĆĆĆXZZ ­­|žŔ+ŻźÂg?űYÂ0”Ć„‹ŕű> GUšB¸N(Ľ0ĆMu>n IDATP(ŢF_˙ q_DźX.Í|šu›ö@Ťă†ťPťh|ŽĽ4Ć3äry<ĎCëeig=ϝćRjĽ róƒ‹í˘şěc)ܞˆ#‚ Źoh9GGLž:ËôŰďÖ˝eTÓk}ĄšąňłľÖ[˨S-ĎěÖچ[áćŤPÎâU*ôMMÓ#‡l…AŰŹŹÁ…’ó}ßcǎmÚr<ţ™üň?~IĄ­Ŕ§>ý:ÄŤŻţŠí;Fزe(ŽŃŮŐNWw{×_ÝťwKƒ WÔW×ę›”ÝjĽ~ŕy†j3…ÇÂőé{J)ÂL†ŕ‚yëův˝ÎąÖÜcRŹO¸1FAXĂBŞż¸Ô@ŤUküô'?㥗^YSrŠ›r-˙ť |vŠe×űŽ•ŸiçČYËłĺ2ŸwŢڋÖ˟A&“áé§ż‰çů´ˇˇ322’ žÇŽ]ťH’k-žçńčGI’„Z­ĆŃŁGůÜç>GGG‡4¸pE}uížyűœČ-Ž‚pCÎąžO×:§ĚęýŻáNFÄAaĽ!śjđ`#ŽŔÝM8œĐ€o-6IäŽaäŽöşŞŔp€Eišąä™s—Źb)´6í1ŤçY›ŕœĹƒŽŔOú„Rk-ľpýsYXi})Źľő\VI˝ĎJŸ„ŤuNވ|Fâ#ÜŠˆ#‚ \1žďłmŰ0đOłoߎŸ8É?ţĂs9üÖ9ÚŰŰčÝԃ^+Žƒƒ˝ä Yp0==Çá÷ŽR,–Čĺ2|öłOđľŻ}üâŗyţůX\,Š̆¸x’І'‚ľŠG‹1š$I˜Ľ\.SŤŐH’dÝ<ÖÚŚxÓŘfoo/ííí"Ę|)Őú4Ü]2ĎQcL3Áo[´fE_áŢ5nňęD‚pť!bŒ ‚pĹtvvđőŻ‡žŸLčÓŢqI’0>ţߙ››C)0FŐËW.ŁUz ‚çžďŁľF+ĹŽ];yöŮďĐŃŮÎńď<ĂŘŘ)ŢúíAwŠÜ0 Lwôp÷˘ڕU3ҁěřř8űˇËäÄď˝÷ĽRŠŮ†jEúQˇ"ŠŇœĂó}ţôO˙”gŸ}–|>/'…p‰AßÚI<[ó]jýT€W9A¸ĽîL7 j“ ÜŹˆ#‚ \1ÝÝ]ô÷őâ{­Jiş::čŰ´‰Ĺů”S(×HőŇZÂÖb›ÎŻOʁVŠťví"› Roa°cű6žsëěڃ5Ő*EˆűĚzƒŕ†gLĂĂ`ňÜFivîÜÉŰo˝ÍĚôLs9­u3źŠą|ă}ă3€ŁGRŠTČĺr×=!cŤQ˝ŤWg€śœ;ćň*żHˆƒ Üz÷ ADŒAŽósóLMMącÇ6´V$ąe~~‘Ů™Yœł\ÜGE]^ŕTZ˝éäÉTĘ ŔZKĽRăôŠ38+OÂŻqóţűďăyĽRŠ9Ŕľőön„%­cŸ)ĽVˆ;Őj•……´ÖT*<ĎŁP(P,ń}ŸršL>ŸÇóźćvľÖc˜šš˘ŻŻŻš­5Zkě˙ĎޛĹH–w~żs׸ąošWfeÖŢŐ {Én6EľČ!G@3´dŘÄĚŔÀ^ćÁ€aĆ̋_ô`=~óŔO3@˛âŒHI#‰C‘MRjŠĹŢŞťŤŞkŻĘĘ=3"2śť?܈›šTVUWeeUČĚ7îrî9ßůŸo‰"Â^ĹŹvťM6›Ĺ0 t]§ŮlŇjľ°, ×uŃul6K*•buuß÷“ź8ýĎő'óľZ ˲ĂÇq’cB`Y‡ĆôĎŮ˛ŹťŞ8Ľ¸ż Ú^Őż …BĄx’PbŒBĄP(ž0kkëüٟţgňůgΜâʕ+üٟý9ŤŤkÉd~/LÓÜą-Œ">űěüÇÂoüć?$|~ú“ŸńŮg‚ )Ş¤ŘŸý'śąxâ>—.]˘ŃhĐívżđ„¸ÓépţüyÚí6Śi’Ífét:tť]lŰfuu•ŠŠŠDiľZ”J%ڧ§šqă•J…ľľ5.]ş„Žë :­V+F,ˢT*qäČ.\¸Ŕââ"ĹbĎó(—ËŒŒŒP­Všuë‹‹‹dłY,ËBŽë‰Đ˛´´DťÝćȑ#X–E­VCJ‰Žë„aH¤ÓéäNœ8AąXTëŔÚ¨BĄP(OJŒQ( Ĺ&Î_źĚ˙ţű˙Śiâű>ÝŽK… žŮbłŐŮV-%Ž”tůʍ! ß@Jڝ.?řáŸó_~üQáş^,¨9Ű=1–4˜—c+´ŁW˜Řł%‚=Ă>¤ŒŤ] r‰cű´;í.l×Ü4MĂqŇé4Íf“vťM¤R)ş]—l6Ç–e%Žëtť]|ßÇu]nÝşĹňň*Ĺb‘d2–––Éf3är9\×emmńńqVWW“ÄĂ+++‰€Ó?Žnˇ‹ëş E‚ d}}ééićććhˇ;ADŁŃ¤PȓÍćY^^$““SÔëuZ­Fß÷WbĚ´Y…Bqđ<ȰżĂđ,ßďůÖ~čNçó¸ôOÂ9(1FĄP(‡†(’DQ@˝ŢŘ9č2ŠöőŮNF´Űí$‘ŹâÁBýТÝ^ß6˛ľM€źxÖĺ{żUçă§ď:;ҨڜÍôô4şŽÓjľ¨×ë@œ°š^ßäÔŠ*Fƒbą€ÇqHĽRT*>˙üsĆĆĆ0M›ršŒçyäó9JĽ"Žă ë:N›t:aźđ „aČČČHň=ét]×'•Jáyś˘^o0>>F6›ŁÝî099Iľ:‚Žë¤R)„€|>”…B‘bąŘˆş„aD.—Sč˛ÝřÐ(Š0 C 3 Ĺâş.Žëâ{aœwmPłĚÜž}.-vü–eb§llËz$šÂPâš.ÝŽ›„ĐîzĚŰ6kš†˛HĽěCŽÚĎóW<ô‰ÂáDČŚi’rlLóp÷›áş]\×ŰĘů%â%!ÓěľŰÜ×.QbŒBĄP(ŠC+śěg´ {Çěżr˜xŐôŢ^khœżl˛Q7ˇźbvcY###H))•JLMMÝՄüÔŠSÉyLNN˝^Š”wTăB011‘üoŰöĐgJĽĹbq×Ő¸ÁďÝ~ÍŻă`˘XUFůáľŰţ„đŇĽK<óĚ3JQ(h’żŮhRŤ×čvş=É/ś_Ó4H9…||!‹Śiň,÷sŐ6´Z-\×MrÝ Bě”M&Ś\.c§ŹGŢ…aH§ÓĄVŤŃjľü`‡7Şiš8ŽMąT$›=¸ë}ˇô…¤őNĎ󆃄Ă0IĽl Ĺ<š\.ÉíśŰřŹÄ…BĄP<*Ӊƒ\fꗐľ-“LÚA ącAIlűűn^{pű %Š(Č"„<ő-d7ŁeŻm‰ŘŔݖ•H ŻZ\žž' ˘]*ÚěVŞxčűîc•ëNbȝD•ţśA ˝öżý¸fŇqĺĘŽ;–äR(o’\ŤŐ¸=żHÔóbí'lďżŢ˙{°Ýďš Ă×őhÔL3EžP@×îł,Ľ$–—ŘÜl†Q˛= #Â0Ŕ4ÍÇE’0 ’$ďA3 ÝjÓlś˜›Á4ͥʁjńIIˇŰe~~žN§ߟ0" 名ŽŰĽŮj211AĄP84ž=ýs¸}ű6ݎ‹ď;B˘ăţąjcłÁ‘#G( Oüâ‡c …âń›jô̞”mó_ű:/źú2mÇá$ÚŔąIäĐ˙w˜ÚěJÜů´ĺÖű“÷j@Ąˇ;LýçÁßđhŽÓcƖ§GO֒ť ;?˙öűŒO>ů„™™žôĽ/Š ŁPýôS^ýőd B†!Íf“O?ý”šš9FGG“ąÇő\V–WCځ›ąˆ˛¸¸ˆëşČHĐjvř裏X^^FJI:ćĉĚÍÍ!„NŕG,/­`Ű)2™ôĄhc˛ş˛Nť¸}ű6~ř!žç%ÉňGGGyć™gb/ÖH˛źź‚mŮd˛é'úůSbŒBĄP<&DRIeˆ&4ĚZ-Äe}›ăė_ƒĂ8A•l6 ~ů!R5•] şíž#b…ďNťˆ˘ˆFŁAĹ9V<ĎŁŮlbš&FĎóhľZ†A†„aH&'ć헹–RŇnˇY^^î%ţíR(p‡vťMłŮLD]×q]—t:M6›Ýq,+++A€mŰɊœ”’ĺĺe2™ ›››H)IĽR¸ŽËČȈcş‹"šÍ&şŽ366†Śi´Űm2™Œ ť~I‰.ú]x,(۟9ßó‘2Ş/^źČĎţs^|ńE\×壏>âíˇßŚŰírîÜ94MăěŮłIžŽţXa"Vô“ľ÷ĹvĎó¨ŐjdłŮ‡jBřžO­VďyÄß{ůňe>ýěSfŚg¸uëgϞ%“ÉqŐżżţëżfeu…ů[ó\šr…L&áżýmlŰ& #jľ:ĺreOą˙aÝ›››tťÝD\jˇŰÜşu‹S'OŃuť|ţůç\¸pßýÝßE×őžŠK§ÓÁqR‡˘ďětşl67“qwii‰(Š’źrým qED$řžĎęę*™ěĚí%Ć( …âáČ@(%Ÿm4řŁËWůŸ_~ž'ĆLȒM×0 ă¤(АşN¤i„Şšě+¸ ŽĘ~y*ëlšBH„Ř[˙ž[4Mò,|ßO’ř–ËĺÄĽP(°źźLŤŐbzzšnˇ›îőzbąH†ÔëušÍ&–e%Ť´š\ŽnˇKŁŃHź)lŰ&Š"|ß'•J%Ożlöúú:ŮlÇqXYYĄZ­âş.­V‹N§O&ÂĎóöĚ/Łxř,..˛°°@.—ăʕ+‹EŇé´ş0w ˆ$ż÷Ësüö‰#œ.–0„P~ŠťščÇ^Š.‘Œ­×oFŒŃjľH§Ó¤Ói666¸xńbOLI[Ż×štéǎăʕ+¤ÓéÄËćůçŸg||<éŁ}ß' CtĄ=4AŚŐnř>}WĎ ¸rĺ );Ĺ'Ÿ|BŠTÂ0 ‚ Ä0␤|>Ďää$v‡/}éKœżp>úO žu\×CF2ůß÷},ËbîŘëëëœ?žľľľŢńŠŢx-i4ę ůC!ĆÔj„A˜Ř%šŚ111ÁóĎ?mŰ¸Ž‹çyxž›|& C\Ď{âŸC%Ć( Ĺ!'Bâ…!ż\Yá?^šĹż8{ 3‰>Ě&÷ƒœĚŞŠĹýqŰó´ žśľMöçIŞĺ¤DF čtĄÝ‘ĄőŢ'vě{(‹ţß÷ét:Řśă8CŤ‘ŤŤŤär94MŁŐjaŰ6a˘iĽR)ůŽt:çy‰§L2`Y…B\…Éó<,ËJbçűBP˙8RŠT’Dxmm ӌ+5˜Ś™ěŁot†A*•RžMÓ8}ú4'NœHڔ ŰK×řŢŠŁü›O/đ[ÇfxedKÓЄö€űaœF_´FĆýeY?~ŒĽĽEœ”ĂÜÜ—/_N’ŻŽŒŒŕű>/^dff†Z­Ć|@EüčG?âšçžăŇĽKT*&&&Mň–ě}žO´-Éää$çΝczzš(ŠřĹ/~Á›ožIĄP VŤŃnˇ)‹čşÎňň2…|ĎópgË‹âąńŕŐ@öM¤HŽŰĘĘ ?üáń}ąąąděěçtp]X>,\ĎJ‚†ĚžšŢ”ŁP(Ї<ІO×küĺÍţŤłĚćrh<(É(ĎGvşťˆ’ŘH Ńă…_` °ÓPӑhR˘BŻ@ eŽ JŢ{WŇÖ.âŒ&Ż˝ŕrńrH1Ňu5–×t.]׉")w&Îí'vÜ­l¨‚\.G&“IJF÷?_*•ČĺrčşNŠTJbơťkšFĄPHJI÷ N]×ÉĺrI8Ňvcmđ8űՕ&''‰˘()›Üd&''QŠ˙ł[‚GĹÁ ëúĄ*'ű8  Ál.Ç}bŽ^ż…Ł›|ŠZQBŒâŽž7CŽX“üh"¸Ç!—Ë%^"}‘4Š"ŞŐ*.\ RŠ$a§Ůl–z˝NEÉóœě÷!*ýDťýęIý\0ăăălllpěŘ1>üđC|ßb~uu•……E(—Ë\şt‰gŸ}69v-v}dϔHĆDA>Ÿ§X,bYéôkkk|ýë_ß1>§lűĐ,*¤l›n§;TŐęęŐŤ´Z-t]'Š"ÖÖÖxţůçw=ó'yËć¸î¤ˆ„ öŞhB$+UŰ+!‰ŢkťUO¤čťœmľ(zĎ]M@4`yŃç—TƒšOqF˘ąRŸ˘íÖɗňD$•é29 kkuŚŚŚX__G×uŞŐ*őzŻçBě87oŢşoƒ uˇ‡L zŽěghő˝#Eqy1úűÜÇnß­DĹc÷üöÚmJ7°4ŚßŤR˘Ú˛bŸ>Ń0 씍ś)ˆzăi_$O§Ó˜ŚÉŘŘĺr™_ů•_áwŢÁ˛,Ţxă LÓ$N333Ă“““IŽ×uŠT*}žŔ4Mtýá&ÁÍd2˜Ś9TŠgrr’—_~™••o˝őš\.Y08rä­V‹k׎1>>NŠTbzzzŕé†ţhüs…Ŕ˛L„ŚA‡ůdłY^}őU~ň“ŸĐh4˜››cjjjÇ"DţUS*–J4›-ÂŢ9=z”őőu“çž{Ž#GڇěŰśžř1Z‰1 …BqČф॑  䏯]'cLgł˜šŘCşxbL˝˙чíú}‚۶͏GGš–I!ČxlŮ  ľąÁ›ľÎ@’ŔƒŒ•œÄCăŃ­`=.lw–‘`ŁQ¤Ůöhť#a@ł˝Že 4­AľZĽŰ=Ł*• QaYV’ße~~~ÇýŢŻÜôýLô>”řňxˇaEœŔ÷fłÉ÷ŻŢŕŐŃ*/”Ü{Rń˜ÚšF.—ĽQŻÇšIdŞôâ‹/&"úמöľ$LôčŃŁ‰ŢĎű1111ô,žüňˉˇc_ °,“b)żŁăƒĆ´,JĽÝn\ľ§X,ňúëŻă8ét:IâŢ?‡\.lj'¸}ű6ĺrĂ08zô(™tD|}ŠĽ†i ťĺŘýŠyÖ7Ö)ăE…ŮŮYĆĆĆp]—\.‡ažĄ‚TĘ!í8‡Ć3ĆIĽČfłIő¤BĄŔ /ź$ňľ,‹'N ŻeYTGFžřgP‰1 …Bńˆ1YÓâÍÉ1R†Î^şĘż|á,Śf>܉CRB(!Ü=ţ8ryt/ŔƒSnHxßIóňęŽěkÉA)ć)Öeöó8Ůş@ \ż~“z˝ÎÂâ@R)#Š"~ůË_&%Ś—––’˘0 YXXč­x)qCńhŰűÓ(ĐxQČżťx™ˇ&Çxmt”´a¨,[Šť&N3:6ĘâÂ2žď' Vˇ!}fť˜łß3iš&ăă’ˆ[ÓĹb‘nˇK˝^HBŞ4M-úÇW(ČfłÉyÇ!I`é´CľZ=zQŸŚë:SSSܸq“nÇMŽłŸ\yđ>iš†išŒŒŒ`őD§ĂĐ'ęşNĽRÁ÷}šÍ&RJ*•J’,żúżMÓd||œ”RbŒBĄP(Á$ptƒŻŽń•ń1śY‹w?€×,ƒŤi‡Ž&DČ<ˆ„dŲ¸ćŘäCcŸ&Ęq"sz­N×í…ŃA é:Š”MąP$—ËHČL?ŹhllÓ4â˛ÝAĐKJ÷˜ŚI&›ĽT*bŰöŁĆm›é#GX][ŁŰé ”ď_o]׹m;ÎɖĎ'U•…ÝĄ RŽÍÄÄ8ŤŤŤtş]P˛ÁśhŰ6ĹbżÍ<ůIȕŁP( šâzŢ×1‚(Bô’ćŢqbĚŰ)R6Ql‚=„ÁSC É…gÚMô0şĂ„#N늆]˜Áßńö¸ügąTâ_ýëT_¸ŸzşĄUÎP(ý˛źqjńT{dZżĘŠŞž¤¸?â<1Eňů8Iď˝TáŮËűB×u Ă8ŕź%Ąe›ŒR ĘAŰ“ţB/<‰^‚ţą–~EÓ4ҙ4GœA$^ŤýëßĎÁ_ďťż/š&pŇ)ŚŽL&ç0؟ďŢfäžăŔăŢ÷+1FĄP(ťŇ‰€0"Ű3ńw^ĄŁëÜLĽ¨&RܛGÍ˝ äɕ´Ă’es´Ű…;LöĂ0¤ĺÔÄdOad0žź?ŠŐD잝6÷ú=AH„=Ϥ~|˜ŘÖbÄďóÝ}î^ţL }ˇß˙E÷sˇÇš×gzßNƒón÷#îńő{˝Î÷˙<ß[;ŘyMÂ0ތĽ*_ąKU(îŇ;sĺ&AćNÇq؅˜'ľ}”ŁP(Š]ĘbÖa3íŕŐ6éz.M×Ý6IDB°fŹF<ÜcL)™ßlrŁą‰>$ĆÄIdlÝ ˛q-“LŠ€ĐԀżżAÔŻz1^¤ĹaĽ/Ŕ ôqţ#eä+÷GÔŤF¸[˘Ţý&˙ű úšŹx?a‡Ą_ŮëžČy=Čc‹zůĺîtĂůęîÜ.Cĺö:ß'%Ć( …bŁI’2 F§ÇYÔ@ŽE¸žOD8]-řL]Ł ‰}ö ŮţŰśéÄysş€–źcëˆ" d&EfŹJАCBŞU˜}Ě̞ĄłÝ`{܅aAn÷;š×ëťíWî8žťŰŚxj[ěŽĎłTĎšBqŸxžÇ•+W¨Őj¤R)ž}öŮ}sŚDQD˝^oŠĹ=÷ť´´Äččč# ÚŘŘŕŇĽKčşÎéÓ§Éd2űö}Áŕ°xĹ´Z-Ž_żŽëşŒ399 @łŮd~ţ6'NżŻŹŃv–––X\\IJ,Ž;F6›Ý‘ěżŮlŇjľ(—ËA€‚T*ľçľ˝|ů2är9fggq)%őz×uSbŒBĄP(žěÉN>"}ü(˓m,?@ʨ—Ś?A. zč!Ańˇj#y´=ź6 MŁd§Č›&ú.Ľ9÷:ŮÝíÚíˇíNŻ‹{|˙~Ű …Bń…GW)šyó&†aPŤŐp‡v]pýúu2é ź˙!†aríÚu ]gvv–Ď}Ě+/ż‚n踎ËŃŁ3JŒQ( Ĺc–%ˆ &2™Ř0‘ ĹÖÔXîřÔ{}Ąč×J€Q( …ânÇ՞—Âôô4AđýďŸˇŢz ˲řđƒŠ×ꏯo°žžĘŘŘ8ŽëqůňeFŞ#\¸p‘ééi<ĎçâĹĎi4,..Ňh4řú׿ŽďDŃŁől”RŇjľ¸téG%Š"~öłŸ‘ËĺXXXŕóĎ?gddÓ4™šš:0!ă^( ĚÎÎňŢ{ď111‰eÚ,,,099ÉóĎżŔĹ šqó:?řÁó /Ř9H‡:Ÿ:uŠFŁÁ•+Wř“?ůNŸÇś-žôĽTLŇuÇqx˙ý÷ń}Ÿ—^z‰fłI.›gjęĹb‘ĽĽ%^zé%žóď0??O6›ĽRŠpůňeršcccüíßţ-ů|ÇI“É:\¸p &''Ĺuťd2Ňé4étĎóđ}Ó˛ëçN‰1 …BĄ–/†’‡ˆ}ĎĂxüťnU7VĄx\űĄűx]ĄPÜۄú̙3¸Ž‹ă8dłŮ$'GŠTć׿ů6şŽEśm“Éž`vî(ŚiRŠ” Ł)%śeŃív“ňĹ]×Eă8ôüŇé4_űÚ×H§Ó˜ŚÉÜÜǎcccƒt:ÍéÓ§Š×ëäóůCۡäóyž}öY<ĎĂI9ąašč†ŽëČ(˘R-aŰöžƒaœŁVŤqćĚŽ]ťĆoüĆo𳟽Ă÷ž÷ßŢWےR•ˇV( …âiˇ7ŸűTSˇ^ĄP(Ч]×9yň$N:ÍWžňZ­&Íf“(Œˆ˘ˆ|>O­V# C&''ÉesÔę5Úí6–eŃjśgvv–|>ĎË/żŒŐËŕy^œh0›%Š"ţâ/ţ‚ŮŮ9l;…”ňž …BĄP(ž”gŒBĄP(O1B,ËâÔɓĚÎΑÉd¨×8ŽĂńăÇIĽRÔj5t]gbbMÓz• \N:…mŰ=z”ĽĽ%Ž]ťĆěě,ŽăP,Éç󌏏ÓnˇůůĎÎďüÎď`šĘüP( …BńtŁŹ!…BĄP(žrt]ç7žŠm§°m›|>‹çű”ŠE&§&ŘÜܤP( ë:ö ě”MŁŃŔ0 ů“S žţőˇčt;źöÚŤ¤3iN>†Á… çyăÍŻ22ZEh*üMqgTéj…BĄP<é(1FĄP(ЧMÓ¨ŽlUÎIţNgŇT*[ň˝JĹb!ٖÉĆÉx+ŐáJĽRœ8Ţţő_#“É$^1*ěHq7ěÖNś 4ƒďQâBĄP(”ŁP( …šěEŃCH$RĆä~IÎ0 U,Ĺ>mr÷íýęƒU4”ř˘P(ŠÇ%Ć( …bˆHJ6}ŸMß§?ÍхFĆ0ȘF<şËý4}Ÿv’ˇLÝx “đPJ")ф@ťËcRě6ń“ă꺖üżÜKiJ…âÎírŤl}ü[ ´W2ŁH>1%N‡°F×Áw54MCůó)O5Ś(1FĄP(CóŚďóď/^ć?\šJlz ň–ĹăăüăăG™Ęd0ľ;ă‹?Ó |ţŕŇUţôú-ţĺ ĎđĆřŚ~ˇƒ›L&_{qťŐ泍3Ů Çň9L% ÝÇAρݪ !ˆ˘¸b’ŽkDQČíۡŠ×ëD‘ě݃ĄOě˛më5]טšš˘\.ŤÉąâašČ˝śŹăűÁP[ü[Ąx0„Hżt]¤Ś!•ŁP<%CÍÁVbŒBĄP(ś&ńÄ+Ň^Ňô|žqd‚1Ç᣾ ~4›bĘ⟛E°ĐîĐöCŠśÉXÚÁÖ ‚(˘áy,´ŰDRŇö:A€†QˆOÄBłC+)Xcé †ĐˆdDÝóXjwO§(Ú)ÚAŔr§KÓ÷É&SY‡ ’üĺ­yţýĹËź11Ę?ž›ăT)G'šÝjJÉHĘĄę¤0…öԅĹě5!í 3ť1??Ďď˙ţďsăĆ Â0n{Lrˇ†Áwżű]žűÝď’ÉdÔäxčhšF*ŮŻâáőĽ€eDŘF„Śí&R+Š'öá?”ŁP(Š='îߞ™áľŃ ?ž_ä˙üčŽo6šŃlň׋ËüryśPJYüƒ™I~íȡ›-ţÝĹK\ml’5-ź($”Q,đD?¸zƒwn/ôēߜ=Ę[“ă\m4řĂKWšÚŘD˜H;üĎ>CÖ´řáő›źť´ÄŚď“6L^­đĺŃ~v{‘–ďóîŇ ĄüłÓÇřƒKWšXŤIIŐqř§'OóĽjý)cÚÍ#fˇ÷\şt‰üŕ,--†a"´Üío€ŃŃQžýíoă8şŽŤ‡HńĐúڏÝAœ—hg[T(pOzpł3…BńÔ Ä…BĄPě9‰ďŽË…ZH RşÁť‹Ëüéľ[T‡×ÇŤüřÖmţäúMŽdŇüäö"?_Xf:—ăH6Í߯Ź"DHŢ_YᏎ\'kęźP)ńÉz˙půŻŽT8żQc­ëňRľĘRťĂ+küđÚ Ţšœä‡×nP°,~}jŠ×6¸\Ťó+Ł#œ)šXkp"Ÿç+cU>XYăo–9U,pŚT䣾 >\[ĺő˘2Ąďp!žŔúžďű„aH…#S˘dgU !@†zž4žçEQďsív‡ {aPRFäóyZ­6AE’tÚÁ0ô$´)ŠâÉułŮ$NŁiŘ {Š˘ˆVŤE6›Ĺ4 Â0Ę"„a„ďű´ŰňůÜP.)%›››¸ŽK>ŸGÓ´D8ň}Ă0BCÓšśĘľ˛˛F>Ÿ‹Ë{wş8N Ó4Ń4ŃËa"ń<Z­F>Ÿ'•˛ˇ.V˛šžu|ívMln6ÉdŇdłŮDhŘş7$Ÿ˘ˆľľu¤ŒŤT™Ś™lŻ×똌IąXxŠÄˆţuG%„V€Łźb …c …Bq€ćç˙öŢčBF’ńtšgJţ~yŐN—˙ńĽg9S,ʐż¸y›ËőM~š˛N7 ůggŽs"ŸÇđ—ˇˆ¤äŻnŻŕE!o™áÍĺb­F'хƷ§pś\ŕ“ő:×6›řÜl6ńوPJ–Ű]ŽÖ[|m|Œ7&F¨Śmć[mţüćţřc677™˜˜`nnŽőőu*• ů|ŽżúŤŸ055EŤŐBJI>ŸÇ0 >ůä^yĺÚí6'NœŔó\nܸA6›ĺoţć]žńopőęUnܸÁÄħOŸfssMӘœœäÜšsX–Ĺ•+WŠT*¸Ž‹mŰŹŽŽ2::ÂÚÚ:gΜÁó\>űě<ŽëRŠThˇŰĚĚĚPŻ×Éfł4›M&&&¸ző*ĺr×uń}ŸO?ý”ăǏłźźŒŽëDQ„ŚiĚĎĎsňäI …üS#Ć1,Â(ĹÁŒŠŞ) %Ć( …âaOv€ÓĹ<#ŽCŮśycb„gĘe>XY!ą5˝7/×@ )˝ĎBCô_믑”†ŚČˆŞ“Â#ź(äß^źÂĎn/1ËĘC‹ß;žvřŢŠźˇźĚšŰćß^\ĺ˙˝|•˙őŐ#9  hź>:ÂÚ —OÖ7řpuƒĎ/ńě­˙ęŐHÚ@E–§ň~î9YÝš]ł ˆ$፠rZ ÍIăş.Q%űi_ÄÍ;¤fË´Ż­ĂbŒëz4›MšÍ&Śi"eěyRŻ×i6›xž‡ďűĚÎÎráÂERŠétšZ­FˇŰĹqršBšÍ&›››,..’ÍfŃuƒőő –—WBăÜšs¤ÓiVWW™œœ¤P(ŁŁŁ|đÁtťŽ?A&“fff†ĹĹE*• žçąşşŠeY >ţřcŞŐ* xžŔŇŇ2łłł yŠĹkk&''ů裏h4LLLĎ盕•Â0¤ŃŘ$“É  ÁfŁI˝^çňĺËźř⋼öÚkœ?žŃŃ‚ äňĺ˄aH˝^§ÓéĐl6Y]]ĽÝnłąąAš\fll €ĹĹE&''™ŸŸ§P(đꍯ>e^1Ăä_’]ĄŘŁľŠśöĆ(uŸflQbŒBĄP(ĽeÄ??sŠŻŽĆŤĐ$0Ë1 ~tkžŤ#œ[Ű ęŘLeŇĚäłÜhśřŤůŰÜ.¸PŤÇyźP-ňáÚ ŽŽă:ďÜ^bÓóůŸ^zŽż[Z#cš|cj‚Ëő×-qEŚůV‹gË%FR6˙ĎĹŤl¸]Ú]tM`j‚ŰíŸ×ëx!t‚€7'ĆŠť.?¸q“+:^’VĂÝ=šU+ĂÜŃişÝ.őz×u{ФVŻłÚ¨ÝaąXR*Éĺrřž$!CSSSO˝Ţ Óé011N§ÓEÓccŁř~€i8Žƒ"n˘($ŸĎ“Íf(‹ŘśM>Ÿcee…ŁG˘iÈ?W,HĽlJĽSSS¸n—ršŒa†NľZ%ŸĎąąQĂq …śm3>>†ŚéTŤąÇĘĘĘ GŽ! ƒž`“gjj’ršDˇŰĽR)“ËĺÉĺ˛TŤUÖÖ֘ĽÓéP,p]”㠁bą@ĄÇ0tt=Ĺää DQÄÔÔ$­V!Ŕ0tJĽR/TJ'NS*•’䎓˘Z­†ŮlŽ\.Ůz’&ź}áOÓ´ťčŞ”ˇ‚âáMȢ(ŠĂ!% U[{ĐĚ`ĺ?čŰňžűŽAĎ]÷łŰ˜ő žžčžîĺó[°íówźť}ţ^ĎO~ÁĎ?¤ď*ŻBĄP(’ĆçYŘ6–îx  Đ&C’ˇ&ÇXîvřťĹUŢ]Z%c|çčΔKX†ĆşŰ姡řlŁ—ŔMޜăVłÍ; |źśNŢ2ůÖĚ$é4ŻŽVůůâtĺiȍ^4LMCJÉ_ÜźEřaÄWĆGxŽ\dľŰĺTŠČűŤët€zę óíď,,#ä “ptšŹiŠÉÚŒŕ]WelÄjšNĘN‘Ëĺ8{öl&đŮůóʟű`O‹%NsâÄń-ŁXŇË˙ç<Ů=Djg~•ř-21´!ÎĺŇ?ţ|>ĎÜÜěƒ>Ÿ?Óűź¤R)Ĺíˇ×–Ÿţš8Ă `ŻMš\bjjrhż333LOϒjľšœž‚ššŁĚÎÎ œóÎ*?ýź6BhLLŒ3>>śăűďVt:Ż'Eˆq]—k׎qüřqU&]ńH‰"‰ëy@ˆĐÄĄcžčÜűPŤ]×Ń5 M×˝…)ä} RĘ8çYőÝ'ßCF r=¤+ŤL%Ć( ĹÓ4¸ôĄžĄ#ˇ-kŽĄóÍé)N œ(äˇŮC‚Łšß;yœ7ĆĆč„EËb.Ÿ§d[<[.óťĎžĺVłIÚ´°5Mßçx!GÉśřoN畑20$kœ)ą ďŸĺĺ‘ ~‘ˇL6}Ÿ˘e3â8üö‰Y^­ŇôCg6—e,íP°,ţűgNąÔî`ë'‹9ţĹ3§¸ŮlIIÁ˛8]*öBŚÔdnĐ`ö~oˇŰÁśmڝ8TŚŃh$‰~ççç{ JějvoŸD‘J7ť‰%}t]Úť6ť‰ăôżçIRĚä7˘ÓéđůçŸ333ƒŽëJŒQ<2ü dsľ…ĐEoÎ{ďß˝uyWąy°żŽ˝ÄpŸŰK2,wőˇ^Űgţ>řý÷âř ö8~1ŕ[‘źÖŤp¨™´E6“"eŮńóŢ{÷ݎŰRJ") ‚×óp=Ÿ „AřŕĹ1pvťŹ%$gú°ő‘^%š84V‰1M?™D‰1 …BńÔ(1’˛ˇň$´c¸`é:gË%ž)—v5…LM0Íp$›MŒ€žŃäčϔŠœ)ˇˆń_ciƒŃôřcëH6Ñlfčpúߝ3-Ś2š3B ‘15ž+—yśÜ3UEÄŠbž“ĹÂŔůHĺVžŻ!ťˇUš&’ˇýź.–e1UŻłX[ÝUˆŮ.:ô'ŮýŞFƒŰ÷›h÷CV´ž—Ôp{ÝŞ°t7űŮ^Šhűąô˝uś Ä…;‹1—.]âÚľk\ž|™łgĎŞ‹˘xd¸nŔ'—6hu=dô &˝=Eî"ŒˆÝühZü‘ô#b@ü”;Bh;ú@)âümrČóp[_)vďÇĺśCßMâŮ"´Xdś-M‚ LŞŢÉŃç—ËeMN-05’ÇqR†ąŸŠľC< ƒ€N׼h˜ö&:F˙ääžÚÔޡGŢA]Úe|î>2ŠbąIˆÝŐ­íJěî>$ďŹtéşN6›‰ďŒ)ŁŞ‚jŒy\Ći%Ć( ĹS3ëÉ/ d´M*Ů}ěßiölƒ{˝KÜńżpy§Ď [+[ŻiťîŠí܇bö50vľ7zł”Íf Ł—dccƒfł‰eY,-/÷ĘXďnцaČÚÚQá8N’$w||œz˝NŁŃ ›Í’Íf“ĐÇq°mť7éĐÐZ­ĆÚÚĹb‘fł…”07w” đşí4ť]ü ¤˜51-MӒçýn<*eá‡]/BO•ŃĚ,š<đĽŢĹiľšl6›8ŠA˘ ­'6EIhÔÄÄÄďű7˘ŚŤk:)'G†tť]\7Ŕ0 œ”ƒe™Ccŕ˝äŕR,JŒQ(Чm".eěÓÓ*ú˘ŠěUC’wü|źú}0ey×ÂĎ^˛ŒTaGŇŔťĂ}Ěfs”ËeÂ(VÚí6N‡|>ďywL˛Ř/Uíş.őzĎóĐ4-)Ó\ŠTX__gqq‘t:‰–eŃjľČfłIuĄ ¨Őj˝ź3:a˛˛˛Âňň2šŚaYśmÓétČĺrLLL$ů,ËJŞĺóyÂ0$“ÉĐh4H§Ó´Z-\×Mr ÄÇě%ůiGE\ťv›7o2;;ËÇL*•âčŃŁęâ(IŸůĹű„0 w ‹”=‘#^üZ2RßqÜ[IŹ’qśďÁ!ˆdě “ôÝrx$–Ű>łăE˘ÉmB̀ˆŚ”KEŽ›Á÷şH)™œŹbŮ×o,ŕű>G&F) Ü^ZceuƒÍVDŰőɅ˜÷>†I)ˆ¤†ŠĹ9âä˝÷`?…QČüíŰ\˝z•ÍÍMFGG ‚ŔÇ$I„ă¤ř­ßú­¤şŢƒ ?ƋšŢ9JÂHŇlľšqăëëëäó9Ž™˘T*aš&HI×uš~ý:ÓÓÓd2ő+1FĄP(F‰‘„QHÝó)[6ž”lz.EŰĆčš.wBǰö6"#‰Ž î×i šF’ĺv‡ÇÁĐ´}íŚPFŹv;dM‹´a˛—C‡…Q„­ëhBSÓé;ąűŃévYXX`î؆a$‡˘(˘VŤą0Ś´s˙Aŕű>–e%!AŚibÍfÇq1ŚďŃŇ˙_Ó4rš¸Sż<śëş!Čd2ŒŽŽ&ž1śm“N§¸ď%#„ •JQ(0Mß÷ ‚€l6‹išqéi-vé÷<Ë2ą,ĺĺ}đčşÎéÓ§™››CJ‡:(ŻĹÓ2D†őr‚ȁP›8´GîŰŻ'‹.C"J/;ÇĹĎ/bŽë˘ë:šnŕŰ{$‹&dŹŇmsdď‹ Śi&2–eaYů|×uąm›BĄ@ÄeŁűŸëç ĐuBĄ@:Ž KĎCÓt4M#›Í’JĽCupÂŽëú›{*•ęU>ŠĐ Čd2H){ĽŹľž'M@„¤ÓŽ2Xý6˘PŚ.RJö)öHźľ5iŢöJ˘flyťˆmICbď”^g,ˇ>(űÂÇ wË^É_’L2˛'Ŕěôz‘ŰÎaďŔÓ-á%ęyČ}ÂHˆq¨ŠŽéńáE˝ó–’(ФőÂośĺóşGĽ‚[›zwĆu]:Śi&ÉĹu]_ŰŃŃQLË@×5‚ ˆC‰Ƣ/$Ô ďűťxŰȤßÔuŰś†Ža†üâżŕ…^Pϲc …BńčDR˛Úq‘€†ŹvťŹu]|ah°ÔqŮp]ć[-,MgšÓĺx>ĎĽFo9B(%Ý(ŕęf“Vŕă^1•v¸XŤ‘7-–:]jŽÇxÚáfłIѲ˜Hgxwy™0ź95F(#6=él†Ľv‡ŚrąśĘt6CË÷M;źżşĘń|Ž×VuRËçYlšŹu]jiM@F˜:Œ:ţzi™‰´CӋXîtRŕ…76›ÉŚšRßd2ăđáę:gË%Žnn2•Îŕ†!Ű"m˝°-ňéŽNv}‚zaętÝ.ľ•Ձä•Ąé¤–1ӝ›kČpg2Mӆ\˘űŢ1śmý'tprnš[qđ}Ošť1bu]'Nďúz:íě˜T)!FĄPlMwĹ]Oôĺ@|Œ”{ăöËĘ8ôç„Ěń!éMňˇúÝĐś' lW[ť3Ť €Ú KŰÎL Cm 6âNĘÔÖőÉyĆ{ńý€ĹĺUFFNręĚiĂÔ¸}{ Ďőƒ€…ĹUŚ&ÇĐ5k7—q=Ű҉ú~]n~‰çVŤĹüü<Őj•vťM8ŽƒŐŤUŤm ëĽR×u‡ŢQt]§Z­ĺÓéWSĘfł|ůË_î-x˜”JĹ$÷Z?Oۡžő-*•Šz˜•ŁP(ŠGI$!7 é†n2–NóţęYÓŔŇuÖť.ç7ÉŚi>cé×67ń˘Kä ‹Ĺv›é\†˘mpľŃćh6C7ˆ¸ŐŹńÚČ(?m.ˇňlx›~@Ö÷Ůô},M§’˛ˆ$ŘşNѲ9ˇ^Łř˜BĂ CŽn6™Éĺč†yˢîůÍeI&0 mčD2ⓍËŕd!‡”’šlŽÖVIi:#)§çĽÓô2†Iۏ¸Ýę`뎎s$›Ľ”˛xwq…'E1eŁËňŸOs;éú´ŽŻÄć^ĹBĚŕjjŇžľ…AźZ{˘Čţż;{űáŠ$J„yŒ'ĚJHS<<5ćŽŰ (}f°]ʞłwšœŘ‹$JŞ‘ätŁ—ÄWŰŤ"PÝK!‘LŇîďřÎ^~,)eÂ$÷JÎ/ˇD!KU÷ƎHRݎ¸pńĺR]×iˇÚ,.­†!RÂĘZF M9Ë䗫Ťœ,iu}N•ňüôö"ϖK\mlö­Ž›óă@ßpŒÇ~čQĎVrłî­Š†ń5ÓĐŻîđKB+űM˜ŠGŞŰÜ)á ĂaAbŔťeŤHő°žIšK ĂxËîţ:rx$ë…ÉĎ ~ěgŕݞČ7Úíë{Úl;ÎD”‰Ť5y~Ŕââëëő^ČN—{îá!A&ŐĄÄö°§CĘŢ!”k—ŹĂşOÚ­bÖk’ÍIŇůţöţg¤(¤PbŒBĄP(žˆ1ĄëüwgNôÂЀPJž:1Ž>ˇ% MŔˇgŚcˇ/Ÿ˜š†|}r|hu\s…\˛ş(zŰ%đLŠ„&UÇ楑roÚSëŁi'NœŕÍ7ßäöíۄa˜”uŽs%얐°çEÔ{M×u^ýu˛ŮŹJ¸ŞP(ž*ᥟ |W79 ]ˆ EJdâĺőúŘžâK}ݘaŠD …DD[=ń€ß Bô™ŢKżRӖ"vŸ”˝|1rŤĎœôĂ`Šč^~™ŢąËmƌDJëyqf ŸJČŤcŕŘżˆląŰUď—rŢ­ź÷`8Ř˝&w~ďŁƒű÷G ŇJŒQ( Ĺ!G}ۀ}݁Ą śťG2zĆ3),]ۡôô`ůÍX ŘiŘěv\ÚŒ ó> ]L%pôčQ~ď÷~/.Ď9’´‹Áş˝šC?éîěě잹YŠ= –RŞ‹Ą8؉Żě r+1o?ÉĘ6ńN”’îWJúzyXśŢ&{嚣$‹Ä"Œ=OÖÝĺѓ:´Dœ(ˆ$˙íC/ą4Üˇ˙˙ ÚŃŤƒŽ<2^ĚŮú^‰F\B[ń>´^ĆᝐLÎ÷Ajčt:\źx‘ÉÉI˛ŮlRĹĎu]Â0LĘ÷“ťkšŚźGJŒQ( Ĺ㋮ Śłé$Ąâą›b LNN2>>~ß{éW%R“dĹĂ$ŠüEDQ<9U( ĺ%ĽÄŽWKP'Î-ô}SƒšdvŤ`ˇUv:ęyŠ„RE[B ôD‹2CÇŃË#§IO°Ń”)űž+[ÉzűßɸęQÔŤ˜4XĂş˙ˆi}9f )p?gŒ&{I†{áJ){áϢ—š/,őŽGúôŕ’ď âjyďžű.słÇ’ü)Žă†!›Í&ů|žNťM§Ó!Š Ĺ"ssÇUŢ%ŠG‰1 …BĄx 2boúĄEjuPqčű1œUő=Ї‡Dő~î0&U†6ËD%zŤŢý˛ł%H")cAFŠoOúzČČ~™ěžЌszE}Ϝ}o•šî 1˘ˇ˝—ŔWjێ1ţ–HȞ #‡Ď§ˇ­ˇ/žčÔśĘ^÷lâăďý–ś€ĄŚiLLL i­V›|>OˇëŇívđ<ŸŔ0 “0lŃuť¸ËˌŒŒ02RUăŸâŔů˙Ů{óËŽűžósÎ]ßRoŠŽŢŮÝŐÝ\%Š”LĘb"Z–-ÉyÉŘ‚qĚü  Ɍ‘cČ1â蟘ž B€Aţ2ÄČ /E<ęmΎ§“T‘KŮ vk™Ź5†‡1¸÷‘ 3CŹˆŠĄrB>”Í)‚%÷lQZŁT^2¤'„ˆNýŐĘoW¨VEُ-'Iš„*߾ւ]xĨ2ASrđVą¤˙ĺü“(˝&W÷LN"óo‘™˘§œ:•—PéÍ0ô}ŸĎ|ć3I›*6ÉR›@ˆŒ*ŇĽýL-cźÎ î c``````@&Ź\ F JM&ŐŰ*ČˡD)íÍE)ł;§wązĨ# öś¤Mëů?—ÓŹó°ĄTĽ˘'ĺB ’üĹ*˙–:ŠI~îߕn;÷‰I˛‰KęCS*‡R˘ WԔ‘oÉpXOČY"JaPhtjć›íŚĚö3/ŸB邐zś0IŁľľc孖eݑwYţÚýp )űľ|0`Čú݈ˇ_뎒BĆ~{)ޘŽƒŐדĹcŰM°ˇ›LŢÉdÓxÓÜórN–”ôZ‹â9Qb]ôÜUžiiRތ™6ÖÍ_šűÂä&šYz5Rč‰B Tސ0Ł|ĄPÝLŠe˜~ż˛Gqş QD\>ü9¤˛6Ůç×”LŸ\ ÄTŤ[Řáą@ý’DŃď÷ !cČƒňĚÓĚ ›L‹É´{ëäM CÖĂuŞT9˘+ĹÔ])ĹÚÚ:—/_ŚRŠÇqAş¸ŽËáNJŘQ˲ŘŘŘ@JIF ‡#lۢŰíRŻ×éőz´Z-˘(âŔôz=’$!IlŰćĉű c``°ó‹`(|UĘ ăé‘0ýW•^[~ŘŽÔə•œÉK“Ô„,Qz&3[ä1×)é"rc\*R„hBj„NŸĎ‰”´4)Uͨň~ŠÉç,~a’|yŹvy7˛ŤCN l”ČřŠĚ;L§%K˛ÔłQ×ĹűžoÂ"ő‚IS”äžť&lŽ˝ą"ŠÓ㐠‹5‰g ¤caY6Ie¨!c >8+Žü.hJ˜ ‡}ŰĆóüm'´ Ŋ^çůäť<–œĺA}¨xn<xçwšző ž_áôéӜ?˲ˆăÇąFt:NŸ>Í`0Ŕśm67ť\¸đgϞĺ•W^ĄVŤŃl6 llt8xđ /˝ô2Ăá$I8pŕőzűî;nŽĄÁ.R2ůb_Lůä$BžDT¤ee?b&ei;os]¨bĤTŠTZ”żUGH ČҋŇR%2E 'bRuLž‰DĎ$*ĺlHńšJ~_šÍÍÚ$űŒšRŠ‘Ůś”H..1Ů{Ľ›ې[ď˙X嗬œ°Ÿ”-M”•úËäÎ칐RŢ5S_Ľacđ˙}oÄ çF‘˘Uľyŕ°ĂR]rfÉâ‘#.ŽÍ.ľ™!c îíbC+Â8 čv\zżľ„X<ˆOdĽLÓ(„`¤^ żÇ†Őc!Ž”źRCßJĹĂś-jľ ׯ_ŁZőąítęŃh4h6›,..bŰ6J)Ž]ť†ÇqX__' CNž˛ârMvx!~‘´Ľ]mO-˘}ßç‘Gᡇ¸ĽgĚącÇhľZX–ÍÁƒ]žűÝďr˙ýgůđ‡?„”’“'O"„Ŕqž~úi˘(ő’ą,Ľ óA@nň™$ ŁŃˆZ­fŽŤÁ^"‹r˘icÝ4ÁHŤI)ĐDš0C2jŚ"ŮuAFČ)EŒR*ŤxˇqîĽT%%rߜ ™Ĺ‘¤'~6™iî$OgŐIĺœ$ *ڤ˙)5"ݡŒŠŃ‚‰şŚx8#‹˜Dp+Š`ëÉ6őîŒ'y‰Źă¸Ź­­SŤ%\źx)+‡ŐTŤ5úý~QVŰl6¸páîťď8.\ŕ̙3,,,ܕŽu˝›Ä)@ĹnH*.řŽäHC˛1Pœ\4§ !c >¨Ťa툇>DŻŮ$J"VÂkźqŚOăü?ňń¨Đ´ÚDƒYŠpŕĐQŽ[xŽ7ĽŒ ™ˇÖšz˝>5Iž]d{ž‡ëşÔj5Ž9„˘0ňuœÉA˲đ}ŠĺŽY´€0ůÖˇžĹ˙řă8ćŘÜ{ŚđVÉȘÜWϧ|‚ŇšDĽ¤Ěă%÷JŮJbşĐ)ŰJaÚŤ´*ŢsÂ÷LÜZrCs)Ś}ltĆôţ-"5͝ň˛Ą´Ý2)´…<š.%ÚÂ$é‰1ŻÎ˝aDJI91Ö:3ýÍKžDŠ4ŞŘ×Ý!c<Ďcyy™JĽŠďű8ŽC­V+źĆ„…jŚZ­R­V9räJ%(ĽŠëĎnÒđŘ}Ď_°SÓfĽyíҘł]|'ćÚú˜O<°°˙ϤĚ7.˙*•BČbÎđĂ4ć2ĆŔŔŔŔŔŔ ˜g÷ú=ÖĆB˛ŮšÁzkĚŰú ?ć/ă)vu‘ű>‚íy\ŇŤ.rÂ9>%×/OźĘ?ç$L^Ł?;áʡ,eÉ-ۘ}Ýě{m÷řźßËŻ}l*ńdqd°{PJqăĆ VVVXYYáŘącŚý îů¸˜“%:SƒäĺCššn™Œ)"ŠËę‘Ó0eË4ԇ‹*Eϒ1ĹXJžœ”›đćă—*ŠpĘÉH“Xë2T~žüˆžŁŕa&œ[ddČÇόŕQJ#$Y{ĺ–4łś˝sŢd‡áş.‡Ľ^f é fł™qSŇ`ii鎍=Ž-řÄŸš+xýJČ8[j^ť<˘ę(~ô:KukŸFZEý~ŸÍÍMşÝ.I’öŰśM­ś@łŮ$Š"Ν;ǛožÉŋY]]e8P­VYZZâĉ<ôĐC|ôŁeqq˅ c``````€•p᝿â{ß}ĽbDŐbăa‡Ľ ĎoŇ ;Ü×X¤Ů8@/îóW\äpoőĹ-¤‡RŠ^Ż¤Ş—ÍÍMÇĄŐjŃď÷évť4 ŞŐ*JŠ"Â:WB!PJŃď÷é÷űÔj5Ćă1RJ8PÜaÓZńÖy$öŹéb’$ôz=,Ë" C‚  Ýn3p]ß÷Y]]ĽÝnÝn!ŽëŇnˇ§T9ť;Y×ZłąąÁŐŤW &1Ä`őÍń<N§ĂÚڎ뢾ŚŃhŕ8ăńß÷QJ1 ¸qăF‘ÂÔď÷iˇŰlnnŇétĐZă8Žë2ŠŐj8p AťŽ‹‚(ŠðHa‚ôŽixžÇp8$ CFŁQĄľŚZ­˛°°PČŮ vÁűýďŸ7ß|ŰśyńĹ‹2ƒ{Ó)K19A˘ôÄ ˇD¸čŹÄ(ŃbĽx"Sä+oÁ„Č i"FL{Ňä„P™Đ3ʕ›:Sĺ*•9–šşě S˜ç^N[=cräĺHů—,Aɟ&3ň…tÓ}݉qDeîÉűmÜv$8î<ŞFĎM}ÚOs‹Ë—Żđƒü׹łřqßlnnň ßáŇĺË–´ű•˘lůVxńĹyńĹyâ‰'řĽ_ú%Žß_Ɋ†Œ1000000H§ČRŸĐ„'Œő‘2Œ6š”\˘ťŇŻ÷^gÍîq}°‚ZŤ1ě-qÝžĆňĄ3ÓÓÇĚď%Žcâ8ŚŐjŃëőH’´_Q5'Nœ Cl۞RźäfŽ•J…ńxLŁŃ`ccŁ Z„H) ‚EJIÄq<}çVJlŰ&Š",Ëb0°°°€ă8„a˜Nˆl{ŠÜÉ;ůűě>¤”<üđĂ<üđĂSýČŔŕŢŽşPĄä%DyZR™LIô¤DIM3Ľž<1ýZ°ęr)ҤdIçĺJS"ő["ąÎ˙~Î9S&mrs_QVȈRŚSţ_E TA×ĚŞcŇmIDJéDh ľŠÉW’$ÄqĚŇŇý~ŸcǎQ­Vą,‹^ŻÇ‘#GÐ8ŽŠ×ëqR­V‹RĽv;•+×j5†Ă!ǏÇśmđ<Ż u,Ë*ţ&MYšLÄă8.ˆ˜Fفëş,..˛ąąQ”78p€FفeY…ŠĆu]<Ď3ÝünžQ%íƒIĈRбؓmo°•‹Q唣’ŠŽ*™ăćç~2I‰;‘””1sÔ%ijô¤$I鉒Ľ(?Ңˆ–Ö"%Fdޏô$Ć:%Â%–%R`[ՊKĹwp] iYT}ۖt6GŹu†tză0)źĺ3çƎŔTړ!î&9ł'ຈlÁjH™™ąQ—É–I˛R’{ź”ˆ˜ÜÔˇxŹt”'ĂŁšż,™ éM0]P4ľPU­şÇáCMj5ŸŠďRń]jĎłS.[â{žkaŰKZ¸Ž…%ƒQ@wŇ鎚ą>`Ł;fŁ;f8 cÂ(!Ž’$ۋ˛1°ŘŔ*y@ËRôwŠÔŤ00.‘<;6M6Úívš~ý:–eäúxŕş.Ýn—0Œh4xžË`0ÄśSžßPŠř \*ně&rď´$I eH~MËoběWH)‹›'Żžú*çΝŰ⠓÷ő÷›¨ôŐŻ~`_2†Œ1000¸{Ť D­NrđöćŚiƒ=ˇ(BRŤ,Pó§MóI’ČŁRKK‹˛ŻŔ{Yl—M"wbo _ îÉÁCˆzaYŚ1˜ć>&Lo=ńŒI4S>,JĺŻS†şjj¤ÝfŒĘŁŻł’Jž+e‚F/FxşKMĜ9|‡śYl-ŕ:–maY)$˘ŹţГpłYá™â%+ż ˜ŐNŸ++}Ţ˝˛Éľ•˝!A¤IE’(TÝ]ö1хaošž”śÖ"-Ű’ŠŠďs’‘:ť5jK)š~ý:•J…0 YXX BŞŐWŽ\áĐĄCŹŹ\'Šb´ÖŘśÍ`0DJY”ŐV*)ńż›dHž4Ç1ŽëEQ–6”ú›…aHŤŐÚˇ„ŒmŰ9r„z˝Îwżű]^{íľ-×ë4}LĄ„¤RŠźoňëŤ_ý*Řó%K†Œ1000¸K°l›¸Ń ş˙~Ź+—ă1EŃšÁ=†LłI‘%GO˜Ń3jš “e‹(ˆš;#gvňŽŁšŤo°×÷bzŠĎ=UÇH‰ö}˘@6[éďŘą÷Ľ!Q“ĽšK­ćŇ\đcĆaL+ĽčVև…÷ŠÔšX%Ź­­łšqƒˇž˙6žëŕW< uڋ-.ľ9rä0‡-ą°Pò$]”é˛SŒHŤ‰<ßâ襇,đčC‡ Äq3…ôűk76†\_íqccČp’$ ŘŮ6tžÜ”ľ‡Đ uŮ÷F>:ó̄węZPŤŐxâ‰'ˆăÇqŠ2TŰś9yň>Ç%Ib‚ $Ž„HU’yůëęęFs‹‚c7$ Žëf1Ď5ƒqœz–AD%ű–ŒÉKŽscöźD,o×rz”´daź˙~ń•Ż|…‡zhO›ú2ĆŔŔŔŕ.]ˆ°,ŹzřąÇ7;¸/żŒ0ĺJ{––#ÇĽrŸ;Xb –-H•öf!gp×F×I/ÜŤ$ÂTňŒ‰ë˝Ţ5Ď#xěqâ?Š[ŠdF°ćü-uŞ")7íM2ULţ{ŽVIŐ"™DĽéAR€eI\Wâ96Žka[6şKŤQĄRqi7*T+ՊMšq‰ëH˘8UĄÄ‰B%ŠsoŻňŸţâ<*)—ţ¤DŠ#‚ d06સc[xžG˝^ŁąP§ŐZŕĐáƒ_âřŚâŻł=֚ TaD§ÓMçR"- ÇąiˇÜwâ0gNŸäŕÁ%jľ*Žë⺊z$/obËBYŕyŽkąPó8r°Vôď8I莭ô¸tľËŢYĺڍ^q­T3diZň%Š6Ţé^§”˘×ëŃď÷ąm›J%%\Ćă1Zëěűd~vŕŔÝî&QŮśR)ąäy.őzj$oŰv‘ hY \ż~˝ř|Q!ĺ¤ÜŚVŤĆđžď3 ‚€JĽBťÝŚRIIą^ŻÇ`0 C„¸Žƒ‚FŁQ>űßűŢ÷8ţü_¸y¤ÍNâĹ_ä•W^áńÇ7dŒ!dśç!l›ř‰'>öxzA1~{g•/q|RKĹÎććÔÄr'ȕ÷Cʤ}ďŚ+Ĺ4—C‚ť oą˜›ˇ¸K7>† ӏ îĘhĘžS`iŕôź_ů߈ţ=úR`Ů6śăŕ9Nš*–-žÍ<}Ȕ_˜LéâŰőz…Ľv•ĆB…ƒ‹5ęußłń< ے¸.…š! JŰ^Ä$*FE%âŹdt›{ˇ„QDÄQDŤYÇśŔąaT2Ë͓´.%fĎ?‚‰JU4IłFŹŽmđúë?Ŕ÷=ŞŐ*žď˛¸ŘŕŘŃÜz !3ťřU€NR%NŌF]lŰâęDŤ IDATŐœ?…—*Żsjů8>¸Œ%eANäŰMŐ"QńyÂ0D)•ú˛Č´ěGŁR’Fi”Đ %B)¤,Ĺ`3IŁÚńž.žçáyŢT{l×ĎÓ×xä&Ęeľ]ůçí”Ĺ|n›}É˙nť}ÉĎA×uˇŮˇý‹őőu^zéĽ[~Ś2‘•úúœä—ů—ůW˙ę_˝/BćĹ_d}}ĹĹECƤ°lЧ'Nˇ3a000000؉ŪšÖÜľŠË'ž<_uÓ.’’"eb~›."âDŁUęőĹ qœ*[˘(f81éő‡lltŮčtšrő׎opĺę Ö76éő‡aD˘ ÓHjO0ą„](m´Ň€š,^KIKÓÍ4Ą0O™{ ÄqB Gtm—úB•Îf ĄQ2˘Ź| Ž#@ă8Žë¤ĺ֞KŤuĎuQ*ĚR§4XŠGŒĘ¸) ĽýÍď+Ýë~(ćžĺŸçÍŃv’(Ůn[:+UÜŻ~N/żüň\ÂĽÜ7óç˘(b<óĺ/™/|á Üwß}üĘŻü _ţň—Ůœ“D*JľBlߏ^zé;üäOüdZV(öB3dŒÁž› ߊŒ1);ľĐ3דŰh7Ro"5ˇ­ĘŞĹxŇéô¸zíoż}‰w.]ĺwްąŮ§ß2Š9kfĘ&IćEę@`IÖéŇ;G¨D!ĽŔśd–]Ô$1á^tń}ž2&?ŢeTy<1ń$:AŤ„p<¤×YE‰cŰxVj$ë8–í#„Ć’Ғ€D‰ëŘ!ˆ˘I śÖ‚DčÂ'FCĘĚdKz—CĹn§ŸßΊPnˇ|>v§çĐÍ^/fü˘ňfI}œôž•8żůć›SDŕl˙Ěż'IÂĆĆăń×uů'˙äWů˙âˇ8uę˙čý#žôĽN§Ó™ôc@d&Čšuţ8Ľc#„ŕ;ßůŸřяăy>śöŃ,qŔ1ˇ?aŘišŞ™ŒěÜxşWK ĚX˙É­ ×áhĚf§GgłÇćfŸľőkŤltşŹŻwčőFŒĆ!ăqČ8  MžďcYžďS­Vw°Ľß/v.o$ŒĂŔąuOp˙!‡şˇĎߋ/˘”šň*÷Š<™*I’Ěü8=~++×ůľňŤüö˙ţ°źźĚoţć?ç×ý‹t66ŚŹźürJ=4Ł~ůo˙íżrćô)Ç)âĂ˙ú'?…ă8†Œ10000¸ů¤ů^%…č-éĆyf7ÚŘ,” c°÷E—Î_ĺíw/ł˛˛ĘÚz‡k×Wšž˛Îęú&N0ˆQIJ0¤ ĚÜŇML•2‘?NŮř]ÄźK€Ö0B’X!ÝTS,™ŇDë‰"fBŔl˝fO~œßGórĽôľY ”RxžœQ҈RŹaŮg< đŤ ˆE˘tZš”•U !K„‹@ @É´”i‡O­5ŤŤŤÜ¸qƒńxLEtť]<Ď'Š"ęő:žď†!‹‹‹\˝z-KU:€şH­R*ĄŰí2‹XěűďżżHJÚ ( —;żű­ßž0Žľmţú™ íšdc˜đ×Îúřöţ™'$IBEŒĆ#Ο?ĎúúÝn—(ŠŠńRd'„&íki:•Ä’VŃśÍMžřĹ_ăˇ;%džyćžřĹ_gccmҝçĘM=$X[[csłƒm;8ŽĂh4&Ž#CĆlż@żŰźšdv’8PNRHIšyW˝›EŹn—•<ďqq“ŤŤ.=_ţΜ}ŰüźÝ6oöYć˝ß~Ţéý™HvłéşYČÍíƒĆ\Ô`?ôS™ÉĺË ){áZbΝ÷ŽÁpĚţÓoňď˙čOŮÜě§×D!Rb¤fá˛Ń×:ĐHĄ.XŽ%H…P$u™šŃR*-ڎ ‚€8I¨HcËbőŠŐVbEgąŘĺKÉ, SöŮúˇ“ř˝ôé”ôAŚ‹ćYϒ\EEŠr¨×Qoć4:%c”F–bIĄPÖôV´Ö$y­Őr2J)jľőz!a°°Đ \ףVŤĐëőp‡ƒ—p—nw“z}߯Ç ý~×őYXh¤DeŰÜ)Œc͟żđoŘ& ˙ŕǚüĚcUl ţ֐Kë1÷röěš2;éőşźůćźőć9ž˙ýˇ‚€ Gaa؜_ŰĽXśEĹŻd&Йj&ë‡Ýn—ßř_ç™g~›“'OńĽ/ýs~ů—˙×m˜éš 5+O’„jľŠă¸€Ŕ˛lâ8šçc¤!c ~ˆ ďe2EQ:̈ƒ_ŔĺwSó‰łY;•Ű(˝KÇ I˘ŢW60ŘmH)ąmĎópçž÷Ó;yc ?żý\߼qŚÂâŃnÍĆ_´ń=,WâÖ]Ž˝°íŰhĽhŻâÖl.ýĹ—˙b•x”Lh›ą ‚š>J§IEq#Řś,žLp§L|u™„™ýĺkĚö7G(Ô –%Çt6’ÔFƒNBJ¤%ŃJ§éRf†ÂšvŤ]”˙aœzăčTI#3BJ*@‚Ęô5ZiT)š{§ę”„EŹľeYh­iˇŰSnY’fł‰Ö:‹›;v¤´#ş˜÷”ăŞs…ĚŹ ň{=o¨IHŚ1‰VxR` Í8J€˝IĆäĆť7nŹpíúUÖÖÖX_[c8ě3\ÇÁś,Tľ:餼›-˛|ă%/‰ăf}BlۖyšRš—Ś—JËÂqźŇ>+şÝM*• ś}ď(CĆlKČÇcĆăń–ÉČű™¨Ďnă‡íÎmŽ,ň}ŸJ%­M/Oî&ídH™r›ĹqĚx0 ͂ń.,@gďr…Ĺí÷Ő(ŠH’ß÷ńŰ犈aśmÓ^l°PľnkÓR _錘ɦNŤ.ˇ7S3Մ8ŠëćýD§eFa1FÔI–œ“z×č™q]Šll‡ÂŔW+5iŸĘ-ˢŮlĐh4Śö{v’>/Ф¨˛żŽ“RڜŒ)oc;bë˝(âÚ5Ił"ˇ¸ŃY–ŘVÍ´WĆ Ďó%•Sš@Ś@@ĽZĺúĘĘÜńeE=„$4[M~ëˇĘDĚŻÓétB~2y9’,Ę›Ä ى˘)$Ż˝ö:q’đä“O˛´´tOU‹†Œ10000Řv!œËng/˜;ąŕ-_Œ……Zd<3‹ đÂÂÂm×ńꏎ>7čs]ˇ¤î•6M'nšZ­şíçÚ­…PŒév{ŘśMĽRÁuÝ۞„äňlŰśq]÷Ž,Öś›°ĺđ}ßĆ…Ŕ˝F’$ĹÂŰśÓXT˲öT?ź]aËDyUyZIꉑ•7DQ!ť]t]÷ŽŽ(Šˆ˘čŽîVďTżˆ˘¨8çďu"žÁ’1‚z­BÜUœ˙O+xU—îľÉ0!ěEŒ7ct’*UŚ uE)iHluĽeŇAK˙ŮW uę%éľÍą­âqQč J‰M3Ç~Bƈ"áŠü˝LÜä$MŮe4ă{“E˛R  Š"Â(ÂśěTů˘–mSŤ. Ľ…F'ŠBD“EykÁěU'ßó˛gĚűď­şˆOžw>Ěűy똰U8oܖĚĘÔqďéú7§ T’@kÍ^TÇH)‹ň­~ż?™÷d„Čââ".\˜JěşŐřÔjľxć™ßfyy™wß}—_űľ_+1ŠŒĚH/11ü͉O IĽ†a˜öŐŃp„_­dFžÎž c````°eń0KÄěĆżź$I8ţW$L”’ręPވH’„+WŽđꍯrôčQÚí6gΜ™šD•“"rÓÜťMĆH)ńýĘmľĺÎ-˘4/^â˙đhˇŰœ={†üă8Ž3U’Rn›ň$S)şţéŸqúô2<ňČ\‚ä˝ŢźSb&oŰśń}Ÿáp´g›qóÜsĎáş.O=ő×řÎw^˘ŮlňĄ=’ľĺivi‚ż—ĚťKvĽçď+ŻźBŁŃ`ii‰żü˿䓟ü$őz}ŞŠlrýěłĎňŮĎ~ś0ăB°şşŠÖšƒN)ŤrÂ÷üůó\ťv§žzęŽËŇsóó{Ľŕ2%}ďo‘YŤU‰ű WŢZA•B¤$Œž^¤k‘E?gőCšNFć~ť‡"ƌ„Üş/Œ\ŒĆcP ϖS×2- ÝÉuŒŢş=1ý=ﳏĺ„Ňf§KżŰMýj2ŁŢjͧVóiľš™R§´ßŇO‰G JĽ‹qĽÓr¤˛ŻMůÚŹ˛ßőˇ{]~˛;çňÎĐUťqn6›,--ŃétÇYżHŻ{GŽ™RšŢÎ\ç™gžáôéÓ\¸p_ýŐ_ĽÓéLČ)!°´N z)“0şT&:.ŢRH<˜rť.őz}O¨b c````0—4xŻwtŢë"۲,–––XXXŕúőë,//óúëŻÓď÷i6›DQD§Óáá‡&Ţ}÷]¤”œ={­5oźń˝^óçĎł¸¸Čúú:—/_&Žc’$áŁý(/^d}}ń8ŕé§?IłŮźŤ“5Ľž_AJąm;”'&;ľpŇZ°šŮeőĆ:÷ÝwĎ>űGœ9s–×_nˇËňň2A°ššÉ`0ŕCúZ§$M€ŕŐWż›ľ•ŕüůóÔëuN:ÉK/˝Ěâb›ÇœÜő>łWT19ĄxîÜ9Ž^šFcĄĹŰ?8Ďâb˒\şt™jľÂââ"Ýn—jľZ9ˇZ-Nœ8ąg˘oF‚í֘“$ ďžű.‡˘RŠđúëŻsúôiŢ~űm\׼ŃhpölÚgƒ ŕůçŸçCúŻ˝öQąźźĚłĎ>‹RŠ_üĹ_äęŐŤtť]}ôQ„źňĘ+ŹŽŽ"„ŕÉ'Ÿ,Ň^îfߘôSaŒš÷#¨×źbÜ.Í…ŠlĆoTäéE̐.ŮKĹ<ă\ Š9qÓ¤¤Ćx4FŠÇI¸şřˇěCćŁçŞ7ni=ď9ĎuXhx<°˘fo–¤ŚĽ"Ó{PxĚe$RŽRZ#Eš $˛Ś‚”‘bĘŔw'š†ýF@ćeóŻkzŸ'i)×§?ýi–––xöŮgÓ%ňrtAłŮâƍ•â*Í;năń˜ˇŢz‹úO˙é3ÝşřO%Š  ƒ€DŠŠ~ôčQZ­V‘t—ý†Œ10000ؓ„Ě­"Źwr‚“oŤŐjsřđÂ0âäɓüáţƒţ€ă÷çÜšsDQČŋ9zô(ßëŻh/śé÷ŹŹŹ`ŮŽí.źƒë8|ďľ×xú“Oóâ‹ß!"Ž\žL{ąÍ_üĹĺcűXQC~7ŰŐśo˝ŕލɣ֚Ńx”•*9źńƛüů׿ÁňéS\şt™őľu–.á86_ýęW9}ú žçŇíöpťˆ7_[[ăľ×ÎqýÚu~îç–ß˙ýÇ?ü‡˙ŕžLxsŔ|ńqŻ'ÝšjăěŮűůƒ?řŽ9BÇ\ş|‰ő 6:~ú§Šçž{Ž÷ Š"Ö7ÖůšŸýY3ćd~JqœÇ QłąŢáţđk|ţg>ĎŰoŸçňĽ+\šr…3gĎ0 ‡#._şÂůóçŮXďŃçőýđÍo}Ľ4Ăáˆnˇ[”@YŇʇw˙óMćłŸ „ V­`ĺc÷ܨK„LFśé[“ łž ebdzlŃ GAj6k‰|ľ^$)ĺ$Ě­ëł'ۏ™Yš’ăPŤz¸Ž˝e§EFČLŢ;Ý~ŹTş0VşX§Â@‘F\‹4b[čR9ŽÚ=/”œěÍoźĚUe‚m§o„Ü bĽŮ*ţü­1Ż_ QZłXł8Ú˛iW÷t8° ŠşrOŽ!šbuqq‘|pĆ(YŁľâÔŠ“ܸą2g~)ś\×Ađ˙ń˙2eö;9."%ö´FjQ\3˘($Ž“-Ţ{RJîŕ~,Ű™š2§1ć{„Č2ĂŹÁź‰É=܃ládsüř}´[‹:tˆĎ}îs<ňČ#ضÉ'9ur™ŃhĚĘĘ –OćčŃcŠş ›âYŇâńÇçŕÁC\š|)->üĄGŠUkˆť|ů›LöRš~żO­Vĺo˙í_˘×ëaY}ä1‚ d0rěŘ1>üásůň•Â_# ƒbâ4Žxó͡¨×k…â¨RŠň‰O|‚VŤuń{ďÜy챏pđŕAŢxă úý>q”đń˙(ŸúąOqćĚY’XŃëőGlvş:thĎŠbćőÝÝÜ?!śeąŮéŇŮŘ́”?ôŽíráÂ;Ôë <úᏀŹ­ŽłşşFť˝Čh4ćč‘c>t˜8NX:pĎ˙wŸçÔÉeŽ]˝Î÷?Č}ÇOpŻäýĆ\z_SR˘‚(—5l -dž¸Ô7%aTń%ĐԌGɔ˛”V8ś˛ČčܓCl-1ʡqłžˇ÷IJžh¤Ëś ˛T)ú–‰Ö„aB˘ Qš0Œ‰ăxJk˘XMElë™ýš<jŹP´ÖŒF#VVV † ‡#Ö×7ˆ˘ˆk׎qéŇ%Ž]ťFŻ×Ł×ëąąąAˇŰ%‚šť‰(.Œů7ßěó‡ŻůÚŤczcÍ'~äD…ož=b­Żś{ i)ś_|U*jľ*őzĺĺeŽ?^řŞĽęV;+ŸbI˘H’¸˜ƒ¤Ç#LU/aTřEQL„ ‡CƒQO]łň÷9zô(Íf“N‡0 ą, ßß;1áFc````°'Č˒¸Ž‹ë:¸ŽKľćłĐ¨ńŔƒgšxéžńođÉO~ß÷PJeuëž~úiţäOţ„ÇSŻ×ŠÖjٝ:•J•JĽÂÂÂ7nÜŕ˙řéőz÷lB†!Z+ćĽSěŢń×qxřá‡ůéŸţ)jľǎĺĺ—_ć?|őŤ<ůēŻźň2ëëüżń7¨V+üÇ˙ř,RJžzę)}ôQžýíoóđĂqńbZ"śPŻSŻWďČ xg Ś4ícݐŽăP­Vi4üżówř—˙ň_˛źź ŔóĎ?ĎŇŇŸţô§yřᇋ8ŐFŁA˝ž°§ˆ˜yőüťI(äńąű‘ńű˙ďżăůçŸç駟ŚŃh „ŕk_ű­V‹Ď}îs|ýë_çŮgŸĽŮlą°°Ŕ`0@kÍĄC‡8uę_űÚ×8{ö,śmóo|ƒĎ|ć3|öłŸĺ˙ři4=zôśMÁwzbüZöőU‘V3őGI˘xš´(˝FLœx§4šę‚ÜnWL' •˜”íƇٕhG’¨•$™‹B˔œI-âŽĎ÷­ď™R@ăń˜0tę˜A„_Аč”8n4؞ƒmŰōÇvR_$!Ńq’’7:ý´iltÎSM?i ńΏ/Qqůňe†Ă!ýţ€ŃhLǜ8qœˇß~›ápˆăxEɨmˢ,úäɓ,..Ţ5öDiŢş3'ˆĚ?çc÷9m:ŘÚćP]Ňë Š´žVŤšĹ‡î^ŸGN‡Ż|ĺ+ ƒBYŤŠ’5Íůóçyĺ•Wśí˙Ű̞ĺĽÔT)Z’$AŔňň2gϞĽRŠPФ)J§Nâ~á ř[KO B Ξ’ěK•žtéť.MJőě,ˇ ٌ10000˜‚”Çqˆ˘čîËëĹÜkŐ-ţćfúfš…F3g—š~ý:O<ů#ÔëŐťžŚ$„ I4ÝnŸĹĹÖŢQt¸.Ÿţ‰OŃjľîpá$˛˙ç›Aîf[†aDż?Ř%uwÚ÷>fI˜ťÚž"¸ ŕ~ńÖäńýؖš\~Ż$wźˇăŘjՑ–U)iPz_ZĎťŒÍúšdę‘[]#ŚŸ™/0ŽHT‚çćIE B§1Mďă4?fK<×Ás]FŁ>Žëd 1žçRq%č€îfvűŁQČĘľ Ξ9†ÇÄą,LyËĽJEœ6Ą5ȔĐڍŠF °>źísG˝ŤçŹk >zŇăřx˙öW#âDą9Lřúš>Kux|šFÓß7ţśK˛ĘɘӧOoźńĆÔăŰ17{|öů8Ž‹ôşS§NąźźLŁŃŔuÝâFSłŮź' Éí`Čƒ-5Çqî!ł ŸÇśmŽ?ÎńăÇďéWÁ`0ŔóҒ–˝°@łm‹x`ÇH”Ý&b’$as3­ëĎ%ňŚdçPž|Ż"‘…,,,đя>žďŰÓśmÇ1}t?_C$´ZuŹ˘˘¤ÉJJ„ӡ ćALœĚf¨šçZZţ4I’Ďq3ă\ŇŠ(P–ĆşĂî5{nĎ*glŰB DÔŤi˙őp‹˛¤(ŽłRAXX¨QŠTžÍş ˆ×tfޝĚń‘ś›V„Díą Šť}m–Á˙x…Ÿú—Ľ§íĺȔŹŮK ˜›ÝůœŤÜˇĘ㥂|ä#H)9wî\Zږ2JŠŰň)+›.ç_qœúĚ!xđÁ9}ú4@AÄädLŁŃŘS*ECĆleYT*•L˛›Ů!‚²,â8b}}Ľőz}OÝ1/„ĚÝ,c ‚€N§Ăh4.Œ˙ vžŒŮŽdÂŃŢ9SŠTЉżiÇ} ­ć-pGŁ''ÍÄ>FOjÄ4•“Eo#Ż3˛g0§ŚéU Ľ˛˛ !:ɗóL*$nˆšŮX.Ľ…˘($H’tÁœ—)YΙ IDATĽTfź*łd¸Mƒ1ÇOÁĆfG(5ÝçËjť‚ř‘“†řa?+,!°çČ;>v{mžS&cňýÎűKŢw>˙ůĎł´´ÄsĎ=Wô ˲n™ć9ŻMrEˇÖšGy„Ó§OD eYS^2­Vː1űăbZŤŐ ™ßÉäNšYLźˇ6Mĺť6IłžŢa0QŤUń}ʄΠ<ŃJGŁýţĽ,Ë.&Xűi’şÚ\ďťŔ^9ÇóńŃq*•JĄ4şčaƒ=z\54› ¤%§•ic=)ŮĚ˒ČăóŚU3yôőlćRž-„ „1qŹp=+SŢ(4ЉůN„ăΰ2ŰÉ$‰I˘×ő° )–-B˘4Ôj5´Ö\šrá8âعøŽ$Šq’*cRrGn%#EĘ%Bí9eŒÁűƒçy["ĂsĚ`0ŕčŃŁ|âŸ(ć–çΝceeĽ¸Žç„ĚíŢčÉŐ0ívĎóŚHŸ)ň/S]2ĆŔŔŔŔ`ß2Fƒ 2™tbfďéÝĄ4i`4&wůם´ďóíśËîßí~ćŰiťę3ďĽOěÄqšÝ×Üjßś{M™0œí§ł%űՊëšY!Ќo 3LQƒ$f9,,0óKɄ3™ŰŠ)…Mę;(ƒˆ( ą¤Äľ­ÔsEĹë6Ƃ˘hŞÔ7çQCÚ( #z˝1ŐZ…$Žq\$ÉT–…c N-Öç¨a$ŒĂˆ0 ądůœČĂ˝Ó÷TZA˛;ęť(Џ~ý:ZkĆă€Á`X|îv{‘áp@„ŹŽŽâygΜfss“8Nh4 †ÄqD’$œ={?FýwţΏ6ˇýúíĆQ×uˇ$$i­‰˘ˆjľĘŇŇý~Ÿ^݃c ´–>|˜vťMĽRĄÓépőęUúý>A^0šâ°ŐjqřđaÓŹďJĽ˛EŁ”šň@ËK™f‰rCĆěyäw5\×Ývákp[KsĘs€IʄiËŰ!f60؏}Ř`˙Áq,ęľjVz4á/Śź_JdD6ÚgĎ͔0é,Aˆ’*fš˛™âEtFŒ„AˆŰ•$h d;iÉ͈̔ʋ­Śˇ!eşŔ­×[¸YÜłçůŮ`r›ßŻ5‰Ň“RŹ9„&‚ÔƒF¤Qó*Iv帅aH†źóÎEĆă1‡JKŹ”˘ÓŮduuľđĆ„a„mŰ$‰" Ă,A*ÉĘÁvŸI’„0 §nÎX–U”Ţěć¸t;DĚźůĘźßsb$˙=˙˛m›z˝ŽďűźőÖ[h•`Y’$QX™‘ÖšĺĺeNž<Éx<ŚRŠĚ˝cŰ6ŁŃˆ  Lů˝ •Wć)#„(śľÝM CĆě›Ĺ„Y\ě\›šś40ř`­ ¸ŽM˝^›,Z š%#_˛ĂŹßgR{”˙y”ł.H™2 łÝ• C‚ @ ŠW+¸n@ĹÉł•ŹŢZb3?Z{ť¸”’……‹‹AnÚîďľÖˆĚ#­œvŁľĄqlÇvŠś’rç=<Çá̙3ٍ$ŸńxÄ#.\@)ůč…ĹqÉۢ?ożœśT~ÎśíŒ8Ss÷5'dŞŐjQ>KĘ2ĆŔŔŔŔŔŔŔŔŔŕFƲu˙ĂśmŞľJŚqIe-Z'„ă!qN);„´‘ŽƒëŐ°l‡YýŒ.-îóÚĽŹ˜¨ĐĐL–ˆéOQŹƒ4ŮĐąZ)„Ö lr+ŕ›—ÎÚ窘­}ł( -yšÜž’@gą× QEé"۲ŹRR[ş­8I˛Eą Š$ě0qŠTŞn‘RŇl.PŻ×ŘŘX§RŠaVÂ˘ąŹ”ŕˆă8K<ŒąmŰśłDɄ8N2~‰ëş$™9ńh4Âó<'M÷ËÓ'sŇ '+lŰ&‚, SJm{MĎŰÚó<._žLˇŰÍČ›—¨TŇr)!ÂŔw0d¤™˜"ź|ßGk°,™ůŰ8†Œ1000řaZœĚ^p vłľ×ĺc4{¨fďÄÜ˝ĹáěĎŰ%(͒.ĺťf÷î¸ÝÎXhŒŹďíq*/Ě yš…‡ÉΒz­’*Z’ˆ(g ”Tń"-‹fłÉţčňŇK/ą˛˛’*âˆ0 pÝĘÄÄWčéčë3ŕ-ĝJă`ŒBăť6ž#҅$Tv %–•–Y˘0*’iBdöˇ5*/QJtšŚŠ‰˙Œ.bśÓů‹ŔqŹ,*U%*IÉŹl1/„ŔÖVąŘVID"a¸;QÎ㠔˘Ůl2Žˆă˜Á ëşŮw§(Mň}Ÿ(ŠhľZ…’˘BŠlć{óäÇśÜgr%KNŚäsžYo—œđ(˙ LJĘIYqO˝žŹ~I’¤ř›œźŮzÍÖE_MÉ-k˘K{ÍTşä­IÉ>ollđć›oâş˧NĐl6đ|­Ň8í8IżŸ;÷:ßúÖˇř˙Ů{Ď ;ĎěÎď÷OŤŮ˘ŐjĽ˛ÔZ+TŕĄ,!$lŤ.I˙ŤwćgIÔ T´š-„†Ţ‚C!c˛ąbhŐö^…­B (•Џm’l'ěs˝Üu˛ďŚsB'm; ­U ÂHü -đƒ)̨•GH˛YäCšH#Dhƒ€ Ž„0¤Dˆ(赌(hˇLó}™ßaĆ.Ś)+Őj5M­VŁP(PŤŐp'Ýť ăF*uÄťÚßęz^•ˇó[śžVg\˛&÷Ý~nśWť´“×&íGÉĎ$×ڙ ÚÚ×ßŐó<šÍ&RĘTA)ůýí`ÍŰUłjôŽgűn‰Ę­{ ˜›ťŠe™LNNĐŰSÄql‚@ŃlśâűÖ4›MNŸ>Mä˛Y˛šŽăbfTŠ•09ŁQZ“Ífş`L׺־Ž}\A€$‰JuušezÇú;|˙-ŚípÍ7r[Š7ďžE‡sňVäpIŸťaČՅí1‹Héw:|Ôb šćžÉť˝×Ť­ ŕöLŻţćçG}-ŢČ˝ˆ]žçÎëf7mkŹ4RŠśŔ@ßÄ{{ˇc÷qĎßđŹ[IvƒRË2Éd3­mŐ†iňŮĎ}–ŠŠ˝üéWţ”­gŒŽÁÝ}l[:‚í qTC43iBĆjJŠĄ^ÇÔ4[+á°QHiÄž…‰ÖQ‹‹4˘–!Ag°Ýžnw ‚“ů ”˘V÷¨Öh A °Ź JE•8śí UÔŽŇjŐą,Űř˘ĺy„Atď†a 1˘'"­R„4 ĚܛuF úúúŇŻŁś˘-+‹éóčééš%ćţ;i[OÖn{5[űˇď˝íí‡I%K{R´$€ĐN|0í yňłU%×isř×UŞśĎˇëîoť,Ůśłd7•'­Łżkš&ĂĂCiŤQ­ÖÄ÷ƒ89Ł•J ”-Ëڒ•׼Z‰ô ŠH›cĺŻ.ÓľŽu­k/K,Ó4°,łëř~ČNÖßŇ`¤Ý J䨟ÜčĘPčcĽ CEŤĺašćuŮü đâžpťčp‹Óŕ8ÂíÎ|×xWĎ.ÂXIĹHů śW™ŮśŮᘿŰqęŽŮ{ß%™›!ű1{Ji ęÚ6ŽeÓ1P’Văiő&śĺ ĺÉ(ZŁ…@ŃNޛđĹl!IąLŠéT2{ žQĄ˘ŮňľŔW‚Íş@™9<Ő¤V/‘ĎJ,!A€‰‘V<¨XO{ˇ НĚ2 ¤x^ŔÜÜ2ő†ŚŐňbijČşY2ŽK.—Ăśm¤R ŁbÂ0ŽüU1(ËW'D­†‚œW#TC‡h;ZĽŘeˇŇ~q=xąű5&ŻűžŸ‚vL†Űž×śˇľW&Ŕ‰ai%Ž"Sü”‡eťZR˘B”Tđ´5B|ßguu•ĺ啴ĺŤ}×ŰůÄxLűülcśWO&>Aú›ŚE*ꍨ2M…!*‘H¨ˆónj'W‚‰xÝâÍů`&bŒéZ׺־𐍲ź' ŚˆÜ\'Ěś-fGv¸˝"&Ťîó˝Ć*’G5ńý VA ]WAËĺbçj+ËővcöVëéĆĺ\ťś]V7j‹ˆĆ*iIŘj!SQ÷Úcv T>*Ö­g“qlL+ŞĘ‘B"•@éˇ^ŰyL„”$Jƒďx^Ě"#Ó0 ‚€RŠ”Ęg˛.Ň0MjLi1MŹ …jú ŁCęŚEF)Zśƒ6 <nĆ}§]?ŰsîFöˇv°%S’j•„K>ˇű4‰äsŚ$k= ¤”)¨ăy^ `$Ő4‰DwÚFDžl’RšĚě•+,--˛´´„Rۉ‚w" žüÜní×Řž&ÚŤú2™lĘýłĹaÔš—ľPIPűG;u@ňŢ.ÓľŽu­kŁC698\×í ˇ˜ócY&F+u`’ŇÝ(sĎu2Š]ű0ÇĘÂóü­ŹoźŽlŰޑńćgÝ9p#ŕGŇꆪƒC řEŞr#Ď´Ëcňţ™iš4›­.łĂÜK’(Žcă8†iE<)xiWŻ×ůîwżËŃcÇRî!%Ň0S Ft´ŃŃF!Ł;ÂP ŚńŃ8ƒ˝†űA€ëÚiE€ĺd°ě ßËâć"nĽN!Ó XpÉfmL#L[˘•Ű–hSÜŚ´$A‹HSIЈ3'Ačř>ŽăRČçc€ÜŽŞ Ä4[8­&Â÷Č>Ą4 ƒŠ‘%Ô Ď˛‘"z.Ś”(aüPέd~íÔ&˜€'ťľFíÓ[UťíŇÜIuKéçäĚLŔ›Äßi÷m’VŤ•‚;QőM‚okŤŤŹ­ŻŇl6p—|.‡Fł˛˛BľRcmmĺĺe††GČvŕŠŽ˝$a˛˝Eu;˙ÍvŔ¨ýů$Ď.ń’veŤvĐ4Q¨J~Ś˝•vëlË"_ČuÁ˜Žu­k]ű8şQĐ`š2ux’t˜Ö!śČFˇgH:3PéĎ "⿡e{¸HMLÜÖćÂ7#Ţ׏YDJ^wŕG„‹ďíů%DŽ$ź@şó^:„ŰžˇĘ0ľÄ‡8n}nďi÷}ŸlśpCdGf.Î"Í&ŞVƒF‚ šnśƒČf1rydlěŚŰgv~&Q럟fVPÚ4eÇŁÜíůu8ĺJĄ6ץźa;‘:J EDßÂ´Ž `şă´űź5 ‰R!Z›]ŔqŰ Â(Cî86ŽăD'–?Ż0 €+• ?xúéś}_`˜6ŚéB;#JťœľĐ)"ŁcAieI&Ƹ˙îC<üŔöí٧7mŮd26 ń}[؀@&šŢ1ßcÓo2aŽţ˘ÁđpŽkăXa˜ÝúúógűŽ“÷ęř|ŒBƀF˝†Đžđđ}Ÿ\>ƒOŃďT•f@9Px4˛™­VEŔHĽśžçÓ }\'D˙Í+Ďó¨×ëézËĺriĹgŤŐ˘ŮlŚŕA.—Ű•T8ń/Ű+  ˘]á(Š|koĹNŔˆ܈€ŸRi“z˝NĽRÁvl*•2++Ë4ëujľ:ŐjÓ4éééĄŐhPŤ×Y]]ĽZŠQŤ5¨×„m•%Š›Xłĺó]nc’kÝ^A Č´ß[;(ľýýí@L;#HSRČgČĺrd2ňůBŒéZ׺־†9‘.Lޤ$sľuE}Ź|@š*hyŃ׆Řňq LCƄ˜ďܑn'sK$ ›ÍfŹBđîŰŞÚKßS' ž§őš"P0”—H I,­uGţäBśWžč›?Ä@ŒV!JľĐşaô"¤™‚5ĎWËHNtKŤvç$$˛;ŽS’š•R’Éd޴ДִÍz]QtY[bqKŕCח:߸Żă9Ž}om•`ö2­ŤW ćç`} ÝlFZĄ€14Œ9>‰9š{r ŤPD˜f•˝ƒő°˝||7ĽĄÝĆzť:Ĺög‘üţö×góVŤíNń W:Ž:Z7Áćę[!_|ĄÂh#AGџÖ`„Ów žôŸcNN“l*]`᝞I]ëâü Uäq]! ËÁŇßkƀŒîŕCB"mŰÍĆčs0檰,“B>ÇčH?{†Ůˇw”ÓăLNŒĐۓ§Ď"Ľ¤Ő XZŮŕĘěR¤fx-ÍÖžâd˛ÁvłA+ ¸VbÖ$—ľŻk‘Ţ­eIŠ0Ő˙KŕűؖÍčč†)1ÍH­ "…"Ë20-‰eş„ZĄ…Äp]DËÇ |Ŕü$BŠôo†c۸öÍWŽ ‚ n‹űFŁ‘î“Žă†aÜjc`ĹňĆŃsnąžžNoo/qűëťŰK}ß§T*‘Ëĺ¨VŤ ÇAń˛FƒVŤ…ă8éB¤P´śśĆúú:H)Éĺr׾ý´sÂAV$–´ľ2ˇŸGí•'žďÓl6šrĺ2łłW¨T"Ŕ%T Ńx͆aP,1 ƒÍÍMÖ×6(WŞŃßžďGŐ4m¤Á‰Ĺ—B‡zb;ł›Ú^ÂIăyŢuÜcŰçuÂwă8NźŽ]˛Ů ×%“qą, Ë21M+ĺ’ů ÎĎ.ÓľŽu­kš“WĂ蝥.“ĂśŃ ¸:çqćźfvNSŠ Z-l ňyÍřÜqě›tČĺL„Üh ˘”˘VŤń‡ř‡AČää$ŸúÔ'šté###LOOi?hw˛K—.qîÜ9>űŮĎŚj+•€—ç<Î.úř!ś¸gŇbźĎLKśˇĘeÄ4t”ěn•Îę÷ČčH^Ôó6QŢ÷A­Ł2?ŽĺLD`œîłĽť˙ՍMţńżÇľk×Bđ裟f~~ž/|á ;:ŤŤŤ|ç;ßazzšűîť˲v•‘đCÍĹ5Ÿ—g}Žn„ôg%wŒX<°ĎĆ6flŤu'Áăہ1Ű_SJŃX^˘ţ˝ďŕżü"áěeôć:"Ňj‹„3Aßq‘##´fnĂzčS¸÷>€](Ŕ;(Ť_ZZâńÇgii‰Ă‡ó™Ď|ڃ4ń­‚`ß÷yýő×BpřđáM֝çy<ńÄœ(w”ľš¨J‰`ö áŮ7đĎžAöÇžˆ3>4-D*ËźsđŽ”âŰßú.fťî:ĚŠ“o09š×u™ezzšţţ>YXX`zz==˝œhm™¸™˜›J4ÓÉ`8nŰž-#_íé ŤŠe]‡{âáăwňŔ}w0<؏mY!Óźƒçů,Ż•˜›[aii/(äŽ-6yáäZ\i#Óv#iË‚–ߢ٪†!ŮlŰvp‡÷€żŐ`nu >ËÔ Ýoś IDATÄ@ ú\Ÿ´B¤­„–e295ň‰äuRٲM޸˝ýełTC%*…B`Ć\"z0(Ćm&–eŁľÍÍnÍľ,‹}űöĹGS.—9zôBDISSS˜ŚŮŃ棾fzz:–GŽáyţŽë˙FŻappĽ)ˇY˜äóů´âĽPWÁřř8CC‘\óN ­5Íf“JĽ‚‚ţţţôÜkŻ„ńGĄŁżżŸŒ›!“É`YfZQ”¨%E ŒJýSŻĺSŤUą,ť Ćt­k]ëÚÇŰÉ#% 돞 Áé3Uţük‚ĺU‰ěž=OzĐkuAŁ!¸ś yő”Çö îť§€m™ÇÝ[ew\7ÃçěŮsźđ‹,/Ż Ľäţ菹ýŕlllňҋ/sú7ŕů^dďŢI^ýu|?ŕ‘GćÉ'Ÿ˘żżŸĄĄAΜ9ƒe9č$ăŹŐg=Ju…iîßksv9ŕâJŔJ)`¸ÇDIšHŒóţc7OŮj'ůEúÔKĎQ4˙#’M|›fušÂ M´ˆU)yÎŽ÷-˘LcłŮDkĹćF‰çž}fŁĹŠS§xđĄăœ8q‚ŠŠ)ţâĎ˙’ý쏂RŠĚďţîďsřČ]<öŘßđĺ/˙<Żź|‚7ß<Ë/ýň?Kýb9äŐš­@‘5 žąyaÖăĜÇDż‰!?̈í­Ű\vżŮ¤ôÔăÔ˙čPW.AĆ@ć H+kŔ÷ĐWŻ,\Ł2{…ŕWţ9ŮÉ)Ě6˛Îţn­VăęŐ9~ú§XŚĹŇâĎżđśmń§úgüËů[üÎďü“<÷ÜsôőőóÚkŻą˙ Î_äŽ;‘ÉfřęW˙šFفF1;{•ů‘G9sćM<ČńăÇyřá‡X˜_ä+_ů3Ö76řŢăOđ‹żř_đÄ÷Ÿ$›Ë`•J…VłÉóĎż€ă¸\žr™ ć⅋4uNžŇ0Če&'FŘżoœ˝Łěab|ˆţŢ^r9Çą@CŠRcsłĘFŠJ­Ö$C,Ë ^oQŤˇX+y\Yh˛şáă ßo‘TÚX1 œĚ9×qќˇží;†‰e: Ž“k8Ô×7šZŢŔ´==YrY§cm$dźŇŘ†Ő‘Ě">™t´U‘źŽm”YߨRŞ *ő?Œ8uDŐBFŹĐD3Śi uHŤŐşé’ÖI;’mŰěß? ˆ¸˛i‹ ~§} “‰ZŚršloÜťąDhűu†A6›ĎđX:ÝuÓ1Čfłiű’a; ?D䵒ÁÁA`Kć:"ănŚsł<˝^ݧÜ0–iҨ×XX˜guu…JĽD­ZĄXČSŽTp'%ŁŽ€›€ ôQ:$˘*Ńôâšľć Ëe)˛d˛™ŽŐöóůz ŚĐKxsUŁv~˜äľˆk'K.—ŁŘS —Í’ÉdČf3XfTíU“Ę´Ú,ĺŠŃš ˆZՂ0ŒČć“öohwÁ˜Žu­k]űřťzT*šMÍó/—řŤo:”+QŇWk€ˇ“~ÂV×MžňגzŁÄCô’Íź],%„ TŠÍÍĽR)-ÖJsěŘ1^yůUZ^‹ 𙜘ŕSŸz?xúépűíˇÓl6YZZÂ÷=>ůÉG˜Ÿ_`llŒŠ˝Sœ:őFzżŚŒúäóŽŕŠ ĽfČF=`ŹÇƐ‘3Ť?BéY­|”Wi"Ěl܆ :ZšőU2­Çşž¸8ĚŁš˙†ń[ؙ1 Êړbžœˇ ’ĚZřAˆF섺óƒƒÔëuŽ]ťĆmˇÝF?űöE­f===<đŔ}\8z˝ŽíŘ!éďďOç˘`J¸}Řf˛Ďâً-¤ڌˆî>`gœő CüFŇSOPůćŽ@Ź4ńveׁ3JE•/?O=ô˙â_‘ðí]—mŰ)X^YĄŮlńě3ĎŃß߇ă8<řŕqNž<ř3g0M‹<ÎsĎ=υ ¸ýöƒÜ˙ýœ?!Ęp†!/^Äu]zűzČfł˜ŚAĄX`ii™őő5677šté2Ş"w}âN^~ůëë8ŽÍ}÷ÝË믿΁űÉd˛|ű[ßćîťďćĐĄCŹ,ŻpôŘá”ßŕâĹKär9ŻSŠz?ÇKk7ăŤ˙ĆĺçA0Đc{}ÇaŁ őZČ ďťîGKoźŠ8wÂíşŕfaa1{šűgQżýżŕĺ 8wCě  iü  P(00ŘO˝Vçëßř&WŽ\áŔý8ŽËK/˝ÄŃŁGY]]ĺĐĄCŒŽŽđ7óuŽ9ĚÓO=ÍĐđ0żúŤżB ÉՍ€k›°MÁDŸdĄäse=ˆÁ˜ŽÝĘŚâLšÖÓ4Éĺ2@ÔíÐؖI&ăPČgęăŔô8ˇŘËäř0S“Łôö0M#m{j4=––7(•Ş”ËUő~¨1Lƒ Ԛ°°Xf}łBŠęă?ŒNӐ(­Q*$ }Licȸb%n˙“čHPř-˛aaKPNŹ]@)¨5ŤT–Js z Y\ÇƲڪh5i%A†~€çE×_­ľX\ZĽRm1ż¸FľĐô†Óƒ҈+T đź) Ź8ČB`Ґ¸öÍQ™LSZĄŠx{â*žNUŸÝ“0íßK@”¤Ľr§ÖĘ÷’ě1M“L&›kUÇFíSfÜZ$Ú…śZv"Ig'/Ľ$!DÚžÓjľ°,‹ h6›Q%Œi*Ĺňâ" ‹×¨T*4 |? ŐňĐš&ľj-j1‹ž×BJçűiX'˙PLÝeÚ‹˝X–ľCEöő×;4AŕyŐj5–†i•w.›ĄXˆHvmÇ!—ËƄť9¤Œ•§člϊ>Tźn"¤ ŃJÄÜAíž•ŕƒkŰě‚1]ëZ׺v‹1ZkZ­Ż4řŤoZl”Žď ; ĘUÉ_}ÓAĘ*ޗ#—3ß҅‘RŇ××ˡżýzÄOa˜dłYÖÖV9zô0őF‘á!ćř‡üŽă05ľ—“'Oây>ř +++ôôô`š&ožy†sçϓɸiś­/+š}Äâ̂ĎËsM*ME֖L™ ôą˛Ä-íGĢ•EüKß@öc?Šk(żŠ‘߃‘BIP~ם ÚCk‰0$B‡dÄię•?ŚĽ'3Š0ěHu‘ÝNNÜřž=9z„Ç?Á‰Ż10ŘOĄP T!SS{™™™Śˇˇ—fÓcxx˜Á~Ś÷íc~~ž^xĂ4Čĺ"uމÉqVVV˜žŢ‡‚á‚äc'ććK!­Ć &w[ȏPŚ5:¨9MĺŤ_A]8ť{￀iJœžöu§#­ŮÄźňċT˙Ăď#ĺ7ɌěŮŐąˇm›‡z'Ÿz’ÁÁ! Ĺ>ô §NäĹ_drr‚#GŽpęÔiNœ8ÁŔŔÓÓÓźúęŤ˜ć ”Rô÷÷Q*•8tç!|ĎŁPČ322ŒeYÜ}÷ÝüůŸ˙ßřĆ7ŘÜ,qđŕíôőöR( ŸËŇ××Goo/äÔŠS´Z=üśmGüaHąPdhhžž"÷Ţ{/ľZ•ĄĄĄ]IĄßŻńR^Âşřx¨*._@|ţŸÂ˙[´°śí #ă`Zˆ„äwń˘U‡áńhOýOżýďs—^ăâ›x/>IxđŚí첟"…—ËWŽĐhԌިłwď^~ög†'ž˙43Óűšzőűgfxö™gdtt”Ó§Ţ`xx„őőuććŽŃŰ[D ÉfCQó4{z F{ ËŠŞ§ŮŹŤîřŮCšž‡VQGĄEČhŤ0 ‰ăŘ ő÷0łoœăÇďâř}Ÿ`jbi$]JZi<Ďgm˝Ěęę&łW)—ë …b†B>G.osńęg/­°´VGĘ"~ƒ-ŚFJŰÔH†€“PŰhĽüJ+lŰÂBŕ*7lↁ4 ĽÁjaˆŘô˝Đ1- CRĚö¨Q66—šňćeƇ ŒřQ€Úh6hľ<66ĘŹŹnráâ5.Í.qńň" Š˝ƒä ýŘn!mlÓFz ľGFkSƒţvĚUâ#Dčv2ĽíˆĘťBc˘ý˝VŤ“ËeS^œw ¤ź Śý˝;ý|ű˙ŰIk>”äőö×Â0z-”ƒ&Iú$$ď[ v¤­UŽăŕy^‡TőňŇ* TŤŐôhľZAÔý&››)ččű>*渉8”bĐŻ]‘(nóRJcZvZU´‹/áfŮî˙&}‘œśGx؎ĹĐĐ`tŽőöDBDœn‘Ľś~ŸQ6[-˙ÉóńƒhJ¤ž“–0ŐF0oŰv*Œ â׺`L׺־Ž}ŒmŤtS¤Ôš ÷„ Z“םÚb;şĂ÷čpۭтo}OR,4¸çhvW—(s”á7~ă×úűf˙ţrŮGf~~žžž>úűűY\\˘VŤ˛o_ź'AüŘŘăă{Á˛,úűűҲٴTW>ą'ę?ˇěĽžwŽYm@LňďM Ď}‡ŕŘ ř:Rpń*Ť„Żü8מJíŔŻŇĐ#Ř ß§iBćŘŻ! żŐB”O"ÂŘ”vä¨ -Ȫ穔l6Ť‘Ícç`&ˆÝ9~zzŠ|ćŃOŃÓӃ‚™™}üÜĎý Ĺb##ĂüÔO}‰ĺĺeöěكă8iďôžé)řÜç"BĺÉÉńÔ IœŞŢŹÁgfČűĚm„ ä f†,&bNŸJĽ”˘Y)łôˇ…qötzí)Ů1h×ĆĂčéAˆź%d¸‚P>š0–ś& …4ĐóGëőĚž_ò”?fťZÉ#Ÿ|˜˝S“”ËeĆÇÇéďďgffËËˌŽŽ’ĎçůŐ_ýe666Ą\ŽrńâEÖ××Ůťw/ŸüÔĂÔj5úúúX\\Ä0Lڧ÷aš{öŒňKżôO™Ľ§§‡ááa666Čçó  ‘ÉdŘ`†ţţ~öďßĎÔÔ^‚ `jjŠ ¤”xžGąXdxdˆ|>Ď˝÷ŢËÜÜ˝˝˝ žď`Lűž N! C˜› ÓBß÷%Ä#żhD}Šƒq›Děxk CPڀň&ÂÍ">÷ÓčŮËč?ů÷ˆj•°ˇŸpPő-ě¨ÂĚu]Í&žĐߟĂóZ<ůdÔîĺş.w:ČłĎ>CŠTâ×ă×xîšçYZZâŕ퍳ň0Ůo0\Ź”–Ą˜ß é1™0šľZ‚ô;ý8Ŕđź­BŰbr|ˆűď9ČŘČ 3ÓLŒ0<ŘG__‘ŒëŕŘ6I­Ń`łTe}­Âćf%坱LCh´jąśQáÍË6•şŚŮTqő‹"Th`Űt‘qűŞŇŠ€Pií“ =l %ŻGJ+fĺô!h!PńfYN\éŕÇUB@.×GĆÍŃ \^l˛Z:Ďç—ľÄfˆ(¤é ä ŁűFÚćo{ î†׎i˜1ßT˛‡$Ň ř„>ž×¤Ő$n;|oó0ŠL ‚€RŠüą#Ľ‚ôů%m6Iť\"ađŠ$É×uq‡RŠÄĺ˗ŮÜXÁó<Ęĺ2ĺreË%7Űś T Ă%ę>Îřřxş<đŔýAŔÄÄ8ŁŁŁéď¸î^;Ć1YIëYťľŻĎ\.×ńZűű{{{;îă­ ŔožI݆ ýhlF ~üż†â\>§ž‡ŢX€üÜö ý,‰~éċOĂŇ<ä ˆăŸ†{‚Ÿ˙exóuřţß#|Ł^{ËŕLJÉńăÇéďŔ˛,&''ŃZDŽä6?őS?I˝Q§X,211ÎĎůçhľšěß?ƒm[œ;wžžžb\.c=ěwxá˛ÇězČŁ6G&l&úş.řGeńZQç:6~ę>Žßű Ĺ<Ĺb+&€őý€fËcmm•RšĘĆf…Z-&1U „Ś\*ł˛˛ÄĘę*Ľr…–‚1@`ĄE$™ 1_ Tˆ$Ŕˆƒ^K{„BPđëxÂBMĂČ éJBej•"T!!fŹć$UAJŁĽHł˙˘m=Xś‹›ÉĄT@ĂkR[‹*rL+⥑NÔś†AJň+ă*…¤úUGH :EÚ%›ˇŤűDëθéjJo§ňřŃbDÇ˝)Bč#dTEœđŠ´W$‰–¤MiuuĎó@G2Ďš\HľZGi…!%BHË"›íl ÐZ­FľZĂkśĐŠŇÎ5ÔN°›Œ{B$œŽ)IG5Oű˙űűűéëë#“É´ů~"YPŃL2•ŇÝ|QIšNĽórëůľsŇ(Ľh4Ôj5Μ9CřOŒT*•.ÓľŽu­k?,ćűŠ —|Ξ×D ´¸‡ŘÜuČä“ÚäsdžFSÓl%j1ŕؐÍ<j5Íó/{źx"ÉN ‚.ÍJŢ8pü^E&#o‰{B0˜7:—˛O÷˝8C* ¨-͒}îO1ź8&ŮŐŽ€Œ‰QÍqî+łT^$Ř41üG‘âaBťN~úMf>÷wôﻊá*„aač9qß[%¨ôbX?°ŠXźËÝ⚂Ѣä#„Á¤Ś´ŚŇ¨ňŐk˙HyĆbě˘ËĚR˝ó{zČ~ńgpžđE.2Â÷·\:§°LÁąÉC<ú‰O2d|Žüo˜ĺ壄"!’Uć%ZŤß$(ŔÎŘAÜťťÁÁ>őŠO^ç@~XóýƒX“I6UĚžŽ\żŠ0Ä~ĆďĂDOÜ š^ÄO˘˙c¸zé ţă_"^}ýš/Ágţ Œď…lÉ!~ëßŔsclŹÂéW?ýyŒĚÎü–eqčĐ!ź= 2ŰÇňřƒ÷ŁÔVś÷î1=ƒ}űŚŮťwoúšŒË°\Kp˙>—Cc6ődAΖŘf—(÷ŁĆ´ź€P)˛ŽÍÄřH,KŹđý€ršĘúf™ĽĽuV×Ę4›-LC’Í88–d˝˛É… —¸pń›(bY6śmaŰ69{a šz€Pť ŔŇ!HŠŠ~ ŠR@É*˜ĺÜZ |-R€ŘL[˘2R, ÍfĽŚeb#ć‚3­¨‚Gë°Cę8ô#ő '[ˆƒZFĹ<%‰i:iUC$ l`šF<ç#ż$ @)I¨"âŘh­Čˆ7&–’NäžMˤŁ3ô&í_âă*'„Âę&Ř<ĽĐŇŔu3d\—PEjsI…JŽAŔúúŚiËş‹‘jRRMmŐKÉţgnŁQ‡˜Çfť„v˛fŽkR*őő´ÚşŽ­Ď ˲)‹X–•~?GĽ*T„ą„7)زÉ6Ŕoˇqďh]ň}2™ —.]˘Ń¨Óß×) J‰ă¸ŘPvÁ˜Žu­k]űźäsŁrîbŔꆡ EDЃ‚űŽYěÝB÷]wçCĆuĄ;lą°¤˜ť&#”Ę’s>qG€ëopmWMŘŒ˝çćíŇí/íÔâńA‚76^ ź<˙w˜ëkC&†ô€mI ňĂţďłYýuÂĆ"Ě(MX/˛vĘĆohîüÉżĽoę MV6ĐFˆßüwiĺšë3|ˇcňv?ß9ţďmno˙˝;Íť÷q…qví"§*WLž˝˝Č̇Ónë“?‚úé_ä+glţü%ŸĺŞÂ˘Šđí3Šż~UňŻ>wwßţ˘N˙3ěćk šqsSňŒšľ—ęװܞ•™đFçöNO}`ĎóĐA„0°'RŠ1 Dn)ÂŔ$ě;†řÖď˘s=Đl!zúP˙Í˙Œ<|ôôEU5€ôščÁQŕE2¨â-‚ˇö@d'kŠ=›o"ĺ§čÜUŽ)pLÉ@îV>‘nŽŹđÇéœö|–×Âńlę&ˋŹ­—(WkAˆë˜8ŽE!głş´Ŕ•ŮYÖÖÖ¨×ë4[ɜąDą‰ëşd2.Ž›!—qÉds8śƒ_ ™[¨SóÂv …ÉŞÓsĎH´QľIKe ˲ •ú4[ ,´– ˘ Řq]b‘§´bF‘Œś`ŤE$™űQۆ‡ďGíf š$ňöbŰŢe’Áž,{FňěŔql6ËMć6™˝śFŁé#¸Žƒ!e¤ž¤Hƒm˲’í:ž’TăťkoqşBhş˜Ja˘‘ şQ!ČіƒF`´Ĺb‘ŁGňÔSOQŠTh6›†eš¸ŽE>Ÿ‹ŞBt6ú)Yp´ß LÓ`sŁ„ŠçF{ëOű~˜TžŘśÝşh-‘‚Ž žäŒÉçs†‘Vá´WÖ$UWi˛ŠÄzűyúV•œíŐXí>J>Ÿcdd„B>ƒm;)yr!Ÿď‚1]ëZ׺öĂâě•Ę!Ż( mƒśgL&Ćĺ ĹBŔ؈äöŰLVVĄV‚PseNąś2ĐżspŻ”˘Z­âyŚ÷nŠ hęőzz0:Žóś˘ďűićáF‚JĎóĂpG Ǜa‰Ďă?ÎŘ؆apđŕÁHb0—KKPFÚ;44Äüü##ŁÜsĎ1jľJ)z{{ń}ŸJĽB>ŸçěŮłAŔ˝÷Ţ۸<öŘcŒŃh48xđ ŠT.—™™™!“‰űŠĹëëëi†íäɓÜyçôôô°žžNoŹŢŁľfqq‘Ż}íkôôôđĽ/})ĺŞyâ‰'i4ĄěţýŒŚDłĹbńŚsAŔšĘ˘CÍ\ŻÍłŠŒmú ů’ěç~œ9úxě•u˝îĆÜşâˇ÷ů?~ö Fďg`ůŤ€j“ˆ`՜'T !Ž! ‚€3gÎđĚ3Ď044”ň€ŕŔô÷÷ŤŤŤôôôP,ń}Ÿo~óo9~ü8Ůl†ŞŐ*•J…‘‘JĽJ)rš\ bTŤUzzzh4˜ŚŻš™L†ÍÍ Â0¤§§']Gh­yíľ×đ<ƒŇ××Gš\ŚX,âyŤŤkT*^yĺ<ňgÎźÁ=÷ÜÝÁEtł1zÝ;ĺy˜;řăţš˙ö?ŠŤ5Ëđ?€{ˇBčą˝Č?ůďŃ÷> ˇF‡-¸6 ˙ĎżC<ţ÷čžA˜9ˆ´ěˇ źŤŐ*ËˈA__ß[ÎÍv´^ÚA˛ŮlÇűßKСŰφaHš\Ć0 ŠĹ"ĽR)Ý'EhşÉűHČÚÚ:×Řłg˜ţŢ’ŐőŽ\žĘ…‹—¨”#`ې†i¤`łă81đâ’Ídpă˙ťŽƒëŘ8Ž‹í¸hlZd­ěQ÷MLŰBߊřך[íAÔ*DiÇvA+”VřĄB i „0Âa:„ZÓ¨×iľ<Źř:ÇÁśŒˆóEk‚PĹ-yNÜVgš&Ą ƒč5A€ Ö¸vľBy3G˝Vfx¨—‘‘~ú{{äś}ƒ<°Xć›ß=ĹŠ7ńƒ0˛eĚç-ŻÉÍęQJ*+´Ö¸Ž›‚ÉzŠÚ̢Šö€ť]2:z?iľ›hŻĘ¸,LsŤŰĂŔ!lľĐľ2aeƒĐ÷ ,- AȞŃĚĚđÚÉ׊ף$išxŚO˝ŃÄ4"sŰ6ą,Çqq]7ţ^ÔƝ U5@‘:VÄ;#Ój˜Dn;ńű¤”R˘B…羊ĹLËBÇIĎóŇqŰž˙éxŽnŒh;“<Ťvn›„ŕ­bĘAFk  Ćt­k]ëÚÇ~ŮŒńZŠjÍ@Ťé—1ďč°LËâk5Íľ…\N26}? ayEąYVŒ CÂЀdxČ`eUĄcšżZ]ŇhŞÔ‘Űn™L†OúÓ4ę ŽÝ} Űśšté2׎]ăđáĂxžďÔë Nźr‚ýö§ ZkććŽqĺĘe …/^bttĎóš|ů ĽŇ&ËË+Ü˙ý,,,ĐŰۋR!HŻĽŮl27w ß8věÍfƒĽĽ%¤”¸ŽKš\‰I2/pűíˇqúôi<Ďcdd„#GŽ ”âôé7(—KŘśÍŘŘšóÎ;9qâUJĽžďqÇwźgM,/#j | ŚŘTőŃś@YA&ËFcŐÖľÖ‹Ţ4UŰAęŃršüڝ |ŽÂýsˆĐ@7“Ś…ś š*ŹËm˛ťŚŚ&Š×ëźńĆh ===řžŸܗ/_Áó<Ž=ŠeY[ýăÂŕÁäľ×^gmm“'OągĎFGGX_ß Ď3>>ÎkŻ˝Ć‘#G8sćL "œ9ó&###źúękQ`áf8zô(śm!ŤŤk w¨%4›Mz{{éďďÇu]fgݞ˛˛Âúú:_üâOÜT0&Q™Xö"BiMËPź°/ĂáŤ.}‹ ëŢă\܄Óó!žjË<łˆ‚Ŕ ੠!Ëő"ăšcHń—QË@›ěľP5„ÚLšŰͲ,>Ěňň2`xx˜üŕ”Je–——yôŃĎđꍯŁTH6›ĺÎ;ďÄś-|?ŕüůó¸ŽK˙‹‹K(R­Ö˜ŸŸxœ(’RňÚkŻńc?öăœ:u’žž~666˘X,ňć›g0 “ŃŃQćććČĺrŠWľZ3úŽ=ĘóĎ?Ďç?˙9fgg)•Ęd2|?"3ľzƒM!“`6"z' ČXU2Î&ssK †{™šÜĂž}{čďcbʇŽsöüŐjíR ¤a`Z&ٔ°UPŃß—VŻ×ůú׿Něßż?­ňBŕű>š\ŽjľJľZM“DžçQ­VS`BkMOOžçaŰ6śmsŕŔ2™Ě-37“DŘN`“iš„š"ĘÍQ)—pl Ç2ĄVEm.ł ĎĘ@?זׂ0Tx^8Y–IjŒfL&-–ebŰů|ž|>ĎřřD$}ŢhPŠTYYYĽV­QŞT˘¤D ęůžŸ^†aD€Ľ‘€1˝}=dsy„xž‡çy)¨œě•‰ńV@uçë;ľ'‘Ętˇƒ1‘Żg˝´NĽŽľÓěVĆt­k]ëÚǎفŤ#T‚0h瀊I‰[U1Ďžčńú逞^ɏ˙¨ĂžQÉęšâ{OśX\VÜ6cňO>oc"’T—źyNŕŃÁ„’ źLŃᡜśÎňň —.]ŚżżĽ4Z ^zéöěăž{ďéčĎ­T*˜ŚÍwâąÇžFĄP@)Íňň2ĺr…矁#GŽ0?żHšTftl´ăľ,›ÉÉIÇeaa‘z˝Ćęę*ľZ¤^ŇßßρřŤżü…BŰvčééĽŃhHtńâ%>űŮĺé§€Ö‚ŐŐ8ŔĆĆ&˙?{ďkŮuži>kíxň97§şĄrdąŠ™T (ZIْşeˇaŮm3h 1mĚüŸĆüî?ƒ`€1čÁx€îÚvŁm-K-*R´DC‰ĹP9ޜν'ď¸ćÇ÷ÜPd‘*[÷#/ęĆöZ{­ď{×ű˝oĽR!ŸĎaŰöÇ+F°î@K Â(i“ˇŞŽî hVňźzţˇ¸Q} G Tł‰ßÉMAť™Ľ:݋@`ŕBĂK@6€ś˝RÁ=%c X[[cff– YYYĄˇˇ—ůů„ŒÓl6ąíĚŚţěfłÍ~đCňůűöíĺúľÇá˝÷Ţă[ßú˝ŘŽ<Ň`řᔄCCCüĂ?üœçŸ˙"ľZz˝ŽišŒÇě˛cźűî{äsYpęÔ).\¸@ľZeßž˝üä'ŻĐSéáŸóikhŇZvéŇe<ŔÚÚss 9âŢ}Ÿ]@fkřŹ5$Íś€ĐE*Ó.’aŕ IiDbźś•/6–1Yl;KˆA tćÖf/.ąşÖĄVoÓlu˘˘Vââ7ˇMî-]×SnáÔ´ MĽB–°đ1B|vMÖC”Y×P2€ĐC4,B@ŢŽK)Ë311ÎČČ0/żü‡ŇkŸË噚ĘröěYžzęIÖÖÖp]'>q’1ŰČâĉôöö`Y6…BL&jąČĺr˜ŚĹŋxčĄăźůć[ ˛źźŒa聏i ĆÇ÷ŕ8śm#Ľdvvއ>É[o˝ĹŰoŸĺŘąŁüŕ?ääɓ!¸ukšJĽL_ŞI2==ś:ľŰmz{{É ˝­Î*ţď܈Ĺ“0¸˜šM⊁'[ ÓÄć+ÄŇP. ]mJ …˙ö Ů†ËNÄô*Šq›ž¤§ˇ—ąąą(qśm4-úÝĽĽE2™ RJLË"›ÍŃÓÓĂ–őöK) ‚'žx‚ď|çďůßůjľSS“ź÷Ţ{ěۡÇq%—ËĹ­Ů´ő!ŇvjÓjľ˜ššÄ4͔ľ¤i:ŽéxžŽ´Z-Z­…BžůůyĆÇǙŸŸgjjęcß]†I8ń0ĘĘBs5VĚöÁ0A7"&ÚĄ§ ?­^řCÄžą#ZĄn ¤@(ąbry‚ýGɘć6=Ÿn0)IÄßzëmŞŐ5Ž;JŠTfyy™W^ů=öKKËě߀0 ÚtRŽTČ­[Ó<óĚÓÜźy‹ůůĆĆFŠ×ëœ;÷.š\–ŮŮšXČŐ R)S­V9uę$Ż˝ö:.\ŕíˇĎR(XXXddd„rŠ”2mę˙|ŔÔÔ$™L†ë×oţŚ"b7î_ÔÖ\Vć=L-@ˇ ”‘ÁĘĐĽ‡Ž…äłůœ…m›q+‡…iŮiŇvKuÉěb“™ůuÖëNW˜}Q;‰tę.Ř-¤ŽĐ4‰R>žď!…Dj‘˜¸`ƒŐ`葻‘Ąkdł6˝= déëą(2:\Á÷‚ `yŐá˝Kóüňý›ŹŽľé8‘Ö› j71ŁfŤ ř†s’ ڎBt@j`ę‚ĺz›™ĽŢš°†ăëԛ>A ° ? PA1vD=jCÄ÷c řZ–ĹoýÖomQOŠünąŮÜ:~üřç -m§ŽT*iťÍƒ häSAĐétČç#&aτaRCĎćÉÚYFň%N ›7Ţx3ՐŰy6Zš˘÷ˇi2Î!D|d<×tl;ďQ˝ą!â†!­f‹ŽÓÁ÷# "ĽZ b&şjÉsE/Ł[ô>ьIžOŹ;´̤Âë"f¸„!A˘ˆœĂ ÜÄD‡”ÉëŰ Ň$kí.łťąťńkR†H#„ĐB Ę%šĄJ!`r\cf. TŒGÉů`żFoERoÚŻŁi‚uĹź@ȍż×ő ՟š]hšĆÁ(Kœ8q‚ˇŢz‹“'bll Çq˜ŸŸçĉc<ůÄc\źt‘łgĎrüřqFFF"Ŕ$›ĺľ_ü‚o|ăëi"ăű>óó |őŤ/Q,¨ô”ŃuÁÁţěĎţŒßýÝß%“ÉĐ×ßK&kÇ'€!CĂCœ;wŽcǎaYĽR Ë2yüąGءo/ľZëׯ3ž'˛“-K<ůēœyă Gejj×ušző*O<ń8ƒƒ\şt™vť}[qÚ{d\ŁH蚄žŽôM–4ŞM‹•†“ŤĄô]Ëb:Y_ây–ë Ý6:U´†BřŞ) ˇ…j T[C‰ŸŰ˛–D§ę˝˝=Ôj5:6===čşÎää>ú(ív‡z˝–ş›”J%úúúҢißž}<ţřcAČĹ ÉĹ#I‘äş.?üá1ÍH ëäɇc‘sW7ć>†şEMظáĘHU 4aSÉúXŚF&S ˇŻ@ĄPŚÖŇ9űÁ7ffiwźX—RG‰&5a|#6ŔÝmÉr”œÚGŽ4Äâß(p]Ó01 C׹,Áž'ŽŽrâŕ0˝• vĆŔ44tMĆŔ0ŹŻűŹŽŹ39ÚËžÉ~ăó‡ůٙ›üü+ŹŽ5⢙,^dZ‡aˆ C<ĎEH Ă4R'ÇóńCčř R„¨.ŽĄŽiH]•"ÁÖF=čjý3Ÿ’÷ĐNĺJÝÂö;­şŽ366ö@ÚdGnD*ľŹ^YY!ŸĎG‡^qűj2o’˝5 Ăˆ˛,‹cǎŇq^ýu<×ŰYcE)\ϏŻZtHşŽ!ŽăĽť]çŃr­i˜–‰Z>QĎ÷đĂčPŁŮlŚ:1É|WJ$¸J|ÝUúyň})7^G"Œ)ƒ,ŒÍ ˆ€™tŮ |éţ^ní2cvc7vc7~mr=A.§S)´Xt ’^i]nĘyňQƒűtЁmEť].'řĆWmj EĽ´Ů9@Óş$F…˘Xđ)äŹ;jshšĆţýűŇ'}îš/¤'J{÷N!5‰’Gy”ŸžňSĆFÇRP(äÉçrLMMa˜Q‚S)— cJ˛”zju•‡N<„ëz9zĂ4#ý“ž>zzzŇD@)Ş=cé5JĄG=ÍĘĘ*ŤŤU Ădrjӌ’ׁÁ~žôĽßHÝjyäôŚ×˙řăÝÁć­¸ŘGúiľ{)Ť:"ˆNîU( Đ8=đ>?×OŇp$pńü6Ą2Ŕ—‘PŻ×Ś/3CŸ1^Učk€ďÁZ:ňEiÜö5Y–ĹÄÄDzM˛Ů,/˝řbTˆI’˝{§br‡ŕ™gžćÚľë˜Fô˜šÔ8qâDÜ'ĐuÁĄCQJ1Đ?ľ‚JĽ'J‚BŗžüĺŘACDEm˙čČ(ý}ý!ČŘ6/žđR‹4INjƒ0=™.äói‚ü™gžIÇşP(Đ×ۇBńôÓO011ÎřřžčuHÉc=šRđ{z*)KG×uöěŮĂČČH—SšÉ—żüĽM÷RŠŃёmď­ŻŻ€cǎݗľPŠ[ů"ͥ㘠WPĄ‡X_D\{ö?Vľx~ú—ˆˇžMužůŻ`dœĐ´ŕâťČůY‚¨EŠ}ߥÍĎľƒć€Śi”J%rš†Ą344Ŕôô-Ž\šÂČČkkkź˙ţťô÷÷˛˙^^}őUÖÖÖ"—ËbY&ƒƒýdł‘&ŚE˘âů|žz˝ÁkŻ˝Že™>|ˆ đŃuţţ2›žž&&&¸rĺ ?ţń8~ü8űěĺ̙3”ËE Ă`rrĽccc|ýë_guu•ŮŮY<ĎÁś-^}őUžxâ‰;´bŢeqŰľśŢqN†"˛•F3Âßő‘RC“‚ĽşFľ-¸ľÚ¤T i;5ZŸvÇĂ÷C”Ň€ČOˆ ö’îVÇnś†ă8é~œ0„XfĚTÓ%ŚŠ“ĎZô”3”Kz ŒWČŮ:šŒ*@“-fg—"k"jà €ľő:͖Cł=ë¸č†ÁÇ+Ý˙8Ž,sţň<3ók4š.BČČîÚUh"j[’R˘kşŢƒH!A#eař^€!ĄÓÖ§´ŕíZu]'›Éuą ďÇWÂFä>Îë_-ó,ar$ú'BÖ××Ňő,ńNŘĆÉ—€2Ý@L7óeĎŘ(ľÚ!.œżˆëFíŽę6™QŠaH躸.Ń|r“Čq2oĽ„ĄÂşŮ-"úÇĄÓqcA„tß' D¸i?꜡ÖtĂ´°-M×ăëă†^ ĘA°‰s;6 ńűŽr>5Śá.łťąťń€1ůŹddHą\… ˆÎš­¨Ç5˘{BłĽČçV|8Ä?łlA.„FSĄ‘€oBť­Rw&)a 7¤TźóéNRDŰĄBjˇ?5’šĆŸ>ýúиr đQîŠđâK/Ľ_?őÔS›6|y6žý|ă_K“÷¤m[îtęő‘Ć*N3SCÔ3ăVç‘z@ä*aȞĽ:_z•żŸű,+ő€Poă˘C Đ:P×92ü&ƒb ą&!ç‚QuIčtź˛4žđpď8NIŞ éŰĺŚTęृŻÉíďL۞ §_kŠŮÓŚŸ)Ô6궔ËÚ.|÷iSź5MăHy/?ZO??rä'NœŕčŃ#›ţNlúzrr€/~ń‹<űěłŰÚ˝†††¸zőjjAžËĺřÖˇžƒń9öěŮĂOđ÷V #%ňŔăféľ#qŇę |ç‡ĂO#žűc8đ$*[A(P_ü&|đKřŰ?G~ű˙„N;. huęId,€{ťűik‘ąő÷v^˙pÖGH4McttôŽ ™”’Ď|ć3ťö֟PqaÜv-2e!$Ĺf7‹3ša\ĚG{ox¸ŽŰHˆX‹cC—Eš.ąL“RÁf|$ĎÉcSě` ?GťU§Óę077OłQcqž”ŕ8&öŒ‘ÍîĄZ]ăúitCçƒ.Ň××ËâRË2dfv–VłĂŕŕN‡\.Gŕ‡4›-Śgfćšgöóů'pć—7řáŤçYŠś•jrDatč!c„I&…vŕAjiœ°e‚ H˜´E+R[˝OcĽb‹ůL|Mď˙úôÉĎ7uŰç5ŒČĄČuÝXäYmˇ6ŔBŸFŁA†Š.KČ4›M:…B!s„<ńēř~Ŕ•+WR7Ż{Z“×ظD€ÇF{DíN‰c‘`3,Œő]śíńÚś˝˝4zŸžç‘@đăŕűžďuľ÷mĆlÓ×R;ďǟÖ:ş ĆěĆněĆnüŠ ŰÖ9°WgřœĎ•AŽřŹŐăc’űtGńî~ĀŃA×AžŚ cŁ‚0P\žpífŔÂRHD'W˝•€Ă%ŮŹqۍ4)R×ý6Žďá…AWr(ŇžÝ Óߝ έ?S›>Űál?~H]jä4[Hä=c÷oĂTw}žd˙6l‹â—béŻŢFŹ9ŠA¨Aŕ#AÖS<Ą_eĘZbÉ(ăSúôjëô›U2aÚ‘Ş˛r50tüvžśŃƒzřVĄ'uŇşĽŁŻBšC;p#ADE”ŕĆcu/Ý÷; Ť;UüűRH2šAN´rÄŻčžš[q:Ţ;ĘS=ńˇs?‚¨g<ţšăťœŻ^ć˙>÷mžź÷ó|í‘Çřě!›Z[  č-„hÚ /_˙1‡[GΞŢ§ĐŁÇ"% ´nîJŮžŰűŠ@)ZKĂ0ژkRťĂHlżîęžF° 8ŒÁSęä5 MŠűÚ pżÇs#їŘC“´úPj˝#x-Xš‰2lČUŔČDvĽRC•z sĐjBé()ńrE´ 4ýžćN†Ôj5ŘżÚNây>333”ŠEˆŰ˝Â0daaR,t~ťÇŸŸŸ'Ÿ/Ëe?´ö„”ňž„Ź…S¤|Wü÷śsBqá¨!„žąşn†;ťE˘*nľˆÇSh)¨cÄĚ´\Öd ŻŔP‘ţž}yŠy C†dlƒŔwÉYşŚXYY„Ŕ3Ĺڝśeą¸´ÂâŇ2BH Ĺů|žľľ5ŚöN>˝==8ŽCŠ\bp¨ŸZ­Îňň*Śiŕz“Łt:m˛9‹RŠ€Ĺb–Ď=š—ƒS}|˙•‹źöć5T\DGE~Âî&€Dđv3ŁĄ‹yŤB‚ Ző„ĺyŚŕŤDt1KÔmďť0Tˇl>mP3ş. ›%›ÍŚL—­6ÎÝî} ó%ŃPńýh-ět:4tLŠĹbęЕü}Ąçá‡OÓÓÓx]ŻáN€Ńśő{ËΕź\-y;ěmtąˇ>G dÇÎ[Q‡“Ok)9ŽK"&>Aŕoî_ś1[5rş÷đRŠ´ ĆěĆněĆnüş2ş.™ˇ8rĐezÎĂqL_1ˇ°´rîýH ąÝQń)8¨”Ş„Šżűž‡Ś)\|?;SFŔÁ˝‡ö1tyŰ#T!5ŻCĂď0[[ćé([y;LĆ´şœ>ÚŠđţV)pC'ôŠ‚Ź4HÎEňú5]Łwj”ĺ?x’ő_GTr…6š)Ŕ—-ÄĐC†ľCZ=/ J!˝Ą4”'˛$Ž—Çk÷P?uóĐItŰžăuQ4—šŰfľSă7Ţ%P!Ÿ™xˆR&őÜćJ*ąÁLÚ\’% ՝GŔ ŁÖŸźnŁmŘ<0!…$gfřçżÄĎćßbYU bǎÔŢŰmóöâ\¨^§ßţ˙8Ú{=Ĺ!ßăňŐk\^ťĘa}‘oŽŢŒĽz%sN!GîĹř2šfď ž!húj^›†çđúÍ÷Š9 NŽ`ŹÔCYEx‡kž4;ˆMpYb“vŰ1Ž‡Ä Ł„ź ŹřäZ}Źů˙‰ßcRbf 4~nžŮX$f.Ŕ˙ő?Á _üď˘wřł—˙ţA]š€ˆ­^‚PÓŠ9Mžo`ÇȝŘ*žpöě;\šr™RŠLoo/J)Z­Żýâ5<JĽ"žďsîÜť=z„ĄĄĄM_÷š÷ţű05ľËE׾˜š˛ Č켖$:ŞëP‚”I\z’vˆ´MCl˚ąA4]ĂśtLC’ą † ŒUŹ00'cJrśNťŐ@Ó4nݚÁ%|ßĂó2´Ű‘“™ëF €fłA­ˇ(Uk~ˆçť.`lĎ(}}=hşF>Ÿ% Cn\żĹÂÂ"ĽR ĎsÄq|/ ˇˇŒe–­g~šŇäs}=ŮHŽ[J”ŠX?Ýí™Iąť„ŮTčĘ.Ńâ˜Ĺá8ű:‡7ŸľľľŘý­2D"-ÁŽ_żA___\¸ŠöJŁŃ “ɤc™Ř\-łťĺH cFĘ`‰Dz#םžXœóúľÝ .qƒ H˙mˇŰŠ7DşDžçĽ-މžËŔŔO>ů׎ 0==ĂjľJ§ÓŮjÜi˝ÓÁ˝Ž}›“ŽD1”ŐuŸEÖŮQ+Z2'Łľ3đ˘ÔŚ–¤ŢŽéT*eNž<š ĆěĆněĆnüú2ÍZ<őh‹ëˇ|.^1qÝč„Ă ÁőślR„ią­A§nr„Œ¨ÎŠąa—Ď=%ÉfÍ؎rçüĽřÔ}‡++3üŐť?áP˙8s^žr†ąâ ďçFuŒ•ű C•RÚélm™Ź™ĽlgSnĹĹĺ[ôĺƜ=Ďł{‰hË2r”đĂ?đy{î"Oî9ځ‡%ôşeIHn™L|őqŽ\œƒ˙ňKü°F.×D7}¤ćƒ"ľ´!È˘$Ud˝Kôo(5:N×ď§ąoďń§éAŢá_ř´‡›ëóüçł?ŕĐŔ8–nđ˝KŻ3”ďáŮ}§š´| !Åި<ˆűÉßcąYe¤Đ›Ú˘6Ý—fčÉț6•lS3UHÝiąÔ¨ŇŸŻPÉŠůlÍ@ }ĂJúŞ35McrpœŻ?Çźů^3˘$§É˜ÂCÜŔc˝SçFm&mç CSš|ub…˘ć“8'Ĺĺ I(‹4ĘČ`Ą!wn#ńBŸ†ďĐô]ţן~›ńĘ˝ůgnžÇ\…G÷C ř[pjô 0¤Ž‘RŠ–×!P%ť÷é+j&Ővśç0Ő3JÁÎâ~ܖ$q—7ŚĎó™É“ßWRĂÖĚ H5]„@&ňŃߤýł˙ť1‡ôÝ ›ë•đ—˙nÝQDü—˙„ş5ré'~ž„űľßGˇm¸Í˝´ľP*äƍLLLríÚ5<Ďăďţî;hš¤Ůh2<2ĚŮłżä7ĎđôÓĎĐl6ŠŐę\˝zË—ŻĐŰŰËłĎ~žżţëżBÁh4šĚÎÎňýďŸů/˙œ^văA„¨6\]ÔŚŸl°D Phš† şu]’͘dł•JއŒrhß {†KŘVÔędY&š„wΝçęj•|>O_o…÷b™&FƒVŤÍűç/Q)÷Ňj5"Ň ň\Ÿjľ†ačärY.]šctd˜\6GĄX`mmĎóhԛ,,,3>>ĘęĘ }}=”+Ľˆą‰żÄíXíśGťăRk¸,,5xçýŢż8ƒÓq!Ö 3 =›ŇD&^_ÇA×´ŘyjCpUÄEu䤁12ą%&đńľŤÂ0¤Z­˛°°€çy VVVPJŃÓÓĂţýűŠ×t:NÜvľˇÔj5šÍľÚ:–eS(äŮż?SSSŸ3&rŮÓ1 ƒVŤ•2[’Ö¤híŘpâBŚě–n`$a×4 lŰŚRŠln‹5VjľZIJ˛í ŇčgppVŤÍěě,gy6ž&ÍH7č.L™äΐwČaîŔÜiLđłűx*úY"ˆ­vfŮ$MץÓVˇ‚BąŔ#<˛MżkŒŮÝ؍Ýř' ĆD;ÂČp‘—ž_ŚVo0=›#ocżš护úM€Ń„ ô´ůڗ}Ć÷ ܙ/Ŕ :žËŮŮKšâń=Gš¸t“żżđ {ň(~peešőNƒ+Őę&{ʃ”­<ď.\eoßßy˙U*V>Í/ç.џ+seeŽăC{yůŇN îăÜÜetÍŕČŕ$ď/Ţ é4ywţ §GĄë:NŕjaĚ>ř•ŒĆ=—fęä†zúĂçXXsń~rgĹ [haY†ô‘z€!JސQ*đ\g=ëTh¤ţÂg;uÓ2wVžđŻŠüäOÉŹÝB„a4ż‚VŕĎ˙7¨+h€pşUĽÄ+”Xú­oQţÜsMżçö ¤č€¨dnnާŸ~ŠĄĄ!ţâ/ţ!§OŸâĐĄC|ç;O&cł´´„ëşüöo“˙ú_˙ŠK—.cŰ6/Ćg—.ý Żźň ň'˙f‹öwĺw7ăí"aŕÇ›í¨ťľ:˘y+c§#I!o15ÖĎřH…ąĄ2˝˝lK'c,..˘… Ţyçý}˝A@_Ĺ|=ŁĂ ö3=3@pĺĘMzzĘĚĚĚRŠô`[Y§ƒ@âş.š¸žGšR˘Óiă{÷N˛źRŲ-tM§Z­’Ď۔Ęyô!,SG×G#PY):Ď h6;,,Ő¸1SeznĺŐ&ëľ6mÇÇuA 1ĚBřHl_ËťÖ~˲Rëjß÷RŤn)"}bF‘f™‘€oĘř¸sPÓ4) X–…ďűŒŒŒĐétČfŁ–ÁĄĄÁxÜ´ô°ŞÝnł˛˛š:Ľĺc{ůOZÜ<‹–eŃétRŃnˆDÍuÝHŻQbóaښ”€ív;mo*•Ji;R’?$1š&ʜ p'Ňt éëëáKżń<Žë˛´´ĚŇŇ27nޤ^Żo8/ÝfŸßĘ<݊Ĉé~œDşÍ­š¤Ű,şťtan§ÉcŮ{§Ś8zô(ƒƒýX–ńŠ,1ť`ĚněĆněĆŻ€éތ4Mrpßüę"ßűQK×3¸Žžś#ĽÉJŒÁD'Éa|ڔ$; ]˜ÚÓć+Ďů?6„v‡ö¤„t­âÓ/đXm9üÍűŻĐpZ˜ŕƒ…ë<5q…˘á´¨;-žž<É_üňež?đ8u§Íjsţ\…Łƒ{šRXÍ*ľN ĹJ nՖx}ć<Ł…~Z^‡éőEžrř)^ťő^t*Ą@ ż’“ű&ŽŮw`”đOž§:TÄyůîĚ †t0 ÍđĐe1 j„ĄÄwLćj+›~çÜěežqâYnTçcw‹K7ybňËœŔĹő=^˝úżsę9Bü0ŕ݅ŤRG×t~výŽŽĚđů˝§š˛:ły*Š€Bľá tˇDëOt4ƒ‘ňżwě7ńŸ×VÎQ÷›išˇéĽm 3Œ[/TÚô %$"eÓHÚ PĎ~…Ęžoašv*śźíëęŢjz.Y+Ë.˝"@JjŤ„(nčłŘ¨2ëáÜěe2†ÉJkŒa!…äp˙kí~ŕss}ZťIŃÎŐVż|÷G<ŕQ~|őm† }ôçËiÂßÝQ2úˆIŠÝÎRţâﳞ+áüâŰ䧉îÔ6ŢCüŢ6ÜR%žaŇŢw˜öWžIţ7˙fĄˆĐ´ť‚1JE˜gΜaxx8b4ꘌĹôô őz=‹œĂ÷}úűűZ­vtŻ;‡Žë”Ë%Úí6çϟ§T*aš'OžäěŮłT*e …ƒ-˛ŤÄ..Ó]Ćó#´Ř‰nŤsšŚI 9‹‡phß “c}rśĽQ*f°-ƒššeÖkŤşřAŔđđ ş&1-››7gazz†B!O­Ö Ÿ/°´´‚i”JeœŽˇĚt:}ý˝tÚm†‡P úű{p\—ńń=´šMlۤPČS,ĺŇĽžçÓh:´:ľZ‡ůĽ5ŽÝZfaąÉŇJZ˝CŤăođcˇ)u„”Ě’&ei$kŠŘâJ#Ôf^)RlkcJ˜3(Jޡľ¤P(P(nť•ËŰ'zŠT˘§§ĽTĘRů4Â0 ÚívşÖ$Ŕ­‘n”ŽoŹ" + 1ĂKŘ3BˆMV X“0c’ď)Ľ0 ƒ bki•‚8N'˝~RJ …Ĺb‘ÉÉ >Äěě7oŢdeu5ŽÂ`łďśöĽ.á{§v\ś.Ű~/^Tň˙övĽŽö^]×Éfł>|˜ŁGŽP*•âÓËYvÁ˜Ý؍Ý؍¨‘Rbpüh?šě?ýE‹wĎŹ×l‚PtYnŠ÷HŠĐ¤˘s8|ŔĺsO:ЋžˆŮVďĽK‰ĄéLőŒđúÍ÷Đ4žl‰šőe>;y2*ŽdÔ3ł˛ôçĘ(Ăbšš†.5*Ů<7ÖćѤäFu˘ĹÖM–škä ŐV–×aÝi°ˇwMj\[%c˜H!ă íŠÄ]ÇK™ľ:ąŁ”cůŕ0Ť?řóY2Ë-d;:A"vP:`âćmÚ+ˆ§Ś°_:ÂĐ‘Š¨?]ŠŰ&2ÝߗR˘ ÉDyˆ_Î^ }2Śă{ěë‹r^!ŃĽFưč˖™ŻŻ’1LnTçYŹ­ńš}ă‡!óőUŽŻÎŃňlݢÖi„A¨hšMÜŔgŞg˜Őfůú (…&dšČl¸ôş5žťuL~U…§ X†ÉŃáƒü˙ŒÜ{~´x†Śß"ˆ ‰îÓ3 d<]tx¸ŕctŮX+ĄÓRƒ´ żIvôkdr•¨@ŮBߔh ‰.4ŽNńŸŢţo űh8.˝ MÇő=tŠ‘ˇ˛ {¸°t۰đÀkŐ9 ŒSw:xAČĺ•<ĺӛ)âž Xm׹u“‹KˇčĎUĐ5ĹFMjŠm¨†ŒßË?žşŐ3HńsżMch+ŻţgĘďü-fł 2@$~oB 4 ?›gő‘ĎŔןěÓĎaKHMűP:ƒƒC;v !ŕćÍ[čşĆÜÜÉČČ0GŽI5N:EĽRćňĺ+ˇ=Őݍw_ŽX:ş.CÇů$…˘RÔ84‘çąăƒ ö˛´´Ę͛7hőö08ŘG_†Ą‘bm­ŽĄ›üň—ďR.—™Ÿ]&›Éáy!JI Ăd~a‘l&ƒeš,/ŻR(äŠ×ꌎSŻG˙JŢAčăyQ+_Ą˜gp¨‚ ˛Żöƒ× čÔę6ŤkMŚçÖ¸xm‘ë7VX\Y§ă8˜ş‰ĄhşžŃNƒ"Şţ"á#ĐQXŃrŻ<Ŕ'$„@m*ę5)ŃL˝Ë5ÇOŎSډ‰ĚýŃîŕHt×u'nŰů´ç™iš˜Ś™&ˇŰ˙ťÁăN'‚@%—ËĽʞçms"ęÖ¤I~–ŹIívĎóČfłäóy4MŁŐjŃétčt:ŠÎNŠT¤ŻŻ—#Gą˛˛ĘŐkטž5ÍÚúŽăČSľI?čNărwŚű1ÔvbÍNnHq+ÜĆÖŽśĺ˝BF9÷ŕŕ Ǐçŕą†ŽúĐBëŸDŚšĺvă "ţ]˙&ZüĄÇ&`eŐZújwóٍÝ؍\‘ôAÔcëůŽCŤŐFš9F§bw…ť/ŘÉŠšă´)‹wÜh“ßY[ďpĺj“ˇĎ5¸pŐŚş–G)#ýI‰¸•suöďmsęĄ,öĺéŠdĐuąŁŢÖMIŮ#Żx-ŞíçćŽp­:Kư8С‡Cýă ëí:ßE“•L[k T2Eޝ:YÓF—u§EÖ°iş-ti K‰Ž×&gf¨9m4)éɨś‘[ŕ1Ő3‚&$e#G^7SÚO#”RŹ­Ő°, MÓ‚€ °m3u¸S ”"đÚ­6őŮejgXť0CpqšPG¸!J(g`˘—ĚąQJG(O-çэřÄńNăÔý\„T˝6Ťí—oq~é&ĄRěăpßYÓfĽľŽ@Pm×.öŃtŰa€ëű„ z™ŤŻ`jŽďŇ \&ĘĂLז(™šX 7ÄóúňځKŰu15žL‰œn‘ŐMĘf ąă ؝“ޏ~_6­¸4RqžžňŚSˇîĎW/đ™­ÎóĘĽ×ůËKßĺŞ3‹i˙¸ Ś€CvČ˙<Ůât!• &UN#žNaŕfڌŚéwľ •˘ę6Šů.,ßäâŇMÚn›ÉĘ0džö‘73*äfuž˘#cŘT[u V–ĽÖ†&É[YZŽ‹!5Z~›P…äôLlkŃMš^” cŘH)hş:žĂáţ‰Řýʤld>–ÓGťfł…ďXąľ´ă8†N&cßuœÓĎŸŔ÷č,ÍQ?ű#Źď˙TŚ?@[÷˘6Ľ–F˝gk˙ě)~ĺkŘc“h–YdKyϖÖÉs&ż—|ÝMĹßpUS›œsş Đ ííĎŮmçú íwľZ˲ѤνL“ČFŘcqć:Ęk“ÉŘX–‰i˜1€!ˇ1HÔH,‘śëš´Zm.\ĺO˙ߟrcśŠç@˜›ÝďMjĐ[48žˇÄŘH‰C÷°wrŰ2č´}>¸p™ţţ>:=˝enޘ&_(°0żŒah8ŽG˙@íf‡rO‰›7ŚĺĆÍiöďŸBАžž *0M M“X–ŮJK‰Ś TľŔA0^@˝ápcf…Ëח˜[ceĽIŁĺâxAâ‰Ř)é¨P˜šŒ€Ěރ‡íă(BhaÄBÇ~ Řl¸ä$"łÝŽŒÉýŞC×éŻäůďç4cC˝d34MnȖߍŃćű´]—F3ÄĚ ˘é˝˝•M÷Ů?ťwĽőzƒvť%­|IîcĂ0°,+fri›ŔĎóČd2¸Ž›>^ŤŐJŮ3ÝzVÝk[˛&"ÝNÓ4ąmÇqp]—k׎QŤŐX\\biyߋDţwÚGîʎůvÓŰ’TWňöVЈÁXćđáĂQ+Z.‡ięąŐw¤ăű>{÷î}X<Ŕüř#ˆ?ÂŽŐőoˇ°”Ú~üŮu`ł[níĆněĆnwJČÄ×4qÂďĺ…Żpjâ8Ż\xŸÎžÉöíĐ!D‘ÓBžÔë˛?o „A',°ěĂ/?GĎČĂŘš!tĂÜÄEg\w IDATŢˆR‘ŔvŢČ „äp˙8ĺA<ß#cXXzdU*…ĆžŢŃô1ňą“I)“۸şVó5/â4ŠéTŒě6Đěӏş&!5!5˛Că˜Ď~“úřf˙î?0ôúw‘2důř#ż˙?ŇűĐIĚRoęœôa­żűń4"ä?'^×îŕÂöëJmXőFĚB˘!Yoú\™Žăzőz‹ęjcÇöR.(WJœ?™ÁÁ>|/`ph0fTÉ؂zŰfue•~˝‡ţţ ‹?~˜Źm!P˜ŚN&“Ç06@ŕČ]1 Ý pzŁĂz˝Í­Ů*7fVš>˝Lu­AŤíăů TĚjLʟcFJ*î/AĹ"ŻQëô÷ž¤â ƒx]ŐA(¤đAč‘AT"Äťán?SW‹ľ‚XÄ×u-őëÇ[wgŤj`L÷ű‰nľéŔ(:Źhŕű~ږ–°‚ Ŕ0ŒPB°¸¸ˇRšŰ5ÝëarMmŰNŰó<ŞŐ*ÍÁýű÷§.P+++Üźy‹•ŐUZÍžçEVďwИšs/{ŠÚ▘1Ýî^RJňůcc{8yň$ĺrŰ2cś– Óéŕy LÓLŤO:vÁ˜Ý؍Ý؍O9Ů˝Đ§¸MQnY:–ĽÓSÉrč@oŞ/„HüméŚUîh%y‰ˆˆ‹Â>+OÁ´ńě"Ÿ´=N˘SŁI‰.ulatą•EŹQüÉôîîtb˝Ulîn—m+@×54͎hν*"ľĂcމ†|ˇ°4Cćț6˝vŽŤ€R|’-BLŠc t”ĝŻíýLˆE×IëĆ÷ؔpíTdw˙źÉslä ‡†öň{ÍŻqsnš÷ć/qł6C6y˘W°H‰ys/ůž}ô c p"SÓçQށ 0Ľ†nfČžšÁÄá‡ŰKäVX›BÇĐ54>]ŚŮöÖČDôT|ä{Ujfś@ĎąÇhîçĆé—PŽOĄˇˇ4 )ľŽy"î ë×bgę˛lŢ˝^;ďS‰ŰVnĄŞpHĆňrŰś°,Űś°3““Ǹ~í„…|ŽlÎŠŘ Â×§Óńhľ]ÖjM–W›ĚĚ­qéÚ×§WY[oĄŇÜ@˘Â¨(—Z—ľ4‘Ä‹›[ Đ"]— p]ŻK''š‡5tÝčŇz!bĂ(RVTbŞ!|6‘Ş0Í[Ň6–˜ĺxŸťín éAÓ[ó‡Ű囀6~ײěÔĆ;öu­VŁÓéÉdbFbĢJl­Ă0¤ŻŻ/j’–Ľdn'śÚݚ3É~šěŠÉßšŚ™śJU*9pŕŐj•k׎3;7Gľľ1%@ßíľ^>úuÜü˜]‡eš†eYôT*?~œŠ˝Sؖ•Î;M“é{Mt{>-ם]0f7vc7văSNëş7ľ­íZ=Äm{ŞŐŽ%ۇb6ŽH,a`é÷Q´NÜŚĘdł›čĘ3&ŘúKŸ`B´ő{w>ŔšKOú@I°Dř8`EîXh˜Ÿ°ËĂNCůaOΡ&Çi)˛ˇě.şĺŽ÷ŐíÁœS2Łhp8›c˙ä>Béčńc ĄEŹ qűv—Ű%ÓbRń$lĄƒŚŁ>ŐąŸşĺřNUˇ‘ƇXˇ*"*}łĽĆ?˙Bäd%ĺSi ˇ ,Ü[D,‚ŰkýÚîŘq‹ĆĆşą3¨ř>Rj(ë͐Î-‡ľFHÇ]b˝Öa˙žaŽšŕłŸ}œ7nqáÂ%FÇF˜ÚťÓ2Čdm*•ý2 Ű49th_ü$Ž9:9ŽÇZ­Ăľ[˜ż<ĎŐKÔę:އçG˛şĄ-{M˜J)T¨đ}/e !"0Á&VŠ"e1H)Đ4ID€ŠŢýˇ’Ř@ ćŕśśNĚP€…aŘD…Ó@ ŰYGk°@ …śĂâůQן;ç?ĘüN\ŒşŮ+Ý lj,ˇu]Ç4ÍmëZÄ\‰ˇLŘ@$Ň}I€˜z˝N­VĂśm˛Ů,…B!}îdŽ'ϗ<†Śit:lŰĆuݔ-Ól6ÓśŚDç&aËhšĆúú:BŠĹ"'NçÔŠ‡Y^^azf–k׎ąśVÝ˜şÖůŽĄßŞ­uˇźa{›]@Œddx„‡:ÁĐĐ0ůB-ž'¤¸Ž›2†ÇAA˙§ć|ˇ ĆěĆněĆn|jJÔâQ@5¸K/ô˝ęn­˛îC‚Ń%ž*n |¤ę=ů\Ýţĺv›x$”čO#!J6Žľ ULëŐ?h°Ó˜Ý/fÓ߼Ć?âÓoˆŘŽÝ[Ľ˙aŽÉíÇ*ŇCHNŚ“HĆ\.wŰ{f' 3šÇ,ÓÄÂL{ÍSC|4€sƒľFŞś'T—ËԎ7Ă' ˆü* D{)ÎŇÂ5Ň1ź——š}-h†D3ôčÄ=ĺ…mgiý*źü=iŁŔń<.źk7şn_)d:ŻśÎĂDP_Ó4B˘‚Č ¨ăJćWBęMľšKŁądŽ™dxxˆršD˝ŃDƒƒ˝ ÷ó˙ł÷ćArw~ç'óuvő tݸI€7ŠŃŒDI3’G#ÍzN;4Ţ]{ě°wíuÄţˇn„wccwcĂáˆÝńzĂ3keFŇHňŒ.˘x“ŕHgăj4ú¨ęşŢ•šź—Ż^Uw㠐 맀vW˝z•™/3ßüţžßœëĆ, ^ŃnÇď[Şś¸˛PçÂĺ*..qţR•Ľj‹FłMŤíŀ¤ˆ­™…P ƒE¤{ ­5R”[Ú)ƒ4t1\b6‹č~í0!b ,­"¤ĐH-;sČX§‰t„Va"\ď ¤ƒ!=V„ ‹çć<Ł'Ś”"—˭АBĐn{DQ,*\(R­@€BĄĺŒř­*Œ~V†‰C[gŽ3Ÿ×l6i6›ŠĆ €ëş+ކ!śm­/ kĹüÜĚĹcccŠułŮLEy bÚȰ] Eą•šďűÔëuJĽRú^ŕ„a˜~ˇJĽ’‚2†e3>>Fe°ÂśŰ8{é ł—fi,4iÔ´Űí´|jő9[_€éźÎômŢśaÇŽÝěŘąBĄ˜Ü_§}Úí6Žăŕű~ Ä‹ĹŰŞëŐcúя~ôăśm|%–eăű!–aŰrÍ$ţúˆžŕ^óŞ7{c.ŽţŤŽď~1aâűéxóIr˘äă8ö mČn[,nM÷Üđ=č[ßGfŁŞ”ŚŃhvěJ)ąm›vť…műärî %㷌E!zˇş ¤âcď˝[Ţ_ív;ÝôŚĽFR†!íśG>Ÿťî6_ýu"ŁEя>ZwŒŕîÇŃN+×ęŹ[K j­PĄB …Ň’0R´|E­Pkx,.ŀ̞ťś°izZ€Rš T´ZíV@­ŢćĘb‹—™š¸Ŕů‹5.^ŽQ]n†QŹ –ô“eš ‹3Bk+\v‹—Ʝ=!D’ Ť”aŃŢU{ăuQI¤˘Tě8}ś•iŐY›„DH°¤&Ö?ľA8ń\ˆBuŻoÁ ÐӧOECCĂH)ĂĎóČĺrT*ęő:łłłřžĎĐĐPÚ§Ífƒ={öPŠT>Ň=AŔüü<ƒƒƒœ={–ááa&&&REQĘĆČçó]ĽožçqĺĘΞ=ËţýűS‹íě1O:ćšĆĹͰkŒĆËŕŕ Žă¤}gʕ ĐbYVş×é\?ާzžGťÝŽ]6GFş>/[˛ÔËŽŠ?Ë÷đ@DeŸ‰­ëŘžm+^-`a~‘Ë—gŠVkÔëu|ßĂ÷ƒT÷'[Ҥľę3ëƒeIlŰĄT*R,–X?gËÄ:Ć7NăóXރJJćĐ ’˛ŞŘ•*ĚršÜGŕú`L?úя~|bÁ˜NímŤŐ$ŸĎcŰ֚€L÷ĎWť^Ĺľř'vQJÜZ:q„´Z-„ŠžůcŰ6QQŻ7( Šd?QYŮUâ;ł‹O9ăä>ť)5 žă8iňŸËš7d§šV˛ŸnôzדĐ}Z“UĽ4­Vœ8:‰łŽi?sZëyą`g>Ÿťý@f?Ňu%ŠÂ乊őŽú:;ŤÍq:efuÂâ„5ęŘä&zR+ŃFŃ A¨š4P­+–ꍦGŤísß˝ťq? YŹśx˙ƒ‹9v‘ă§.łTmĆ×2ŚÚkâZ˝€™łJ˘0BŠhŐdŇ$ŕ&Á–RƢ­€Š‘Š]Škˆ|‹Ř‰ĆĚËąöH”ĚÁćY7s§ŒŰD$ş;„HR4Jç‘ÂÝ2Áh#(3ńd"8ŤFŠxţń<‰‰I.^ź˜”ÜĂÂńőсΚš9‚ HĘrVÎűŤą0Ě~1fʉ”Xkę<—’v;v[*•Jäóy\×%‚´ß,ËÂuݔŮbŘ2†ÉR, Ø1ÔjľĐZ§eM02š2YÉ\+ŸĎwéŘh4‘ąČÖztKÓ¨7B°yÓ4;śoMmŘëő:*R,UŤ,..Ňl6QJŃhÔY^ާ.QëĆÇMąX¤RŠ011ëćHž” <˘ů řËUŹĄ˘ŇNĄH””˘742“ŮöÁ˜~ôŁýř”1FÓ"–——“zlk…uęÍHˆîävJż‹¸u"žZ‹ÔŇqœz#fł^ŇWrĹŚéz“ëOsbŁ…@ܲqť|¨ÄÝöݔnŢ{2 ě4›-Z­V*:yťž‹ě¸Íş)q=6žŸ’ůÍ|ĺř$ÖN7ű˝Ď•Ó℡‘ˆ(vě űqťŔŃĽIae\¨ú‘i'Ľ‰THF]ĺńx6˘Ś‘j v Ôqr)ľmŃö43—Ú4š!ĄžŔĺ%ĹҲĎĹKKĚ-ÔŠ7<Úm? CB`I‘0KŽ˝–Hۊ?3 Ó×fK+M‚Ů5wj2k›&ŠB”]c! JkĽťćš˜MaĽâĆąŰTÂŽĄS~$„Œ× Ą’u=˘ľR‘˛nzŐŚm;ěÜš3iALNާP(&ěʸFF†B01ą>ĂxŇYŔUA>ŸgçΝX–ņ z¸ń!Ť­ +Éu]†‡‡9xđ ů|lĐť˙ˆűDt4Faş Ž27ĺDĐaÂMĎóLŮ:ív;ĺ5 !s ß÷Ó+ uj2ŽKƑIHA;jÓ˘E[ˇg 'rpŠśe§š6阆‡q—ąąŃ”=­Xó<BĄ@ĄPHżƒi3™jÁäRŇĘšřś3<‰ =dk™°Qžf‹ĄÉ)PV˘?Ö[ňŐcúя~ôăS’¨dÔfNŞbQËNţöQ’×;?AČ|ęáߌ+g6ł۲‘ŽLUô{7ٝžĘcŰQÔąű\yŻWżÇOw.Žo™ň‰­%–ĺŕ$vŇ˝ cśüĹü?SąśLŻűÄíˇ˝cřÓ_DŁ;'áR’ËĹĽ}ŤfŠprâ쑥˘Ť>sÖ˘Î(Ľ…ë&ĺ)ýň¤ŤŽß:Ă*Y­„gľ’a$ź1˜Ą‘DJpiŢgĄvŢź„ç‡iŮE§äIJ%Jé˜Ł@ö|fŔ›Ń§2?Ď šĆ%HÖZKbf\$ş0 řjĹ A‘Za÷jɘĎV*Ö‚Ň S&vą–™Ď‰H\V‹ü(iŁpoŢÇčřHlűú•[až“2z× ŰvşœţĚŢĐAfh†R@,­ł64Fź×$†­bĆMÖÉ0M ŰĔŻAGŁĆçĹb1ŐŘË [h4-4 N&9\FÄ(śˆ_ŁŃ†!ĹbĽTĘBĐl6p]—\ÎĹqěÔ `ýúőé=çr1ł)ŰVćžÂ0ě¸<ĺ 1KK—PĹ Ţr UË%ds™¨QEËh'‡e9HŰžmŤvŒéG?úяŰ0č ŒY„WlŹúqËű ˇ/ÖŇęÉn8ĽTéĆŚˇ/z“ŸŤYWgʎm˙ŮşIŤIÎÖ˛ĎöĄ9î÷Őíď§ľćŔ~ŹŢ^śmŁt,ěžFţßqYLŇĆVœ¸7˲Rׯ˜E’ľ“mفqQ˜$ËŮr”ÎgĹk’"v(˛$–î¸)™˛‹úXZ'˘ůY'¤+&.ŤQ؎ƒăŘ]ĺ†]sqr KvŇĘ0 ‘Z_Jd4ß5*ě[1PDl}ę]Er_A"Ľű‰W–eŻi PšËY]ˆY§4ŹĂ|šŸż’‚1ccc”J%\׼Ýnăşn:N xa„› ŕÖ j4 jľ“““iš‘)Ż ĂZ­†RŠršÜUĘ 'LҖ\ ŽĐ›lÎoF$"×ŘÉž@çwĹb1-nľZÔëőT×FJÉččh ° šÍfş/3S>Ÿ§^Ż“ËĺŇď›j܍f;—§84œ–oYź+°ćÎpF§ˆň}kë~ôŁýřÔm~WŰ ÷Űߍ%÷kőE–y‘­ÍîÇí흍%‹kÚK÷ŸŻĽŸÖ˛Š_-‘Ëž°öűęöƒ1ý¸včäqŇ(S&Wv-Ȗň˜˙–Ćh(SzŇaŽh¤Ô=şTNč>¤‘–DKkť$ŔJŻŰ‘q&=&mćw)`cÓ¤„Ňˆ~ëj 6†iĽT tdĘlş\ő:S:Iz\ö¤ą„DĘěáF/Č~Ó7őzĎs>%Î`Ýz\fü@" Đyž‡ďűéX3,Ł=“eHˇ$!ľZ-[ëÖ­C)•2X˛‡ƒƒƒŠeVkŚX,ĆâÁD´T Oy8ÚaKq3D‰Őşî¸VdV(Ť×bßů,×uq'Ű5żËŠ÷:$ehĚuZ­š\.ꍔB$%zšŃ ôŕ8RE(ŻĺŐű`L?úя~|ę6u=ŽIq)…)Sę'"ˇ> I˙•nާÝM?ĹúýtťGłŠĘRşŻň?Ýĺ|rí~îˇ÷GíŤŐ´•ÖJüŕcÇÎ4ëžíŒký÷šwtƒďű¨żżŮ×ů¨ßż÷ľÝ˙ŽK4űĺI×nÁ´čîIOë{×öt­I4ϲ ƒa%dÁ‘ŢůGdl´;{^+›ź ŁŤ–^D¤ “Îýʤ䳓ČcYeŠ€3,žLÂ.’›1ŹĽ5"Sš’ÝŐˇ8-:Î7ą58€Ń“‘+˜Yćý7§Ż:ďGŕý¤1F\9+†^,–ŇRk e´Z­Ô) ĚeçcSşÔh4’ňŇ\ j0Íź'Ëd2 „4š ”P´Źśc“S9*… Ä웰㺔ËĺhľZ)Ł%ű}|ßOAŁ%SŠTR]?óĚe-ĂsšÜŠďgX:f,!bŁ3“ŐىßkĄ…D Çś sy{ćĹ>ӏ~ôَ€é,¨‹ŢXÓ²ŹtąěÖśčýwv#ÝűšŐţţ([™ľ>cľ×ÜŞűYíýŤÝGďŚEŹňßz•×Ç@˜qŇZ”uú*"ŠÂDč×íč!RJ§ëUľčv]˛m Űv>D’ŮGc>j_Ĺtö(ĽŔŻF+Ʋä ;ň›ŸĚˆxÍZŻżÚunô3nôuz9ďĂ´Ag^TJgÄ<ík‚gý`‹%[z´˘ěKݜS˛ÖҐɞ×˙Y0ŚSf!RES6’eš¤ŸŚť™&ĆyŃŹuQk‹8–›h7™×e™ŁU“€w˛ăÔŤC#(­R_ó{)bdsÍôš—Â݀×MŒĎƒ5w˘K'ŀ$Œ¨VŤŠ@ˇ{Žă¤@Őââ"ĺr9[7ĽIĆĆ:{Xe˜4DIEŽ4‚Ő°ŠnƒlIrĽ^ËKÇśé×uSŔ% Č‹iS6UŤŐRűń,ˆiŰvZʤľŚÝnłźźL†Š#RěˆŐŃŐń<fłÉČČHט5 hśüÜBśmŁoÓęƒ1ýčG?úqëá˜tck&!XażŰ˝Ńž‘Żő÷Gd¸Ć5Ĺm¸qďľűžÖç @Ś o™$ż[ 1kâ G_WáăÜt‚mǁF$°WëǀkąëÄÚ:@WO´ú%h7+Iˆ˘ß÷R‘Ęl_0ÚuŽSÝ~Üî~ŇX–ÄóşçŔ~Ź˝öÂŚô(ËÂëšO2ç˝ĚĂ@ɊŤfKw✊˘tŽ’V‡]–&śĐĺÔÍŒ•”1‘€ÜąHzüű,ëŚ źKŞ’D†ĄhbăL$ĽDZ ű%šWeKŞĐ‰Ńő* N?nlžU*ębIEQ„ëş‰Ł ĹČČHŞW¤”˘Z­ŚnvĆąÉ0N˛nK1ŕ†Ům™ÔUIůT˝%¤#)%ŠElËFEńgúžOľZe`` ˝Ś[žď“ĎçÓk4›M•JĽ ¤4bĂĆÉ) î˜r:ŁÓh4şîŐq†‡‡S@'[~Ő Ę˜öťLő>ӏ~ôَaÁĚŇńAăşšŒh_?>ˆ,Ů ĆbwaaۢëOkM>ŸťŞF?nmˆĚÉlźYŠ]˛&­ž×ŚT*ĽŽ$ŮčýřđýÔisc›Şˆ˘pşiăra€˜ë)=ëÇ­é3ˆbK\ŐOŒWa´ŠKtÖĐÚ1mśZéQ\śÓfVŢí)=ʖPŹöXŹâ%6âçOŁQÝĽL);!jbaáъ(ŇŠ`poé”Ht`4‘0fĚ3ߍę"ÎzKő˛M;{˘¸œIkŠ˘´dęć­ć{ŢÔ'†Ű-ßěŘћń“C 0ćy^W)ŽmÇîvžçĽŽDRĘTo&ŤšbŔš˜Ÿp#Š"lÇFĄhŤ—ýˌşŁrů2qÔĘĺ2őzJĽBŤŐ˘ŐjĽ6ݞçĽŘćpĹhşŒĽz2YM1ÇqşŘąY(ó{ĽÍfŰś™››ŁP(¤śŕA¤Źł0஠ÎĺrŠ#•q•ęƒ1ýčG?úń)HúÍßQâşN&ÁěÇǝˆ¤'<~ĐŐgJEé ŇŐ/ľńßÖÝgŸ7&’Ů]ÚozĄ?HVöY.—Ł^o¤5ěĆ]ÂqÜ.Đlľ$ ű<öŠmf“ř÷şkž‡ôű䚀Œůw|âŞŇľŮ@K)pŤ/$ű é3ÓWž—mZŇúôťąß@HăÄŇŁ“S˛‰ß%Ĺ7 3ŚKܡG[Ў„šW‹f5ŔRgž˲Rf@ „ZHŤsínŚ i)“hb@Ś;7ӟҺóśôúvćžU×űĽXÝŇž÷žEG‡ nt‘č’ š[PŽ$nńóŘťěÖ ÈZm9˛ëđÁ0\ ó#ëüŘl6(—Ë)ČŃjľh6›ŠVLçpŞÝ5>Í5}ßÇvl‚0`9ZŚ5˜Ěm@‡7çv• đŁT*Ľ ‡Ń]ZZÂqÚí6B<ĎK­łGFFb€ÂśW‚T‹ŚĆôŁýčǧ1‹”eĺ?Ń9öí8Ľ^­ŽýăŒxÓîJđăĹ]\ť_’ͨB#H(ÚW9Eën_˝ęvďz&>ƒOBĐŐWaR(”VMîŻ&kţŽ˘(q‰E*,™¸XVzڗ}kŽí, ź7˝ŃöëJ~ł¨Y&‹Ÿ€~YËŮ드mÓJ4úLĽŐÖ+˝Ć,˝rž1óŠ4ó‘^•+…kłďςÉ1KIŽ`dfYٟɌͰů|+ÊéĄIY:óĎ>“]eSR¤%H˝6čÝ÷-SŕIém\žzËŢ`J)[ K‰%ĺUőĽ>Ě3˜ËšjžůxçşJŢL›öŸS+ešÄ ÓĺŽÔ+rk܇ ŕ’Í-—Ë)@bŔĎó°m;-Ą3lĽÂÔĂ:Ëá2%ŤČ8ăXÚBştG×%k§ŽĹäz…BBĄŢ[ŁŃHŮ3…B!˝7S.•˝fv|š§`ň}c†_”Z| !Čçó …Ôů  ŐjĄ”"ŸĎ§í–?FD¸ĆôŁýčǧ ŒÉžx}œ`ČŐďQ÷œ¤­˝qČ ×sĎ sĐ&1č?ě­űżŽŠ­@kÚa‹šö)ZŞĆ ľŠ;Žc9Ha!’ éڟ˝đ"2̌~ŹöldÇŤfnä:aŃjľ9yú ‡ß>Ęű'ÎpĺĘ"m/>­Ť”ËLNŽłçŽÜwĎ^֏a;všŕÜHҝWŸ%íĄŢžęU>JÖŇatĘ"ôU€Ąo´Ż˛ÚY ęÎJu:O÷Ą˜U&jč*ĹËjŹŹÖŽJé.@$s™l˝ŐŔ™(RŠ]uäɎÍěZ–%‹lƀ’•NO™^î}6ťĘŚzl´×<ĽŃ•ÉęăEjU&‘Đ …„DŰK y̓k/ŝ9Á$ôhĂÇąťžI^˜DźŰŚ”ęś7€acdْ7ëŮ3P1Ű3"ütŽ(“Ë庘0ÝcD¤ě(نąPsĄPH™Y€..ĹΆ!ĽR  ËşÝn#-‰yxÂĂ}ÖÖxŽ“\A…)#ÇşY ř^›iٰ~ýz€TŽT*u ›÷F‹j˛ómŠČ.—KYÍfo`_Y—(3ŒFŽů<@ő˔úя~ôăS˜”\ lIŘD[Ƥň:Wýťń- }žüů“ `rr’Ýťw%‹çt;‚.ťĚ™™´ŇlŮşšc‡šJ˘jNăځćŘEŸˇ/¸–ŕŢi‡íăŽőq—mĹuŮכ(fičAäsŚ~˜ĂÍżĄÍ2y™§¤ÇsśąŢÝÁHn#ŽG +ůcęö ÷X “Íq"ťŘqâ×ÎĚĆb…ý†Oču˛ í0—bŸ‡ IDAT!ÜOÎ)yvš2Z›É”}˝ďÇ'…oż{Œď|˙gźqřó ‹ÔjuÚm/݀9ŽCĄghp€őë×ńÄçáë_ý"ÓSq]ŰśŽűš[ZŞrř­Ăh4÷Ýw/š\>=áěí§ŐʨzŰŕ“˜ŕŻVNąÚ)~6ńťÚ÷č}O¨#Bᫀvä3ďUYˆ–B0,ˌşƒä9é` ‰E6 NŕĐk4›Ńłyóˇhˇ[ěžk7ŁŁŁŤ–“ôŽĂ'NŇn{  ńäSOóšĎ=ƎŰoĘü|;çAcĄÜĚĘ`NVëŤÍˇ]óqV@W“2QV›ŸWcaUÝźô˛SŇ닎w,řkě¨W&ÂćŰ)•h’ăœ$Stó˝S–”)­k\Ż…f“Ýlť˜?Űl‘€(uqč”#A˘ľâʕ+)3¤RŠt÷őú2íśGŠTJYڤ2‚ذm‹ĺĺ:J)p])-ršÜ5žéŐŘTWۃyŠö‰Ö‚FŁ‘˛3bˇ Á.aÝřťtRyĂi6›´ŰíTŸĹ!av­9Ř0Îw@1űžfŤVvÄRťĘ@ąĚˆ3‚4Žív_ÓfYfq§ÜďҤB¤%JYáBĄ:eÁœ|>ŸŢˇdŒđł’‚ eş˜§,d’ ä$.bć~|ß§^ݧ÷kąű`L?úя~|–6}Ym­hűm”V8–CÎvÓSŠ[ąš×ZŃjľř7˙ćßňőßú[źöÚ!ç‘GNśóç/đŁţgîš÷ž~úžüĺ'8îa˛aădş8fkxÍi BixsĆçO_\N˙$ϟôů١1‡%>i}qíݡҚF¸Ě‰úafŐ Š˜îksž™čM¤').łÎŢÍ´}/ůÝó%,aÇ´n™čä'”‚l*$ŽraĹĎ80`Řő5Ť_" Ë^Äы>ăeÉŚ÷”ÝHÚ$Ö|ŚĚŸKł—ůWňďř÷ßů1íV #*I\LˇQHÓk°PmrrćŻz‡ďüŐOřoţáßĺoýúŞ\—řŹÖš?ýÓ?ešVGHÉ ĎżÄÔÔFĘ|ýˇ~3MVĚ&3+Jh~gNGĽé†ň“ 8 ąś€ň‡eŞřQ@=hňŇň1~´ü*ݍ,ëVÇĄFCExĐÚÎ×ËňpĺnÝ2‰›î˘…¸*C͔ť=ůäSüäÇ?crĂGŢ}—o~󛌌 w=Kڟ”R|ď{ß§X,ńŕP*ůĺ/Ÿgii‰ŃŃŃ.ąÉ;K§Çtľ„ŽH:ŕ‹FŠnĐd-&ÔĘr ą&Ř­Ł3–Ůş‹Ń°jFbą]’9C*M:Ľ”1@Ł×ŘҌOÝľÇHŸ_˙,R ‘č’ô~śs˛Ú8ćw†‰Đëř”e­đÜh' :ÖݖeŃl6!ă¸D‘˘V]Fi•ąçy>AáşNźF*-ŐŃÂP‘Ëĺ“ç^áy>BHÂ0Z÷öŠé“¸ßŻď[zžŸ24 Ă ŐjÓnˇcĆU˛F›hł^Ôj5†††R°ČĚmŽëŚ€‰yżh˛?7z/Ĺr‘+­y@łŽ´Žv˝EMTIKŮrš\—Ĺş´ …Bzxg$ß÷ŹÎŔŔš\.mťRŠD­VKżłyfÇáʕ+Řś2w‚  X,Ňjľ’öňR‘Ţ\.GłŮě˛ňÎ=YPŇ÷ýÔ&۸2EQÄââ"Ĺb1ľ˙îƒ1ýčG?úńYe€f˝Á˙ąđ#ňśĂ”ă+Ă+UP^„ޘ Ž-(ĺŹkŇ|Ż•áŔ‰‰ ŞŐ*J)ţÓú333€ćŕűyíľ×š2?ĎĚŮsüŕ?äŔ}h6[üô§?ăĹ_"—ËńÇüÇüٟý­V‹Gy˜'žx‚|!OÁĄ™6RhlK°Ž"™ŤGźtĘgď÷ŽL4šFPc68‡ŻUźéšHĔf‰& ÔýW8źAÁ+3˛ź™q{+Łî&Jî Y!gąĽqę¨Ul!şV4›-žzę)^zéeJĽçďü!““Ôj5\×eqq‰ď}ďű|ó›żĹĐĐĽR‰0 ńMżEÁ)P´Räs(ĽX^^î_ kŌSă’dĘ}ŒPŽaą°Č܇)ŤĘ(Zk …Íf“áááĚ1Œ•………DtÜO]ĄL™TĄPȔqŀN 1Œc}m@(ŁŻcl°ű̘~ôŁýř,nü’Ó-ŻÝâżŇكxƒĺ*ŠPž?şŔы!Z\ŰbÇ:›/ě"'W–5ÜČ)lźY‹8uę­V“Ë—ç8qâôGßâ;ßůKΝ?Çäž÷ńĚÓĎđĺ/‰S§Oł´´Č•+—ŁÝjsęTL×ßşe+ů|0 'Tšů”r’Í#6a¤š¤#.Ő˘´ ëNë+­ŐöóÁeBŃѐ">›BĄą„x´Uƒ%1ËŠđÜv‘A1Á˜ł1w3#ÎE{„‚]Á‘6R;HVgľ4›MΞ=Çöí;§ÝnóúëođŢ{ď144ÄÄú –—xń…—€Ç{Œ™™sĚÎÎ26:Ęşőëx饗سçnxŕ –Í|CńÔ{ GZ8Ÿ÷ŘťÁŚR´–¸#ú¤ĂĚ0 ŁĆ÷^~ímţ—ůoyí­Ł´Őj˙ţŸţ=6LŹĂś×=UJqđŕAΜ>Ë/ůĹb˝{÷ŕş'Oœ¤T`bb=ď˝÷>÷ÝwwÝuO?ý gΜ# î;ŔŃcÇزy/żň*a…Oţ”•'j/SLŚ\Nâ DŇNŮ-ńlÔ÷;őłk/."uNđ}Ÿ0Œ(ňŒŽŽđěłĎŰśmĺý÷séŇEĘ%˝~ˆééiăăă,--16>ĆÔÔ47nŕÜůsaŔ˝÷ŢĂ\[s`ĘĺÉc!Węu/vzt›űąS÷ŽDÜ ×᠔üń#Ÿ‹Ís´”ßIčRÁEŁ÷‘Š÷OéԚH´ńĹY‚óœô_¤$‡)Ë1œuŒŘÓLĺîf0żKÚ+6ˇĹb‘{îŮωNđŢą÷¨TĘ|÷ťßçK_ú33gš<;‡ďlظgžţ%ÍF›3gÎP.đÁ'yřĄůŕƒ“|ík_M7/Ť^ +Iچlžćb-â’b߆;ȤŁOdžß÷yűÝăü_˙ď_ňę[Ç Bö×č$ĺ“ëF8xĎNśmž$ŸsYŞŐ9úŢiŢz÷$ÍśÇúţӔJ%ţŮ?úCĆdž×LB´†S§Nqůňe*ƒe\׼28ŔĚĚ cccĚÍÍáűwÝľ›3gÎpęÔ)ĐÇśp›|>G.ç’Ëĺ°mëŽ(sů(ÚUšX\ůdă˙ĎÂOůŠ˜†žşx|%üyó9ćÂeţÉČט*ŽKôšŽ~.\ŕôéS)kliąĘĚĚ ó óěÚ˝‹M›6qüřqšÍ&=ôív‹“'O2::–ęٖEĽ2ŔśmŰyúé§ůҗž ŸĎ÷Šî` &űw݈n/ÜыY}ŽJĹq{Ř#˝ĺk•$ué˛%ŔqŞďŇe-/ŇJĺôűH ĘčŁX)pÝőŮR¤śĘŮűPşC̖ÂĘŢś@§{^}œlŠHEXB÷”Â~ČçD\}Ęş Ĺ{˘Őʤť;Íśm&&&ŘśmCCC×ýaHuŠĘäääużÇq&&&™˝t™˝{÷Ź)LoĘl\×M™ –eQŤŐBP,SpĂ0U gʐLImŰ ’óíFJ#u ;)ň´rVâ˛ä TGôx`` ub ÐĹĹErš\:י1ž°°ZVg˘Ly‘)Ą3 ’˜Ď1ěĂŽ‘RŚŽL3„jľ]`Nö˝ćZŚ=ŒŚŽąÔ^\\d||<j˛ŽM}0ŚýčG?>3@ŒFE!ţĺ÷X|;¨Ć!ńÚ JăxÎťĆîvČçm\×ĆóíVTŽššYÚ­6–má:9lÇaxx˜\ROŰťÁËţˇë:üóţψ"EŠTdŰśměÝť—šš9îż˙~ŚŚ6˛qăF„ěßżĽĽ*““lŘ0IĄPdqq|>ĎČČ=ô žď3::ĘŔŔB€-lśŠľ>¸1T’ět88ťnâOTĄhGmÎľÎŕGńF0ë%¤H˙[ڌ"Ń˙šPDuŐ`NœĂ-Šb„KÍă|~üÎĘ< Ž\™Ăśmććć¸ti×uY^^&Brn­I„üš¸9Çą)óäÜB †††˜ššJ7Ľ-J9A >Ě.GŘR0=lqçuO‡˘ź\ođg˙ńŻyţŐ#xŚŁÖŘţ4ŽeąmóřŰ_äţ{wQ,ćńȂ›ăŇěž|î?üéK\Y¨óçß}Š­›§řÖď ×uVݟٜÍC=ș3g˜ššĆqśmŰĘŕŕ[ślA)ĹŚMÓlŰśíۡ°eËfţëż˙_255Ĺşőë( Ln˜$—Ë݁sŰőż6RUo™ťô$?öߢĄŰ¨ě‘÷ KëL–Ɂ5ššnň7ţ–\ţŠőuĆŹákÚ_ďÝť7MŇŚŚŚřáţšbŠČŽۘžžf` tŸťîş‹ ٸq…BÇśăňQK&'ފ 60=˝ŠÄ|ęŔ™Xüś7Yî¨NcG=EÄę‰˙Z ĚjŻMő9’˛!™:üˆ7D˛e˛`‹iYŠ+˘`%łVZw[o˝3S\;őWЍŻXSGG°âŤÄ$ÎZQ°rˆ2Ě ¸=”Š]ójľ*ŽëňŘcŁTD>Ÿ§^_ŚP(d’ş6Ď󘛋×ŮĎţó8ŽC­VĂ÷}†††ÖdşAŔââ"űöîĹób]’(ŒRđdľPJŃl6i4ěŘą]ťvRʤ Ájmčş.ŽcĽ, -S2nC†1’čÍ:9ރŻ|ÚQ$ŒćFÄ’V:~˘(Äą"ĽŽDQĽ€‡‘‰˘ˆfł™śƒ"°Ě¸t]7-™6l•ŹK’SĚ7ßAkMŤŐ², …Bú~ÎA€ďű]#Ć)* ™Ď6ÎU­V‹áááÔŇúZĺg}0ŚýčG?>P ~łŠ=ű*vĐLEř„V¸­ó4gße1ż;Ý$Ľ˘y@­VCV*\˜9ĎâüŽăËçČĺó”K%ÜD(m- ĆPL?÷šĎuŐţŽŒŒ°}űśôuĂĂĂé"g^ˇaÆ.÷ܳŌP X_ąříűĘxaźůË;ąć͝˜§h4Ëíź‘ž”ůëĄ@&Ůüv•2‘”2‰ŹŃhše9ĎYőžďáÚůŽ ˜ÖšRŠÄţýűyűíwřÜççáGćá‡áľCŻqŕžűŘźySSSD*âמđk<đŔýĚĚĚpúÔiśmߖž¤eéč#%Éť üÍ;-Î.XÜě0=bcÉ;كşÇˇ" #Ţ|ý}ž÷ŸŸ§ŢôĚśľvüBh†řÇďěÚš…gž“ç^~/ (ĺ]~çëżĘˇ~÷Ť„üĺ_żŔÂRƒ˙ď/~ÎŻ>~€­›7ŽzŠi’ú 6t=#6L$?×é†zóćMékÖŻ_Öš‰‰ ´Ölܸń†,źďD@şúüőŇŤ<í˝CCˇb F% ŒXÖ=™˜é֞dNmíó“ö›l_šŕď䞘,]ŞWJ†††xôŃGŇ>¸˙ ąs׎T'add¸+[‘,7MŠĹ"żűťżĂččH‰ťă˜ŢyĆ2jUćŒčq6ę€ÝöÖiÉNF#&+ŒŰ)Q2 ĂęŕŒ†.vJˇƒSJ}éšů:׍_ßwŹ#K¨tÖŤ:6ĆĘ:9x0ŽQŮŞŐޏť]¨4čŘ~Űą-,ðɜšžžy?žG+mĆŤŐ%Ţ:|˜ĘŔ###´Z­4iߡo_ʰX Gožů–e388˜2LjľŸűÜçÖźß÷9zô(…B‰ŔáÜůڧ§˜œœ\sîŤŐj9r„fłÉúő뙛›cllŒíۡŻŇv+ËÚ ťÄܧa’„aˆďűärščĐÉţ1ĐËz™‚U §ó8ŇNy!Œšœ›–|e˛ cL{™9rqq‘BĄ€R*uSŠľÓâ×pČ|ŹĹ´y†˛Nž–eQ­VSŰj#:lŔ-SžĐnˇS ¨Ńh`Űv*lܙŒ8o­VŁRФď7BĆý2Ľ~ôŁýřŹ@0]ľťęĘqrËgÁJě “ˆ$š|ˆ`tĺŃő驀mť„A„WŻÓź0Ëȟ~›ÂÂVÁÁ.şŘĹÁŻ|‘đ‰Żŕ$ľÇkšz˜E´÷g&VŻ­XRPĘA)wç÷]¤gk'YÔuo„-a6EŚßČ0bDҤŕT\3ŻcPF ńfÔ҂‚?€ľnuۜٺu ›7oB+íŘ0“Ö!ĽÄśl6lœě˘Â ą˙žt̆ŮóږäŃíyönĚńŢlČXY˛iľĥćÓ=žă¤ešŢŕ˙ţó˛\oŁ"ŕęš!–móŔ={8pďnžüĺ̜Ÿĺżýű_gtx'/đł_žE>ŸăKżz—çÄ鋜™šĚ~ú˙ŕ[ßH7Ľ˝÷cœĆVV>úóöi˜Iđ–3ÍKü¨uˆU'ň#Xôár}b=ŰBÍ{?™m‰pa$‡ŘX„-e¨¸ˆœ„œ…°J*ćYć'ޛ<ŢŘĂćňŽX{űŰ;>üđĂh­ş\ŹŽŐO1`Zä+_ůňuť™őăNbô  5f_dÜÍřŹ`qő)1/Q‰ŰQ<Ćş_c˜‹ŚŮŘűö&ç"“ŔöŽĎli“^1WvĈă”!%vRÎblŽ;RťYQcŃŐBÄ]٤<űÝł–ŢńÚ<Žm32<@ąŕÄ÷"ô ëÝYR"„BŠ(qŕ]‡J=řJé„MâűRŠ.{ꏨ°&~íĂ?’jŸ˜~Î:ţŹů|žÝťwŁ3Ľrš„ŒQ*Ż:ď łgϞŽë¸ŽťB{(kM](P¤cKÝh4şl­MéMľZ%|†‡Gđ0 Yś–ąFQ^Dq  ű#ŽkÓhś(r¨(ÄVچFř֔ú˜ň§FŁAľël-)%ËËËĚÍÍ1<!†˛zŤ=(– Ło€†’w™ŠĺQ$W(Ĺ ´ˆ‚–„˙űżběě삃(ťXžž÷—˙‘z¤üŰ;=é'7#‰TœX>‰FD:و&@ŒL¨1RËhщ–Œ"T"eĚČä4OJ‘0iDbńm3!îĆ1–ć]§Ť"dŽ‚š–{CßG pmÁXY0Vvďŕ~‰ŮJ)Ž;ĹŤ‡ŢCëXüňŞß_ ňš>t7s 5ć—ůÍŻ<ĘŢÝ[p›ÉőcDZđڛđŰ_}ŒŰŚ8{ţ őF›^~—Ż˙úŻ0P*ő]?Bż…QÄËíă/F!âlđ:Œ:UCç+­Ń˛[¤9M“m‰ŘZF>´ůĐ8bş #9"Ą8^ć…ć1& #8ňúˇżąŒuCß%kéۏ;;ň9›Í†Éť˛Ç}Tx^':*Ý:$b%–#čbş¤Ĺ)ŁšŃąlŔĎBdâ‡Ut–ŽA@Ł­ë¨w ! \ĂÝŃ@3jŐö^ ÂeОPk^ąˇ“yq÷čDG+PIّÂ.} •yÉüŻ",%!ŕ-Ą„ˆ…™G8Ľ5~;]ů~ T)ĂŹJŔDmXNRĆ.LJ#U„-%‘×Ë"ŠT˛ˇŒű\iZŁuHäɘ– ţ(2Z42usĽ ňQd­xŽ”ÖA܌‘ŽAM۲"P‘Dj J㉠= ކ`­a\.ů.a|ÉŰĘôÁ˜~ôŁýř$$)Ő8^ć#Ą™“°(%ă F˘xů:D+P Â(>ŻŐZ#›XÖ’Ý źÖˆ €v;ĽÚvťÎtí0 ůůϟäîťďć…‹lŰśľKŁ˘wă/„Ŕó<Ţ~űöíŰNj/žČŚM›Ůłçn~ůËçxřá+Îńˇ IDAT‡¨T*Š›SJ“ÖšóçĎÓnˇŮž}šœťb#ˇ{'›pdiáٍ_FœÄ=šŤBXújĽÄ=Ă…–ű gŹŐžĺÂőÁ}0ŚýčG?>k@Œ0I q-ţ"ďR—°=Ňüf#`J‚ Ô:ĺóÂÉ6n/pĎx˛*éĺJbÚkFçwÍ=ŽI×TŤËěßż#GŢĺȑwšxń"{öěáżx–Ýťwó /Ďxŕűٲesš?~ßxď˝÷¤ŐjqáÂ%ΝĄZ­ây“lٲ™çž{ŽjľĆć͛‚ăÇ?Ŕu]6n܀ă8xžÇŇŇ÷Ţ{/‡ŚT*qáÂîžűnîşk7ZkŢ~űNœ8Á–-[áő×_GÉŚMÓ>ü6…B={ďž%ýd,­_ž=ċ /“łrŒ;#L9“Ü_ÚJŢÉÓh× TŔî‘Ý  QŠT˜fĎß˙Ú)jłËĚŞóh4–€(ó„dLnŚT(Żšń6 ăÜÜlŰâWőWyůĺ—řĆ7žą*¸Ň ¨˜×Ä6“ďž{„ńńq&&&:`ăčŃŁěÚľ ÇqX\\ä•W^ĽZ­ňľŻ}ršÔ%´ˇÚI}–QÔl6™™™a||œ‘‘‘4i] „ű° €ŇšV;Ŕľ]ĐÉĆ\ŠîSćä˙]×âŃvóŻ>ĘĐ`‰b1ÇĆÉQ~úĚD‘bb|„ˇćÍ#§řő_;Ŕr˝ĹŮóó@œ 5Ú‹ŐÊv3ßea~ĎóÓúůç_ Ýjsŕŕ}9r”'žř5.^œĺ… 4 šÍ&ů|Ç{”çž{Ď3Ö×gůÁ~ˆÖš/|á œ>}š“'OąaĂŚŚ6ňěłĎrß}÷qđŕ~›CŻ˝Î–-›9rä(ľZ•-[śËĺ8yňŰśmcϞ=ź÷ŢqŢ|ó-vlßÎńăpüƒălذM›Śyűíw¨×ë|éKO0::zË­5‘V,„ËĚG˝aŸł÷Â|}b^iĄ}t;Œëęň1œGN[ʰi ë1tՃł Ôá˜.ƒ%P(ŽD5ŞacUҰ:ÄşńőlÝś…×_ƒ‹.ňěłĎR,–Ÿ­[ˇRŤŐX\\dtt”Ÿ˙üIĘĺ2Ĺb‘}űöńĆoĐh4Xˇn?üRJž}ö—TŤľTç —s™˜˜ŔqŚŚ6ňӟüŒ}ű÷ńÖ[o111‚ÁÁA–—ë:ô:ĂĂĂ8pë֍3;;Ë/~ń Ęĺ”Rź˙ţű|ůË_ć7Ţdbb=SSSźůć[Ź_żŽƒ244„eőÁ˜ [Ěťîéú÷‰oߤœęf€†ÔÁŇö¨ôă“őě÷Á˜~ôŁýřl‚3Ŕ“Žä[â Xš–d\C)–~ń>lĎńć9+˘j}ujíľ>UkM­Zĺg?ű9íśÇÖ­[šreĎó™™9Çôô4š\Ž &˜ezz ŰśçĹ_bďŢ==zŒĂ‡łsçNÚíËËË EöďßĎwżű=|ßgÝşuŒĄ5<˙üó|ó›ßdaažC‡Ţ`óć͜;wŽjľšˆžÚĚÎÎR(I… /]ş„”ccŁźřâËÜ˙A,ËâůçŸgzzšJĽBąXěQŽFÝ@Ö@Ëksxá(ÚsDDœç8b˝OÉ.0n˛ł´#ű, %›C+.'Ë;äÚy­Q‘CDSEŒ˜I!ĐR˛ą¸GŽ]Ň!A°{÷.._žăôéӜ=;ƒçůœ9s†K—.ąwď^Μ9Ă=÷ěOą7Ś‚~ľZĂ‡ßN\Ž07w…#GŢĺ‘G&BŽ=ĘŘŘ(J)žýíoó­o}‹]ťv17w…0 šti–VŤEš\B)EŤŐâwŢAkÍ˝÷ŢËűďżĎÄÄDj׆q™ÍŽŰšrežRŠÄââ§OŸćŔGŽajjŠ 9sć <đŁŁ#ŞĎ¤€˙áżűžüĺŰüěŮÜ:{ ß 6Ię†`óćqţîď|‘ ُŽM.çň…_9€›Ëó“_źIušÁÄŘ0_{âślšŕO˙âi.Î-Ł…°4‘ÖřĄJXŤC 3"śďt_Ç믿ÁéÓg8}úLęĐ1;;KŠTbϞ=üä'?ezz€ź?)”<ňČÜ8q’W^y…K—fÍ3Ď<Ă7żů rš<[śl`ăƍlٲ…Je‹_ăńÇăÔŠ34uĆĆĆزe RJ*•ślŮBŠTbzzŠ{îÝĎ3Ď<ƒďű|đÁ(Ľ8|řmžđ…_ť.vÓGdša›–jÇ,1[ćňúúߟ@U[hˆT‡˜ ăçE۝ł[ˈÇÖ#î…ŁČýĂG˘­ř-ő¨M3ňŽú=fggšűŽ=‹ĘĽmĎăÜšóüŢďýǎcff†ršœŠdž?ß˙ýßăÔŠSźđ œ?žRŠÄ‘#GxŕAŤŐfŰś­üÍßü˜ßű˝ßĺčŃŁœ={–ŃŃQÖ­[ÇéÓgX?ąŽfłĹřř8—.]˘ŮlňÔSOóŰżýM,ËÂuc튥Ľ%.]şÄŻüĘŽÔĺ$Ÿ/Đh4Řż?ţńOńź6/^dóćM VRkâ›ŐWŸŠ„,„­ŰŔűŹ‚]7űz×*ëG?Žo0őÁ˜~ôŁýř̂1Ů:aDüžw¨ÁËA ˇXáŕß˝Üâ˙üE•­Çšüa¤É;ÝךŃOvs9vヒ÷ߟuëÖ1?…VŤ…çĹjůĺr™RŠLťÝŽs!)qÝív›|>GĄçÝwňřăqôč1 vNjUâf+Ýń6)m†‡‡ĐZáű•Ęǎăţŕhˇ=Ţyçm^yĺežň•/“Ď8xđ GKĆ­ĆśmJĹ"…|>ľ]ĚZš×}Ř  N’ĆËőy.ůóřĄF!^T§ÔšÄg›3 ŰLOްD-Rf‹ż Ů,ZWđ E€ )nXdă`œ(K!WÝ´švs‡VŤIŠ4ÖąMăÂÂľÚ2o˝u˜ăÇßgýúuź÷Ţ{ěÜš+Ý úžĎwżű]}äq–—ë,.V)ňLMMńWőC<€m;:ô?ü Ĺb1ľäâŐW_c׎]¸n<ŕÂ0äůçŸÇ˛lĎ=÷<š\ŽgŸ}Ž{îŮĎŮł3ěÜš“‰‰ ~ôŁżfǎíœ9s–Ë—/sŕŔţĂř6>ú§NŚX,óÁ°˙>žýíoóOţÉ?ţp`Œ”lŰ2ÉŚŠuüţoŽ—^?Á÷ü2ďžžZ˝EF8ŽEąŕňˇżţ+W–ęüŕg‡řÉłoÓđ#”cƒ6ŽĘ֚`¨ŤšÍ&łłłźńĆŹ[7Žë¸X‰EłŮâҔr"Ű'çó@“ĎçŚRŠpĺʨ!ćZ¨WŻ Ÿ›El-cýÎVäcëĄ`§:j ö•yڤ”ěŘąƒ#ďžËž}{™_X`ăƍ‹)—ËÔjUÂ0LY`Žë2::Ęŋ—hˇ=îşënvîÜI…8ŽRqżU*ąžVŠTLma}ß§VŤĄ!yžňźúękŘśşŮśăŘŠŤÍÔÔżńżÁ믿IEŹ_żÇą) ‹EFFFŘťw/Žë266’ĚÍůÔ^b7˜>°p# >ýrŻ[˝ďŃŤhÖ|‚@ž~|Fü>ӏ~ôŁŸ˝ŔŻ{uQ—‚­‘âŽ0ÄRŠcZź\o3<”çűI•s‹ú˙gď̓ä8Ď3ĎߗgÝGß÷…и ŕ‘I‘"i‘”dÉ:ě]…'<Úđ†=óÇĚăŮŮđěLÄîěěnŹ7öyÖÖڒ-ٖe‹e[E‘I„hœÄŃÝht7úîę:óúöŹŞŽn4€ĆI€Ę'"ŁťŤŤ*ŤňÍďËď}ň}Ÿ‡ÉéĽ1 OŠ510WŇc1 ƒőô÷÷Ą(ŕş6Ńh”ŁGR__O2™¤ĽĽ™t:Uľ5ôm#Slٲ‰††îť/H˘Ń(őőu„B&ÉdÓ4číífóćÍěßżĎóčîîć‰'çŔý†ÁC=Čřř8‰Dœd2ÉŃŁG1 ƒóçϑĎçčííĹ0 @211Áüü,]]Ü˙ý9r!>ř śmaǏ§­­­üž JĽmmm¤Óé›NOeÎ3oYXžß:&(nŮE IQ€&B” E¨¨ĺ6Ëľ™śghmî¤ŰíĽT(2gÍ2)/ą ç(zľfĄ$Ş˘^u°¸˜eff:;;_„utt”ŮŮ9ÚŰŰxŕxýő}žPk˲x[–ESs#śbrr’ţţutuu˛˙ŰĚÎÎqáÂ(““ÓtÝŹ&o§Nćcť>ĆđđţgÁď˙‹˙€\.Çôô,‘p„ććt]Ăq\RŠCC#466TmE+ÄQcc#‰D‚x<Ž”’ćć,Ëb~nÇOŃÔÔRľI˝‘ŸÓ40Mƒ'?ž•vŽăô™KźöÎIÎ_źDW[#­Íişo=aÓDÓŐŞŕŁçůDCcӜápˆś6źvt´säČQ:::hll$UIɆ†zĆÇÇQ5…ŚćF"‘0]]tt´sâÄ Ž=Â#<âťhär cš&…Bşş:ĆĆĆŘłgĎÍĎ{BVMBÂ(Ÿ h iAÝYÔ„VžăÜrk§RqˆŚ ¸ƒóČĂÓȋyܗF’ˆ¸O 1aVÍ+&jŠ˘°sçN^yĺçěŰ÷&MMôőő099iÔŐĽŃußUUľňqďF×5ęęҤR;˝Čŕŕ ét’ŢŢ„đhh¨'ÓŰŰM$Ąšš‰X,ÎŮłg9qâ˝˝=,,d¸xq”ŽŽvÂá0uui^|ńöďßO}}=Űśm­ĆŕÔŠS$qşťť™žö+Ő::ڈD"lßžŁG’N§IĽ’źöÚ/xúé§yçwčččŔó<úúú‚ m€_Ĺź7@€ťďÜ_Ăă5FfŐߕšŸ•­âý§•7Ё”ĚOíGzÁŃ Ŕ=…ʝO×őp]Űą)Käó#JS{ďšç*z–U$‘H\&Š+ĽÄ˛Jˆ#ßÂźô&2’bJS™R͞¤Ţ*‘_,đoŢ{WrCIBŚŽĄ)ˆR– üœ?<ú$C ZÔ@‰¨1ĹP)]ZŔŮq?‘˙řď1MsU!Ď_uřĺ˙LÓDU4\ĎÁuB!łÜ"Ş+%ŤÄ˙=řן:yWÚeË*P„çŰR Ť&;›ŮRˇ‘ŽH á4 #Ć|qoůk†J#´™-tDŰiľ'‚°–W"‰łŠuąPŹJ*Ôţ_3ćřńtvvŇÚÚBŠTâű߉M›61<<‚Žk¤R)6oŢĚ׿ţÇěÝť—ţţ>4ÍO -Ëbßž}˜f]×Édٸq--ÍüÝßý=ííŘśĹĚĚ,>x?żřĹk<ţř'hooçĉ“Œ311ÁÜÜ,˙üŸ˙ŞŞrňäIćććq‡žž>†††p‡h4ĘɧčîéBÓ4lŰĆ4M4M'“Y 333ĂŔŔSSStvvrâÄ bą8ŞŞ°{÷ǖ‘1RJł(Š_äWä˕U˛ŞcdŰ6óó UÔęᓉdaŃŻD9||„‰ŮÖu6ącc'şî÷´,ćŠ>1Â_ü`?űŢ=…mű.+UEŒ…řW˙ěţŮ>ŞiՊŚ`lA>_ŔśÝŞPˇeYčşZKeţł=‡c™!ţÓô÷8ŕ}P 6Ňö`<ËâíoEǗ4Tˆë6Ma_äˇäâ˝7‹œ+Ą|˘Qo Ł˛.ţmÓo°+ľaŐqľtŽýę%‰žç‘É,ú•TŞÎZŒÜü9ŃfňâŇ.‡0MĂŻřRUTUš˘ƒßÝx ¨´:Ž‹e[äó,ŤH2a ›A5Q€żR,‰Šž\÷ 0؀8ĺÍ-o^Í&k~֚hŐ..ťeTĆ ŔÝx =I˝'Ť"ŁŚ*xaWŒ=ą:´pĂđ+.윆Ł—ŤÉ‡ň–•ÓšFsSäťę†„(_ˆW‰Ă;óÇ9š9Cž¤!”¤ÁHáz.gňŁd‘3фFJ‹‘ÖSôD:y8Ţă‹Î^ˆżeăƍ„ĂĄ˛Ŕ¤Î“O>‰˘Zu‰DĽąą‘ŒŽŽV[*4Măá‡frrŞ,ŔŤ‡Đ4Ç˙ĄPˆL&ĂŔ€F:ć駟F×ý%C˙:‰ýý}ŐvUUٸq#3338ŽKss3áp¨Ş­qîÜyz{{Q…ŚŚ&ňů<Šâ'â lŰś EńŤ4˘Ń(áp˜……yš››o(‘ó[NT&g3 člIŁŠţxŠ Œút×őŘąŠqú?~ű uI:[RLÍeyéŐ÷yůď3tq ´ň}()—­ŻMĽĄ1I{kŸx07E(´h)ÚŐ:Wŕ ß EΔ7‚œńTCč*(Ďr‘YÇטI(Ý1řX=âž:”°†RłŕUéRiP“kIÍWĚĆ Ŕ­G@Ć Ŕ]JĆTĘA"…ďZ˝ť3ŒÚÁŒřşBQČg`ćbU]ýäi‰ďžTŃz\]˙îVÓ;Ű'Qv}R¨ľkžŰŕyĂŮ ŚŠ9,—j[’Ŕ˙] †ađÄŸ ĄĄ]×/{żşşşęďŃĺúúşŞNÉ !Eŕ8.˙ůŰŻąą§‰'ďßČŚžÂ!MóۑtCĐ6‰Ĺœ˜ăЉ !ř?żűűß;ÇäLśrŔŤ#Šzć–CŁé*Ýíôw5űV׍ŒQ5;“KVŤ+’|q;'“˛ƒŕS¤Í´VĹ0 J‰@F4¸żą%…¨3‘Ąrť’~ťRŢA^* Íáž3…81ňkđl˘ĆE(á…Ůbv‘2ăŐö˛ŤÍnUşMzKąšěöeî^•ń´n @@Ć @€R”“9Ÿ°X"W*+uݚđ­L-–îß_;‹ĺw*8Yˇ„íš—Ý–5ˆĚMjó‹JÂ!Ch$´0şPîÚ{іëpfaŒ™BŰSPËqe"F~ „đĽ˙ÝŽ'ąqQ=QƒôˇĘó+ŇI=MŇH˘ĺ–Ř|&“I<ĎąXě˛vŸŠ¸qmťČ­n+Đ4í†+\nŽƒt´7ă:6ńă÷ř›_ ˛˝ż•ßţľűŮť˝ÓĐPĘßÝ0t’‰(™l‰ˇ/đ“wÎR˛źrkÍeçm͙‰‡ŘľĽ›ÖŚú+R*‰ĺş,şEJŽ…ţy#ŤŸtEkLů}ä*#L V}|ľ× ŔTušADŃŻHB|ب|&CÓŮęç'ů÷°đq h@x)DY,Y,;śÂĺ­0WDž:ëË*”‚Nľ‡Â„UƒU}çdyN`㑷K= WVćQšÄŔ]Îu­i^\í~e˙?U¨Ä4“°â öU9¸đ[ňdUćj‹ňr9żXšę hžŽáŠęľv€‹$뙾˛dJyrĽŠ$BQ UGUÔňýü+_¸+Őľ˙—RÖ$‡ŤźV‚tláâz)=ŒĄ¨weť‡çšĚsdÇUŤU. QE­ëxbĆóŤfW)ťX—‰Ľâň$Ŕ:MFÉPb™‹Ň•Rž‘Uuˆ˛m×u1MÓ4ń<ď|ç;€@U5úűűŮśm+Žë i…BŸţôg<ó̧0 ƒ‰‰ Ž9ÂsĎ=W}/Ă0ĘvĚŽăTu>Ž7Ńţ0zŠ"ˆFÂ|ůéůÓWɔöex&Ëů×őd‹%Úęâ†Ćô|–ƒg&řěǡň7Żź­(xÚň„~ůŻ~u‰ŚÚ[ëůԃ› ™Ćegl…d)¸6sVžůRŽL)ă“8F˜ˆBW|ˇŻLŹŽa"ŤIűňqĺŸ{ âň2Š2šćJËsz˜¨j ¤¸++.*ß{}˘“§ś2ěN2#˙+k җô˝l~AJ¤ŇTPBQř|/BŐęU(¤źOč›Y—jC˝âŘňÉËu˜ąr,–r̕‘RŇ ˘z]ՖWŠU-Ér­9Pŕ“ě!]ŰEę!"BG˝CÖŞřˆŽĽď"W™k*íÁ‹‹Y†F.ŇÔXGC}]ľjŐń<­źfŹÜ¤ńĘ× UU.{_Ľć%’§ânŠŞÁœ1p÷3/pĹ;ßÔȪ˚qéŽmőߪJiă&2őóxmÄŽ’”<‡ŤČXfšŸœ>ČXf CŐšŻm=››{h‰70_Ȣ* ép|ŐĎ7_\$¤™„tٚČNććë&ă™iÖŐw Ő$B<é12?AWŞ™˘g“sUt%tW†FU5ÚĂő¤EŒœ;‹+|vE^š"Ć'Z¤OĆTœ–ĘĎQŞ ÷R[BA AJŇnÂĐŻmlŰ6gϞăâĹQ"‘(ýýëءďMbąÍÍÍlßž Çqp—Ď~öłLMM18xŒPČäŇĽ 䡡‡ÉÉI8H<'‰P*YĚÎÎrěŘ1\×eÝş~FGGéííedd˜x ęÖs7bĽýwČĐyx×F}÷ ?>2FŃň¸8_äOţé]>šŤ8pĂԘ_,°ľŻąš,ožžˆg˜ŕÉ+W8” ľHHăĹ˝lčmĹДĽäşćł¸xä\‹ŒUŕĺSű8?= úęÚŮŮžžžúVT.ĚMљjŽtľ‹é‚]“Q#„*RzäŹyŤˆí:ÔG“„tsäâ12‰žt+.Y§„.LEżŤ§żˆâ3ő181ÄOÄ ŽB•FúVňĘŞCř gŘ??˝2ifH˝rĎŚ÷ keKgąú´ëJIÖ-‘ąňź=2ČÁ‘ăH)éŽoĽ;Ý̞ŽM”‹˘m‘ ĹĘäĚ ˘TzLfgi‰7TŤ-Çb*ˇ@X7p=—ŚXz‰Ôeń˘OüÔG’děšPЁQ€nŽëqirš…Ĺ˝]m„Ă!¤”źuŕ0ßúöKôővňűżű[475"ĽäâĹ Ůşy=Š"đ<ÉüüĆ&h¨KÓŃŢR^ƒ8\›Ŕu=ş;[1 żŠôŇÔ ăSt´5QWçkľyžÇŠ3ĂčşFogP…1p׌’H ˛VŁ œů áßY•”*ýâ!Ęi‰,30KČDş.N4†“ˇń sŮ]Š•C‰¤äŮXžÍń‰sDtƒßÚő c Sź9t„śd Ń4GÇϐ)娋$p<—şpœ˜a43ISźžˇ‡ŽŇKąšŠ— ó—H…ăŸ<ώÖ~ţâÝó/ů"'/ a¨]éÎώ’×Ͻǿzô˄tËsń¤ŸWÝ-—ěĘÝnSÓyźs %ÄąŮ.,N3šŸaÚY$/-\é!„‡‡5„‹WN˝jɘ !# ($CiÚ#KíoBŞ\p3Ť<é!ĽWnYöQ*•–œěl§z˝r])ýJEŃAHÜrŤłí8ËÖDғHĎCzKJ×qBŕ¸^š2tÉ1T–J2& c஄˘(ŠÂr1<‰ŔĽęŢRžŕyR˘Ôh}TîćzÂהń„(‹ŕ*O9x9š@ÉVŽjĺZš¸şžÇL>ƒŚ¨źqî=fň 4'˜ÎÍÓ[׎í:Le縘™bCC'˙pęmvˇp`ä8÷lg>żH<f&?ĎÁ‘cDĚŽçaš6śë027Á?œ|‹n˛­u‹3ěh]OŢ.âx~Ť'˝ť÷˘Š¨4&Ň<ÝĂŢÂ.efÍÎ0ź0Éů… Î,N0fϓĽ„+<„_1S!gjD9+3B€ŽF“YOc´n ˙9ŽăUuwRé4ąX Ó U[‘üóJ­/ŽëŰ3;ŽSvARŞ 4EQp!ŽťôXĄP ™LR(î=zStMe{_}2Ǣý>'§ <ɏ spd†ĆD„\Ńbb.O޲ńT VŤ¤žŻß$Q]áɍ üî§ď§Š>uU‹{Oz¸Ňeta’ţĆNŢ<Wz¨BĄč”p<Oş,ZNOŁ**Ç/ ńpďV~|j?ŰZ֑ŽÄ)XEKyŢ;ĹTnށŚnÂşIÉľ™ÎĎóý#ż 1žĆń\ú:Ѝ˘í„zUőDrˇ+Ăúí_*ő=üžň<ńéŸńŞ{œy­€ˇ”^\qT* qÇä“lăˇg}}†Ş_uʈ{ŇŁŕ”(96# “|pöÍą4c™<ĎoĽ´›ƒŽóńŢź?~]Óywô$ńP˜-Íë˜É/`š§Ś†97w‘í­ëą]ËuX(fyĺƒC,– 4DSĚŮŐś‘’că”uşŕŕĹÜôş˛."™ˆcK.›úůÄŁ÷ł~]‰Dźź&QhjŹ#JT×B’‰8şŽW4MĽĽš)%ZÍăué$‘H˜HŮéŃw6ThomBQ”Ŕ> cŕîM@TUĽíe~äGDFxN5őHĄ ÂqĹUÂľŻ•sŻu[­üŹljyÓʛč@Jć§ö#†?@€÷źrIĽëz¸Ž‹íŘ‹%ňůŠĽŠ˝÷ŞwÄW.ô}ÁŐ"‰D˘zw ’TŞěü"3ČÍĎ@Ĺͨbł˘ęxZO3AQ—˛éůLąŽëˇÔH‰(_dCąÍ==˜‰řę–Éĺ÷)J‡™b–‰Â,ݜ>ā‘c %/l{”˝ÝŰAJÎώąPĚbę˝é6\8Ά†NŢ=IO]épœ#ƒÜמ#cghNÔ3Cä ¤„Tœca96;Ű7pnvŒ‹ó“¤Ă1îŮAX3‰ë!ŞY&eîВEJćç3˜Ś‰Şh¸žƒë:„BfŐşňź•ŻŤýÝó<\ĎĹvrĽ"Ss3œžźŔኳ+ŒsI.bKWzHák’¨x´…ÓüÁÖ_gW×f UżćÝ#˙źtŤçJU<üťa•ĎŁŞjőůľů0nuąTqTRĽ,ÂçUj•÷­źîC]^–ĹEE×u<ĎŁPȓN§Ž˜ŘKOâz.–ăprč"˙×+GxmŹDÉqq<__ T* k„ĂĆU…Ő%ż:ŢW7ó]k_{§ŽŮÍîó¸â÷[=Á—\I‹đęßOŹxwyŮă~˝\AÔ>_ʏŞĘ˞u7ŽĄ¨D7>Ě6`Nys˛WłÉšŸň ^dL€Ü%dLmďl%ŠŻôÔĘrËB,‘1Bʏ„-ŰÁęÓ|E—DYş#žjRRĆô]_r¸”uO$žJđŻĺj×ňÚĎx˝k‰š—iB%ŹÄőşPďč üľ’1Ť‘0ËâWţé• 1Y‰˝ëY\äüĽQޝ<ËŃĹ ŒŘsdßąjWއ?|đ7IÄă¨ĘÚ Y{^űó—ť]­üŤ=~ˇ%Rk!cV‹Wes=l.Ď/Ţ?Íߟ˜bpÖfÁv(ş`×ČĨĺELD‡ú°ÎŁ-!>ťł›m}şąĚ-â2rsĹ!+yóv‘’[Ş:P\ń˜‹+-Ůn,AP„‚ލ$őaEťăńź2Śúť,ĎĹxryŚgg™ČĎ0ĺfPÔŤqZŁ ÔĽÓD#Qż‚ĺńšę÷–•ÁŸurĺ/Â]śWń˛^–Uć„UâTý,+ŢKŽj$5“°˘ŁÜA7Ľ€ŒšcŮÄR „#Ń2IţŤ@šŹ•&™H°Ľw=‹…<ă Ӝ_¸DŢľx°m€X4z™“Îľc{}gĹĘŘ_)Iş÷öŽ~~×>Ś* ąh„§voe׆ENOsr2˅ŹĹ\ Jއ" ˘*4†zR&ŰZŇôľ56 LMC(bmÇŠlrf(*i=LAQąĽ{GŒ.TBŠŽŽ¨Z‹Ňĺť×uŽ*(eÍ%-'ŽŇ!ŰńĘí]~{‘Rśn˝ś>Öj§>3˘…:=JAčXŇ)“gţ˝_ŸŒYcR#Żë€řçŚP):†˘.JwË̢¨¨z͌WőˇŕV! cŕ'+‹H*É|•šÖ]Ü[D]žůÎ?!4BŞś”KH–œdn7¤/D|YBs›wžě¸‹ÚŠĽ›8Ś5äŒUESUBşA,ĽľŽ‘]lZ5I]YÁ`ľSVŹĂkĹŞŞůV‰„ :ëxÔq(•J”J%\××YŃ4 3dbš~˜XĽ˛lubS– Ěňs¤Ÿ|BĹĐĂŢ“Â.W@•1q­A˝šŤXmžś†ńx]ăG,U* 1=ÄÚî_éˋË_z=óŕ˜Şť˝q @€>ZȘ¸SÉŁđ4}'c™¸ŮZ“ű;•Ř.ËŽłúâŚ3Ćrň%ýŒöŽěŮśír|jĆĺV×“đ_F¨ŹŒń^ŕĘ žëz¨ęR‚Ži*ĹbńŞ­/WJ躎ŚiD"‘Ëţ_KŹ%FË´cĘm(wEDŇ'ˇl‘şź˘ŔwëZ[Â#ăá֍!qăRÜÜnďteLĹIÍŸŻ‚y&@€î2&@€îT.T^čúš gŽ• ˘”ňśí˙8HËó€ŰlĂ[Ń (•ŹňńŠ­zPŞąş݃Ľ €ˇ žçůšM5™ž™FąXŔ0ŒënQšŞÝń*U×S!) 5˙ę5H铜žçĄëÚ2RËqlŰF×ő™l °4––‰€ @€ŰŔ7/@€îÇ Ş­Žă’ËĺŤÁŤ=ďvl÷Nvpg’ŽJ’Ďçq]o™Po%Vž'Éçóxž\SUL€Ű›4 Ÿ Óô*!#„(˙ޞ¸¸XŽş¸öX\Ůnt=äÍU ™•f„ç;őÔ ßîíΕ]@ő…\՚8ů1Ëçó8Ž–wăρ.šŚß{׋¸‡TĆ Ŕm ^ޤ• Ş*†a`Ű6ŮlĂĐQUľź0Ž<ďzԗżćj%WzţŇçźńýŢĘĎt#ű^űă˘z7Řó$†a,Ťś˙~%V™Ě"Śi ięužë;wnÝńšŢsévžG×:>W˙œĎsą, Ď“čşŞŠ(J(ŻŞb&Žc“Íf1 MÓjĆađßćYŻC)%Ľ’ë:ž3ϊż2ßY–ŹÎşnTăt#óÄ­š?n÷ÜuľyöV~‡ľÍ +ç@ó˛90@€dL€ÜSXˆŠŐŃ4żíĹś}Ťl×őV­’ p›ŇÚ*%MÓ0ŒŐې*ä™×u)•,r9ç2™ˇ7V•QÓ4LSż,aŹÄM×őj ŒeŮ E\× ĆŐ‹•ßÚ§( şŽcšĄU“űʸ2M×uq‡b1[ľp÷́ŕö" cŕ/‚Áż;Ź( ž§ß5­żŠ1¨mWŠÄ`Ľ†H%VŞŞVËúÜŮXUĹŤľPH)ŤD€ßbćăęÎF !VŐj1ŤŚ€jűŸëşŐJ@\‰˛ƒŇ˝÷j1[mlqťŽ„@Ó(K7M’ @€ë˜{ƒC @€ˇ6Y\M„réŽťŚ…îJ׼ZÔşŽŹćŒqw/¤ĺ-!7nUŹ–’Fp]oYëˍŢ^–4:6v)çXEC GŞŠ‚zÓU›í%ńÚ%§”ZAŰZ㣓ěËe6ăľÉţŞq.Ÿv˘ć4ŹmQ’,i:--(× Zďöău§?ďjDtĺ\ôĎKEŃŽ;ćWrČZiAżržž˜Ő|ýšÚ6Ş•ŸézŽí•>çW>÷„UËĎŐ;3_Ü|ů¸ pďΓKç1˄ϯ÷=*Ż˙0P{ SĽ\eçUÇeEsďƏxŽ‹P–_WŢü ČÉ @€÷!sĽ¤äzńľîľÉˆm;”J% CŻę.\+)ş;ˆ˜ť‹YŰgžąĎ+ĚŘić_ţĐÇ~ŤĹĐ>÷g4mzô›[DşŽK6›%Łë:  ĂŔ˛JÄbqt]ò,ršŽë‰„‰FcM)W’”Ť“*Š\vúyB"<¤ô°\’+ą]‰ăz @SŚŚ`Ş şşÜĹé^Yœ/ŻZöŸ;ň=V2gÍóŔeNŽ‹e۔JĽŞ SUSHLÓôçĂrE΍$ąů|ž\.‡Ă0B‡–Íłžî‹ŽëkÚOĽ•ŽP(‰DŞíž„œe3‘ń83岊EŁ%Ąbhʇ@˘ŐÎŃîu2&›Í˛°°@"ž žˆ_׺ŁX,’ÉdH§Ó†ńĄ|˲XXX@QTŇé4–e155@<#•JůăďNJ”—&'‰D"¤RÉeß?—ËS,I§Rhz.Ș¸çCWrTZë‚hÉňŐ_ü;ŽG6W`tb†ł9;:Cwkš I:[눆CUaŕ•ÖżkMڧ§ijjÂśmňů<ąXlM ąL&ƒă8$“ÉUďVyR’)zĚĺ=Š6ÔER](wm^+o*ţŽk“ťđ>rň 1ą€Tň\Ü˙ˇÔőnGŃôŤ&Ź×Âôô4ßýîwŮ˝{7}}}ü§˙ô?óľŻý7|ăßŕżűˇ@<çÍ7ßâ­ˇŢFÁúőëůô§Ÿ#‰|„ďň‰+ćĽÄ^b;.Óy› ‹6̗Ę8\*xä=—„ŽĐŃؐTčN†čŒë$B:şŞ\׸r]—™™ŠĹ"ŚiŇŘŘˆŞŞH)) äóyęëëoKl\OR˛=fr’źĺ1ꣂĄŔŠůčV4ˇâ}jďîŰśMŠX T*âyŞ˘‚ˆrae_–U˘dYhš†a—ľÜ\í3UbőŇ÷_âĐĄwimkŁ]F/đůĎžX,J>Ÿ'Ž022Ěšsçy衇ĐubąH<Ç4Mćçç‘R’N×aŰ~2‡šxqŒď~÷ťüÁüTUœ0Ÿ÷řű÷ňłą=xăŒÂŢu&ö‡‰‡‚ťńn ĽR‰wŢy‡W^yÇqP•ßţíŻŇŮŮ鯅 ]K&*ŠRoĂĂĂěۡ^x††ÇŠVŁT„ž+—­!Ó4Ťz^†a`ŰžxˇŽűmŔB4MĂuÝ*‘jŰö˛÷Š•ĽR‰ď}ď{?vĄ¨|ö3ŸÁó$ßúÖˇˆD"D"aŢť—G}Ó0}jĎŤ^ś…~ŋPPQv čş^]Sĺr9ţřëĚîÝťyöšgŞŸËśm~yč]Nœ8ÁžđRФ˙?E`zp‚Ș¸ëÓÂ+,ú×rg˝V”Ňóüddq1ËÉsŁÉňÎ.› ţ1¸pśĂgŘݟd[§Éću$“ɲVƒXÓgŞěłX,ňÍ?˙ż÷űżÇÄÄǎăî§ŠŠéšÄÎřř8Ĺbąœě+ŐU{áŢËOŽ8uÉfž ŮФóHˆţ&Cűč%RJŹbkâjvrQTwčůů)Œh˘Ş[r#‡ĂÄă Ξ=ÇüÜmmĢŠ…"–e“É,ňĆűxöŮgčîîâŘąădł9BĄ0Ş*îéqľzűŘ՝xdÍćIIśPäÝKE^łygĆfŇŘ^ů—~‹ B‚p0čxŹĹ`o[˜††ŚĄ( *ĐUö],y˙ý#9ň>B¨ läńÇ?A(BJÉđđźĂoýW_šf•EĽ•e巓rľ1.ޤî/‡‹ě?ďpiŃĽ5Ą˛§[ĺĄţڊýÝlëܕŞŻgŽŹ}?Ďó( ärYŰFQŞ૕•_‡F€Pđ<—bą€Žë˜†é'ŸkřLŇ{ăƍ<ůäăŘśÍůóC”J%Ž;Îěě,‘H„ŠŠIŢ}÷0---9r„T*Eww†aręÔ)ňů<÷ßż˲9zô‰D’†úJĹśmcŽ„ăă6''‹’ˆ.P€CĂš ⥠U(ŔÁu]fggq]—'Ÿx’—^z‰ˇŢÚOkëp™l)ą~ĂzNž<‰ŚilŢź™Ó§? ­­•d2Éţýűill$3==Íčč(gϞĽ­­††FŽd˖- ˘ŤŤ‹l.Ëřř8Ÿţô§9uęgϞĺńÇçČűG˜™a׎];v Çqذa†a0<<–-›ŮˇoMMM hmmĺžűî#›Íâş.>ööäő×ß`ŰśmŒńďţűÇáwßă;ßţť?ś$ź˙ţűLLL „ ĄąĎőČçólÝş˲8~ü8ŞŞ200@,ĺƒÎ0==ÍŠS§imkevv–_:LąX`Æ ĚĚĚ0>>ÎÜܧOŸćâŋtt´ł}Ç6ÂápĐĘ cŕ^K"ýDrmeůžçůwîgçřĺąsźwÁa8—`˘Ô„Hl‡P +?‡‘ěŕ’ŢĂË#Óź3ą@×ń“ěhUřؖšë0tEQה9ŽËáĂGČĺrĚÎÎ244B[[ŻžúĹb‘7`Ű6çΝcÓŚM ‘ĎŘ´i˲(K‹~Ň‹ĹřÄ'ĽŠŠ Ǖťčđć™"– !]áܔŞ@kJťŤČ˜[ĄSM"ł‹,:*ŠÖű°D2pôvŚŚŚI´őUó÷I€CĄëÖ­ă˝Ăď38x‚§žzĂ4RŕşNĄ€çš¤Ói4M§ˇˇ‡P(ôś^Ž+˛j\<OJ.Ěçxé|ž×Ç.Ŕr=<–ÚgVžCIŔYƆޝÉđl—Ĺ':ăԅ D™\™| …B läĉşIooäüů!şťťP•“'N1<<đ<‡zˆ‰‰ Ž?N"‘ ŠŠ‰ĹĹE.]şÄîÝť9qâŽă˛yóăc ćçhimĄT*ňĐCŇŇŇBe6ďńăEf= &=^9í2Т>ŚpŤ¸š[é:VCš\–\.‡ôܲe‰đŠŐ¨ľÇĺDÉą-\Ç%‰˛R/xőĎë[/^äčŕ1ńőЧ‘R266ĆýŃąaĂΝ;G"™`}˙z S%hë 1pŻŚŽŤˆ9ÖśPĚÍgřŮűyű‚`\t1ď&!\!éšäç>`ňĐ_Ó°ësÄ:ďC$:óZ¸˜™ćxn‘WĎcO‹ËłíŚŽ.…śĄ;Ďó(•Š|ýëĚââ"Śb˙Ű9uú4étšÁÁcôöö ( .Œrňä)~ř!~ţóŸSWWŽëüô§'yä‘GĐ4•Lf‘ŚŚ&< ƒc.Ž'iM¨„ •LŃăä„CŢňHG>zw˜¤çąX´˜Mí@mßFIۓĚĎŮäł6=Ž{SŽ%šŚŃŐŐĹţý¸téëűץi:ĹRŁƒGŤw8˙éŸţ‰ÖÖ6&''ůň—żÄ˝ŁŐskáIǓ\ZČóg'˛ü|Ü!cW„SŻž ö°]É{6Œç XŽËsëŇDMUő*qÔ4ĆĆ&’ÉĄPUŐřŮO_Á˛m>̓O~’RŠÄ[o˝ĹĄCż,ŰtŤěۡ§Ÿ~šsçÎ1==ĂÔä4ýýë0 ƒBĄÄŮłg™™™a~~­[ˇpňÔi4ÝOžN:Mcc#ŠŞpbÂeą$‰…­ •ĹĚĺ=N]ry8ŚÝuób…ˆÉçó,..‚ô|ĺbşž0óňRĄ•bťŠ˘`Ű6…Bp$|MŇH_kŚłŤ“;ďò,lŰbjjšcƒÇxđÁÎŽ„ŠBąX"‰DCU"‘ˆ_‘cšœ?ŽH$BąXB(‚|Ą@6ëˇ !čLkDM…šœ¤äHfsíuАJ€7‹‹/R,–čëëĺţîgjzšććf}ôQţôJG{'‰D‚ţţőtvtňÍo~“Ů™96mÚD*™F*Ľ’…eYtuvEinnŚžŽS'OÓÓÓĂŕŕ étš/üĆP„JWg|ç;EŠXâă/<ÂOňSžyĆoú“?ů\ÇĂą]Š…"Ží"=PUžž>öî݋a˜ĚÎÎ1za”M›63==ĂkŻ˝Ćž={Ň#ŸĎ177GąX,kD 4Őż&nßžŸüä'|ĺ+_á›ßü&cc9ţ<_űÚ×Čfł|űŰߌĽĽ…śś6ž{î9Ž9‚ă8ŒÓŇŇâ“Ř5óQ"‘ŕńÇçäɓäóyfŚgčë]woIßȘpĽĹ˙ĺWsŰqř˙ó˙Ćą†ĎŁÔ÷㠁@AJŻ”eúďŰ˙ ÔhłĽ-œDh:Rk$C9ş83ôoüü?ňüŻ˙J(tYŰŇj0 ƒŻ}íw8~ˆˇß>Čb6KWgO<ń8\ĽĽĽMӉDÂtvvňÚkŻ‹ů: ´ľľŽřŽĐšR8rBş ŹĂđŹGWŽŽ~4W3Ž'™ËäŃFźtK8ŽÄsfÉ-ňů<ńxü†ß_QÚÚZůřÇ÷˛uËVęę‘~ř!&/M‰„ůҗžČ‰'ÉfłźđÂó¤RÉ55Ňłâ’4-ńç§ů٘͢ĺáÉľß×ŹŹťm.ć%˙ߙqež'űëQőë!}-!Ý0Řűńc˛ěŚS(ظq7L&yůĺ—éííazzŤT"6YˇŽÓ§ÎpćĚYš)‹H)éčh§Ž.MCC™L†BĄPľôîHŤhB +˜šÂĐŹŞ :Ňę]݊fEfa•ňÁ_IĔý°DĽUi!S!ŮTEĽT*˘j*†a\ľ…TUUśmۂ˘(´ˇˇ‚Ç{”H$Ěoţć—Y\̲qăFÚŰŰ8wî<†ĄóÉO~’‘‘ahnnćđáw) <öŘcôőőpáÂ(şŽłyó!(óţž„`sŤÎÉqƒ÷G-2%dX°ťË )1nŠ˘`===|éK_ŚžžOşÄ˘Q‰$őőőôőöaŰ6şŽ‹ĆčééÁ0 ćççřĚg^DJ_ß*NÓŃŃI*•˘X,’JĽyôŃGřÇüG6lŘŔČČ‘H˜žn˙FM$á‰'žŕß˙áŕ‰'ž`ÓŔ&Ć.Ž188ˆiěŘąƒśś6ŠĹŻżţŽë‡q]MWˢô…|žŸţě§hŞĆěě,Äb1Eáĺ—ÄÔÔťwÎ×f2Mƒxýü§ŠK×ńĚłĎpéŇ$ŸýÜgimmŠ’Ç†a ¨ <őÔS|pú4]ě}x/…Bç~í9<Ďăŕcťva† „ěÜľ“ĹĚ" <űÜ3D"yäăÄb1šš9tč—hšĆ};ď#ăşăźđâ l Ťť‹}űöáyýëúŠŻŻGQ˘Ń?üĂ#ĂźđâóܡsšŽúšb܈5<.jţŽüŽÔüŹljyÓʛč@Jć§ö#ƒţ×Ü[đʋy×őp]Űą)Käó#JS{/Š˘^—ŤJąX$™Œ_–¸ŐęXśĂ×˙ôĎřóÓ‰Ý_D*Kźšt,Š—>ŕä˙ţëX “˜=Ź˙?&ŇľU5¨HŇ)Éž˙^¨żŔżţż‹i˜Kš י ­lŁŞŰ­ň/÷´’ (k$źÖ˘IdY6o˝őłłsĚĎĎłuëvíÚY%V_¸‰r­ČŇg÷÷ó#ŁŁsi…m˙?{o$×ufůýޞűZ™ľWĄ6ö H„@J-Q˘ÄžnIݚéVwLwŘî 'ÂăĽm‡ĂvŘî°cĆă°Çăđř{śĂš–:FRˇvJ¤Dq v  ľď•••űúV˙ń2Ş@)Š˘ZůEdTUVž—oš÷žű{žsb~iWßű嵙Z­ŽiZ+ĽŮl˘(2~żďŔ™mÓhÔ) Ž{É.`QŔąLšš Ť7¨çśpL×­EdBŠ’#G ÷ !Š2önKlŰƲmüţŕž>÷Qę+N‹~%ü űUąXBUßۘgŰ™ľEŁŽßďCÓTTEmSâűœçßn+ŚiĄ:ľZÝ´‰$„Â{ô×>ęç˛ŰĽH’$lËƲÝĹEQ\ąjĂϢ˝íxÔžgv۝HŔue’$oŰöóβ]$Yvˇś2ü/˙ü_NĽůťđŇé”;ëş ‚ŕŮáËvŸlƒšî8¨cš&´@Çqh6›-€[öŽť=żrlŰqEEV0LÇqey›X–é}› Ólę‚ËŚ%ŃűűxیŁďřŰŞ*Ÿ €č€ŮzY­—˝ëĺěúéܙďYÚyÇ ĂŒéD':щ@쾢†#÷cźô]lŮÁ˝Ł¸Ś!cPĚ Â8šŠ-ƒŤÄyçłFvŽcOäţň˘ď~Lďĺďd‰ôĹdz˘n’$‰˛(ü­”uÇĐ)ÎM\} ŸzŮîAPüśI°´…ž9O3 9ԃĎ×÷ˇŁNě Ăśyk˝Äľ‚m;`!ě°vő/ApíÖeQ é—y$Ž1V¸–mrm§Ža;ŽƒáŔO7>ťUäÔp „‡Ăćɲ̉ÇYZZ" 30Đď%1îjÂ=ĽˆOą̂Ď+ˇ’>Â}O×uŹ–îž—ăPŰ^agţ2ŮŐyŒJÁą\°L”(ćvhÖ+ô:&áî}’ ÔíJ Ă@Ó´$hŮ麝ř ŸŞŞîyO”DDiŻuŰćš>ŸďIŠşgŰűE8ć?ú˙Cp‚Ą ×ďŢ÷ƒ€ĺÝßy÷yÜ}Ěíó˝×1íŢÖď÷ßőýďÖ˙{>ĆNtâN+ëD':щ\F#CƒřŤ[؂Ž#Ţqqpp|r8 HÁ8h*–ěŕHśg #8Je‰Ń/ş@ˇâz/aaŢăv÷n@ž#ţđŔýÜ˝íĂž÷ŃcL˝AîÂčYúár͟DTUDŮĆŞçŃVňěŘ}Ԏœ"’ę{_çŇ^ĹmOtw˙žű3ťŮMŇʸ×=|Đ}˝Ťk÷ďwëvÜëťßÍ.ýƒŠşnňóŐ—=ć8-~Ë.‰ ¸4_Y€T@ćLÇ{Húč ČüŤŤ9ndk8–#€ăäë&/­Ö81`! ŇťÚÇ?ěšJ’H,#‹} ×@ůȗžě֋ąmŰŸÚ×̨—Šl-°š4CacE‘đů4ÇŚYoR(”Đ-8ŽŒ˘FRďp8óVôp mĄvIRű˝Ýlš{ő‹ű1 ď÷żöko_Ů ’ÝŤÍÜ˝wëߝč恀˙ F':щӉNt˘ŮäîI´( D"aĆúăĚםÚôhÁÁV%¤hŇýl0‚ăS°%GśqlWWĆŠćčűˆE­ÉýťĂ1mŠvű˜$éá,ąŰŰZ–ĺ­P파ďM:Ţ}ťmúq›ĆÜ>žö1˝—Ÿť“Ÿ_††ăŘÔË%ę7~J\ĘŕĎnáD$Y@ô ؎Ił&˛•+PŰ\Ä>pŞuMŢ[ŮÄÎÎWŽ\ń4žóď000@2™dll AxőŐWY\\DΞ=Ëđđđž$pˇ.F›†ÝڌˇËó.\¸ŔŔ@?/^ä™gžń(ďím>žç\îŚÝČţ2tmlÇĄRŤs=g˘›˘[ş" -ĚŇnëÂ"" #1gÇ"<9" Ť"š$bÚ•Ś…Őę#nŚîĐ4Žěč4uEň?°mďNčś_}PÇŻƒfĐî2‘whđ86z9K9ťÉöÖ&Ş$4r”ŽáIË$ťş@cnŠ\f“Ôö:Ąî,J¸ë ‰Ý*9˝WéLť-OMMqăĆ-žüĺ/˘ë:ßřĆ_ńěłĎŇݝöĆŚÝýç~€ËîëŢž˙íž•Ďxíľ×ŘŮŮ!™Lđä“gyă7yúésH’Œ(şűťző*ŘS6´{˙ŚiréŇ%čëëë€2čD':Ńc:щNt˘żH‚€˘*=¸Ÿk›3řŇ}ŠÜĘIlME Ç)Ÿ†- ’ŘŚž˝ŔÄž~|>í=iÚüä'?ĄŮl2<_űÚżćšçž#P.—čëëcxx˜ĺĺefgçŘż’BĄH,çʕ+ Ç;ŃNt˘č€1čD':щ÷ ĆhŞĆ‘CűŃ˙Íy”ŁŸ ˝¨íŽŞ"Ćş@)ĹńŠ8˛€#ś\D,›Ćö<'=Aڇ Ă0¸ví:ôG_ĺʕ+Üźy“ŢŢ>˘ŃőzÝď“eŸOŁT*‰De™×zňčŃŁ„Ă!˛ŮŹÇ˘EÉľŤ-•ƒ/Z[[ăľ×^ăŘąc\¸pAČd2,//säČΟ?ϑ#Gxíľ×" ńć›oröěYü~?Íf“RŠ„(J­żŽUŚ, )•JdłYćçç‰FŁż0ĆÁe“d.˝ˆ‚Žˆ›´ťŇnné"H’ƒ&۔ç.SËeP}„÷(ré÷ű‰FŁlmm‘ÉdřŘÇÎ077ç•,e2úűű‰Ç㈢Č'>ń Żżţ:ŸűÜgůÚמƳĎ~ŽŮŮ9nܸŞŞDŁQžţőŻ388D$Ĺ4MšM .02˛jÍWUU•#GŽ`Ű6ŻžúĎ<ó ˇoߌR)311Îúú:śí°ššÉúú:šŚńČ#“\šrĽej˛´¸„mŮüäÇ/ňďţĂđÁ­r“ÍގmZŘśŐ*LM†„_ćxˇ/O&xŹ'ˆO¨›ˇsuž~ŤŔá.Ÿv™eśËĽŚËŒqÇö`Co’ŻË ÚNˇůmcjęĎ?˙<ögĆŇŇ2Á`I’0 MSMS1 Y–1 ƒ`0ˆ,Ë4›MŠĹ’$ Éĺr­>č§Ńh I˘×MÓ¤\.Łë:>Ÿššy–––8qâÄŻĹŘçjť´4|öXI¸Ľš˛ćcňܗ8pⲏ JČ2˛*sčŃ'‹Ęüůű2ąě‡oćʕŤ~÷{D‘Ë—ŻL&yë­ˇED"I(ć'?yąą1dYáęŐkäóyڧgxňɏ󳟽Äŕŕ Žc †řÁ~ŔłĎ>ëZ­gł,//ł˙~8€ă8 yAŕ…‹œ;÷ ˘Ń}}}źöÚë:tóçĎ …¸~ýńx‚×_“H$›ožIWW’Çw đXSmpżÍŹz˜1v7‹ëÝúęnŘ}ÎżsŽaY–'&źťŹś=׹mۛ+H’´‡ýÚŢ˙űŐnŮ˝ŻRHş}ü´řţÝe”ť…˝yF뺡ČďilĺţlLŰśŃuY–ßóőžťlúAĽ”íš÷z_tÍQćéĂśůӉNt˘ż!@LźD­|„&–ŹŢI05 )„HÇßđl@ŔM„âcC‡˝IŘť=´ŰS]7(K‚ˆÜúÎFŁÎ‹/ţË2‰Fc„BAĆÇÇyţůçůĂ?üC7 4Lr;y2™ ~żŻýŻxä‘GĐut:ÍövĂĐš|ů ŠTŠąą1öíöžť\Ž’Nw300€iZ†ÉŋS|ĺ+_!‹˛ąąI­V§TŞpěŘq …@fł‰ŞjlmmóňË/cYĂĂĂär94Me{;Ëg?ű /źđbËÂÄů€)˝‰ŁĺPŤŐŮ)×é‰u#JŃlš;´œy4 )¤`@ąR'lۈďQ7F’$‰[[lŰöŔ%]×1 ƒh4Ęúú:étÚKĐ8€ $ ‚Á ńx‚D"I>_dg'‡m—¨ŐętuĽąm›xď:čőôôL&I${@ƒjľĘőë×9v옡 ő°űo6›{łaüěg?c˙ţýěۡď=ťalll ( ŠTĘ{ŽëşÎÖÖ‰Dżßď•i ćççyâ‰'ú;666źýÜëűˇˇ3ôőő´ű”‡˝÷ů|Žó寠œˇĆt˘čÄG0DQ$ 0UYŤí „Ă´r@dÄXÜu) …\ÍŃM ÁÂŽVHʉHčĄFíh6›lnn‡‰ÇT* …"étĂ0¨×k4MŽ]ťF?R˝ÁhMĚśˇłôöö'Nçúőëäó9,Ëâúő8p€ńń1×e!Š"†aĐl6Y[[' ă÷h4ęBŹCš,…V)ÁÖÖŃh”P(ÄÎÎ###loołššIw:Íá#‡ůËżü:ŐjŸOăčŃŁĚĚĚ| Ž%wĘBllËb3“Ą4xŠpoUsAĎĄ6ËȒ‰¨Šč˛˛ĽÜÓKAb-_Ł×vPZŒ€‡=8QéëëennŽžž>4M# ąžžŽ ôőő‘Éd¸víŽăĐÓÓÓ˛ř”źÉR__>Ÿx™é\“ΙË5ř“c]|qŸ""–ă°RŇŠę.¨łŰłLŠř€dIâŠsOńÝď}`0K8B’d&''ŮÚÚbll”ţđGH’ÄҒÍĐĐP‹9cŮĘĐՕÄđaYÁ`€G}”Őâĺ˙ IDATŐUúúúšyóFŰśŠT*hšĘO<Áĺ˗č'™L|`BŔF4š pEŢľŇ*⋥ †WŠn/I¤‘$Al ‚;ÍzÚö2Áh-šz‡>’ač†ůŔ2%AˆĹbȲ‚˘(hšĆđđ0Š"HĽş<6S0Ŕçó‘N§ZIHšŚ222Âüü<ˇoߌŃh˛˙~şşş°m§u_]{ÜTŞ‹t:E(D× ‚ÁŽăL&<÷™ŃŃQ2™ FƒĽĽ%şşşe™h4âő•p8́“ĚĎ/P.—‰D"äóy Ă ŃhH$ČçótuuÇ;`Ěo@ŘśMĄP ˇˇ—FŁÁĘĘ ŮlUUćƍD"‘ě ~żŸńńqnßžM˝^GQĆĆĆŘŮŮáęŐŤhšĆČČ7nÜÄqlΜ9ƒiš<˙üóô÷÷c’$‘Nť@~6›%sŕŔOűȑ#„B!}}}\ż~Űś9}ú4Fƒ……Nœ8AľZő€ů™™śśśčęębtt”ۡo300Ŕââ"ĄPˆţţ~nÝş…Ďçc``˲Đ4ŢŢ^DQ¤Z­’Ďçš|ů2Ď=÷~żŸ™™jľ]]]ž5ööö6ů|żßO"‘ X,aY&šŚŃ××Çíۡq‡ŢŢ^fggéííejjЧžzŠĹĹEúűű!ŸĎłşşJĽRńŔĎŢŢ^nÝş…(Šôôô°¸¸ˆ$I  iŽ|(" ríÚ5|>ˇnÝB–e,ËâŇĽK4›MΜ9ƒŞŞœ?QY^^f{{›`0ˆŽë‹EFGGY__÷töĆĆĆČfłlllpđŕAŽ_żÎńăÇšző*]]]ěßżŸ@ €eYĚĎĎóňË/X__Çďw™—–eŃßßOš\ŚVŤ!şŽsâÄ |>Żżţş7ŚvwwŁëî| VŤ39ů…Bˇß~›S§N1??Oš\fbb‚ĹĹEN:EĽRaaaRŠÄŘŘ™L†Z­Ćŕŕ †A(â{ßűgϞĹçóQ.—I§ÓÔë.8ŽŞŻžú żó;żC:ćüůóôőőQŤŐh4¤ÓiFFF¨×ëÜźyÓ4byy UŐƒƒA._žŒŽëěßżŸ™™™ş‹uŔ˜Nt˘ř[ť…L|šĘD_ŠĺÜ:Bßžö§@ÂQÄ@!ÄV%OWÁěĘ6ƒq?ĄÖ ČĂÚíJ’D4ĺąÇC–%vvrźňĘŤř|7nÜ ŤŤ‹H$L/žřSžň•ßż#,ŮZ-*‹ ęuˇƲ,úúúČfłLLLpéŇe67ˇهŚitw§QU•îîłłˇy饗Š×댍ŇŐŐĹ+Żź†Ď§ľŘÝ9r„Ÿüä'Äăqbą(‚ °˝˝ÍÖÖJ+‰’[“,Y–ńűýTŤU._žěQ]?Ćcl ÇÔŃMVWW‘ý!ĚčYJ Ńl"‰€ş#R1dJ5ťPbm}ŁAÂAVIB@Ó4Ç{IrKłyäRŠ”wO:E.—CQ’ɤ[ţŚiœŮčb‚H4ńVšşşş˜˜˜ ‰ i…BÁ[áTÓ4špá"§N=F ŕg||Ź•TJƒ!NŸ~›LŤŞę­îď-}_ý ×Ah0B˛ˇ]'%Ŕt~śXäŇV•î€L@ÉÔLĘM›˙ú\ż5E“´‡[Ů:öFL˅I@Ŕ'X¤#ĸI’D(âóŸ˙<ßúÖˇ˜œ|„Z­F&ă-ÉdŸćc`p€ ’É$šŚaŰ6˝}˝llnĄ¨2áp¸Ĺn€íí,‹‹‹†‰(ş,’P(D˝Ţŕ•W^Ľ§§›`0ˆačyńŢÝQŤŐ…;6łm@Fń‡ ÷“_şNfú-‚ÝŁbIljĽ<Ľ9ĚZ‰řĐ!č.°´ľšÝh>p E‘‰‰ Al1MlLÓŔ>űŮĎĐh4‚-°Ä-}üqWDť\Žx@Ë͛ˇČdś‰ĹbLLL ë:Íf“TŞ I’‡ĂŒŁŞ*˘(˘i*çΝCÓTjľ:˘(ĆřÔ§ž&“Ů&‘H0>>A"' đÔSOĄëM‚Á`ˢXe` ß[ ŽÇă{˜1>Ÿďb™uâ×+Úí}aa€G}AX\\ÄśmŽ]ťĆéÓ§™žžfzzŰś‰D"ŹŽŽ244DĽRÁqŢ~űmâń8ËË˃AŠĹŠ˘Ëĺ(Šâů˝˝˝źů曆(Šěěěx ‹ÍÍMLÓäŃGĽŤŤ‹ţđ‡¤R)ŠĹ>ŸH$Â[o˝ĺýnyl“FŁái$E"ŞŐŞÇě¸}ű6‚ `ƒƒƒ\šr…t:í-<8ŽC˝^§^݇=‘úĽĽ%‚Á WÎ+IóóóŹŹŹđÜsĎą´´ÄÖÖGĺ­ˇŢB–eęő:ŠTŠ›7oz@G  RаşşĘŕŕ †aP,ą,‹‘‘š|ů2O=őÍf“×^{'Ÿ|’JĽBOO[[[Ž]ťĆ—žô%ŠVŤĚÍÍqčĐ! WCŞRŠpđŕA’É$˛,322ÂććŚ< “Ífi4üčG?âŤ_ý*ľZ MÓ<@+‘H Ş*׎]ăÜšs˜Śé•FĽÓiŻÔľŻŻĎÓŽŠÇăœ?žÇQ) |ó›ßd˙ţý(ŠÂ•+WřřÇ?N.—Ł\.óĆopěŘ12™[dłYšÍ&ńxźUR+qéŇƒƒƒX–…eYdłY8rä+++Ôëu†††řŮĎ~Fwwˇ`éşŢZÔťŽ(ŠÜž}›ńńq"‘óóó8ŽC"‘ŔśmRŠ>Ÿĺĺe†‡‡ŠT\vhĽRaee…Gy„ééi$Ibßž‘ÖsÔŕ‡?ü!Ţç<Đc:щNtâ7€š_"Š) ÝüxyQś˝ĺx‚>¤T-VŒ[˘$ŕ”ˇЇ|÷´"žďA–ůŁ?úŞ—ĽR]<ýô9dYĄżżI’PU•íím††ˆÇcí÷ÄÉ㌌Ž i*@`ĐĎɓ'QUżße™-FÜ#Üž}›X,ŠŚiÄb1Ξ}’ršŒŞŞÄb1AhŃü Âá‘H„Pč$…BŰś …‚„ĂalŰć̙ÓT*7iSdTUĂď÷ńĺ/‰`0Čg>óé–]Žź‡Őń‹16śeŇؚøůrĽ[Ůj˘d G ˘+J+ɓZ‰‰Őh edĽÁÎö63ßúßéŠúˆ?BřđÓ^"ů0Z[ŹS"á0‘Ý *xY–$bŃ(ÉDPUĽuż“ť>ŠěĄˇŰDű=×.ÝA–dţÎo?G$E‘eؕD.e¸ŃhrúôăD"”Öőčéšłâäo ß~Đě6Ŕ˜ŠGé•V˜34lÇÁ´ÁśĘ[ĺŚwąTI`ĽĐtŰA\°Ĺ´níTąm§UętG“Y†4ƒH(řŻ2§Ÿ>‡ŞŠ$“ ţäOţ>Ą[bWŻ7ZV°~űď|YV0 ƒH$ěi(ŒÇ[ [„ßű˝ßCÓ4Ž?Ćää„7ůtŰCŒO~ҝüˇŻwť>˙×!EC7Đőf‹Ąr‡#Š"ÁŽ>ĹOié2ššˇ)(`c›&’Ş‘9ŒëAÜĘŚIŠTA| Ť[Đjßdg÷xœÔî ŠŞîűáPĂ09÷‰ł˜–…ŚŞƒABĄĐžö!Ę"ŠŹěiŤÝé´Ű˘1dĺ÷ťÔy—AvKtú^eťűëŢ~˙a­đv⣲,3::Š \şt Űś‰FŁ8ŽĂŃŁGYZZňDÔÓé4étšk׎Q­V=đ6S,qEQ<­ˇś>G4Ľ^ŻFI$-fWŇcaŞŐ*###œ>}Ú{î8p€­­ şŢdaaÓ4[ŒZˇćr9˘Ń(˘(zŔP{.ąžžîąXLÓô˜Ĺb‘RŠä#šŚíŮΝ(LNNrůňeňů<ĄPČeĚé:‚ P*•źŹZ­ćÍo\ÝŽ"ĄP˲‡Ăłźźě áp¸4šó”RŠD&“ńĆąPȝËD"nŢźÉĐвějńľ÷ŃÖŇi˙m!|I’đů|ü~?•JĹÓxi ę+Š‚ŞŞtuuQ­VůîwżËÁƒ †iš<ńÄ,,,x%˛í{Ő>§H$B0IJ,*• Š˘‹ĹĐ4fł‰až˘(”ËeďüÂá0ŰŰŰčzÓ[SU•fłÉĽK—…ÂŢu5 ĂÓj)—Ë€[NU( \n8FEâń8śm300@8öŮBĄĄPˆD"AŁŃh-ŇŨŐj‹Eď9 éďďçíˇßŚŻŻfłI>Ÿ÷´yúűű™˜˜`ßž}-F؇3n ńž°ëďöď⮟í—ÔzÉ­— (@ĚŠmżcwFĆNt˘żVŃÖ°Zv¨†iĐh4ݕK5HşäĄY íUĘFŁA4žor´[¸Ž^ŻóâËŻđ_źrƒĆs‚cŰؖŽ`;č3W(ţë˙Đs„ďēH‚„ )˛?˙kţQÄßűíύ„˝ Πťkˇ¸5Ŕ7nÜ ˇˇ—îînے`jjŠŁGŢłLĘu6ŞR­V=ŞđÝÂtw~ˇřŰÝÖÖťŻŮîăßm7ťűî%ägŰĹbÉí /Éł-Ěz‰âOţźú/˜/Ƙý{'ž Oá‘dA¸#´gš&őZFľJĄP łľAň'˙3ăZžŽÇčúę?!6ůÄCƒhwĘq>ôĚňjkp÷a†|Жâm!— x}%Ţóžç*uţű§ůć’IŐp8!R%‘'úCü7O 2÷ŁÉ"Ýâßţ›ŰźşZFˇvľ#ŠÄr4ŔŸC•ĺűŠDînˇíűÚÖ°ŮŰśÚZľ{EďĘźťĎŢËMéîëýŤcjľ:Śiyz%n=żěpťŻmŰĚḚ̌¸0ÇÁƒ=懧ÓŮph”ó4Ę9H FPƒ1AÂÁľ4ßm•]*•˜›cxx„ńńq|Đ5i÷Ť÷Ôłœ;bŢkמGŹŘš˙ů HďׯŠĹŞŞ=4+ͽƙľEŁŽßďCÓTTEm‰â/ý¸?ČóoˇÓ´Đ Z­ŽnÚD’BaDQâ×!,Ë"ŸĎÓh4<ĄÔFف(Š@"IÁ`ršěŮlÇqđűý$“Ięőş'Əǩ×눢ˆßďG–e*• Ífżßßď'“É Ş*şŽ{‚eY”J%oá —ËŃh4ZŽbw„}ăń¸'Ćďj/…(—Ëž"‘ ^ŻŁiů|pÚs+WŽxÇ800HOO7Őj˲<}Y–ÉçóT*şŽ{Œ‹7ŢxƒsçÎľ´/přđa|>ŸHx ŠT*ř|>J%—ݍFŃuÝ[´¨Őj¨”Ďçi6›$“IÇÁçóQŤŐřÎwžĂ—żüeÂa h6›čşÎÚÚŠTĘťĆ.›F’$JĽ@€fłIš\öŞí…Ó4Éfł cš&š\ÎÎĄ vĺEż?@š\f``€ĹĹE‰@€FŁA­VĂśm˝Ô֝Y]]ettMÓX[[kąűÜqckk‹\.ÇĆƇn•hşL×\Î-YďîîŚRАJĽ<ÊišƒAŚiz€˛Śi”ËeLÓôĆ˲ź˙˲L­VóŽA0ŤT*čşîí+‹yףŮl‡ŠVŤ^9jűÚ$“IĘĺrK[/z( ăŽĺ˜€ŐzŮť^ÎŽŸÎÝÓ´űňfL':щN|Ł=‰ďŠĹHk"łĽ,(2ĺůßaë:b<‰4ƒç—ŸŒÝ߲اČ|j_ŒŸŽg(ëŽęśĹë+Eţď4ůˇNvsv8FÍ´˜ÎÔ1-ŰcĆȒŔ°ĎੱŇC´ŰťŻ$ Ý/ď'<Ů.GPUŐ>ՉďÝ Ó{ƒ\v—ŔÚÚ###­ňš˝ Ş Šřc)|‘¤;űľlW{(Ű1šÍ&ËËËXŚĺš‹˝cŮ6 ÇD7 ρiˇÝö;Řďj‚ˆOTPZ żđ+Ń:ńë’$‘L&ą,Ë{ˇËQDQ$‹yý`7#ążżß[€ił,zzzźE6 Ú~.…ĂaĹę8}}}X–ľgĚj‹ĆˇŰqťdön°š=n(ŠBwwˇ ´ZÚ@¸ĚŻ6p&IĹbŃÓ˝Y^^Ćď÷aŰś'ZF˝qĄ-Šť{§ŮlrâÄńV‰ŽĹáÇ˝˛YAˆD"ďXěqľńŽîn;ŽăąL"‘Č;ĆćršĚ“O>I8ö\…|>Ÿ|´÷ă‚(wśkƒZšŚyŸť;şşşźßďĹCű§]Â%Š"cccŢg4Mó˜TíëßfšŸ­­-Ç!wŕt]÷ôJĽB,ó’Öö{[[[ȲL__şŽăóů<˝EQ(  Óf oooÓl6 ›Í’Ďç‰F٤ÓiAđţnłhu]geeĂ0čëëóJˆLÓôÎŤ]ňÜ.Qj—*& Ľě8™L†d2ÉŔŔ DŁQ†‡‡÷Ř.;ŽĂúúşwÜmVćý˘-bÜţ|˝^ßł¸%ýýýôőő˝ŔŢ= BĄwŢďw,žßś.Čąwěź{Źi_ˇh4ę•'ľ‹w‡ řý~NŸ>ý&󽎫ÍjŐuýeĘw?Çßí\Üc5°í˝ a[˧]ęűnתP(P,üĐŹŽ;`L':щN|Ł˝˛ÇLô7^@űěďâ˙“Ď]ýÍďĐüéĐÎ~ ߎe!ÄŁč/˙„T#KwúÓďůAŇvc™C&'÷séŇĽ]Ľ @€t:ÍęęŞW nY&KKË8ŽĂÄÄ8 Ž[@oo/†Ą“Él{uƚć:鏭­3>>ŽŽëĚĎ/ŕ÷¸}ű6Š˘044Čôô Ą`ČĽýśô˘ą(ˇnÝÄq\ąşz˝Îúú:ĂĂ̌ěűpœm×#,SÇYz™˘Şě–žhĽeüˇ×QWŒ D” ’&ƒh#9uh°kUňyC°iá0ƒ&Jcťź‚ă›Ä‘DמüŽUDA0›˛Ů`˝˛Ăk‹W0m Y”X+gč ęL ˛]- ő˝2/WsHLŰŚŞ× i~L@ a6ÉV‹ř UV*>|‡†ŠSiÖ¨~BŠpHh22Â=ËÜ>Ü>Ă;ĘťÇAş"~ž›Ls#ˇĘĺœEĂ|÷ýę?šÝńěmçŽVLPřLŻĚgĄČ"˘(<„|űíˇ1M“FŁé%ÝÝÝ,//Óh4čďŔď×XXX$‰ĐՕd~~I’<'‹l6K:&™LríÚuŻN^Ő4^úůËÄb1ü~˝˝=,//c˛"sâÄń_XůĂpÚ"ӃCCä yśˇ3ˆ˘@:&şł‚Űfńľ˛œV×tu}lĎÎ}qq‘ŐŐU‚Á űöík%Pív*îblÇĄl6Ůi”šąľŔěÎ*ŞŹ%8Ů?IÓ4h˜:a-€,JnÍž śĘŁl,ۢ܏ó‡pľ• Ó [+áSTlŰŚ+óŔ ˇm9›Up +Ľb4PTĄtv@˜NźˇĐuŤWŻym,u…Ťggg9{ö,/žř"O>ů$ÝÝÝ{’îééiOĺȑ#X–ĹÖÖýýý<˙üóœ9s†@ ŔoźA,cjjŠgŸ}–p8ŒišĚĎĎ{‚šŻżţ:Á`ƒ"I/źđ“““d2üqTUŲlX__'ł°°@.—cppŐŐUDQôÄ}üqŻĚ'ŸĎ3==͉'(•JlllJĽřţ÷żĎŔŔ€7>ŒŽŽzʊRŠÄoźÁ§?ýisssd2]ŚÍ¤™%—ŰáĐĄĂ^IL˝^gjjЉ‰‰–r@ čiÓX–ľ§ŒŚŮlňüóĎóĚ3ĎxĺPťÇ^ŸĎçJťKPŰô˘(Ňl6šxń">ú(‘HÄ+ßiĎ w3ƒ,Ëň˜LťŸ}mŃîśVL{ĚÔ4Íďőů|ޘ ěaŔ´ˇ˝ző*###ĚÎÎrňäI*• ˘čŠ•+Šâ˙nM™ś^™ë⨠ënÔT UÓpl›Z˝ĆŇâkëkœ={I”0LWGFS5tĂŔqlYAŐT0ôôwA˘ÍŞ)•JŽč}oŻ‚ełYŽ\šÂă?ŽOóĄ¨îńśçV–mŁi*šŚQŻ×Y[[C~üă{:G0ŚčD'~CŁ-&yd ô_˙ SGýť‚‹a\zsu5ňŇŁO@ł†ń­ŻŁýü‡ý˝ß%N˝§Zýö ŐľkיœœD–%Ö×׸uë‡fjjŠS§g}}Irktoߞe{;ËOœbggA˜šşL$AU%.^œ"`š&ľZŐŐUöíŚP(´œ”şšzőŞgŸX,™Ÿw'EׯßŕěŮłź}á‡beu…Ť×Žąľľ‰ ˆ,,,ÇÉçóěŰ7ěŃhŮÉŚÓZmą‹fي´ő‚Ź;ô$ĄXÉ1‘mšŃDŹä]15DŮÉ-(6MP€#}}CZDa§<‡EtÔű–™śEĂ6¸°r“JłĘÉţý88|˙Öë<1|‡AneQ$EtĹd FX 0ťłB:”$W-pyă6çFO˛S+ŃŒ ‰"Ż,^c0–&ć! U˝Îўq  סćiMőŒâvÓtL,ÇFÄ_)s/ źÝÇ˘Š Çťřă|™˙őr™˘…ĺ8m\íŢŕ¤ĆŽ˙ Ž€(‚*ŔǓz˛D$€,˝{ť›™™add„ .đą}œ fgÝţ#IWŽ\ĺńÇOq떛`dł;LMMy ŽťV㋋K-‹ĺ•JšeG. šzĺŸüÔSĚĎ/´ú#ř|Ž\žĘ‘#GöŹôţň°Jgϊćű)S’$×~˝żżŸ••%vvv°,‹dŇ ! ‚×w—8¸:O6şŢdkk‹ůůyś3ۈ’ČáÇIv%ßőű­ł]Í3ľ>ÉţGk^œ˝@W(Ƒž1ś*9֊Ű5""“Š!–ň›čś Ŕ§ßćKGŸŚŽ7hMbSk3ôE“Tš5őŒąœßd8ŢC@Öx{mÝ2ˆúCtŁčŽEÓ6QEĽó ěÄű7EŚT*ŃÝÝíiŠ(ŠŇr\ŤcĆ=çm[áH$BłŮôŘĺrŮ*• Á`ČÜníg7ËAQ”–ĺ°ŠăŘřýA˘Ń(7oŢdrrr``sóćMNœ8A,ă?ř…BŽŽ.OóŁ­)Ň.iƒľZÍ3ęőşçžÔÝÝÍ÷ż˙}RŠGŽŮ6ŐëuOĐťíúTŻ×‰Ĺbd2ˆĹb|ó›ßäŕÁCŁćęŐŤô÷÷sńâENœ8ŔíŰłŹŽŽzâąĺr™\.‡ <öŘc,//óŇK/188H:ŚP(’ÉlŃÓÓÑ#G0 ƒóçϓÉdźň*Qéííekk‹H$ÂÎΎgQńâEşŽłşşĘÇ>öą–%t™D"ŽeY hdd„z{{IĽRĚÎβľľEąX¤Z­ňéOš . Ë2lllŕ÷ű=g­üă ť@,‹Ĺ˜™™Á˛,Ž^˝ę‰î žy挌Ś<çŁk׎QŤŐH$ěěäŘÉćH$źţĆë?vœ}ű†ydr’ršÂ›ožŒĹ. IDATgssUUůżţŐ˙Í'>q–jľĆććą˜ëŔäęĹ8rä(†ipńâ››ěßżŸbŠHŠX"Ďĺe…ĄĄ!R]Ý‹nݚŚR)“Ďů˙Ÿ˙Ç{ŹŐ/Ęř|KKˌ …xä‘ TUaxx˜šš9ęő:o˝őVŒéD':щßô •,Ë<ýÔS4 “ţüŸŹü“ŰČ˙ř?GH%Qżđ;0ЇQŘÂü—˙ńšüŮüż˙ĹßőěßK†ÁŤŻžB*Őí: ČŽ{R__/šŚŃß߇Ž7š~ý:ĄPýű÷sűömj5w’wüřqŢzëmşťÓřý~fgçHĽşH&“Ôj5ŞŐ*ŕ֙g2 …ŠTš^xŸĎăÜŠáu] z ÜUţő ňšťBĚÁvlVň[Ź—w˜L ‘Š˜0 ÚŇŚ–cáâGšuá8ażĆ玍"2Ď?ť°ÍRU@ˇ$Đşˇ¤K@Ä/ <Ő-ńĎ pp …"‰8qÚ>ŸŢŢ^EĽˇˇ—FŁÎĆĆdpp€jľćY‰OOOsôč>őŠßbzzš—_~UU˝Ül6ˉÇŮŮŮassłuˆáH˜ţţ~2™ ĺr…ÁÁbą87oŢüĐŻő/̾ǽ6s.ŸŰĄZ­aŰ۞¨˘+ëC’D,ËĆ0 ęő:š\ÎK1z‚‹kˇ(5*ĚćÖOŇŠPĐŤř$™ŮŇ6›ĺ‚Z€BŁBÔ`Ł´ĂvĽ@Pół^̲VĘp´o‚™eĆĹŻé™vÇř˘ď3š“eŮÜÜ$“É`YŃhÔÓfŰ˝ÓfôI’D:Ćśmfgg=}ĽösŐ0 ršÁ`ĐHFFF<í”Ýe@€Ă‡łąąáélóŇK/122âiĐ‚ŕéż´…hۂۍFĂ[m~w‰J­Vc{ŰľŻVŤ^)“ažmŹiŸG[ŤŽ-žŰfŕ¸,œ;eSm—F×ŮŘŘŘŁŠ×.Cęďď§P(xç÷ď|‡ƒślěS=z”^xOúÓźńĆë|á _đ4ZÚĽKšŚą˛˛‚ßď'•J‘Ďçšxń"ţçÎK/˝ä]ÝÝÝ4›M677) ”J%XŤ×댎ŽzÂŔ?úя˜˜˜`rrŇśĺÇ?ţ1ápŘcśœ9ó1^}őFGGéďďçŰßţ6O?ý4ů|žÁÁAýrüřqţâ/ţ‚/ůË\ż~gžy†ĺĺefffĐufłécÉd’ýű÷Ól6ÉíäI$‹Eęľ:Éd‚W_}•żţ›osóĆ …‚ť׺߯źúsŞŐ*Śi’Ďĺ‡ĂD˘Qϰ]2崘<Ąpťľ˝ŚižvLw:Şi9r”“'egÇzOĽSؖÍŕŕoźńŐj•#G\gąRąD,î~W›=Ôdî€1čD':ńŔ´'J^ŠR4Ęď>÷ş ţâř§ĚýĹŠřţĘłĎ!nŹcýÓ˙’Ţ­ ţł˙ŕóšĎ~†Ŕ]Âť›ĺóy†††řâżČňň2ŰŰŰ‚زR ˘Ş.•łŤ+ÉĘĘ ™Ě6>ŸĆ­[ˇ¸yóŚiqřđ!~úӟâóů8tč Ž>Ÿ†mťŽ’$z ă÷ž÷=&Ď>ű,ŚipóćÖCp?€;I ř|šOĺô™Óźţú눢ŔącÇ( Üž=Ăţý“㊿:ŘV2/"kşk+nƒb ¨Š@8X`é`ëśén&ʲć űŹ&ˆ —1#ˆ€Ş#UŢĆÖ˟Dź+yl'ť˘("8nűč '¸˛5‹cŰ<>t˜íJžőŮvŠ CŃ4Ľz…ƒÝ#ÜĘ,ą¸łĆßě (’ĚZi›ŮU6ËšVIŽ…ă@ž^ał”Ă/kŒ§‡(4Ęě‹÷PŐ랸čtęWŽY‚h@ĺó'ÇéŠüç7šT’¨–kwÝrÁáŽó’E„¸&ň…~‰?=5ĚH ŸrÇvůÝÚ^[˜1 ŕóšýččŃŁÜž=Ë­[ˇ8~ü8Ůl–ŠŠ‹D"nB15ő†Ął˙~2™ 333Ȳ̚sçřöˇ˙QÁçÓPU™@@kŃ­U‰8WŻ^Ĺ4-EöhÜö8ö~ˇu'‡ćƍTʕޠѨaY…BĄEżˇ¨×ävvŘŮÉaššćCU5ţ˛$síęu|~}ý¤Óéw˛„\ŮDDdI"ęQiÖYÎońšÉ3üŐĺp‹ůˇLŃąŠu3żł†Śjô…źźp‘/ě˙8š(Ұ Î/_Ătl&ť†ZŽcMKg1żC@ó1ífťV`4ŃGą^Ţ ‰BgŠŢ‰÷śm“Édxë­ˇE‘ÉÉIOłĽý˙_|‘‘‘Qúú\öD0dg'˅ p‡P(HĽ‚ˇ˘(ĚĎĎ#Iáp˜Ă‡ľzO& 2>>źň sss;vŒT*E(ä˛inܸÁŕŕ áp˜C‡ńŇK/Q­Vyúé§yűíˇY]]CUݲč7ß|MÓ°m›ééi&''ńűý pôčQňůźWƙH$˜žžćěŮłŹŻŻłşşĘÂÂ'Ož$266Ć7žń Eá™gžáüy—™áA~ôŁ!Š˙?{÷ßFy˙üswÚ˒ĺ˝â•8Î ƒ@ „0CYeĎÚĺW:č˘ăE”.ZÚ2ŰR Ľě•śŒ2’@iČىáŘą-OٲľŹ}wż?N÷X˛ĺÄq‚IÂ÷ýÂD–ĽÓÝ=wŇ=_=Ď÷ËcńâĹhnnFII âń8œN'fΜ‰ŽŽ.´ľľăŔ˜0aöíۇ˛˛2X, Vú[ŤŐÂăń`͚5X¸p!4 Î?˙Ź^˝EEEX°` ŁŁ}}}(..fŠdYƂ đĆo›ś¤&6›Í0›Í$ ­­­ĐjľŹÔśFف$I¨ŽŽfm–ZéH]?ŤŐŠp8ŒeË^Dž^QĄŐjqꊧ˘šš睷{÷îEUUKŔk4aľZQTT„wŢyŮŮŮ8ďźóđúëŻPů ´´´`ÓŚM())AWW‰4-ęęvaďž:H˘ŁÉ„D"ŔX,NFĎqˆF"ˆDŁĐhľˆĆ”ŕ“Ůlb×^‘HbB„Ţ ă9ĐhÄbQôôD`ˇg)U¸ź^ź´ó<űěß1}Út”—WŔáp ŽŽ;wî„ÓéDgg'Ţ~űmTVU˘śv2D)mŰśĄłł'Ndĺą?őĎËQÜOĽ­ !ŸŰ šń.mŠcŠŽK,žŔŢ}űńëßüëZ\ÖLŠi?fŰłpĎ÷ž‡YłfB§Ő¤&ޤşJjňË#YˇL0Vî˜}úpšLËL]ף鎶´ľZŇ:äéKĐÖń˜Ňђ9H2䈌Qó‹ŚDF;ű2™“=>[V1€˜ąńŠ/ÁwZz™”uˆK"<ń´xťđfÝǰ•‹\w°WLY„b{6śÖA#ŘŢąLš‡FO;Bń(ú‚>Ĥ.Ž=ďě]§Ń†žýá ŽžšoíüóĘŕ !%Đ `QĹl¸|nčqÁiśáĚ 3Pœ•=Ż…So…n§)Ś´őĐ &kťd(ÁÓďÊ]Mxż5‚˝Ą8"  Yi ­˜ľ< LLłó¸|’ójĘaą$sědČQs$ÇůH#H†ŽóĐżuwťŃÖ֖,óŞĂÜšs‡˝WtuuĄŻŻýý^ˆb œůŠäŒ9Ü{0şŇ֙ö“úţŤËďëëƒ pĐë´0 ee4_,e%aŐoiŐźę4I’`4™1}úLÔÔÔ°uJ”eôÇCč ű°şi;<.äZhô´ăŞŠç`‚łţ^¸źÝhěkÇœĎÄśö}°›ŹhęmÇ@<‚ł+gテ˜Q8 Ű;ö#!‹˜–_…–ž.L-ŞÂŚÖݘ’Wý˝.ÔćNÇńŘŐ}Só+qzéh8Nzaü’cSi듧´ľ$Iě\PGŸ¨9MÔrÉꈑúúzL›6•3ŽÇcŕ8ž%ÄUŚťyóf,^źF100ŔŞĎŠ9HÔuV—Ëqęëë1sćLVrZÍ­G’#ň”<-ę5ƒ:ýI˝~P÷…şlQYu+ŁŃČŁćWQ?ËÔeEŁQh4ö7őRŚ.O –ŠAě`0ˆşş:̜9“•ţV§eŠŁ}ÔęZńxFŁ‘-# ążŤű_Íŧ–šV÷‡VŤ…N§c őË:ľýt:âń8>ţřcźňĘː$1šl!ů9­L+UŤTŠŁ—$ILŢÇąRÓA€ŐfSr݉"Ľr¤şŻĎa #É"úZëŔ­˙2´ąpr|0č")לxˆśŔ Ę''§ç käÁOYžC‚Ó 6ýidWŸA#$Pé. 2ÂR}Ń úĂ4őľC”%Lt–Â’L,*J+ËËś39úCIŘŤ$eI}9%˙… ‘}ěŤŐƒ4ź2DIÉŁáč-˛´č˝’Ŕă“Ŕ÷pÁ˜Ô AŚŔ†”E ‘x=ý~4š˝h쏠g †„žăĽoѢ&ۄ Nd™Đj<—,!΍ű9ŚV#;p ˛ ”—O`ÓR‰Dŕrš‹Ĺ0qâDö égŃÁ ‡#c Ƥ–žM$đů|đů|J‡‡S:>‰xńx ńDńx‰D Ę}<¸´Ťp.íJ}đ<3jt0 zXýaKŚS0†‚1cÝVőß`0ČFUŒe9jŕD}š`@Zr}ĺý;0ę×T߯SËmćşM BDŁŃaď‘#˝†ş ęűÍfcݧ_Ô÷üÔm>žƒA„BĄ´ňÖŁ]ĎÔŔ†(ŠiÓÚĆâíˇßÂkŻ˝6ćçÇă16şSŽÍ— W_}5.˝ô2Äb1řý~8Ů~ÄsDŻ×~ęÁI!ăH:rřÇqĂ2<ĎĂh0`ŇÄj|ăÎŻaéÁƒ(--AaAAĆ0ˆkqCşKÍ> ˝Y7ą 8ˆŕ¸d­\Y ŹpŹąĽÔ†gů=”˙’Äl´Œň8Ić‘e,=äúńŕ`âuŕôVXľFZœÉaźŠLjˇoh7Pθ])+’!„4řúÇĂ haäľÉdŞă{źĽŽJ9Tg>Ó/ő>F€E#ŔŹĎAyAI‰8DQJţ]FœŠ”ŇbębÇűă8:SŚL9äcŒF#&Mšô™wř2ú9üš—ú\uˆ~NNěv;BĄ"ae´$‰É ‡IR‚!˛”žŘWN ľZ-œÎœCv.xpĐó8tfœF Hށăa´Đóŕé͘|*祚%??‹ĺ¨ň;ét:–WĹăń śśZ­áp˜%ěľŮliĎQs{ŒF"‘`e˘ŐŠ:‡ŇÚÚ łŮŒœœ‚ŔŞ)JOO Ëç"Ë2ü~ÚzöőőaϞ=ŕy“&Ő`` „ŇҒń›"}űË`0°ŃF---‡üźH Ĩůpü~?ź^/ Ň*nĽ>VĹ3ŇűéG}tT`pšU4ƒŃ¨9ęă>ăŐW_…ĹbÁ”)S“× rĆí‹FŁĐëuăŇfŒ!„ńíNąé6Ł éœpȲŒňňr477C–e̞=’$aűöí0 ,‘rMM ÚÚڐ——Ç’ŮF˜Íf–řˇŹŹ ===hiiIVŻÔÁívĂd2a׎]())$I(//GOOT*ěŠŐ´ôz=l6\. PRRÂŞatwwC’$¸\.äć梍ŤKIˆ>y2DQD]]ĘĘĘĐÜÜ ­V‹’’|ňÉ'p:p8xěąGŮ1głŮÇáó)Ő˙”s4Uů’$9ů%‹’ăĆçóAX,fÄă1ř|>čt:đź€`0€DBD^^^ň=]F,Ś$gV÷™2MIL™Ň‡$‰x衇p÷Ý߁ÓéDcc#A@yy9ęęę`ľZQZZŠ;v ›LÁB9I:ü˘(‚çš1wć”ůݚŒC|Ѓ86‰DbXŕCšˆËÜ´:˜4ڌÓ*Ž:БP8d{r/+ÉDÇu:ƒú9ľk=žŁb‰úްÔę9C;ô‡1&)¸BçŮ訥ĄÇłš;a´űX=ˇR§BŒőüMűńÉŃkź püçc„Š(&čŘ>‰‚1‘HŘťwŚNŠ &Ŕăń   Ńh íííhiiÁźyóĐÓӃ˛˛28p<ĎŁľľííí0 p8hllDCCœN'8ŽĂ„ X'­V —ËQL 77€’dV™˘†ÉdBOO6l؀D"žž>Lš4 ńxÝÝÝČÍÍĹƍa2™ĐŃсěěläććbç͈F٘řý~̙3‡U0ęííÁŔ@W^ye29x‚ÎP§ţ8ôőőçydeeaŐŞU˜:u*ÚÚÚĐŮŮ ťÝŽÚÚZtvvaďŢ˝˜;w.ZZZ ŃÚڊÎÎNÔÔÔ6n܈yóćÁăń ˛˛íííƒ8x𠚚š0qâD‚€;vŔçóaΜ9ˆD"())ËĺÂţýűqúé§cϞ=čěě„Ůl†ßďƒNWÉŚwś´´ŔáPŚX~đÁ¨ŹŹÄÔŠSáőzáőzŃŘ؈ěěl6’0Ăív#cőę՘?>ślقžž>ŘlYČÉɁŐj…ĹbßďgŻ×‹őë×ăĘ+ŻÄsĎ= ˇŰÍrß VB @Eäĺĺ"‹A Ę´^Éń•“ă„ÇÓ‡Ăżßěl|>?===(..F,‡Ď× ŤŐ Çœg2Ď I"˘Ń(<ž^89É@Ÿ2ľ­ŻŻƒ<ĎĂëőâ7ŢŔ\€uëÖĄźź‰DۡoÇ… ą}űöQÂ˘` !„œÁĽÓ¨N8šuQp!eŢ{ęÔˆĹbĐj5#NwÉÔa<™Ń?řł)fÄ%;Ť˛,§WUâ>ýśŠD˘ŕ¸ÁÜj)äH$Â. FŸĎĺđIŚÉ‘„éŇχD"Y–ÓrpQTJŽ67ÉĐŃNG[­i”Gejš<žgŘgńž­tšbG”đßÁ˜ƒ˛Ž¨FفÓédt`°ZŁÝn‡$IČÎÎĆŢ˝{Ç‘——ˇŰ ­V˧‹ľľľp8ÉʈKđk0`4𐕕•ŹžŁä_1™LČÉÉA?ŹV+rssaľ*#9ÔŇYYY(//G~~>ěv{2‡ƒQ֚Íf”””ŕÔSOeU™˘Ń( `2™Ŕó<úűűӎa­V ‡ĂNťÝŽÖÖśRŮJ’N‡É“kYe˘H$‚ÎÎNÁd2AŻ×Łľľ.—+YÁȂââb|ôŃGhkkƒÉdJNmŃ#;;;™`])Ěqôz=jjj0eĘ˜L&„B!đ<ĎŚpĺććbǎđűý(**ÂţýűaˇŰŮg›ŃhDWW-ZN‡˛˛2ź÷Ţ{˜>}:ŚL™‡ĂŽşşz6‚PÉŰ$Ŕbą°ž<Ď'ĽM ŃŃс‚‚‚ŔJT˲Œ’’´śśB–eÔÔÔ //yyy“ÉÄÚF͡ŁávíÚƒÁŔrđ)ďkĘÔ`e_ë!Š:;ťX’aĽ š:šU=ŽĽd?1YJ§TŚLś łöäy!Öjűó<ŁŃŻ×—6-iϞz̟?%%%˜1cŠŠŠP__ŹŹ,ôôôŔfł[BJŕK!#KßLš^R—Ç!Š čtşdÉBşđýŹŰXŠĆ‡6™tRmCQ“Ł-´ŹźdŚNĚÉÖ1;žƒfńxĄP˜u0Ô6E1Y}B€!YňrXϚŒŰ%Ľ,‰Dáp” O+IŻ 4vÝqđVu9’ |”Ŕ÷ř“H$ŕvťá÷űFát:‘Í:ő˛,Ăăń  Ą¨¨ąXŒ`Q;í:---l”Mmm-bą˛˛˛›ŤŒlhoo‡(аŰíđů|(//‡FŁA"‘@GG"‘ŠŠŠFÁó:::  ‰Dب!ŁŃČ*şY,Vää8 …ĐÔԄH$żßšsçÂď÷ƒçy6ŁąąEEEˆÇă°ŮlčëëG8‚(*š° Áqşşş‹ĹŃŢކ%K–€ă8ô÷÷َˇ’$Ábą°ŕFŁA @vv6’›› I’pđŕAV1*ŁŹŹ ĄPVŤ999$‰Uǒe:Á`z˝ž9ÔŠ[~żŸ­›FŁANNš››ąoß>üă˒çQ69+p8ÂŞf‰bąXœ}ąŐßßĎFđ‚ˇŰ ›ÍƉ &bV§Rő÷÷Ą´´ńxvťUć’e%ࣔžVžŹAÄ .šä̟kӎŽäçç#°’ávťŞ)BȉŒMnőbOţŞ”-TżŚăřveHR˛"Kň˘NŤŐąoŐÔśRJBĆŔót:mZ.™ńřœb1HVćl+Ľ-҃cŠÁ3ľŤĄójźĎ-Ľ%˛o+×V:&Ľ“KíőéÉŤďq˘˜€ hٔ ÜÜՔ2]ëç˙566˘ľľUUU(((8ęŠjŠÔŃ+C§,éń’ú…ČXłÔ Lc9f†N/Vőőőaűö((ČGuuő¨ö_je§ÔvŮ´iŚL™ÂrnjôźÔý˜)H××ׇ]ťvĄ´´•••Ť×Šę¨‘öyŚőřÍoŔîÝťč9˘(" ˛QB˘(" ąQ3#m‡^݃N§gŁłŽÔ´iÓpĎ=?<äct: US"„“ăx°ÄcęđŘh4–ü• S?äSl(ëŒp’ß Ă.ŚxžgÓ(Ôoó•乊mEöiwđ‡9sĐjui†&wU‡ż+%S/PŠ>ýó‹cç0X #Sç*ľ­b1ĺÚV}$ăŐVƒÓ”÷@ MSúœŠÇăčëëCA˛2ŁŞŞŞ •••GčHĽŒBą€‚$I‡ĂěG-%}¸RÔŠ×UąX ‘HfłyLĺšŐ ‰:úćHAáp89Ňfř󳲲0oŢ\–Ťd44 ŒF#ËßRZZŠÓO?ľCŚš˛,# ą@ˇÓéöšyyyXźxń!Ű4‘H ŽŽUUUČĘĘĘř÷h4ü—°ˆ IDAT ‹Ĺ2ěommm—ŠXR+kĽ~deeąQzj%CI’2cÔí8Z#­ëxŁ` !„| şC?,Sďăy>ůÍ˝V~Uý„|şmŁţŤv3uSsǨAő[Sj§ńĽśOjŽ˜Ą’ęmuŽźÚNň8V™"ĂĎŤLüƒĽĹ5Éċ2ľŐqĐV„9y$ ôôô ŤŤ EEEhmmEII t:+aląXĐŮŮ @†N§Ç››‹ŇŇRôöö"‘H ¤¤DEEËESUU…P(„îînLŸ>ĺčˆFŁčîîFGG›r’››‹ööv–ű¤ŽŽ]t:::`4Ą×ëáńxĐŐՅSN9…u’ăń8ŞŞŞ`4 ™¸~ż•••đz˝pťÝ())A__ ŃÔԄÜÜ\deea˙ţý¨ŹŹd9@Z[[Q^^Žx<—Ë…˘˘"Řív8p^Żľľľ0 pťÝhmmEuu5ÚŰۉDŸŸ§Ó‰ććf äĺ好˝ÇÁnˇc˙ţýhooÇźyó`6›áp8ĐŰŰ łŮŒőë×ŁŞŞŠĺ´Q×)‹Ąąń4- ŘňÔQ)jΖÎÎNhľZ´´4ٍ¨FŁ‚ ŔëőB§ÓĄľľ555°X,¨ŻŻGss3ňóóałŮŕt:aąXĐÜ܌ěěl6şi͚5Đét(//‡^ŻGss3ěv; :::‡ńŸ˙üW]uöíۇÜÜ\8´´´Ŕjľ˘ššńx‹-B0D[[ ŕőzárš ×ëŃßß­VŤŐĆŚůý~ zřý 6zRĂqü~2ą6›~żF٧\‡…Ă!X,Ödp/Ё ŢƒA˜LĆd^9fł Z­’$&BR27IRFh644 ‰ ˘˘&“ Á`űöíC^^Ë­CÁB90™1ŠA˜ÔaşjYję„|&-6ŞŠVCK†óŸ“Ę*Çc-Óy6RG_ ĘĐš5ţít¸ŃŠí§ś‘z^Ľˇ•:}óPÓ87ĹspZâŃ-gč˛Ćöž“˛ĆřŁŮ'ÇŽ­Č‰I šFěŮłfł˗/ǜ9s Ë2<ƒÁN‡X,QY5ž††ěÚľ ,@cc#:;;‘““ƒUŤVĄŞŞ hjjb#8Ԝ$jŮĺÖÖVäççcϞ=đz˝˜9s&€•Ľ÷ů|čďďÇşuë°xńâäHĆ8‚čěěB$Ann.BĄ ĆDŁQlßž………čééA}}=JKKąiÓ&`ÓŚMp8زe ć̙—Ë…šš$ ôöö>üđCdggŁ˘˘[ślA(ЧžŠŽŽÄb1„Ăa477#776lŔÁƒ1ţ|´śśB’¤dőĄ&œ}ö"tvv˛’Ůjyďx<Ž––477c„ ,Ÿ‹ÉdbU{<ˆéÓ§Ăív#Âçóąź7‡ýýýŹ]‹Ĺ Óé°|ůrTWWcâĉضmKĚ\WWÇ*-Y,öeĊ+0oŢ<´ˇˇc˖-¸ćšk ŐjńᅪŤŽşk׎Euu5|>VŹXsĎ=ĄPˆiţóŸ˙`ÖŹYhhh€ p8čěěDAAÚÚÚŔó<úúúĐÚęBqq1ÖŹYŸĎ‡ělź^/œÎl6rH”ÄÁÝÝnV‰)@aaQÚű‘ÍfCss3ňňňĐÝíFvśÁŕ6› &“|éíő ++ ‘Háp<Ď! ˘ˇ×ƒ’’’d>‰„Č‚\Á`^Ż/Y:<ˆ>úĽĽĽp80hjj‚FŁÁ …(C!'bgdh'q¤cęZş >1ڗÚéłŮďŠçĘHsĎ3Uś}U%r,ƒf‡ ČԖě$äŘĐétÉňżVş8PJ Ť÷éőzFD"”——łDźj’ٝ;w˘ťŰ FĂ* Ŕď÷ĂnˇĂăńŔëő";;›HĚÉɁÓé„Ífƒ×ëE0„Űí†ÓédÓuÜn7Ün7:;;Y5#QTňLdeeąőSŢ#8$ Fäççł*m999Řšs'L&z{{1qb5ÚÚÚ‰DPXXN‡x<Žžžx<ô÷÷ŁźźfłZ­–ĺ)ąX,ÉJ}˜L&–äXI4Î!˘˝˝˝˝˝pšZ100Ŕ’ËŞÉŽ­V+&L˜€?üűöíĂěŮłÇaľZŮ!łŮŒH$đz˝hooG4…Á`@QQŹV+˘Ń(Š‹‹ąk×.–V-Ľíp8H$°gĎTUUcϞzđ<ĎŚ—iľZF˜ÍfLŸ>ëÖ­ƒŰí†ĎçcAlTH_Ÿnˇ @999ŕyšššp:0™LđűýhkkƒŐjE @II , Ěf3zzz(SÜ,3ŤĽ|đ<“IŮ^uʨ­H$ 5oŸŇĆdyđ /F‡Ăżß5ˇÇqˆD˘Ź˜,ƒ%‡dD"á´Ü~fłRAI%pœĚS5łŮŒp8 Y– ‡YK-ë­Ÿ0ÉH™Š—Ŕ7ÓĚ } ÷ýä_ĄůڄÚQHF”HˆˆÇŕĚ68.ó—ÔNÇĐŕĚЄsôóŮýÉq@eNţhK!ÓĎńw. śŒeäxűœ”0đRZ­’ëAőŠŽ>Ť$Ë2ĐÚڊM›6ąœ˛,ُ¸.— čęęÂÖ­[qđŕAX,8Ź^˝ŮŮŮđű|ȲŮá÷ŕrľAD"–8w÷îÝčďďÇŔŔşťť ĄŐjŃÚڊććfdg;ŘşŇVd(żßűď˙ů°@ĚɈ‚1„r˜‹Mő_ƒšb"–,ÇG„B>X‚V1>8j”ă)s´K$Aqq1Ěf3ôz=***ĐŰŰ QY%5ÉŹ 0 hnn†VŤEWWňóó`łYáp8ĐÝݍݻwĂjľââ‹/Ǝ;‰FáńôĄˇ×˝^ŹŹ,čőzř|>455aҤIčëëc#lěv;Ěf3ŤÂ¤ŽKww75Ió‡?üßţöˇ0uęԓ~[iš!„†ra)'GĹpĐh„ÂÄcaƒ9Í !„Ďx,ŒD, ŁAÇJY~nžˆŸőĂ×]ŮŽ¨s§Ń şşĽĽĽp8pťÝ˜?>A@aa!8ŽCUUôz=$IÂyçI’PYY ˝^Çƒ ĘałŮ`ąX`ąX ÓéPTT„H$ŸĎ=ő{`łŮ0uęTää8“%…-ŕyŮŮŮčííeyjԊ5ššš˜8q"BĄ éőz:‘ÓŐՅ˝{÷áá‡Áˇżý-<üđ#¨ŻŻO{Ěu×]Ňl/c!ä0gŠybAPĘjđöv"ݏź@ò !„|žHb>O74Â`iŘ}ş’şÎjé^Aŕ KR˛T ‚ ;;ŮŮŮ잏Ź,vŰd2Ą˛˛2í9ĽĽĽiżŰlśŒĎM˝/++ Z­YY6P1›Íě1eeet’#ŚNMŞŻŻÇĂ?‚[nš?üáNÚíĽ` !„ŒââŒç9Č2 ŃHĐé´G˘čsˇ!;Żź ŁE!äsAăđtť Ć#0čuĐj5x!Ä8ąGŨӒ5 b ąhFł•=…Ůl†Éh8ŞIŽ^?&OŽÁŢ˝űŘýőőőřáťÝމŤĄÓĽ_kÇb144€×ë=aˇ‚1„rˆ‹35'ŒA™'Ż“!IâŃôt4ÞS­ÎŽç“eŹ€VŇz$ŠŻŁ>'Ó}ęc‡.3óßeśC/8S7ôš#=nčsľž#m[Ę˝HÚ5šçęuF{_Śý7üqň°śí>šCčPűĺHÚîpŰp$ű`ěËTŰ,˝íFóÜc}LüşGßvŁ=ڇˇgúk–m7üœÝ~Ší2ӟÖűŃŃî—#y?é¸ú4ŽéĄës¨cúXżfżŒđÉÄÎyedˆ2J$ ĂŰŰ)Ąbôz4‚†bNôDžƒ#ayđČ€fŤZžÇQşM´(CŽUŤVáňË/Ç}÷ݗvż:Šşzx t:ŞŤŤąyóf ĆBČÉzÁ1ôMŁŃ° M(!ĄŻŤź …$)ŽŁKî›ú.C bh'ax§aôÔŠŻw´ËŕFąüąŹëHŻu,–›iýpˆí:–Ë;VűýpűŕpŰp¨żËGš/2ľWŚőí1}¸çŒ´ßÇrśíä1ƒÇrß~ZÇôHçްíˇ­Ł=ŚGťĎŽäýčhÎÁ#١Gű^r$Ë8Úcztű›ç•Š;’‡A#đ0 Đj5Đj´Míúšyâb’Ÿő‚z˝ 1NŽ‚-Fk q„Œęšvô–-[Y–ąhѢ´éuęňôz%łvíÚ´çyć™Éżíu%I¤` !„œ8h< \˛ZÇq<ŻeDQ„”C%H’ňC!„œđ],ž§Ń@ŕ9čzjž^Hb¸´@̉>2FxÖM’2˘ŃúÝ­ĐmĐ-Hš(7¤C8Rňˆ×™ƒŕăůüŁëˆýľS_˙h*[rGš˙q Ö˙Dn˙Áç'ń1=?‘HŕĹ_Ŕ‹/žńQ˘˜€aËE1ybL댸íăőţEÁBŅ™:ěgӐ”7nžW†1KĽĚľ„QţĽ˛×„BNÍŕčXYdŽ Ĝ ՔÔĎvYV*€ đH$D$bA„˘S>ăeY:Ĕ°ôÎjŚ)cCŸÇşć–3tJńHÇáS šdĐhä)ľ™–;tŮGň÷Ămӑţ{¸ĺŽô÷‘ŚFŽôÜ#Y×cąN‡kżĄ÷gzí‘ţžięâĄÖ}´ë5ŇóâŃđˆcH7#ü] Ó0îÜô`L<†H4‚x4”1<–iœnękú=í#ś/ǏϔD ĆBČ^¤ŠA Ěđ<ς/ę$K#^¸B!'Ňgutč`ŕ%5?Œúˇ=™ëĐ`’ş !Q!ŠDlôŤ,SB@ř”Î˙††ý˜8q CÚý‘H űÇüş:ÍČç.Ď ă˛Ď(C!c¸PSoŤÁŽăĄĆ]Rƒ2„Bȉţš7RâDÎs¸ĎůÁ‘°$IÇi!H$AJű҅˘4ŸN#đcëÖÍÇüuM&ăČď42†BŽď ľÔŰéŽ1„BNXJő¤áŸ{#ý{˛Ö+Óą$đ<YŇžpĄĎ{Bü VmLŤŃâü§` !„÷iCçĎfš7L!„œčŸw#}Ž}^2ęH™ÔĎ~ Ä’ržđ'Ö{ćP#j(C!'օÚh.LéBȉňŮ6R"ŃĂ}֝ŹűäP‰n ůź’tbœ<Ż$ ů„§` !„œpŽÇęq„Bȉôův2o?x%äđ˛Ź6x}žf]yNSikB9ąŽD !„r<ŁĎ­Ěűö !ՖÁë÷0ëz<c¨!„|ŠoŠ?„B!„œŒŚLŽĄu=BŒ!„B!„BȘ>g­ë˘` !„B!„BĆŹ° gÎ;ý¸_Ď3睎‚üăb](C!„B!„ŁrĺeKÁsÇoˆçx\yŮŇăg}č!„B!„BČŃ(,ČÇmˇŢpÜŽßmˇŢp܌Š(C!„B!„c`ń˘¸ö‹—wëuí/ÇâE ŽŤu˘ŇքB!„B9&.ťäBX­üíٗ ÉŇgş.<Çăś[o8î1c!„B!„r -^´ľ5ńĎ7ßÁÚ ›>“u8sŢé¸ň˛ĽÇŐÔ¤TÜ(îçR~Woó)˙Ş?BňG“üŃа˥ž řŒ#b„B!„B_]ÝŘ´yę÷­~ŕ˜˜á96›Ľ%E˜2š§Ď™5ö ǃ3ĺÎŕHţˆÉ)ĺGNůWN.%ő6†ÜV^f¤—r›‚1„B!„B9šS0†řB!„B!„Œ# ĆB!„B!„Œ# ĆB!„B!„Œ# ĆB!„B!„Œ# ĆB!„B!„Œ# ĆB!„B!„Œ# ĆB!„B!„Œ#ÍxźˆŤ­’(ŇŢ&„B!„BČq‹„qyq Ć”OĄ%„B!„BMS"„B!„BWŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!„B!„BGŒ!Ç˝žž>ěÚľ˘(ŇÎ ä$ŃÚڊ††´N„B!äsICť€Œ‡+ޏ ]i÷ ‚€œ'JKKqÁçaɒsa4Ósđ`3nżý …púésđčŁÓÎ<ÎÝ|ó—ŃĐиęŞ/â{ßť›vĘçP[[Žşę:öűc=ŒÓN›xç÷đ‹_ü ˛,ăk_ű|éKˇ|ćë{<Ž!„B9yŃČň™EÝÝnlŢźżüĺ¸ĺ–ŰĐŘؔö˜;v  6oŢJŁc9 lܸ˛,'ooˇ×]śěxꊿኧţ6ěu?Ťu"„B!ŸOŒ!Ÿ ‹Ĺ ˝^ŸvŸËĺw~===ěžĹ‹ĎÁôéÓ`2™đŐŻŢAhçr‚ťîşkQXXˆělnšĺŚq{Ý×^K Ć|r\Ź!„Bů|˘iJdÜ]{í5¸űîoz{{ńĆoá™gž…(ŠđűxđÁß㡿}`łŮđ׿>A;“Č”)ľř׿^§u"„B!Ÿ[Œ!ŸŠœœ|ĺ+ˇžzęo€5kÖĄ§§šššxë­ˇńŤ_ý†=~íÚUltĚćÍ[đúëËPWWŻ×ƒAĘĘJ\pÁy¸üňˆ˘9x°/˝ô 6oŢÇƒAéӧᦛnÄŹY3‡­Űƍ›°lŮ?°gĎ^řýdg;0{ö,\ýu˜8ą€’gâç?˙%{ÎsĎ=ƒI“&˛ß—-ű~÷ť‡<Ďăíˇ˙§Ó I’đĆoâwŢGkk bą8JJJ°xńٸţúka2™Ř2.˝ô ¸ÝĘhĄ{îů˘Ń(ž{îôőőăă˙N—qß~ňÉfźöÚ먍ŤG DNN&Ož„ŤŻž łgĎbKÝÇUUUx晿âÉ'ŸĆʕ+áőúP]]Ż~ő6̛77mů.— O<ń$>ůd3  œď~wôůaîťď~ź˙ţ Ŕ-ˇÜ„‹/ž=ô0śo߉ělnżý˸䒥čěěğţô6n܄DBČÓq÷ÝßBYY[–$Ixë­ˇńŢ{ËŃŘ؈DBDAAA˛˝ŽAiiiĆ×˝úęŤpóÍ7ŕ‘GĂćÍ[ Š"f͚‰o~óŽ´ç¨ŰűÜs/bóćÍđxú`ľZPVV†K/ýÎ;ď\h4éo§[ślĹSOý {÷îƒÁ Çe—]ŠŻ|ĺ6,Xp6{Ě˙ýß˝¸č˘ Řďë×oŔëŻ/ĂŢ˝űX›Í{:nšĺFvŸŽśÍS÷Áźy§ă?ř|đ÷Řşu;ŒFć͛‹;ďźůůůĂ˙ý߯Ąśv2yäq´´´ŔéĚĆœŰo˙ňˆÇăHmĘ)Óńä“fóűýxůĺWńß˙~ŒŽ.%ĎTEEžřĹ+pŃE€çů#ŢćUŤ>Ć=÷ü8íy/˝ô2^zée|éKˇŕk_űŸĂŽÓ+Żź†>Z…îîn’’R\tŃů¸ňĘ+ŇÚ>u?ýú׿@NNüOhh8ƒAĹ‹ă˙÷Ž´s\’$üűßď°ă7 ĂfłbʔZ|ń‹WbţüyôaA!„BÁBŽ˝+ޏ O?ý dY†$IXż~.˝ô #>ţ7ŢÄ<˜v_0˜ŔΝť°sç.Ź_ż>řpřřăŐ¸÷ŢűFŮăcąÖŽ]ľk×ăĆoŔ7žńżěoO<ń$ţţ÷çҖßŐՍwß}+W~ˆŸüäG¸đÂóqÎ9‹đŕƒżG$Ź^˝&-łví:vű´ÓN…ÓéD,Ăwżű}|ňɖ´ĺ766˘ąą˗ŻÄO<ŽěěěaŰ˝iÓ'řčŁU‡ÝŸ/źđ"üĎi÷uvv˘łł}´ _ţň­lÝ1ä IDAT¸ăŽŻ{^<Çüďžű>ťŻŽŽßůÎ÷ńČ#` XŰÚÚpűí˙ż?ŔˇbĹhkëS^ŸÎÎN|ýë߀Çӗü˝ żüĺ°ŮlxđÁߣ§§7%`ąűö}/żü˛˛˛ IîšçGX˝zmÚ2›››ŃÜ܌ˇßţ7~ó›_áŒ3ć{Ý`0€o~ó;hnnf÷­^˝ťw×áĹŸcm°mŰvÜ}÷÷X;€Çӏ§ŰśmÇż˙ý}ô!\˝z îšçǐ$ ‡ń÷ż?Ż×7â>ČtĚuvvâ7ŢĊ+ńĐCżĂŒ§ó6÷űƒ¸óÎťĐÝíDŁQź˙ţ |ňÉfüýďO#77wŘsvďލżü寏­ťşşńěłĎc׎ÝxüńG†LFËĺráßř6şşşÓŻG}}=Ţzëm<öŘĂ,ŕ3Öm>mmmřĆ7ž=,ůž={°gĎŹXń}ôĄ´ŕŠjßžý¸˙ţ_"BĄ–-űšššđÇ?>Ęޟîťď~ŹXńAÚsűúúąfÍ:ŹYłwÝu'nşéFú  „B9‰PÎr\p:ČÎv¤>F"IţřÇÁŘôéÓpĎ=ßĂWžrë¤)ĽsîvťńłŸýœb,3Î;ď\TWWłeźřâKŘącgňškÓ:Ĺ%%%8˙ü%p8ě,`ńë_˙.— &“ gu&{ěš5ƒÁ—H$‚-[śąß/źđBŔ“O>Í1ƒ×\s5Žšćj8JÇżľľż˙ýCˇýŁVAŁŃ`ňäÉi#C†vF˙ô§ż°ßĎ>{!žůÍŻă´ÓNe÷ýýďĎĄłł3cÇsůň•˜5k&&Mš”śĎŸ~úöűţđpZ ڞ˛óçĎĹţýűŃÔÔtÄíżrĺ‡čď÷"??Ý'Ë2~đƒĄ§§šš9i#.úúúąbĹJŔňĺ+Y FŤŐâꍯÂ]w݉’’Ö^>ř‡ŒŻť|ůJ¸Ýn̛w: Gô÷{ąlŮ?Ůzüâżf˜ššÜuםiÁÂ-[śâý÷—§´Ô@ ̚5Ó§OĂoź™q=Ö­[Ÿv̝wŢš¸ő֛Ů1 …đӟއX,vĚŰźžžńx×^{ ćÍ;=-ؔzžĽúřă5¨ŹŹÄő×_‡ĘĘJv˙Ö­Űđďż3ć÷Ÿţô~vîó<łÎ:3mvě؉_|ůˆˇšŹŹ 7ß<<ĚÍ7ߔqT\Ş{ďý Ĩë”:Ęh÷î:<ôĐŁŸűÜs/ŔjľŕŒ3ćÁl6Ľí§-[ś˛€Mj ć ĎÇO~ňC,]zqJ îŻđů|ôAA!„rĄ‘1ä¸a2™ŮČŸĎ?âăÓ:ŽW\q9`Ú´Š‡Ă(++CiŠŇ÷Ý÷10 Tdýë_PQQI’pűíw`Ϟ=ŕyë×oŔŒ§ŕŐW_cË...ĆóĎ?ŁŃˆÎÎ.\ýMˆD"ˆFŁřç?ßġžu.¸ŕ|Ź\ů!`ďŢ˝čííENN6mú„už -: Ńh˙ú׿Řňż˙ýďbéҋ(ŁƒŽżţ&tńűý°ŮliŰnłYńÇ?>ĆŚIebłŮđÇ?>ŠŽŽnD"aśo–,9—^z% 0ěۡ………Ă]?üá÷qůĺ—~ôٟ°‘8őő{’măÆ ƒŐfÎ:ëLüöˇ€ă8Ź_żwßý˝#n{N‡gŸý**ʇv¸óÎ;pë­7ĂĺrᦛžÄ‚jÍÍ­€9sfăŃGBww7ěv;Î:kA2Ŕ—ƒŸýěçŹăžir‡§Ÿ~ĺ‡Ă¸ţú›X0 žžžíŤŸ˙ü>tuuĂíîĆŇĽĂjľ˛ L{{{˛S݀ĽK‘œ×7lýŕąÇţ„_|iŘöżňĘŤěöŇĽăŢ{•)5_ţň­¸îşŃŐՍîn76nÜÄśďXľš řóŸ˙ˆ ”ŕŢ=÷üŤV­ü÷ż#Kś]ZZЧžzz˝áp×^{›šł|ůĘCŽjÉΝť°gĎöű~đ]v>ňČăxůĺW(Óżüĺ[h›Ď>{žţőŻaŐŞŃÚŞ77Üp=žţőŻy~÷ť‡°lŮ?ďżżwÝu'˛˛˛Ňž_\\ŒgŸ}&“ 4â替Ä*6Ő×ďÁœ9§˛ŠXŞ›nşŐŐUřÂ.ÁěŮłí@YY);ć!„Bc9ŚBĄvŰnĎńqVŤ&L@KK ŕxŻżţOLž< 55“0wî\TUUŚt¨v˛ŰUUU¨¨( |ËýłŸÝ‹X,ޞ˛R6ňb׎ş”@ÍF@aaŚOŸĘFľěÜš 0ţ<ŘíYđz}ek׎Ăe—]š6JfѢł`2™°gĎ^€Ÿ˙ü—i9gRƒ"MM1s㌴űĎ;ďźCbŔl6cÖŹ™đů|Řšs^xáEtušąuëś´ÇĹ㉌Ď_źřvűŒ3ćł`L,C,CkŤ+mÔÇĹ_ĚŚ[̟?ĽĽĽpš\GÔö•••Ź]Î:돴`̒%‹Y ˘˘{÷îeëšššČÍÍE{{;ęë÷â駟AggÖŻ_?d{ăĂ^ˇ˘˘‚˝ŽŃhÄŹY3ńŢ{Ę—`p€'SŚÔ˘şş ;wîÂűď/Ggg7öł@Lęú8p í5žđ…ĽěöUW]™1łsçnvűwŢĹ;;q?54ČŒ9š6Ÿ˙ü%,ÇQ_żgXn—ůóçąéKŐŐUČÍÍaAŤ`P (×ÔÔ@ŤŐ˛ăóÖ[oĂĉ1iŇDL™2iŁś!„Bc9f<úúúŮďŠÓU2š˙ţ˙Ï|/ë ť\.¸\.Ź\ů!üϘ3çTüęW?‡Ífƒ×ëOYnzţ‹ĄS}˘ŃhZ^‚‚ôőČĎ/`ˇűű•őK– vĚÔ`̆ Řc/źPIŇęőzG˝O2˘,ŁzîSOý Ď?˙bZŽœŃ2›Íƒoí°ż´ß‡vűctşÁׄôٓZmę߆—6D"¸ďžűąjŐj6ę`´L&cúbĘöŚ.jŐŞńŰßţ.mÄËH|žÁýc0Ňr˙dęT=ć}L„Žy›ŰléÇTNNNÚď~ż˙ˆž“:}íH¤ž§fł)í8t8p8Çô8Ë:Y,ƒŰ——7äąžĂ_Z­nŘńUP˙ř‡xđÁß# AEěÝť{÷îĹ[o˝ žçqőŐWą t„B!„‚1„3˙úכŹ#ÍóüaŤ‡ÔÔLÂŤŻžˆíŰw`ëÖmŘż?vďŽc˘Í›ˇŕ/y ß˙ţw`ˇNMéîîI[NccPZZ‡Ă˝^ƒÁŔ:Ç]]î´ÇwwwĽuU\p ĆlŰśÍÍ-ěđělN?ý46aŊw‡M9Z。œUŚây—\˛łgĎÂäÉ5¸îşŁO:tşDggjk'łßSG‹Œ‡ßýî!ü÷ż'ƒV\yĺ˜<šąX?ýé}G˝üśś6Ü{ď`ž–šsOĂ9眍‰'âá‡ĹŽ]ťGě€G" °ŔBŚźCšř%Î>{Ѹľy[[GÚďCŰ/Óńy¨çŘlc›N“zž „Ňö›ÇăAccĘĘʐŸŸŽă>őă<Ó:ƒAqťÝC›5ć×šč˘ °pálÜř vî܅}űöĄž~˘Ń($IÂŤŻž†SN™ŽsĎ=‡>,!„B(CČŃëëëĂoź…gžy–Ýwć™ó3VpQšÝn|üńj¸\íčëóŕ˙ţď^h4$ ÜqÇ×QW§L3RɞrĘ)XˇnC2ř҈ƒ›YΘ_üâ×,'Äľ×^ƒťďţfÚT¤5kÖâk_ű* şşşÓŚ0rĘtv{úôi(..F{{; ^ye0ď̒%K؈ŽŠŠrFV]壏ţ‹Ë.ť€2áĎ~ĺĺe¨ŹŹÄěŮł2Ž9œM›6Ľ‰~üă{ǤÍ&L(ĎólŞŇťďž‹sÎYŽă°víşQ9–>ůävű›ßź —\˘L :šD˛ŠśoßÁ1ůůyxä%š˛$IčííöřĄ%ą×Ž]óĎWŚÜ|đÁ‡_cʔZ6˝ćż˙]•ŒůóŸ˙ŁŃˆŞŞJ̘qJĆŕČŃ´šËĺÂÖ­Ű0{ö,$‰´JZFŁ……ÞłzőjÜqÇW ˇŰ 6˛żŠSŐŠkŞ‘’žO镢VŽü€ĺgyᅗYΘ‰'âůçŸÓ6§ŽÓáÖ'Ó:}đÁ‡lR“îjľZL™R;ŚăkßžýŘźy3\ŽvŘíYřöˇżÁŢ/żü*śžĘô/ ĆB!„P0†1zőŐ×đÎ;ď ‘‡Mϰُřţ÷ż{ČçK’Œ‡~ ‰„’ ÂăéÒ%‹á÷ŇňUÔÔÔ.žřB<˙ü PŚÜqǝ8óĚ3pŕ@Řă-:‹eÔ`L[[nšĺ6L›66ldëŤÓép啗Ľ­×…žĎ*ĽVÍšč˘ Ň:ˇK—^ĚFŃ<řŕ°˙ŘíYXšňC–\´´´Ż˝öҘöŻÁ082cëÖmřŕƒ˙ ‹ +›îÇSęöžűîű°ŰíhkkÓO>}L–Ż×ŘíŢ^^}rrrđöŰ˙VîÎ8CÉ )SŠ~őŤ°mŰvˆ˘ˆ÷Ţ{?ăk\}őU,óţű+ …P[[‹­[ˇ˛cQ,[öJĆ`ĚŃśůˇžőœzę,¸\íiŁ\Î9gQZ+U__˙˙łwßq9î˙Ç_M!Ąa‡Œc;Ç:˘ĽBĘHdďN!3˛Ň ;2’=‘ŽŽă82˛)*ŠÓ‘yŹCËďtŸn­;ßNgüŢĎÇăztĎ}]Ÿu­w×őšč×o őęŐĺÚľëŠńu2#íĐ××GMMMqĹۊÁ<}ú”Ν;ĺřhD˝zőÁŃ sćĚYŢ˝{ÇéÓgł­§ŸRfCCĹXS‡ć÷ߟӮ][,--TÎÓŮłź~ýšˆˆóYÖ}ťlW˝ŠęŢ˝x‚‚V*őą† ësçNŹRŔ¨NĎdç!„Bń"ś‹WŻ^g ÄłjՊlc1|ŹB…ňŒëŽř/÷ŋ‘ĚŸżˆŕŕĹ p5<8ă 6ĺʕcÖŹŠG_źxÉwßV ÄôîÝKń¸Zss3¨ř.>>žƒ)Ć´ŃŇŇÂËkJś+ :thŸ-ŻĆĆĆJˇđ¸ť Qن¤ŚŚ˛gOëÖmPbtuK2kÖôlW¨Ş}űś¨ŤgŹÚ&1}úL||üĐĐĐŔĐĐ PÚoüxĽŰQââ∈8O5”‰]ěěÚ)”OœčI`` Ô+”ů›š~IéҐ´´4- dęÔéDF^ŚaĂŮҗ,YRi|ˇo߲wď7ěß˙­RŰdemmEŻ^=ďúégVŻ^ŁÄ¨ŠŠ1~üŘlOB*Œ6ŻS§*Tŕ̙Ľ@ŒĄĄ#Gćü´Ą6m,yýú żürFiŒ˜ć͛áŕńt°Ě‘3ĹĆĆś/ĎźřřĚTŒŤ“––Ə?ţ¤ˆiÔ¨!ö˙ä2[[˙yĹŃ˗Ż8rägϞË3OžžłWĽĽĽqüř Ľ@LÆ ţ§ń\ÚľłĹĆŚâýá,Pl3Óä4płB!„`ŒŚĄĄAšrF4kÖ//O6o^Żô¤źôčáĚŞUËąśśÂĐĐMMMJ–,Aƒ pwÁşuŤ)Sڌ"˝ĽĽ7ŽŁS§ŽTŹX---J•ŇĽeË*n Čäć6ŒĽKcaa†>ZZZT¨P{{;ÖŻ_“GŕE9őޘL:::ŹZľœńăÇŇ AôôJĄĽĽEĽJ•čÖ͉-[6ĺx’ŻŞ&Mž`Ţź9ÔŻ_ŸbŊQŚLilm­ \¨t•Ç˙˘J•*Ź[‚­­5zzĽĐŃŃÁÚڊŔŔ…Jî…Áƒ2j”ĆĆĆhiiQž|9ú÷ç¤B™ŠRĽ^‰……şş%)Q˘ŸޘĽKcbb’ăo:wîĂ4jԐâŋSž|9zőę™íŞ/MÍ?/N7n ĐŞUKôőË˘ŠŠ‰ž~YŹ­­X˝z%ÝťwűKÚźX1m–/ÄĚŹ•âˇWy…dĚ7SőęŐYśl ľk×FKK‹Š+0hĐ/^ lš={&ööv”+g„ŚŚ&Ż^˝Ęseccc6oŢŔŕÁ111Ąxńâ+VŒ:uęŕĺĺIpđ ŕ:ŸRćîÝť1vŹ;ŐŞUC[[›âŋ+Ž°ËŤŻoÚ´ž!C)ň¤Ť[’zőę1nÜ‚ƒW(ž˜ô)ÔÔÔđóóaÌi4mÚ=˝RhhhPślLMżÄ×w6>>޲ĂB!„řQSásľ,ď3_Ťgů›9i|˜4?LڀP&99ĺŒTľâ˙“ääd’’’¨RĽŠâł‡âčŘ]ń~͚`ĹUREÉŰۇC‡ž2nĹ Y•ďoştqR J=xđ@Ü܆I# !„Bˆ˙$mm-Sŕ9$ŠŚ´Sz–é}–ż™˙yĚúš^2fŒBŞwďŢ1p  ¤§§cooÇçŸ7ćÝťwěŰw@‘ŽbŊ4hP_*L!„Bˆ˙‡$#„…¨Xąb8:vbٲ@Ćc§żűî°Rš%Jŕă3+Çńc„B!„˙}ŒBˆBÖˇoęŐŤGhčŽ^˝ĆłgĎ?ŒgSž–-ż¤oß^ůT-„B!„řď’1c„B!„B!>(Š1cäy!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$Á!„B!„Bˆ"$ÁQ¤ŇÓÓißޞV­,xóćJż‰ŒźDŸ>°˛˛ĺôé3˙ęňßž}SSs’’’ţöźěŘą“îÝ{I§üyřđ!îîciÓŚ-ÁÁ!…:ď &1cĆŹ\żŸ1cŁGýWŐW~yNLLÄÔԜŘظż4ÉÉÉ̙3ví:0b„ťt䏶/oßžĹŮš7ëÖmřח+4t]ťvçéÓ§˙ĘüOž<˙€żťqă&:9rölÄߖżœÖY''gBC÷i_Úśm;ŚŚć9N9ĺëďäëëĎÔŠÓdŁ“‡śmířîťĂEś.$â˙7MŠQ”΍@]] *pâÄIěííňýÍÔŠÓ033cúôŠÔŹYăÎĂ˝{ńôę՗ĐĐTŠREE(ěÝű 6lb˙ţ˝Ëň—. âĺËWRąb…"]v‹ÍUţS|œg‡Î¸š ŁK—ÎEšýűżĺčŃcřűűPĽJeY‘>˘­­••%őë×űחĽvíÚXZZ˘ŤŤűŸk'CC,--Š\šRĄÍł°×ɢěKĽKëą|ů˛˙ĚţE!Ä?cD‘úţű#´jeJ‰%ůţűďó Ć$''óüůď´oߖ ęKŠ˙´¤¤G˜š~IŁF ‹|ŮEŔř/ĺ9)é5kÖ U+SéÄ9PWWgôč‘˙‰˛|ţyc>˙źń˛Ę•+Çäɤ/} ĄĄAíÚľdBń×íפ DQy÷î'NœÄĚĚ 3Ξ=—çĽŢţţXZÚ0věxĽŰ{§_żAXZÚŕäԃ7+ýöâĹH\\†aiiƒƒCgÖ­Ű@zz:ß}w˜^˝úŕěÜ›Żžžă˛˙řă‚ƒCprrĆŇ҆]8qâ'Ĺ÷ááqrrćřń8;÷ĆŇ҆#ÜILLTšĎáôčŃKKFŽÍŁGňŹ#__ź˝} Y‹˝}'şvíNDÄ9.\¸ČŔ.XYŮ2lŘyň„ŠS§acÓ{űNěŮ–gż˙ř!UúBbâoLž<›öŘŘ´ÇŰۇ/^äšNŞş~ĺ&k_Ru_üý÷GéŮł/Ö >’óç/ú-Ăyí×rŰżd–ĹŰŰ++[:łre0iii*ď/?vţüÚ´iËÁƒ‡>i—Ů""Î1t¨ÖôčŃGi~ޤů”í“*ůĘkżpőę5Ĺ÷=zôáňĺ+ůś]~}R•uI•4ŞOä՟“““Y´(‡ÎXXX3l؈<űƒB‚1B|8đ=EZZ­[›Ňźy3tuKrôčą\Ó{xŒfďŢÝ̚5ƒđđ}rđŕ!ćĎ_DˇnŽlٲ7ˇaŹ_ż‘#GŽ)|Ǎ›HóćMŮľëküü|Řšs‡ÁÖ֚•+ƒX˝z%K–,ČqًrčĐaƏ÷`óć ´nmĘ´i3ůíˇ‡Š4?áčŃŁ,^<ŸM›ÖóęŐkćΝ§řţčŃ˜3gŽŽŘ°a-:udÁ‚ĹůÖÓůó¨TŠ";wnÇŮš›"83{öLvďţmmmć+ҟ=§§ÖÖVlذw÷QěŢĘŇĽËi/^ʁ˜0a<ëօPŚLiśmS>p Y˖-ŰđđÍƍ밲˛`âDOĽ×ǏŸpölóç0aÂ8ĹçǏŸřp˛łŽ€~üńGśoߑcůŇŇŇ3f‹ÄÄD<ymërRţ¤ęúŹęöĽ ůÎŻnňŤ_“ęÔŤWC‡žWZîáĂG°ˇˇG]]ˆˆsxzzaoߞ͛70j”k׎'$d­Ňośműšqăư~ýš\ËłaĂ&Ú´iĂîÝ_3hЖ-[ĄĽ§§3a‚' X°`‹špá˘RĐńc÷ďßÇÝ},5jÔ $dsˆŒźÄňĺŤT^nZZcÇNŕˇß’X´h>‹/ä̙ł\šrľ@ۀüú‚—× RRRذa-ëօŸ  •šŽ“YżT•ßžř—_NăííCçÎlܸŽ.]:3oŢÂB=žÉoż–Óţ%Ӛ5ëhܸß|Šżż/‡&(heö—Y“'OĹĂc4ţ§m܂‹6̕ýűĂĹźysŮ˝{&&&Lž<5Ď —âŸKnSEćűďż§ukSŠŰ% IDATJ”(@›6m8tč={öČ1}ɒ%ŃŇŇúpŇc€hѢFFFTŤV•°°˝\ž|…vílyňä)ďŢ˝ĂĆÚ ĘSĄByÂÂv+îńϜ>zzz9.{ʔIź|ů’˛eËŕâ2˜Í›ˇrăĆM*T(ŻŘůN›6UQžAƒŕííĂű÷ďQSSăëŻwbooG˙ţý¨Ył?fĺĘŕ<ëŠB… tęÔ€ž}ű°jUÇwŔĤ:ŽŽ]řsǜqeH[† ¤XŽšš3gzóŐWƒŃĐĐŕŰo0eĘ$lm­?¤Ć­[ˇHHȸÂć?ţŕëŻwâç7sóŒÝúsăĆMBC÷в嗊2Ϛ5#Űx ŐŤWÇŐŐ€ňĺËcggDž }FŃV&&&ŒĺVč묛ŰPĹ-SŁGâťď­ňmUŞTÁÝ}˖ńüů3>ü-×(€……ǏŸŔÝ}IIIüöŰoôëׇˆˆěí툈8‡ŚŚ&-Z4Ďřɨż˛Jő—iÚ´ŠXYYŕé9‰Î¸u+ŠŚM›dËC~ۗœ—ŤÜnŞô›œÚvŢ<Ž_żIZZšâłźäˇ­ű˜ŞýŠ ëóëׯóÝž4ßůŐÍĽK—ó­ß.]:˛zőƍƒŚŚ&QQŃÄĹĹ1ožż"Ńťw/úôé­hçǏ˛–aĂ\y1bXžˇŸ988(úFϞ= ŰÇůóhÔ¨!—.]ćúő넅í˘RĽŒąX|}gÓĽ‹SžëMXŘ.ʕ+§řŹ}űśüřăO*/7"âwîÜaďŢÝTŹXQĽĺć$żžđŕÁ}ÚľHľjUXąb)ŊËu,ČúU@H^űâ-[śag׎ú+ö‘OŸ>Q\’›§OŸ) Ř ŕęꢨ‚î×>ŢżdjÚ´ Ýşe´Kٲe1€€ů îJńâĹUÚ_ÜşŸq>ܕŽ]ó诪ľAϞÝŰڎˆŒźĚöí;°´´P)MAˇOŞć+ŻýRXŘ>ʖ-ˌÓPWWWKşş˙äúPe]R%Íŋ‘*Oä՟ýő5kš(ę`ňä $''+Ę+„`ŒŮźxń‚Ó§Ď2kÖ ĽƒËýűż%!!ccăÍďŃŁÇěŰ÷-qqqÄÇß'&&†ŞU3kÔ0ÁÚÚ 7ˇQ|ůesš6mB›6m 4࢚š׎]'2ň2ńń÷ˆ˝Kzz:ďŢýůߕRĽt;K}ý˛¤ŚŚ’’’‚śś6ąąątéŇQižÍš5ÍwŮFF†J'{”*Ľ—ĺÄ]‹””?oˆŠŠĆÎŽŇ<žř˘1ŠŠŠÄÄÄ˘ŁŁCJJ 7ʖ—Ě“Ľ{÷âyűö-'z˘Ť[R‘ćՍט˜˜(•9§z,_ŢH齞~Y˘˘˘óŹß~8Îľk7¸?;wb”.ŻUŤŚŇ iůňĺ10Đ'&&FhQ%MVśś6ěŢFˇn=hŐʔŚM›ŇŚeŽůŒŠŠÂĐĐ@i g555>˙ź1ˇnÝĘľ^nݺŝwďčŃŁˇŇü^˝zÍýűżŞÜŁ˘˘hÔ¨ĄR 066ćÖ­(ĹÉsŊĺ˙’őś|ůňYÚT Ŕƒüvďލ;CY¸p ‹ÍĎ5 `iiÁš5ëxüř1çhÔ¨-[~Éôé38s&‚/żlŽtՋ*˛n_2¸ó*G^ŰUŰ-ż~“Sۖ+WNéÇÇ'äť})hžóŤUęˇ]ťśqúô,,2nűkܸ‘˘##/y‰ýű÷+­Ÿ/_žT|–@É;€ŽÜfe˖á͛?y50ĐWšŽŽ 6Č7Ŕ°cÇN˘Łos˙ţ˘˘˘144Tyšąąą*N 3—[Đą×ňë ..ƒ ZÉɓ§hŇä ,,ĚŠWŻî'ďż?E~űâœö‘Í›7Ďwž9 ૯_öÚŻĺ¤N:Jď4¨Çťwď¸˙ľk×RižˇoÇ0xđW”+gDŻ^=˙§c¨Luë*ˇcÆő9qâ„Ęi>ĺXL•|ĺľ_ŠĄQŁJ‰† PŹXąOŽUÖ%UŇäx"ŻţÜłg&Mň¤wďţ|ůe ZślŠiK9ŃB‚1BäîřńIIIaúô™Ěœé d\˛ —ŽçôŸŚÜlÝşľk7ŕčŘsssŞV5fƍJ;ˇšsýšyógĎFpňä)VŽ\żżć*-cňä)ÄÄÄŇĽKgěííŠUŤ&_}5´ŔĺÎ,cnď˙N9eeăĆu”.­|˛ŹĘč âŮłg¸¸ ĂĐĐ[[kĚĚZĄĄĄÁ¸q•ŇĽŚŚeűíÇăP¨’Fů@ZŸíŰ7sîÜy.\ˆd˖mŹZ̚5ÁJQŞ´—ššZžĺ40ĐgíÚŐŮ>ĎzUĐţSĺ˙=}*{~“““yóćľŇÉnnj׎E… ĺ9ţ"çĎ_ eˌÁŒßž}K||<çΝWşź˙ݐßöĽ°Ú­0śÝÖeĘŤxůĺ;żşQĽşşşX[[ńý÷G03kÍŃŁGqs–%¨­›ŰPŹ­Űäpr_ŞĐž,–ŰUNymW##/1nÜD,,ĚhÖŹ)öö¸ví:,PĚŠž {Ôťw/ŹŹŹ8uę‘‘—Řşu;˝{÷däHˇżlý*¨ôôôlő­Ę~­ řŞş_ËI^ű5Uç{˙ţ}ěíí8tč{Ž˙1Ç~]Đ6ȞŻÔĽ)čöаś˝9wĺŐďó[Ž*뒪i cűۤÉěÝĘ/żœ!2ň~~s¨V­˗/ESSNë„řˇ‘kÚD‘8|ř5dűö-lÝş‰­[7ąmŰf,,̲ÝןŸđđCôěé̸qc°ˇˇŁAƒú<~üç8oŢźáúőÔŤW—Áƒ˛bĹ2ĚĚZś÷ĂN/ďů?ţœS§N3eĘd\\ckkž~YĹUUłf .\¸¨ôŮůó ˝nëÔů,Űu—/_ESS“š5kP­ZU´´´˛-űüů?Ç,¨Z՘bŊ‘˜˜HŊÓoż=$-­pďCŽŒźĚÇ ¤wď^˜››ĺxwçÎĽ+‘âăăůý÷ÔŽ]ť@i˛zôč ÷iŐĘw÷lۖ1Đńąc?äx@Tˇn]?~ÂŻż*_ÍrĺĘU>űěł\ËřŮgŸńűď/ĐÖÖVŞĎ;wb t)qÝşušzőşŇ˝ŕOŸ>%!!Ď>ŤýˇŽÓŋ—ŕŐŤ×Jő˙ńŔŇ+VSŽ\yć͛Ă…‹xřđažó577çŇĽË\źIŤV­ĐÔÔäË/[đý÷GILL¤uëVi@!żí‹Şí–_żÉŠm“’’ءożâ?Ţ::Ĺyüř‰ŇIeÖy桭+Šţ¤Ęöĺcůĺ;żşQu˝ěÔŠ#?˙ü çΝçőë7ŘŘX+žŤ_ż‰‰•Öϡoßńüůď…zšż‰‰ II”ŠMIIáƍ›šţćŘąăÔŞU_ßŮtíęH‹Íyńâe–[ŤV-?~˘4hřü‘çr?%Đtőę5 pvż/cÌbçÎÝšŽ“…ą~}J\˝z]éłK—.ů~-ˇíÓőë×?ęÇWĐŃŃÁظŠĘűK++ f͚Aż~}ńő“ç€ŽŞśÁľk×>:ޏB­ZľTNSĐíSaôZľjqőę5ĽŤ†Ž]ťžçŐIů-W•uI•4Ÿz<ńą¸¸ťź}ű;ťvL™2‰+‚¸té2ŃѡĺdC Ć‘]RR—.]Ś_ż>Ô¨a˘4 2˜ű÷ďčązőŞœ:ušŤWŻG@ŔâăăßßşĹĐĄn„†î!>>ž“'ćʕŤÔŹ™q€ ŻŻşş:çΝW4-“žžúúe ?HLL,WŻ^cʔi>@ďۡGŽcăĆÍÄĆĆqđŕ!Ĺr Ó A8|ř›6m!&&–ăÇO°pá"şusBOO%Jŕč؅  •;vœ˜˜X‚ƒC”J”(AŸ>˝X°`GŽ#66ŽožŮÇر㉌,܃ÖjŐŞ’žžNhčîÝËhŸŹO‡É¤ŠŠÉ̙ŢÜźy‹ .2mÚ,ęŐŤÇ_|^ 4YíŰ÷-ŁFćÔŠ_ˆgďŢoxţüwjÔ¨dܲńěŮsŽ_żÁÓ§OiŇä 7nÄÔŠ3¸pá"Ńѡńó›Ëoż%Ňłg÷\ËŘ´i4¨ĎĉS8wî<ˇoß!00/Żüţűď*ו““#Ż_żÂŰۇ¨¨h"#/áééEíÚľó Jäćĺ˗ܾ}GiúÔ§‰d^ >wî<˘ŁosäČ1ślٞ-řś—É“'`eeIłfMńő“ç-,Ěřá‡M€Ö­[ąsç.ęׯ§¸,='††F\šr{÷â?šćˇ}Q…*ý&kŰŢşĹŋ‘xyÍ`ßžŠŰ°š5kJXŘ^Ž˙‘ë×oŕăă§4€r~Űşżş?en;ňŰž|,ż|çW7ŞŽ—Íš5ĽL™2,Y˛ [[ĽŤŇČ޽߰yóVbbbůůçSŒ?‰={öęöŽeË/111aÚ´™\şt™¨¨h||ü”LΊĆĹĹńÓO'‰g÷îPÂĂĂ ´Ü-šSťvmŚM›Idä%nŢźĹ̙ŢčččZŮţřă<<Ćłpáââîrőę5>B͚5s]'ó[żJ–,ŠPdŢ.V˛¤.ˇoÇäű4ÂÜôéӋđđƒěÜš‹¸¸ť9rŒÝťĂţçňg͗*űľ÷/™˘˘˘ YKLL,GŽcĺĘ`œœş˘ŁŁŁňţ2óřdäČá4lXŸÉ“§*=}ëSśqűöŕťďÇƍ›9vě8}űöV9MAˇO…ąíurrä÷ß_0{ś/Ńѡ‰ˆ8ÇŇĽAyöűü–ŤĘş¤JšO=žřŘüů ńňšÁőë7ˆ‰‰eçÎÝ/^œŠ+Č ‡Œ"ťŁGĄŁŁ“ăÁ~ýúő¨\šr‚S§zRľjÜÝÇâá1##CĚĚZ){{Ďä›ožĽ˙Á̟ż;;;†Ď”QWW—qăưzőF“ăAMPĐR0dˆ+ţţôě錞^Š•ŰĆŚ 3fxqŕŔA rQ rYŘLM[ŕĎącÇ2ĕĽK—Ń˝{7<‘áSŐŹY??öěŮË A.lßžƒ‘#łŽ÷ůçiÖŹ)ă™4i ĆƕY´hžRPL•4ŽşvudѢ@úőÄŽ]{˜:u˛˘oš™ľŚ];[ÜÝDzjUęęę,^ź€:u>cÚ´ >’‡#8xeގ5eíC‹/ nÝ:̚5—Ą\šr••+ƒ”îϏĄĄ!ŤWŻâŋŒáΔ)^T­jLPВOş}ě̙ Ź4­_żé“ÚŃČȈٳgqĺĘ5\]‡óíˇß* „Œ]ýüćЧOoĹ“&M :::ĎÇo7k֔ˇoßѲeKĽ>ţňĺ+Ř&šńđÍĺËWčßPśGŰÖöEĽŤ ý&kێ9/ŻéTŻ^ŔŔ?Ÿňâć6”ć͛1{śSŚxńů獕ĆÉo[÷W÷§‚l_>Vć•ďüęFŐőRMMÎ;r÷î]:wî˜mť9oŢŽ?ńa;?k&M_¨Ű;MMM–-[Œž~Yƍ›ČčŃcŠ_żMš|‘ëoşus˘Ggüüćŕę:œë×o0`@ż-WCCƒŔŔ…T­Z… &ăá1ž–-żĚqĐęOĽŤŤËŠA$$$0tčpƍ›€‘‘!~šŽ“ů­_zzzôęՓ… —(côăřńăřřř}R>ۡo‹§çDvíÚĂŔCŘ˝;Ti˙řОćK•ýÚÇű—ŹóIJz„‹ËP–, ÄŃŃw÷Ú_fÝöřůůššŞôőSˇq&x°oß~ r!<ü;f̘–íö˘źŇtűTŰފ+˛lŮ>LÂŐu8óç/bôčQyżĺˇ\UÖ%UŇ|ęńÄÇüý}¨\š“'OaČWâââXştąâa˗ŻÂÉŠ‡œ|ń/ĄŚÂçjYŢgžVĎň7sŇř0i~˜´- LrrĘŠj!„Ş|}ýyóć sçú˙Oi„â’˘x2`ŚQŁĆPťvíB ˆ‚ˇAdä%FŒpçرÊŤqţNNÎôë×gçî˙˜şJLLÄÉŠۡoĄF “ON#ţ“&yb``ř—üóOˆ˙o´ľľLç@  ¤~˜Ň>LéYŚ÷YţfFÂłžćŁ×€\#„Bń—taţüEÄĆĆĎćÍ[‰Œź„••…TPřîťĂôěٗ'~"11‘ .˛térš5kúˇb„ř+Ü˝Šé—RBüKȰŰB!„---ź˝g°zuŁFćőë7TŻ^_ßŮyŢŞ$ Oťvś<|ř•+W“˜˜ˆŽnIZľjĹčŃ#ĽrÄJZZ>¤yófRBüKČmJB!„B!„ČmJB!„B!„˙1ŒB!„B!„(BŒB!„B!„(BŒ˙9oßžĹŮš7ëÖm(´y†‡ÄÎÎá1Ÿäädć̙Gťv1ÂýoŻďmŰścjjžăŔ455'66Qó€ŒÇaO:MV!„B!ÄßJžŚ$ţőf̘…††ŢŢ3ĐÖÖĆĘʒúőëý'Ëť˙ˇ=z ŞTŠüČSéŇz,_žě/kS!„B!„ř/‘`ŒřĎQWW˙O?˛2)é5kÖ U+ÓLž444¨]ť–t>!„B!„PĺźUŞ@''gBC÷ŕí탕•-Yš2˜´´4EšÄÄDź˝}°ˇďD›6mńđO\Ü]Ĺ÷žžţx{ű0gÎ<Ú´iˎ;éŢ˝GŽăĐĄď155çôé3JËËwńŘŘ´ÇÁĄ3ţţźxńBąÜœn155ççŸOĺZŚÂé×o––689ő`ăĆÍJe155çŕÁCôěٗöííłý>.î.ŚŚć\˝zMéó7ÓŠ“#éééJŸ'%%ajjÎćÍ[šzőŚŚćřű(ĘťqăfFŽ™™ˇoßŕäɟ8ĐĺCŮ°a“Ň|3ë4$d-ööčÚľ;ç¸pá"ş`ee˰a#xđŕAĄö‡K—.3jÔllÚcg瀟ß\^˝zk›œ?žţýciiCŻ^ý8{6Bń]Nˇ€]ź‰ŠŠ9oŢźQú|ǎŘŮ9`cÓ/Żé<}úTVR!„B!„cÄϚ5ëhܸß|Šżż/‡&(h%iiiŒ3ž¤¤G̟Ŕš5ÁhjjâééĽ4ăÇOPştiÖŽ]˝}Ö­[M“&_ТE3ÂĂ÷ŃźyłlË}ňä nn#ŃŐŐeĺĘ ||źšs'†‰=?š,bţüEtëćȖ-qsĆúő9rä˜RşmŰžfܸ1Ź_ż&۞>}ڰ7“ŤŤ ŽŽ.ŮŇVŠR…°°]”+WNńYűömůńǟ(SŚLŽm:mÚTŹŹ,đôœDçÎNÜşEÓŚMTnť÷ďßăă㍶ś6ţţłqvîÍŋ‘9ó„B!„˘°I0F™:uę(˝oĐ ďŢ˝ăţýÔŽ] 555~řá8׎Ýŕţýî܉2ž”ŠbĹň^nTT5Tbʕ+§ ř=fßžo‰‹‹#>ţ>111T­ZU)MĽJ•ňœGťvm â—_NciiÁÁƒ‡řüóĆ8?•*Uř¨ÜŃŘŮľSúě‹/“ššJLL,Mš|€‘‘Ąâ{uuu444(UJOń™śś))Šy.;§|őőËćš>--;v}›ű÷ĄĄažeĚZ/™°‚^óŮgľČéë—%&&F‚1B!„Bˆ"!ÁQdRSS?z˙çU)Ϟ=ĂĹe††ŘÚZcfÖ Ć›ř?/÷ýű÷…ţ›­[ˇąvíť`nnNŐŞĆlذąŔËŃŐŐĹÚڊC‡cf֚ŁG2jԈ]ŰdßČČKŒ7 3š5kŠ˝}Ž]ťÎ =_9ľcNMű)}D!„B!>•cD‘š~ýşŇű+WŽ ŁŁƒąq~ůĺ >ä믡 ŁŁd >[ęÖ­ËÁƒ‡HOOWŒĂ’””ÄéÓg°ˇď ¸-ęńăÇÔ¨aď€ľáá‡čŮә‘#˙źeęń㧔-Ť_ŕüuęԑI“ŚpćĚYŢ˝KĆÖÖŚPĘ]§Îg\ž|…Ž]Ÿ]ž|MMMjÖŹńˇőƒcǎSŤVM|}g+>űĺ—3˙ó|‹/ÁŤWŻy÷îŊËľŁŁŁINNV\“ŔłgĎŠ]ťśŹ¤B!„Bˆ"!řŠ"MHČZbbb9rä+WăäÔŞUŤJzz:ĄĄ{¸w/ž“'fٲ*Í×ĐЈ;wbš{÷^ގŹ899ňúő+ź˝}¸u+Š‹#ńňšÁž}ĐÖÖŚL™2Ô¨QƒĺËWqůňΝ;Ďüů •ćQ˛dI^ż~Ă­[Q¤¤¤P˝zUN:ÍՍ׈# `ńńńůćőăů4k֔2eĘ„­­"8ôż4h‡aÓŚ-ÄÄÄrüř .\DˇnNŠńbŠBɒ%Œ`Ü˗/Š^˝*qqqüôÓIâăăŮ˝;”đđđľiN5j€şş:sçÎ#:ú6GŽc˖íŮŇéčč0cĆ,n޼Ņ ńňšI˝zőřâ‹ĎřţűŁôîݿП %„B!„™$#ŠĚ€ýHJz„‹ËP–, ÄŃŃw÷Œ[rjÖŹŸŸ{öěeĐ śoßÁȑĂUšoßž˝(Y˛áĉ“Ůž744dőęUźxń‚‘#Găĺ5ęŐŤřgŔĹĎo6ZZZŒíA``..C”‚"ŚŚ-iÔ¨!C‡şqýú ŚNő¤jŐ*¸ťĹĂcWËň>óľz–ż™“ƇIóä he’“SÎHU˙˙ćääLż~}pvî.•‘ƒ7sđŕ!víÚ.•!„B!„#mm-Sŕ9$ŠŚ´Sz–é}–ż™ƒQf}ÍGŻ3FˆżURR11ąěÚľ›áÇJ…!„B!Ä˙Œâo´~ý&Ž=J‡čÜš“TˆB!„Bü? ˇ) !„B!„B|Pˇ)ÉžB!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1B!„B!„EH‚1â?!:ú6žžSéĐĄ#66í>|$?ýtň˙u$&&bjjNll\Žif̘ĹčŃc užů)č2˙ žžţL:-×÷˙;vě¤{÷^*—ăŸâŸšŻÝ¸q“N9{6B6˘B!„˘HI0Füë=ŤëpRRR˜8qłgĎÄxV_Ň IDATÄĄ)SŚąeËVŠ öîý†.]œ”>kѢ9ff­‹4…˝ĚœĘ%„* °´´¤rĺJRB!„˘HiJˆłˇoßâëëO‡vxyy*>ˇ°0§^˝:̛ˇ333jÔ0‘ĘĘA—.˙_,Sˆœ”+WŽÉ“'HE!„Bˆ"'WƈľS§NóěŮsÜÝGdűÎŃą ŐŞUăŔƒ„‡ÄÎÎA)Íŋ‘˜ššóćÍĹg'OţĚŔ.XYŮŇŁGvěŘIzz:űm:ŚŚćüüó)Ĺűťwďáá1›ötéâÄ…KxńâEŽĺđőőÇŰۇľŘŰw˘k×îDDœă…‹Šź 6‚(~ăääLhčĽůŒáβe+˛Íßß?€yó’”ôSSsVŹV,7óv’̲EDœcčP7,,ŹéŃŁĘł >ĽŹ/óÔŠ_:Ô KKzőęGDÄ9ĽßěŮF÷î˝07oC÷î˝8qâ§<˕˜˜ˆˇˇööhÓŚ-㉋ťŤrżJNNfѢ@:caaͰa#ňüýüAppNNÎXZÚ0p ‹"™}ĎÉəăÇOŕěÜKKFŒp'11Q‘&55•ĺËWáŕЙ6mÚ°€ÔÔÔ­çĎ_ M›śŠ6{˙ţ=[ˇnĂÉŠÖÖípuÎ/żœ.Pűeö3ooŹŹlqpčĚʕÁ¤ĽĽĺ›Ÿ;vbg瀍M{źźŚóôéSĽůnܸ™‘#GcffĹíŰwˆ‹ťŤČžžsů9|ř––6ź}űV1Ÿ>}ĐŁGĹűwďŢaiiÑ#Ç>ô…ߘkÖăççĂĺËW˜8Ń3ßéJ•*˛sçvœť)‚3łgĎd÷îŻŃÖÖ& `ţ'ŐŠ‡Çh\]]PWW'<|C† Ě5í‚‹6̕ýűĂĹźysŮ˝{&&&Lž}€={ö˛~ýʖ-›cÚ/^PştŠ\缧WŠ/^Şźě 6Ńťw/úôé @ľjUyüř1!!k6ĚUĽy„…}CĽJ•™>Ý uőŒxçěŮ3éŰwŃѡůěłÚ9ţŽB… tęÔ€ž}ű°jUÇwŔĤ:qĽO@ŔźOŞÓ’%Kb` ĄĄyŚíŮł;-Z4 cG"#/ł}ű,-- ­ŹssJŁF =zß}w˜¨¨h>˙ź1żţú+zzĽ°°0CGG‡Ž]iŰÖ]]]€Ëľ~}ššš/^€^˝z2z´ϟ?§L™2ůćç×_PłŚ‰"O“'O 99YQƏM™2‰—/_*úŠ‹Ë`6oŢʍ7ŠPĄ<iiiL›6•%J0hĐź˝}x˙ţ=oŢźáŰo0eĘ$lm­¨YsˇnÝ"!áAžů˝u+Šqă&0|¸+]ť:Wë|ýőNüüfcnnŔ€ýšqă&ĄĄ{hŮňK•ŰŻiÓ&të–1.Oٲe1€€ů ㏽˙o´ľľđ÷Ÿłso.^Œ¤yóf888Đšs'Ĺo6oŢJ‰%˜={‚ƒséÜىӧĎ`nnĆ_|Ι3´n݊łgĎѴ餼ĽqŽÎ;qúôYš4ů‚RĽ2ś ܧ]ťTŤV€+–RŹXą\ë˛ző긺şPž|yěěě¸páƒäíۡ„†îaâÄqŠvŞUŤ&QQQÄÇߗˇB!„`ŒřwJLLTb2Ţ˙ĆŠSż(‚ك-zDEEç:ż/^˘§WJĺĺGF^"2ňű÷ďW|öęŐk^žT-¨sëÖ-nܸAűööJ'Ś'†żć 022TźVWWGCCƒRĽţźâG[[‹””Ôżź ęÖ­ŤôžaĂúœ8q˘PËúąňĺË+^ëëë(nłľľa÷î0şuëAŤVŚ4mڔ6m,󜟚š?üpœk×np˙~wîÄ(Ýn’w@Ş“&yŇťwžü˛-[śŔÔ´ežËťví:‘‘—‰żGlě]ŇÓÓy÷î"MŠRşŠ@LF9˒ššJJJ ńń ¤¤¤Đ¸q#Ľů6kÖ4ß`ĚíŰ1 üĺĘŃŤWOĹç÷îĹóöí[&NôDWˇ¤R611)PűŐŠSGi™ ÔăÝťwÜż˙€Úľk嘯Ď>Ť­ÄTŠR}ý˛ÄÄÄ(‚1•*UPúMTT5Tb2‚msëVććfXX˜ś€sçÎŃŹY3RSSÁ˜3gÎŇ­›Łâ÷..ƒ ZÉɓ§hŇä‹ăIŐÍŁ/)˝××/ŤŘĆdÖiNí$Á!„B!ÁńŻUştiJ”(Ą4†KĽJ•ňÔaűöŻyńâzzzźxń‚°°o°łkGŊšpá"­Z™ćúűĚĎ?Ú¸š ĹÚşMś´ĽJ•RĘWn󰲲ŔĂcLśĎUš*ăďöń8%ů[ňW—U__ŸíŰ7sîÜy.\ˆd˖mŹZ̚5ÁTŹX1[úgϞáâ2 CClm­13k…††ăĆMTy™Mš|ÁŢ˝ĄüňË"#/áç7‡jŐŞą|ůR45ło6'OžBLL,]ştĆŢޞZľjňŐWC˙ç˛çĐľ˛š˙>ööv:ô=Ǐ˙˜­ďnܸŽŇĽ•oăËěPĽý˛÷‰´OĘűű| ”×÷jjjňkI``IIIœ?gçî@ĆSľ’’’ˆWşŠŤwď^XYYqęÔ)"#/ąuëvz÷îÉȑnnĚ[ʞ֐cŸB!„"/2fŒřG)Q˘ţ”/_Ž’%Kŕî>‚ŚM›äšŢĚŹeʔfůňU@ƕ2‰‰żáĺ5“ĐĐ=ÜťwŽ3ţë_źx ^˝z­tľBÖqęׯGbâC*Vʍ˜Ţž}ÇóçżŁŽŽŽ¸%ăńăÇšÎăłĎ>ă×_ŁB… Šy”,Y’ťw良ĽUhuĽŁSœÇŸ((ţúëŻůžĚćçÚľkJď/_žB­Zš]ýđחőŃŁG$$ܧU+SÜÝG°mŰ&ŇÓÓ9vě‡Ëy™‡HďŢ˝077+đ@¸qqwyűö-vví˜2e+VqéŇe˘ŁogKűüůsN:͔)“qqŒ­­5úúeyóć•—W­ZU´´´8ţ‚ŇççϟĎ÷ˇVV̚5ƒ~ýúâë;G1ĐpŐŞĆ+VŒÄÄDĽţüŰoIKK/Pű]ż~]i™WŽ\AGGcă*šć+::ZéJ¤„„ž={NíÚš_-Uˇn]Ž^˝Ž4ŽĚÓ§OIHHP\ĽSąbELLL8pŕ ÉÉÉÔ­[‡şu됞žÎţý011QpÓŇҸző††8;wÇßߗ1cFąsçîOę‹UŞTFSS“ŤW•ëăҼ˲ńB!„"˙Î˙8_~ق}űÂT Hč0cĆ4&OžĘ“'qpp yófěۡŸ›7o2r¤5kÖ QٍŤŤ3wî<úöíĂ˝{ńlٲ]i~ƒdâDOŒŒ 13kMbb"‹ŇŹYSŚOŸJ™2e¨QŁ˗Żb„b$''łeËVĽytë֕={ÂđńńŁgĎ¤ŚŚ˛†‡ą}{á ôŮŹYSÂÂöR§Îg”+WŽÝťC•ž2S˛dIʼn´‘‘!<{öœë×oPąbĹí@۷FÔŠó?ýt’cǎ3oޜçYeݡď[ÂÂö2mÚTŒŤqŽçϧFŒvý¸\ŐŞU%==ĐĐ=XXXŸí S%Kę}‡„„Œł˝Ÿ?!ŠŠŠxxŒAGG‡]ťB)^ź8+VȖ?===ôőË~###ŢźyCppHŽăËä¤D‰8:v!(h%zzĽŠ^˝GŽýŃÎóˇ™Ë9r8ŃŃQLž<• Ö ŤŤKŸ>˝X°`ŠŠiÔŹYƒ+WްxńRŚL™LŊTnż¨¨hBBÖbkkCll+Wăäԝ|ÖÍY <ˆ7oŢD˝zőřâ‹Ďsý““#ťw‡âííCż~}yóć +WSťvmZˇnĽHgiiΎ;iÝş•˘üŚŚ-ŮšsNN]éţřă<<ĆÓśm[z÷îÉŤWŻ8|ř5kÖü¤žXŞT):uęČňĺ+(^\ccc~úé$—/_ĄD‰’˛ńB!„*“+cÄżžŠiKVŻ^‰şş:óç/`îÜy”,™16GÖą!ŒŒŒ˜={WŽ\ĂŐu8ß~ű-cÌĘ6Żyóćpüř † qĹß.66ÖLš4^‘ĆĎo6ZZZŒíA``..C”1544$$$˜—/_âî>†1cĆQ˛dI–/,ÔŰÜ܆Ҽy3fĎöcĘ/>˙ź1 6P ôęՓ… —°gĎ^ĚĚZÓŽ-îîcYľ*$×ůN˜ŕÁž}ű4ȅđđď˜1cć9Îł(Ę:hĐşvudѢ@úőÄŽ]{˜:u˛âäüărŐŹY??öěŮË A.lßžƒ‘#‡+Íłk×.üńÇ ô)))ŮŢűűűPšr%&OžÂ!ŽÄĹĹątéâ’VWW'(h) >ô™zöt.ĐXEńÄŤnݜX´h1..Cyöě9ƒT}cŽŽŽŸŸŠŠŠŠ‡J˙ţ} aŕŔ!lŢź‰Ç)žś¤jű Џ¤¤G¸¸ eɒ@s|œ|V-Z4§YłŚxxŒgҤ)WfѢyyŠ Y˝z/^ź`ÄwŚLń˘jUc‚‚–(ÝdiiÁ‹/iŮňĎq|ZľjĹ˗Ż}@WW—+‚HHH`čĐáŒ7##Cü>š?N˜ŕAťví˜Ď!Ž$$$Đż_Ů !„BˆQSásľ,ď3_Ťgů›9i|˜4?LڀP&99ĺŒTľ(jĄĄ{ذa[ślĚő*ń§ÄÄDœœz°}űjÔ0‘ 899ÓŻ_ĹŘ,˙ß˝˙ž´´4Ľ`Őşu8qâ$›7Ż— B!„řĐÖÖ2ž)@2úaJű0Ľg™Ţgů›9bÖ×|ôŰ”Ęłsw9BŞ9sćq˙ţ}FŽtC_ż,7oFąk×nzöě!•#„B!T&Á!„BE#F #8x 3fĚâɓ§Ńłg† $•#„B!T&ˇ) !ţŻ˝űŻůzŕ8ţND* ‚Z)ĽśQIDBcS5B5ŞZťF+öŽ=bľ R?ZUUŤö,ETS4j†DĆďr››Ü$7Dšęçő<ßçŢű˝çž{ž+žűqÎůŠˆˆˆˆˆČ™1LIřŠˆˆˆˆˆˆˆd"…1""""""""™HaŒˆˆˆˆˆˆˆH&R#"""""""’‰ƈˆˆˆˆˆˆˆd"…1""""""""™HaŒˆˆˆˆˆˆˆH&R#˙j§OŸÁĹĹŐäňĂ{2ä;FŽü˜ž}űŽ‹‹+żţzńšlĎÇiٲ- .ÖÁÍdÁÁëyë­Üźy3KŐ%"""""/+íyLœ8ŽÂ… ­+\Ř)CęŽ^ý "##3e;Ź­­ŠSǝ×^+§ƒšÉJ—.ťť;šsçÎRu‰ˆˆˆˆČ‹GaŒźJ”(AńâŞKÝM›úfÚvXZZҡooĐ@ĺʕ¨\šR–ŤKDDDDD^<Ś$/ź0gÎ<üüZâîîI§N]Ůľë{Ł2ë×o E‹6¸şzТEŁ÷Ç2|řˆdőĆĆĆҸqSžřb™ŃúcǎăââĘŋ—’}fřđôď?Ŕh]tt4őęyą~ýüüZźŢđţýű÷?~5Ć˲!C†qéŇeBCˇăîîÉÇ ĺŰľëHŤVí ŻŁ˘˘pw÷dűö&÷Oxx8ŁFĆŰť ő hÔöŔŔąŽeɒĽxyyăééĹ|h4ǜ2I™ű™Ýť S§ŽÔŠSV­Úązőâââ ďűůľdɒĽôîݗڵëđË/ç ĂÉž˙~7Ýşő¤nÝŒů1÷îÝcҤ)x{7ĄQŁĆ,]şÜPOHČ6ôI´_ţ`ȐaxzzáééŨQŁšsçŽáýŸ>L׎=pw÷ÄÇǗ… ڕ´Žřřx–-[ŽŸ_+ÜÝ=éŘą ;w~g´~~-Yˇ.˜#FRˇn7nĘʕŤĚ>OEDDDDDaŒČS‹ŽŽfÓŚÍ,_ž‚7n|„S§NłiS°Ąý<_ߡřć›í´mۆ*U*óÓOűyóÍZěŰw€jŐŞÇţýđőmÂŢ˝ű¨ZľŠÉúłeËƢE󰲲"WŽ\Oöekúö ŕÖ­[ä˗€ěŮł3tč`˛eËŔG YłüüóaŢxăułË$•Ög/ţ‚śmŰĐŽ][Š/ßţÉźy čŃŁ––ód|}›$ŤßĎď-Ă\B^^őŮ´iłĄŽzőę2wî|NŸ>mrHŃŐŤżŃ A'Ăđˇ™3?'GŽDDÜ$** OĎş*TB… ˛aĂ:“ç̃X˝z-öÇËŤ>ÎÎĽżĆâĹKŠSÇÝPÖÇLJ ęĐşu+6lŘĚÁƒ‡¨XąÂ3§"""""˘0F$Eááᆠćńë?ŘłçGš4iœęç’Nŕ›đ#Ŕ‚'NrřđQÂÂ.ó믗ˆ‹‹#**ęɏrOÖ­Ű@óć­¨U˅jŐŞááánV{‹+FŊŘş5”W_-Ă?ě!:ú Ô7YŢŇŇoďFlÝú mŰśáöíŰěÝťiÓ&›,ć̢˘˘hŐŞ­Ńú{÷îóŰożŕćV› 6pŕŔ^ýubbb aĚO?íŁyóf)nƒ……;w~ˉ§říˇ+œ?xÜC)Á+Ż8€‚ boŸŸ .‚sĘ$•Ög>ÂáĂGřňË/śŕîÝťä͛€Â… ™Źż@FÁOîÜƁTŽ9ˆŽ~dňł]ťv&(hťwďĄjŐ*¸ššRŽ\YJ•*IÝşuđ÷5Ţ ZľŞxxx˜ F._ăáÇT­ZĹh}ĺʕذa#qqq†óľPĄFe^z)‘‘žů<…1")ʛ7/666Fw/Jz—$SR›ŔwȐa\¸đ+M›úâííÍ+Ż8óîťÝ ďçϟŸ•+—rŕŔA:̲e+˜={óçĎÁÉ)í;2ůú6fîÜůôë÷Űś…âé遭­mŞĺ—.]ÎĺËa:tGG‡Ă {űü,X07ŮzęÔqçłĎ‚¸~ý:˘eËlܸ‰ëׯ†ťť›Éş˙úë/şv큃ƒ=őęŐĽvíZd˖•‹‰‰Mö٘˜˜t—Iţ~꟱śśĆßż;uëz$+gާOFjŰś uęÔaϞ=>|„ĺËWŇśmkz÷öÇ‚ńăÇrúôöíŰĎîÝ{˜5k.cǎĆÍÍŐ¨žřřř iĎłž§"""""’uhÎÉRlll˜0a, ŔÖֆ>}zQ­ZŐ§ŽďÖ­[ěŮł—aÆеkgęŐŤKţü/zܸqƒ+W~ŁV-úôéŊ_ǎ;ÍúŽúőëů€}űöłwď>“Ăe+Z´(•+WbǎěŘń-ű`aaa˛l™2e¸}űÖÖÖ899–óç/zS899Q˛dIžţz ŃŃє-ű*eËžJ\\_~ů5%K–L1Đ:|ř(׎]#(č3ÚśmƒŤkm“Ęůóç =‰Â¸}űĽK—NW™ôÖűÚkĺżf´íFqëÖmŁŢO-66–ăÇOŕŕ`O˖-;6~ýŢc͚uDFFrňä)ʕ+Kç͘9s:ľk×bƍÉę*Q˘89sćL67ÍŃŁÇ(]ş´ŮŰńŹçЈˆˆˆˆdę#YNŐŮźyCş>séŇ%Ła5 ŔÎΎüů_"$d ŽŽŽDFF2gÎ<ŁŔ›7ņ 1b8/ż\”ýűpëÖmJ•*•ě{zźœBBś˛~ýV­ZfčâîîĘęŐkxóÍZ†msqŠÉš5kńó{+Ĺú‹/F\\ÁÁëqss#,,ŒéÓg&˙CaeĹG˘sçwˆŒŒäłĎ‚(WŽœŃśšS&˝ővî܉Áƒ‡âčč@íÚoΔ)ŸńúëŐRÝoĎęÁƒ ¤~ýú´mۚ{÷îşgggΜ9KŸ>ý8°?5jTçňĺ0Ž;ގˇw˛şrĺĘE›6­ šIŽ9qv.ĹţýűŮ´i3ŁĚnSzÎSQ#ňÜ%˝ű<žčÖŰť!AAŸ8Ž.]şQ¸pazőęÁŋ ĺŢy§#qqqL™ň7nÜŔÉɉáÇđ曵’ŐiggG›6­™S™ŒřŒˆˆˆˆˆČófmÝ¸<˘˜'Kě“%.ŃŸč1aÂČÄĎIňPĎ‘gÉůó šIƒő^¸ FDDDDDD2ž&đyťwďĄOŸţŘŘä˘˙žÚ!""""""’& Sy"3†)ŠgŒˆˆˆˆˆˆˆH&R#"""""""’‰ƈˆˆˆˆˆˆˆd"…1""""""""™HaŒˆˆˆˆˆˆˆH&R#"""""""’‰ƈˆˆˆˆˆˆˆd"…1ňŻÁ˜1ăńńńĹÝݓví:˛qă&Ăű§NŚI“fěۡ˙šľááÇ´lٖ… ˙ăűcĐ ÷qqqMśôęŐ€đđp\\\ůő…ńő* IDAT׋OýQ€Ÿ_K‚ƒ×gšs*+ĎgľzőZ´hŁ?YPtt4ăĆM¤AƒF†ëóŸźžˇŢjÁ͛7u`DDDD2•vüŰĚřű÷ÁÖ֖÷ߌƒƒ=‡aÚ´éÜżŸŢĆÁÁwwwŠ)üÜÚammM:îźöZš§Žăňĺ0Ú´iOpđjŠ-úLíqqŠÁ{ďő6Z—+WΧŽoäȏɖ-ŁF}ôó7ąxń|ůĺĆ,}>žxxÔg„O‰‰‰IőŘűůľdĺĘU|řáGxzzŃĽKwÂĂ˙`Ýş`üüZááQŸQŁFeÖů’PçşuÁŒ1’şuиqSVŽ\eö9ÇÜšóiܸ)uęÔ#0pÁÁ덆\ĹÇÇł|ů üüZQˇnşuëɏ?îM×qŠŠ2:î÷îÝcܸ‰4jԘşuĐŻ_żür>]絟_K–,YJďŢ}Š]ťŽŃç‡0×qqqeéŇĺ?~WƎćyźžúő&ű;ÔŻ_#FŒ4ëZHřŰ´eË6Zˇn——w˛íJéšOíH¸†ŚLů _ÜÜęŇŁG/ŁsXDDDDĆHÍŚM›Yž|7nÜHľlőęoPž|yştéÜ9ó8yňqqqŠ~ćÇ÷2jÔh|}}X˛d!M›ú2qâädĺžývK–,d„ą|÷ÝwŹ\š:]Ű2oŢBúőëCpđj^{­,#FŒ4úÁž ^˝şĚšŔÜšł˜6íÓ'ĎçłlŮ zőęÉâĹ hÔ¨#G~ĚŽ]ßgŘţţíˇßčÓ§?ĽJ•bŢźŮL˜0ŽĂ‡0cĆl.œKŐŞU¨^ýuBB6óĆŻ>ť`Á"şuëÂźyłyůĺ"|đÁ‡FA‹9–-[AÁ‚X´h>`óć/ še˛l@@_şu능Ľ%!!›éŇĽÓSí'_ß&8pˆˆˆĂşďż˙GbđňjŹü͛7ń÷ďMţüů™?cÌćčŃc <€7ßt!66–Ÿ>l(ĆŐŤWšvíšá{ll,..5’ŐKż~š~ý“&M`ţü9XYY1tčé:'§NýœŻżţšAƒ˛pá<ňĺËˊŤŇ<!!ŰhÝş6ŹĹÉŠ ýú ŕĉ“Ě›7‹ůóçpđŕ!Ă÷¤už$Xźř <</˝ô’éŘʊٳƒ^OHČ6–,YŠŁŁmÚ´˘]ťśd˖Íä˙† ĐącœKqóf„Ą—E‚%JĐ­[W ,HÆ 9tč;w2{[üýťSąbúö}­[C9{ö\˛áÖÖÖŘŰŰ`oŸ;;;îiЇ‡ťa¸[b6l˘pá"|řáXZ>ΰ?ůä#ÚˇďČšsżPŚLiŞTŠĚO?íçÍ7kąoߪUŤBllű÷Ŕס {÷îŁjŐ*&ëϖ-‹ÍĂĘĘʰÍmÚ´ŚoßnÝşEž|ůŇ<'ďßżĎW_}ͰaďSŻ^Ý'űĄgΜáʕŤŠƒÚľkQŠREZľjIŻ^}˜:uŽŽŽ8::âęęĘŠS§Ě:_řřřĐ A=€'AĎfŸŔěž#—/‡ńđáCŞV­b´žrĺJlذ‘¸¸¸䘚Ŕ7ľ ŒcccY˝z çÎýÂoż]ĺěŮs888¤ŮƗ_ţűüÓľ} *T¨`ôşRĽJDEEńŰoW͚÷ćiö“ĽĽ%ŢލغőÚśmĂíۡٝwÓŚM6ůgΜáÔŠS†!đx8ŔŐŤżSŚLiÜÜjłaĂf8Ŕ믿NLLŒ!Œůé§}4oŢ,Ĺí°°°`çÎo9qâżýv…óç/ IIíœ ťÂŁG ĄJ‚×_Ż–fS ŔßőfϞŔ(4ʑ#=J×ůR¨PŁ×/˝”ČČfՑpLMmKB“PfđŕĄäÎmk(sďŢ}J–,™bâí݈-[Bi׎-7oŢdßž|öٔ'Îâŕ`o4ś……•+Wâ̙3é:Ż .ôTÓ:š4iĚ AC¸sçvvvlÝú >>ŢXZZšu-üÝžôMhnÎ5Đşu+Ţ(mŰv FęÔŹY—šú‡MDDDDaŒduyóćĹĆĆĆč}z~4.\˜.]ŢÁÉɉѣÇ0hP@˛2qqqÉz̘ęAóOKřĄó4Ň3ďáĂG0`0nnľyýőjx{7âĉ“|ýő–LŮŚ¤ëŇťÝOťŸ|}łtér._ăĐĄC8:: ÁJŞN7ú%[ŸĐkĽNw>ű,ˆëׯsđŕ!Zśl<žűÓőë× ĂÝÝÍdÝýő]ťöŔÁÁžzőęRťv-˛eËƀƒ3`Ÿgě1̈ó%­:Bƒ¤×Ľ•Uň˛–,YHŢźvf_Ďžžůâ‹e\źx‰ýű÷S @ĂqOí\˛°°x.×jzσęŐßŔÁÁž;vR­Z5~ůĺƏĚĐv<í5Pľj6n ćÇâđá#Œ3Žâŋ3cĆç&ˆˆˆˆÂ‘,ÂĆƆ Ć2věăÉ<ťty'Ő!/Ÿ>ƒ˝{bĺĘĽF˝"#ďceeeň@ɒ%9~ü¤Ń‚#GŽüă۞ôˇ^‰Ĺə3'G3ęrôč1J—.a]˙wěř–W^q&0đĂşüé™ë͕ˆ{÷îEŽ9¸z5y'N˝>zô(9sćä嗋šőŁři÷SѢEŠ\š;věäĐĄŸiÜŘ'ĹÜeʔa÷î=*TČPćΝ;œŇqňäI(Q˘[ˇnĺűďwS˘DqöíŰOHHyňüÝŰŔÁÁ‘réŇeŁ!-ŠŠXą<–––Œ?‘öíŰqůr˖­LVîüů ̛ˇ€ző<ůő׋̚5?żˇ ?F“˛ˇˇçŻżnqňä)œœ ‘?ţ§ŢOžžY˛dááá|řáđË5oţë×o`ôč1´n݊˜˜ć͛ϵk7XšňďIeÝÝ]Y˝z ožYËpÔd͚ľřů˝•jGpđzÜÜÜ cúô™é:Ž6664k֔  YŘŮĺĽD‰âlßţ?.]şLöěÖvžšsž˝Rʎví7iĐ }úôgöěyĎ´Ÿ<=ërĺĘ*T(““S*?L˜7owďŢĽOŸ~ôë7[[[fĚř̨÷•ťťwîÜĽfÍżçɨUŤwďŢĂÍÍ5ĹúK1fĚhÖŻßČ;ďteĺĘŐôîÝ3ÝÇ6  /͛ű1eĘTşvíÎ_ÝJׄÓć0ç|Ɉ:  AƒL˜0‰.]şqĺĘ:thoTŚgĎîtčО9sćŃŠS–.]ÁŕÁđńi”ćqżző*•*U4 ,--™:őS^}ľ #FŒ¤gĎŢ\ťösćĚ2œćž×OĂÜóŔÉɉňĺ_ăʕ+xzŸăő7#é5oÎ50věhŠ)̐!ĂčŇĽ/^äóϧŚ8ťˆˆˆČ™…ë-˝Nxn™č1aÉödąz˛Xف|Ńя~ŇŽ–ŹäŃŁG†‰JáńІ^˝ú°cG¨Ąçˆˆüsâă㉍5 ť.\ĚŽ]ťYştŃ3Ő…/Æ 5ÜńIDDDD$ľuvŕđˆbž,ąO–¸DK|˘Ç„Iü?'És@Ôä?hëÖPćÍ[@@@ß'ˇc '(hŻż^MAŒH1nÜD~űí7z÷ö'ţ—8}ú,k׎ŁuëVĎTďéÓgŘźů+ěěňâááŽ-""""˙őŒ‘˙œ˜˜–/_ÉÖ­Ą„‡‡“;ˇ-ľjŐ˘oßކť‚ˆČ?ëć̙͛3Ÿýű÷qGGG7öŚK—wžz"Úk׎ѪU;Š)ÂG \š˛ÚŃ""""’LfôŒQ#"""""""ňDf„1šŔWDDDDDDD$)ŒÉD cDDDDDDDD2‘‘L¤0FDDDDDDD$)ŒÉD cDDDDDDDD2‘Âů׋ˆˆ`̘ńřřřâîîIťvٸqS–h[`ŕX†ńÂîű_~9‹‹+ׯ_`äȏéۡڎ#<<W~ýőâ3ŐłfÍZš6őŁAƒFÜšs'KěăíŰwđîť=Š[ˇ^^ތ=ưżŹXąW–/_aňó..ŽÄĆĆ­˙öŰ]tď§ŢŢM>|çĎ_0*súô\\\iÚԏ¸¸8“í>|..Ž,]şÜ°Žnݸ¸¸&[ŚOŸ™âv>zôˆ ѢEÜÜęŇŹYs‚‚fńŕÁƒ ˝žBBśĐ°ĄOŠŻEDDDD2ƒ•vü›EGGăďß[[[Ţ0ö>|„iÓŚs˙ţ}:tx[;)UŻţ‘‘‘Ďý{FŽü˜lٲ1jÔGVçŋ—˜6m:ö§RĽJŘŮŮýăűsΜy,]şœ–-[ĐĽK'îÜšËęŐkéĐá–,YHᅍĘϟż:-Z4Őz-Zň$řhN§Nxř0Š/żü’nÝz2eĘ$^˝šQůżţşĹž}űŠUËĹhý;wřá‡ɖ-[˛ďčÜšőęy­Ë—/oŠm?~"?ý´ž=ťSŞT)˜7ożţziÓŚč⑊ÂůWŰż˙WŻ^%44„¨Ył:_}őu˛0ć›ośS¨P!“ßS°`J—~ĹŹmŒŒdëÖP&M››Ťá:.R¤'Nćć͛äϟ_˜ˆˆˆˆź04LIţŐ˛eËF\\ˇnÝ2Zߎ][Ł˙Mż˙>ăÇO˘QŁĆxyy3dČ0.]şlô™ŻżáíˇßÁÝÝ?żV,Y˛Ôđ^Â0˜-[śŃşu{źźźˆgٲĺřůľ˘Nztî܍]ťž7Ş7::š >ĹËËOO/ǝâ6=xđ€9sćáç×wwO:uęjTgHČüüZňă{ńók…ťť'ÝťűsęÔét•‰ŽŽfʔĎđńńĹÍ­.=zôââĹKŠîﯿĄUŤv¸ť{Ňťw_nܸaô~âa$ŠíłĺËWŕç׊şuĐ­[O~üqŻQ=/^" ` žž^řřř2věðĄ-Ú°}űśműWöîýÉčłąąą4nܔ/žXf´ţع㸸¸šÜĆ-Ú07ˇş´hŃư=ŁFfܸ‰xxÔgőę5ÉÚ×°ĄăŒ†5…„lĄiS?žűn͛ˇŚ~ý†,_ž‚đđp „§§-[śMÖvă}˝…2eĘ&9rä wďžDGGsďŢ˝ż˙˜[ZŇŁG7~ţů0_~ůUŠő~őUĽK—NVŻ……}űžÇ˛oß~Ł÷ęÔqg÷î=Üž}Űh}HČ6<==ˆ‰‰yŚëŘ ţúë/ŁőUŞTfŐŞeFALZד9׺ˆˆˆˆˆÂ‘$˘ŁŁŮ´i3˗ŻHöc?ŠęŐß |ůňtéҍ9sćqňäŠds[ÄÇÇ3xđPΝű…I“&0{öLrćĚIţÜźy€-[ś1iŇš7oƲeKđ÷ďÁ˘EKŘž}‡Q]+VŹbŔ€~,Z4€šsçłlŮ zőęÉ…ó¨Wσ#>⧟ö>łgĎă áóϧ1dČ`věŘɲe+RÜŚ)S>cŰśP `éŇĹźůŚ #F|Ä\3”‰ˆ¸Éňĺ+™2eëׯáľ×^ŁOŸţ†Ţ攙;w?ü°‡‰ÇłnÝjJ–,ɐ!ĂSœä˙ŰɸqiÖŹ ‹/ I“Ć|úéÔ4gŇ}6oŢ–-[A@@_–,YH:n <ÔDDDŕďߛܹs3kVŁGâüů <€… çRľjŞWÍźńĆëÉ:ooośn 5ZżeË6ʗ/Oɒ%’ľqṌů_~š… çŢűöŰ]ä͛— ćâíÝ(YűƏËŋ—čߐџ,wďŢăĉS,X0‡ńăÇ2ţ"† űÖ­[ąiS0uę¸óá‡ńđáC“űí̙łÉ† %¨U˅ůóç;wîD×MM›úRž|y‚‚fŚxí¤VŻ˝˝=ŋç̙łIŽłęäČaMhč7FŮéÓ§iŘĐ ˆŚk>WŽ\´n݊ >e̘ńěÝűQQQ&ËŚv=™s­‹ˆˆˆˆ(Œ1ačĐáL˜đ)3fĚŚG^Éţˇ<1+++fϢk×ÎěŢ˝‡wßíAłfÍYž|…á‡ńáĂG8uę4S§N˘RĽŠ8;—âăGbeeĹ7ßlŔǧëׯĄE‹ć/^Œ† PŽ\YŽ=fô}˝ző V-Š-ʃX˝z-}úôĆËŤ>ŻźâLǎ?~ EŠü=—GéŇĽ6ě}ʕ+KŁF^4lčĹÁƒ‡RÜŚaĂŢgń⸚šR˘DqşvíL\\\˛^-ƒ  TŠ’8::ЗüůółyóWf—ůý÷Ť8;—¤bĹ *T!Cąté",-M˙YXľj ŢŢ éĐámœKáăÓ?żfiϤűlŐŞ5Œ9‚:uÜ)^ź;v N7‚ƒ×°aĂ&lllř䓏)[öUŢxău&NKťvm‰%_ž|88Řco˙x15¤¨iÓĆ\şt‰łgϏ'‡Ýšs'žžŚ'j͗/ŸĄ÷…˝˝=ůňĺ3źW˛dIŢ{ϟW^q&oŢźÉÚW­ZU>ýt|gΜ!**ŠV­Ú}îŢ˝űüöŰď†×7nüÉćÍ_qńâEÂÂ~ă… +VĚč3‰'L˝|9Œ‡RľjŁ2 s^$(ZÔx’UGGCH`Š……'Nœäđᣄ…]ć×_/gÔSŔÚÚÚ¨‡‡……ĺʽʅ Ě.Óşu+Ţ(mŰv FęÔŹY—š)śë×_ĽiSăăR‹´öŮŕÁCɝŰÖčX”,ůřGýŮłgŠXą‚Ѥ°  @fŸGŊŁbĹ lÝĘŤŻ–á‡öýˆ ę§űœtr*hôÚTűěííyůĺ—9sć,ŽŽľȓ'7šrĺ2 4ňäą3:> Ą™)yňäáömă;:uî܍sçţ>wŚM›L͚5ŒĘ”*U’wŢéČ…‹ŮšóťdőÚŮŮ%Ť7ąŰˇď`g—ÇDŔՄ7qîÜ/źňŠ3ĄĄĄtîÜ)ĹzLMŕ[ŹŘËŠîkOO<==¸sçßż›… —püř -šgŘ_Š]Oć^ë""""" cDɛ7/666FwäIzǘ´~řwéňNNNŒ=†AƒžüXÎςs“•ˇąą`ůň,X°˜f͚âęęJąb/łxń’Tż+>>ţšěƒ!C†qáÂŻ4mꋷˇ7ŻźâĚťďv7*—ěű“ÎۑV™ŞUŤ°qc0?ţř‡a̘q/^œ3>ÇĘĘĘŹm~Ú}°dÉÂd˝3ŒÚŻžž™;w>ýú˝ÇśmĄxzz`kkűĚőŚÖž”&Í}e˞ʥC?­;ö˘˘˘ůóĎ?é×o€áü5„ěŘń-ÓŚ}FϞÝÓŹ7ADD—/_ŚlŮW“˝WŽ\Y^yĺBCˇsűömîÜš‹—Wƒ۟ž |“˛łłŁI“ĆÔ¨QŚM›sřđ‘dĄSJŇşÖEDDDD˛ S’,ĹĆƆ ĆR°`lmmčÓ§ŐŞUMąüçŸĎ mŰÉć9‰Œź••VVV”)S†Űˇď`mm“““a9ţ‚aHNHČ6ZˇnɀýđönHůňŻń矩Ď1Q˘Dqrć̙l(Óöí;8wîˇ~Ĺ1 oIDAT—§Úţ[ˇnągĎ^† B׎ŠWŻ.ůóżDdäƒdĄJây=bcc9uę4ĽK—6ťĚŋ—xřđ! 6`ذ÷™93ˆ#GŽŚŘvgçRÉ~ħ6ÜʔbĹ^&GŽ„‡‡‹?ţ¸Fllܓ° ,ǏŸ4:Ś×Ż_góć/Sř8Šúőëů€}űöłwď>|}›dPH’ź}7oŢäʕ+”)S:ĂŽ…&M|8wîœŃÜ7EŠĄTŠ’œ:uœK™ülöěŮ1b7Yż~“Ń{žžůĺ—_’ÍŠOPĐLR >|}}Řľë{víڍťťk†Ýţűűďwăîîi4/ŇăëřńyŸ3gNłę1çZÉ Ô3F˛œ5ŞłyółĘúú6fƍ ¤E‹ćŘŘŘpäČQ–-[Aóć~XZZR­ZUʗÁƒ‡ŃťwOňĺËGHČVÖŻßŔŞUËȓ'%JcϞ˝¸ššbkkËÚľÁ„……Ľú?űšrĺ˘M›VÍ$GŽœ”*U’}űö1kÖ\&M˙T?Ěíěěȟ˙%BBśŕččHdd$sćĚKöCŇÚښĎ>›NݰłłcůňÜťwŚM›˜]fҤÉÄÄÄЏœ9s˛vm0šrĺÂÉÉô­ŠŰˇoÇ|ˆłł3îînœ9s6Ůú´ŘŘŘĐŽ]>ýt 11ą8;—âŘącLú9Æ ÁÉéń<4ëÖ3jÔhÚˇoGdd$łfÍ!..žf͚ŕŕŕȁšté2 8z꜃!C†q÷î=ʖ}•Ď?ŸĘK/˝d˛mžžŒů‹/eáÂĹT¨PžaĂާWŻ>éÚƞ=ťcg—‡9sćqíÚ5 (ŔŕÁđńiô$hq`îÜŮ|ţůtz÷uv\]]é×ď˝DÁPN:E§N]>|(ŢŢ iÓŚ5“'O#"âŚa._ß&„„lĹßżG† !JÜž^˝ú=ťŽŽľéßżŻŃ<2ÁßżĽJ•bíÚulٲ ‹Ç˝?&Mo˜›&5˝{÷ä‡~HÖă¤[ˇŽ/^œ5kÖňő×!X[g§J•Ę,X07Ő2oŢźÔŠăĆŃŁÇŇ6´dÉRŁŰĂ'#†%+kmmÍěŮA̙3Ÿ™3gqçÎ]ňç zôx×ě^-ć\ë..5ŠXąÝťűôY˛×ډˆˆˆˆ¤ĆŒő‰^'<ˇLô˜°d{˛X=Yʁě@žččG?iW‹dŒ-LŸ>ƒĐĐ-ĎTćżŕŘąăřűżÇŚMÁéšXDDDDDţťŹ­łťˇ€G@4ód‰}˛Ä%Zâ=&L0™ř9Ižę#"/ ČČHΟż@PĐL4¨§ FDDDDD˛Íh("/œÝť÷ЧOllrŃż_íÉR4LIDDDDDDDä‰Ěڤž1""""""""™HaŒˆˆˆˆˆˆˆH&R#"""""""’‰ƈˆˆˆˆˆˆˆd"…1""""""""™HaŒˆˆˆˆˆˆˆH&27Œ‰×ŽI•Yů‰zƈˆˆˆˆˆˆˆd"…1""""""""™HaŒˆˆˆˆˆˆˆH&R#"""""""’‰ƈˆˆˆˆˆˆˆd˘Œ ctˇ%yŃeHţa™_Ÿ‘ ɂLĺO•…X>§†‰ˆˆˆˆˆˆˆź(24ď°|Q #"""""""/Š Ď>,ŸcC5|IDDDDDDDţmçĎ%Ӱ̀ƥöž‚ůˇ1'ÓxęĚĂ2ƒ™RCâtEDDDDDD$‹K)żH+÷H—ŒcâSi`<giiń—ާˆˆˆˆˆˆˆdeOň‹8’g‰=s cN“ô–MiÝÂ)éŘŞŘčč˜0RÉĘbbb€XҞ 7˝Y‰‘”˜ôŽ‹2ô‚IňÄŢż÷¤ЈˆˆˆˆˆˆdewďŢ=‰qc*çHěŠć•IĎ0Ľ”ž0>•÷ăŘ“'ĎĐ!‘Źě̙3HŢ3&99ˆY,Ě|Ď"ŃcŇĹ2Ńcś'‹Ő“%;Čł5..Ţ^‡VDDDDDDD˛KK‹+++oŕ6<bž,ąOS=e’Î-“搼§Ŕ7>•çIťńÄQüqm­ˆˆˆˆˆˆˆdEOr‹(R]¤k~SĚ cL}Q| Ď78!Œ‰~űíöŤ---"txEDDDDDD$+ą´´ˆxűíöŤhţcçr’îp&ľ0&>ë70ă0ćŃŽ]ťţ:~üř4bÉJŽ?>m׎]ńxhRâ0&qÎaîݕR[¤>gLŇ÷-L<&ž3&ńź1ü=oL6Ď“°˝qăĆŕźyóuĐĄ‘Úíۡ–;::Nîó8ŒId拉Çx蒩áKéę%ó4wSJéŽI`zž˜¸'}jēĄI÷xœS$ž…uBďS!LRéîć…1OÓ;ĆÔ0Ľ„ Š~˛Ü­\šňćúőëżuýúőY eDDDDDDDäyą´´ˆ¸~ýúŹúőëżUšrĺÍŔ]ţÎ(’1IçˆÉ°^1öž)•Mi2ßÄK҉}&÷MşdrŮżűnˇ[… ĺްąÉ]ÁÚÚŞX\\üK¤ż÷ŽˆˆˆˆˆˆˆüˇĹYZZüyďĉ§zx¸íćÉ|śü=IoJC“LMԛ4ˆyę[[?m“řľé eBSĂ+ŸľHĽ """""""ňß’Ň †’) 7Jčý’4xIüÚÜ&ľ›ĽÉ*iaâuÂY¤đĽq) •Ä$lxâ4 ˝a,­ӁŒˆˆˆˆˆˆˆüˇ%Hß)áu\’ő‰‡"%˝kRjҞ9ˆô…1 §Ȥ%.Qů„%qŕb™¨ţ¤=jH´>‚‘˙ŚÄYD\’ç‰{¸€q“ôNĐńf.A <}˜‘ڐĽ„ÇԆ.Ľ5ˇ &-ŇřnůoH) IÜ;&éŁ9ÐĚé óLA <{a‘ĘsSaLŇ׌‚0=4É"•v+ůoH- IŚÄ™xnNřb*Œ§˜Ź×”Œ1žś—ŒŠ÷LÍ ciâ{,žÓśˆˆˆˆˆˆˆHÖŸĆş¤=cR fĚ `2Ź7Lb`˜ŰKĆÔ:SĎSžd‘ Ű#"""""""YGźëSŽ”ZŘb*xÉđŢ0‰etxaN/™„G 3ʘzLŤÝ dDDDDDDD^,ńfž˙i•1§ éň<‚‹ÔćsąxĆÇ´Ú­ FDDDDDDäĹoćúřg|L­Î ń<Ă ‹4ž›Ҥö<łśCDDDDDDD˛Žô WJü<ތ÷R{žažwˆ‘ž^2ć>ĎŹś‹ˆˆˆˆˆˆHÖf)=Ď´Ţ0‰eF a‘Ž×Ďrűj…3"""""""/śřtžon—L b ó szśX<ĹgDDDDDDDD í^2ćźNi]†Ę–‰;%=ó˝(t‘ôˆOÇúřt֑Ą2;ô°xˆˆˆˆˆˆ$ˆďe¨*äČěů_戈ˆˆˆˆˆü;Ägr}ń™˝˙tHań/jŤˆˆˆˆˆˆˆdmńĎŠl†Ę*‡‚É ń˙t˛b˘`FDDDDDDD2R|VjĚż!řP8#"""""""éŻ] """"""""""""""""""""""""""""""""""""""""""ň/óăzG¸%´ŁIENDŽB`‚bazaar-org-bazaar-43ce9f7/screenshots/categories.png000066400000000000000000005111411520414637400226270ustar00rootroot00000000000000‰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`‚bazaar-org-bazaar-43ce9f7/screenshots/flathub.png000066400000000000000000004625631520414637400221440ustar00rootroot00000000000000‰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`‚bazaar-org-bazaar-43ce9f7/screenshots/library.png000066400000000000000000004706671520414637400221670ustar00rootroot00000000000000‰PNG  IHDRĚ˜q.Ňl-tEXtCreation TimeThu 19 Mar 2026 04:11:41 PM CET˜NtEXtSoftwaregnome-screenshotďż>q IDATxœěݘ\uŮ7ŕ˙ŚlzH#„@čĄJ/ ˝÷fĹŢ_vĹAÔ÷CÁŽ  ˆŇ{ÇPB‡ĐSIéŮ$ťß>'Ě23;ŰKvvîűşÎΜ2gΔ3;3ç7ĎÓ/@闠‚ĚPQf¨(3T*ŠŔ E`€Š"0@E˜é=ŞĐŐęeOȢk¸_€Î"¤ÓÉ;ÚĎ}ŹiÂ4í ôŃ:î' \Ń´@¤4÷ Đ[Đ )äţz+Á™7 ˆ¸€ĘSŃá™J‹tçmĘZŤ;Ă,œŠÄ GWÜf ťtEČĽ˘‚3•ôčŹŰ*ô4xЈŕLĽ„?:r;ťę>źş* Ň‘őöúĐL%„6Ús;zżÝĽŁ–ö\žW‡fzs°Ł;‚2kňţĘ€5oMKÚz݂3oę­Ą‹śÜŽŽZś3.Tžö†TÚršŽZś,ôĆ GkoӚZŽłáŔš×Ýa’Ö^ߚZŽ,ôśĐEg…[Złžrjß”‡ŽhłT×Áům]ŽÇëM!ŽŽ†\ÖDˆŚł/ô\ œtu8Ś3Ö_zC@Ł+ƒ2 Ř´u9€œÎ¨úŇóÚ˛LUîaŽŽ„eÚ:˝#ó:˛,Đťľ%|ŇŮ!˜śNoë2=R97ÚŰBŠŤ§ˇ4Ż3/”—ö„Lş#ÓŢŕLY†fĘ5¤Ń™a™ŽLknzk緆0 ”Î‘´7¨R×ÉӚ›ŢÚů=N91ÚSŮĽ˝Ą˜5]u¨,]YMŚ+ƒ3eš)ˇG[)í Ĺ´g™–ڎv>Pyş˛˘Lg-ÓÔ´ÖĚëQĘ%źŃžJU'wtZ{–zˇşv.ÓŢiojZ[ćŻqĺÚčhU™ŽoË´ö,ôN]–éęńŚŚľfŢ×ӝ–iďźÖŒˇeZ[ć˝W{*ľtvXŚ˝óš›ÖšykTOl´%,Ӗń5˘iË| ÷ęŒŔLW„c:ŁúLkć­1=1°ŃUUeÚzž5óš›ßŇô–ć˝[{‚&ĹÁ–ÎČ´7DÓÔ´ÖĚëv=-°ŃYUeşę|K™śV™˜€ĘŐրIKÓęRç…b:ŤúLkçuŤžŘčHU™Ög:Žim5šâË5ľLjĂ| ÷jKKŚşÔşŔLńůŽ„hÚS­Śši­™×-zB`Ł+ŤĘ´g~U+/×Ňś55­5ó:B:_W…<:Ze&?Ó\ŚšeÚœ)Űj3k2\ŃÖę+ím§ÔR8&§OëéÓĚú[Sq&ľazk Ĺ@ĎŃŃđG]ڎśSmŚ7’éě–MŠóťÄš ^tvU™śN+|)’i) ÓRk¨Î ĚÉ@ĎמHs™–Z!ľ&@S[b™ś†dÚRyŚ5㭝×%ş;„Ń•UeÚ”i*S<ż¸şLS™–;ŠÄ|€œ–ŞĚ4Xi.0SŰĚňÍUšéŠĘ3ĽĆSçwšî otvXŚ-Á˜ćN‹+Ěä‡dš:ßŢę2mšżk”˝ś„@šjÁԖ*3ľ-œŻKŤĚ´÷´ĽiĹçK§6ÎďÝĘhK ŚâiŒÉ?-„)>-Ž ÓŇv´´ÍĹç›#,˝GkC ­­ÚŇR€ĽšŠ2ŧůçë:é´šóÍMkÍźNŃÁŒś„ešďhhŚŠŠ2Í Ĺ×ŰÚĘ3ŗ+5­9Â2Đű´54ÓR—ÚVœ/δfHŠcŐgššÖšńÖÎë°ŽgtfXŚŠJk3Ľ†üj2}Š.×\Ľ™Ś‚4ĹóJmOKf ÷éH`&7ŢT`ŚšŔKqő˜Úç[ Ď4uښ°L ÍôK]§˝a™ÎŹ&“?-ŠÉÇô)q™Öśf*ÖĎ/&0•Ť­™RÓóçU-ßT`&ˇ\.Ó7•ßÔĽÂNSŰP•wÚŇüşŰY•ߎŚnssó:¤ŤÂÝ–iMU™ü LŸÔrՙüÓžyCSa›TtšÔĘéĽÍ@ďіĐGm+§çB/ľyóWĺ ľE—kޚLm+–K)u¨eSsçKˇv^ťtE0Ł˝a™üńŽ„drç‹C1}JL/œÉdú§ˇB2-yšjŃTŹ=÷ˇđ ”Ÿö„<šťLŠL)5LÉgV¤ˇ4Ľ‚2Ĺçk›XŚšëmOxŚ5㭝×f=)0ÓްLKUeŠ+ÂôIM‡gŞÓę Lnz:ŕ€†vÚi[Mœ8qËáÇoZ]=`BUUWUŐg­úŮ“@ Đý"@˛ŹŽŽöşş4ŤŚfůË ,˜öĚ3ĎqÓM7-Ě[.B/œŠIM‡dŠŰ2ŐŚ–ŤÍtfřR㭝×föX“a™R­’Jľ_ĘUÉŸ? ~č—[öÔSO]űcűŘţăƍ߯oß>“@YľŞöŢYłfÜrÉ%—Ü|öŮgż–Ţ ĂŹŹ–§Â@LŠ 4Ł™â–M)•qhŚ33–ɝooX&żŞLßTş%SnzT”[ćĆoÜmҤÉ﨎Ž>$ô˗/żţžűîýűx_z+ŘĄ™šÔ80“’Yőć*jó†”Úš)YŁĄ™5˜ié|k[/…üLnźTťĽžEÓŁšĚŔ7§gA™=öŘ냪ɽUTšëŽ;~œ‰@̲´şęL~`fUjşmSJŰ7ľ§USkĎë”ŔLßÔ9ş˛Sńů–Â2ůĄ™žyăšóQQfpŒýë__çškŽůĘŚ›nöĹ>}ŞÖO˝Td#6ÜpĂŁžň•ŻŒŻŤŤ{âŽ;îXZ?š˙›ł#ˆRœŃ¨K…YRËŐĽöeCšÓ–JťtV…™ŞVNďhX&äWŽ)–ŠJĂ3š!ŞĘDŚŞŠS§śĹ[~łţü PY–>őԓßÝvŰm˙“V‡^˘=ST›Šmb¨KMˇfjmľ™ćN‹Ď—oizŤuF`Ś=Őeš Î4š)–ÉÍ´–‰ę2–‰TTŸyóć2tč°÷&€ śhѢߏ5ňź´:đ˛"­ÍŹJ­ ÍÔ ĹĄ™Rá˜ć‚2­ Ě´4ŻE}R׊ja<ZKšüńćÂ2Ľ3–‰*2ý8ŕ€ĄK–,=GX ĽĄC‡žwéŇĽçrČ!CÓęB$‘ąˆŹEqţ˘šŹFqA””JNIŠůÖL­ÉštŠžŠc:ŁşLkZ1ľŚŞLœ?` •e>üáúĂţxnßž}''2}úôŮčÄOÚqÌw<řŕƒËÓęĚEmŃb‘˨+ĎiŽÚKkÂ2í Ćt(LÓŃ$NU+§7wă[ ʄâ¤RsŐdňƒ3–ŠŢożý†˙ç?×ţ¨ţŢ!ĐHmmíCGuän¸á†őŁ5iu{ŚÎD‹ŚşTşUS~;ŚÖ´f*ŐŚ)˙´ř|Šń–ڎ¨#™ŽŹ.S<Ţ'†gšra™ę´:0ÓwɒĽ˙Ż_ż~ű&š´jŐĘ[ ô•´:™ÎäB3ľ- Ą8<“RéŕL*š–RéđLŠńÖÎkRŸÔőZÓsŞÔ´Rý­JőĹJŠqř~iuXŚĎœ9sN–hYßžýö3gŢ)é­Î>ýRăźFJĽ;ĺ”Ę|¤Ôţ I§ë—:_kŰ4•šŢԝU\eŚřČbzT—éóĐC>|řZďIP!V­Z•jjjŇʕ+łĄśś6ŐŐľť2-TŹŞŞŞčߞúőë— ŐŐŐő_öMP †öž‡zčÉvŘáßiu#ŞËD&#żLT‘Éĺ7ęŇ[َüJ39UEÓŞRéĘ0mŢníý”ßÚvLĽÎ7Ն)˙|SC.Óˇč|ßźůń@ řÚמ6öÝď>ńÇőçű'čĺ–-[–-Z”–,Y’VŹX‘ge cbŠ})öŠŘÇ"Œ"@˝ÝŘąëL^śléżîşëŽĽé­–Kš`L*q>wÚҗRÍeIšZŽľëkľö–°éŹŔLKĄ™Rĺ{ňĎǐ ĚäZ1 ‰óoźńĆéƒ >*@/đ/^œÔşGTš2dHVuzłĽK—\˝ÖZk‘V‡e×+ß<żęÍĄ6†iňĎם/Ş)>ŸÚÜůbmţĺXŸÔšZŰŽŠšPMKŠĄü Mqˆ&ŞÉôšöÚkw– ˇ‹Š2 ,–nű\ě{ą@oًkŻ˝aˇ”—ÉHĽóMĺ@ň§ľT€ĽšË77˝]:ťÂL{Ű1ľŚşLqe™\u™ÜiŽşL߼K—˙¸oß>“ôBľľľŮÁú•+W&`͊öLÇO}útöďŇ gXľŞöŢAƒ|6­Ž(“Ť2“Ť.S\e&żŇLkŞĚ4U]Ś­UfşĽÂLg%vZ›Ɵ_*P“ ĎäŞËě*,@oa™7ŢxCXzˆŘcŸŒ}zŁČ`\{í ťŚÂ*3ĹŐeŠ Ś4Ľ­Y‘Öjóz:ó§/mǔŻjĹ2Ľ–ĽjĎ=÷:6@/Ľô<šMĐ[íąÇ䡧źlFjśŁšeR3ă-MołîŹ[ՎéůŐdŠJZ3}ĺ+_Yťşşú˝Đ˘E‹T–*öÍŘG 70`ŔÁ_ţň—ÇŚźŒFj>ËŃRř.Ä´¤Ť3-ąÓÖ; _ýĐ瓟üäž zĄššš´lٲô\ąĆž ˝Ń§>őŠ}ŇęœIżś]˛Ă‘. Ń´50ӕIž–Ęďä÷żĘŒńăט WZźxqz>ű*˝U^Ĺš”Z—ůčęÜIŤľ5őÓQÍőŸĘŸ^jčStš?˝ďžűî;´oß>“ô2QľbŐŞU čůb_}vŕŔ  #jVÖĽ…ËëŇҚş´źţüĘÚú‰u XÓęP÷Ť?B= _UT]•† ¨JŐýş­ƒ e¨śś6­Xą"â3c uuuŮŞŞŞ˛ĄoßžŮĐż˙lčÓ§Ťľ_d2<đŔĄ7Ţxă´:Ť˙ňłľožÖĽĆ!šŞTú?YţôŚ–é˜iЎTG^!šŞ<“§§SO=uŤ˝VLP^f€Žˆ ĚÜĹľiÁŇŐÇ këOn~rizhúŠ4cţŞ´˛VjŚ'С*­?˛_Úqƒę´÷f ~\š*†ş´xy]šł0ĽáƒŞŇč!}gh!™ĺ˗gĂʕ+›]6žÉkrßőë×/ 0 zRxćŤ_ýĆV7Ţxă}Šqą“|šiíý§•ťlkB6íÖÝfŠuĆ+FßXĎ6Űl31@/ż:jé‹ g‰}6öÝře @[Ě_R›^]XŰpđ‘é5éw÷,Î4ôL ëŹ9‹kŇCŻÔ¤Ÿ\šŢ?ihÚdí5}–îˇËVĽu†őI#÷źŞ tŸ˝,Y˛¤S~üŸ-cˆÖżńٌÁƒ÷ˆŕĚÖ[ošyýÉýiuVcEę˜n­(SlMܛ-ő¨j)DSŞ%S6lŘf z™ššš”ű.ĐVŠyuÁ[a™_ŞIçݸPXڌź4oUúÁu Ň´Ů~ôP‘ę÷ÝŘ‡íł•+‚2óćÍë’JÁąÎXw\ǚ6|řđMß<[2ťŃŒâ\HU3óťEWfÚ{#ŞZ9/›=ýű˜ —Q]ʓ}h‹¨,3gá[Ů×ÔĽ_ßł(Q~VŹŞKżšwq˘rĹžű4•#>˙͟?ż[Â,qq]kň3g˙ţՑÍhČj¤Śł-ĺ>ÚŞÓ5kŞ^O{nHU3ÓŤúö­Z'@/ă ;”'ű.ĐZ5+ëVˇaĘsÝăKÓÂekŹCôĘë+Ó-Ow~… ĘGěÓąoÓű-_žźŰ,š€N\÷šĐˇoßČf4|éĚ*íşë.Í^ţüSúÝď~_™1é}ď{o:řŕSU•ĐÝ^~ůĺtë­ˇĽ{ď˝/͞=§~˜M;vlý0&Mš´[Úwß}҄ °ÚÂ卦×ČYô ËW%ČöńŃý|OŐŰD+¤ž–ɉméÓ§O0`@ę&Ľ˛ůCg%ĹZZW‡ŻŤ-{gU+§Wľâ´Tč%7ô)qÚďÍÓúć 1>,Î×ÔŹ¸;eeÚ´çŇ׿ţÍě[SöŢ{Ďtúé§ĽĄC‡6š—;ţř“ ŚmťíŰŇżxJÚjŤ-ôsćĚI@y3fLŞĎ=÷|şč˘ŸŚ;UËďşëÎé3ŸůtÚb‹ÍTşW^_•…f×ÔĽĎţi^˘ź č_•~zҨDe2 *­?˛o˘÷ˆ˙͟??őD#FŒHýúuF͔–UW÷ß˝ţ$˘Ń“ŞöÍóšĄöÍa囧u%NsC*ϟÖÜijbźĽéÚҒŠ3TľrZţ<‘;č…",óń˛Ů°L¸ýö;Ó˙üĎçJ–u›:őŃô‘|<uÖ÷ŇÜšsĐ{̛7/]ýőć–^xá…ŹYŤV­Jçž{~zď{ßßę°L¸˙ţ˙Ś}čŁéG?ş [T˛ĺÚľ@Żfď}-Z”z޸m-ĺ=ښétݘiJUŃyAčĹâ—QYfńâ%­Zţ駟Nç÷ăFÓëęJéP[[›Žžú_Yő™Ë.ű}ŞŠŠI@y‹–mď{߇ŇřŁô\]żo˙!őTŻžújşëŽťÓěŮŻ%č­.\˜N9ĺ‹éňË˙Ňä˙ăćÄ˙ę?˙ůňlą.¨T+kЋŮÇ{—%K–dßköTąmą=PŠ HČƒtO=žÖioHF°ĘĚ5×üťĹĘ2Ĺ"óœœĆßęËÄğüä§éĘ+˙™>÷šO§}öŮ;Ýë _řJzâ‰' Śm˝őÖéÜs˙/ľEĎŻDńđÏdÜŁGwOrűíw¤üŕœěKŞţýŤÓ7żůľ4yň¤˝I싧žúżYĽ˜b“&íš:čŔ´ýöŰĽľ×^;›öÚkŻĽ‡z8ÝxăMéŢ{ď/X>Öë:ďźsSßžJŐPŸ€Ţ­Œöńɓ÷JÝéž{îHĺ$žƒčĄa”ąěŽďK:’ďč{Ggf„W€ÝpĂŠ­âŕÜM7ݜN>ů˝Š­^yĺ•ôŐŻ~#íśŰ.éŰßţV5Şí=Äă×ď|xjŤęęętŰm75Œzčé74ŒŸvÚŠéČ#HkRń6sÎŇ^{í™Ö”żţőoőŰđنńu×—ޏâ݉ňT– ?ţxjŤM7Ý$ ><-X°úšşpᢏęĚć›OL%Jw܉ÓÎ8ă[iҤÝZťŠôç?˙Ľá×f+VÔ¤Ë/˙[A`揳Î.h]sđÁŚ/}é ĘÉůç˙¤QXfĂ 7L§žúľ,(Slƒ 6ȆcŽ9: ť}÷ťßO/˝ôRĂüX×\˜žđ…ĎĽŽď n¸áŚú/çďM3gÎLŻż>? PFŽ•śÜró´ďžűÖ{§~ýzŇď {†o|ă›éć›omĎ{NĘÉP Ę!,“Ű:tčĐÔKE&ĽÓÂ6=ëgX@EˆƒÜÝyšœűî{ ~úŠÜ˙Ů/ƒň­Š('Q™ć°ĂŽĘ†/~ńŤŮ/ŁśŰnۂeŚL™’zš‘#GŒ5"AoňÔSOgÁĆ|;ďźSúĹ/..–)ËIJq™|ůË_ÓÓO?“şJü<÷ÜóÓťßýŢôłŸý<ŤxóꍳłéŔ‹Ďu×ݐžůÍÓŇÉ'0 ö„¨.łlٲT.b[c›įٚBnѢŊ=˘úCGŁ> çËŻL“ŤHłÓN;,óŕƒ§žćӟţTzŰŰޖ vŘaűôÉO~.kťUěćÍ{˝a~„lžő­o§ż˙ý/Yzť{îš#QZGÂ'Q97Ź˝ö˜ěG6ům›K‰j˜ç÷ă4kÖŹlü?˙š:ľGló AƒÍëŽon;3 TU4e&Ş.\{íőŠ­vŘĄĺVM2dpúЇ>Ţóž“Rg9öŘcŇ^{홀ö+UIŚ)돳N7n\×F+VŹH=öXÚy睍EŎşşşÔˇoßÔ]â1éßż˘wşőÖŰ Ć'MÚľUm˜šďvŰm—‚0ËmˇÝžŢűŢ÷¤ÎeŽ¸âŠ‚iăǏO?üá˙Ľ7ިaZ|XÚgŸ˝S[ŇÂ#<"}ęSOŁFuźBMwzýő×ÓUWý3Ý{ď}éĹ_L ,LŐŐŐiÝu×ÍPuÔië­ˇ*¸Ěo{Yşč˘Ÿ•\ß>űĐpţśŰnĘÖ՜›ož%]~ů_ł6Vń;ŽwżýöI'ôîúÇcxŁĺżńoÖ_ćֆń#<<vÚ7-÷Ż]“Î<óě†ńĄC‡¤n¸6ľäľ×^KżřĹŻÓ]wݕćĎ#=*mľŐ–éřăK;î¸C˘2ě´ÓéškţÓ0m™zR`揳ÎNwÜqWĂřÁ˜žôĽ/´xš§Ÿ~&ýńJ=öxZśŹ&;Śţśî”ŢţöcęîŻŰhů^xą 2GźÖ]sÍ?ŇóĎ?Ÿ~ó›ßeŐwâ5㳟ýtś/ćD( öíťďž'=óĚłé7ŚŞŞŞú×Ǒi‹-6ŻŘ+íąÇîŮ´–nŰ>prz÷ťOHűŰőŻé׼Ył^Í*üéO—ĽëŻż!ýđ‡ç\ţg?űIÚhŁR)qŰó›ËĆŁ˘GŹÇŻáz–ř”ď ƒLuŕfîťďţN ĚLŸ>˝Q+ȏ}ě#a™AŻÖ>đŔ Z1=ůäÓéŘcKŻ;öł+ŻüGýëĐCiöěŮY8eôčŃiŰmˇI‡vhś/ľäůç_Čţ×Çužúꏴxń’,ä­ŽvŰm×tĚ1GeaÁbĎ=÷|zĎ{Ţ×0ŻwÝu[V)ç⋞ydjýţ˝ }ík_NďxÇŰK^ç”)Ö˙o.\”ÖZkxÚ|ó‰ő_Üď—m{KďňĹëׯ~őë연q_3&í˛ËÎőăIőűü† ĘY|ŽîˆřN3>Ÿ‡ř~íœsέ˙üѯяđîšçŢôÝďţ  ,ߙuDl{WĚ,űü†Úŕ@ˇŰu×]˛vFˇß~gŤ/óń4kßĐ*ůÂ>ŸśÜr‹TnŽžú_ő ”ľ›Éż™6mZ6üýďW¤Ł>*}őŤ_ęôŠżţőoën˙ź`Zˆá?˙š.]pÁšŢ2Ł93gÎŹ?ŔůÉ4gÎÜźił˛áŚ›nÉ*}ć3ŸęŽ_Ͱ†í´Óށ™)SJĺ.Bń+ł¨„‘óĘ+Ół!öˇ/}锴ďž-ăú—žôŐ´téҒó#üvöŮß/Ů/ŞöÄDâ5ó´ÓNÍüˇäÜsĎK7ÜpSŁé{ď˝Wşč˘‹ ś%Â6Mfn˝őö˘Ëď),Ó͚UřÜéHu™œv( <ΜůjęLŤVŐ6šV[ťŞÉĺżóÓł IÎŕÁƒ-˙‹/¸ŕÂtůĺi4/ţ_ĹpÝu7dŻWgžůí’űRŹăüó’ţú׿eA›|ńeúÔŠfĂď~÷űôšĎ}:wÜťRK"÷‰OüOZ˛dIÉůq?ţńEéĎžźŃź¨Śs÷Ý÷fĂŻýťú/꿓…R[Ą›Ďţ‹âö˙óŸWgÁš¸?Űx€ž˘Ł™}čƒőďýÜ0Ÿýż÷˝˙KßřĆWB3wÝuw6­řşN:éÄÔݘ){žIֈÓO?-mžůć­Zöío?śä˘ŚB"ăĆ­S€ęŒôłŸ]X–a™˙űÚtÖYßk–)%HE_ăÎôŔS ZR‹aßúÖw˛_Ĺt‡ř"!îü°Lą?üáYuzż8@ŸŒŠWTc*Wó潞Î=÷ü‚°Lžššĺéűß˙żŹňLK.šäŇ&Ă2/˝ôrúú׿Y2,SěÉ'ŸĘöń–ž|ôŃÇJ†eÂŔýZîŽ;îlrۢbNžC=$Ńó̝[ř:•D:jíľ ×1gΜԙÖ]w\Łj)ń?.Â(ĽD¸e“M6nâ=Eą¨¨V*,S,Â$ŸůĚ)ińâōć}˙ű˙/ýĺ/m–)VSS“hoźńćԒ .řq“a™pęŠ˙[2,SlÌéӟţ\V‰Ś9oź1żţuĺÔ&_+â}Ěgœ™U߀rŐÔçőÖ:üđCÓ'>ńтJŽąÎłĎţAVŠ9~\ç‹ßWŸ|ň{ŇťŢőŽÔÝöJĐ[*ĚhËe&Úv\|ń…ŮŻŤ#ôQę\”,Ę2MýŞz›mśÎ~ů;8hăĂd qžĹÁĽý¨°É[l‘>đ÷em ^}őŐě ]ü<çŠ+ŽĚZٌ;6vŘ!Y ŕţűH—^ú˂őüřÇç54lŽ"͟ţôç,0yňniüřőędżPО"<ńÄفŔhšĐŐfĎ~-˘%T´–‰r´?üHşĺ–Ű 4ţň—żN‡rPý6Oô^QijłÍ6ÍZ€„x<ôĐ#Mö˙îérűÖ6Űl“ísq{"X’ť}!ŚE%—K/˝¸dŤ¤śhOűöŽťîœÖ[o˝ěődܸąŮühђŚ1bDöZĄÂX.^Sţöˇż7̏*VwŢywֆ­ém0;]o˝ńiçwĘ^_âŕ~NěQa"'B1Ó§ĎȖĎUmňĹžţśˇm“¨ Ł‘–$mď˘5cüŻĚ‰˙)QľlâĉiŻ˝öȞżńœkÍ{‡ŘOň+äĹ>ÁŢŘ/űĺć#<’UiËľŠPßOúóôĺ/żŐš-Â:QI._´o;âˆĂłöKÓŚ=—~ţóKÓË/żÜ0?B>¸“ŰŻ÷ß˙ßě5`=&§ 6Čöů؟BT˛šíś; .mŸŽ=ö¨´ÖZkŐo÷ęmĘ˝‹÷V˙÷çÔoűOšźÎýëßŮéV[m•ľˆœ7onöş‘˙:-Ś˘mUźŸ€rÔĄ“\›Ô‹/ž´aZŽ=S|ڈjůrßovTf⠊ÎýˇŹŠŔL[.1Đ EťŻý+éýďoşéŚ›łD ,HŁFN;ě°]VÂżš6L#GŽL\đŁěŕŐčŃcŇńÇż3;ĐÔ]Ž˝öşŹÂBsâQ[ÚŁëO~ňăéĹ_Ž^H˗פóĎ?ˇ!čżv‡vTĂÁďř€ýđĂSłƒmš‰!˙`UNiŠeߔŸüäüězrâ ZTyÉwď˝÷wK`&ÄÁ¸ /<żĄ5Ɖ'ž;;řżşĎ‰Ű|íľ×§}č‰ŢmÇw(”<řŕCe˜ űěg?Ý0~ÜqďĚŞOÜvŰ[mŠ"hňřăOdAÁŚ >źţ÷ٍÚEá€H›mśYzĺ•Wę×53}ó›_Ż? ž~Ă2xöŮgł0ZNřo.0Ž>úČôŠO}˘äë\ŹsܸqYŤ§œŰoż=Űóf=ô &ƒAŹYQ}%ż‚ITƒŮ`ƒ RGW1b­Ô٢ĽŃsĎ=WđüĎ<óL6üęWżÉ‚&;ďźcÚwß}ҁíOĹâ˙ío~óť‚iŃ2-?ŘťÝvŰÖżFí˜rr•ŘŽş*#iXg„†?˙ůϤ^xŠţý‹Ůž™¨‰˙őcÌŽßˇ>Ó0íĽ—^Ę*ü4×*-îť /üqÚtÓMmwqś­ˇŢ:]tŃ !ĄMž<)Ťž“Ż­t‹ŔnSb˙PoN´†űđ‡?VP%/Ţ/Ěô|“'Ó=÷ܑĘAg…úsĄ™Ÿ˙ü ë,h鏰Lčě$´Q{2!ÝžÁ˝ĽÂ PƢ"ČÉ'ż7ľG]S•ŽżţĆ—ůŘÇ>’Ú"Ş>źóÍ—[ÉŐŐý ŞEźţúźÔYŽ>ú¨‚°L8ę¨#Óţđçě€cÎkŻu_‹…/|ás a™œ8@yŐUWg;sn˝őv™ ™?˙ů­v(SŚLIĺ**&}ôŁ.˜á“˙ůŸO¤ťďž§ $ó]wÝÓl`fu%ލM×Œć*Sä÷5ă7š]>čGŔŻŠP`\oů~÷ťß7L‹RÓů™8¸ţĘ+ÓĆc]t`˘gŠŠEůUOzčáf|đÁ‚ń 6˜:[t/źđ‚tŮeČZř-X°°Ń2ąŻÝsĎ}Ůđă_T˙żäýé˝ď}OÁó;$Q&gěŘľÓťŢőÎFëŠý4*=EP$ˇî8űCŘx㍲Ą9ĽŞÝźţúüf3ŸřÄÇ…eJmwřěg˙§ŃuDđ0*îėęâ‰aÔ¨‘M^ßúëŻ_– ö‰÷ jÍéÎ÷ ĐŮ:3tR*4“Ż3Ă2a fʂŔ @śxńâě€rü=v͘13káňĆ –ËýŠ˝3l˝ő–%§oşéƁ™ü*])ZsmťíŰJÎŰwß˝ 33gÎHô~q0:ôć*D…Š]ŹżţzŠÜD5Š8˜_,Âs[mľez䑩 Ó^}uVłëjmx0Ţżüň+饗^Ž?-Ďf§§žzş jOhéu%*?őíۡŮe"ü!…Ü—tĎ>;-k-—ŤV\]&ÂzcÌIôL“&햵ýÉšá†Ó1ǝ:âĆo*ę,]Ą_ż~éƒ|:é¤wgÁ­űîť?k-˜ʉ˙o^řłlŸřÎwžÝPń(Ş0ĺ‹˙ËßúÖˇK^_.,“mÎr™bQŠ'ţ×OŸ>˝~˙˜mSl_ą–žěŢa‡JN/Ţî!CgUçJ9çœ˙K­ľŐV[”œďňu×ű(‚ĎĹďďcZ„ňé^ĺ˜QƒzŠřoVĽeÌé%çG{„Í7ß<pÂqiÔ¨QŠ5nżýŽŹÉÎ;ď”ĘU|`žńƛłVSńŤđîÖTŰŚÖśsęlëŹ3ŽÉö,Q(_T ˆžĎq`”Ţ+^"4ᱜ8đ]ށ™ąc›n#íŒň3óćÍOÍ8p@łóŸxâÉtĺ•˙HwÝuwAĺšöjéúÂ:ëŒÍĚG%’œ+źë]Ť+iÝv[a îC=8ŃsEť˘Ÿüä§ ă÷Ý÷@öŘî°ĂöŠ=â\~'^ë÷ŰŻkŰŤE%Ľ¨¸”Ťş4oŢźúג럋ˇĽ›ož5ű’ďQ˘MQ´+ Ż˝6ˇŃúZSm.̟_Xą)B$˙řÇ?ë˙×_Y2´ÓMí“ĹŰŻ;miٔžö~şBŠpK{Eëĺüŕœ’?P‰ëřя.¨˙źž2kÝÜz@ťăŸőđ "°FüéONçŸ˙“?pF ’ŤŽúGúĹ/~Ţ(Q,ź}ĺ+_Ď]~ů˛V]éœs~öÚkĎԙâţ8őÔ˙Íڕ•(Ţöś­ł* њĄ4WĺBiŮĘm™ň3ŃÖĺ˜cŽJĺŚ-ĎďŽ|ŃuĹW6Yň9ŞÄD+§Ř–çŸ>uśƒ>¨ 0s÷Ý÷f™iӞK3gÎl˜Ő¤"œ@Ď5a„´ŰnťdA™œłĎţAý˙č‹Ó°aĂR[,X° ťlž]vŮŠţš¸aęNȍĘ/1DpĺsŸűBýóň­jN2Ëf:ň?gŊš†óŻżţzúřÇ˙§É L´AŠPŕíˇß™:ƒ˙•´Ć=÷ܑhŹł37ÝtKýw‰ç| ˛çŚĹő\xáOS˙ţýŇ!‡tü%= 0Óăuu`Ć#42wîÜtŃEˇúĂfC.¸ŕ'éűß?ťŮĺ˘-Kˆ™qžŤ3]áškţ]–‰ÎG}TÚkŻ=Ňć›OLcǎÍ>ěžtŇűz|`ŚŚŚŚäôĺ˗§śˆ64ń˜–ú5|ţÁöÜU—Š Ńş'ßC=R–Ő…fĎ~ľÉyłfś`9r­Ôqđ˙’K~YđšťÓN;¤<0mšĺY˜¸ß.şčg]˜‰×Ż /ź(-Y˛4ꊧ˛×ű`šý÷ß?ŤDĎö™Ď|:}đƒiřB÷Ľ—^J_űÚŠé?8ťŐĄ™ËÄeň#ń˙ŠO}2uśK/ýezúé§Ć÷Ýwß&­ sĺWŃÉß'Ö^{tÁňşŕ‚óR[ýä'ÜöaÆŚă?Ž~}ťfĄhÉ6ţütŘa,Ţîh‹ÖÔ˙U PüȤ٭ĐošĺśôĂţ¨`=ńýާ?ýŠ,sŢy?n˜§UiŚĽ6Ęe"2']ö+€ŽúIPhŇă?Ńd˜˘)k˘5њ-Ľň|ň{Ň˙üOăˆK–,N=MTżÉ7mZéďO<ńTj‹E‹gívvŮeçFón˝őö‚ńńăËŻ%íłńĆĽ‘#G4ǖ.]šžy晴ŐV[ĽrňđĂSÓâŋӐ!C ŚGŠ'Ÿ,ÜWÖ]wÝÔLÉ˙R.îŁď~÷ĚFż4‹íč Ńgď˝÷N×^{]6í â˙Ŕ}÷ýˇ`9í˜ĘC„7O8ářŹR\NźFřĂO§žúľŹúSsâ˙yT–)ŽŽÁŞ­ˇîüý÷ľ×ć´ţš>}f:üđC› ‹Äü|l8żńĆ̋}´=A˝â˙őgžyFŁęJŃ˛ŠłLœ8ąŃşăq(Őžňă˙TnŰlłMŇŚ›n’>řŕ4nÜ: *U„N:ŇÖ8žťúż˙;§Qe™SNůlA™üĐLŽŇL|W°ß~ű¤öę%™œ. ÎřĐí,X˜ÚjáÂEŠ7(>@]zăăăÇ7>@mh^}uvjNЁ]u0ŸŽźňŞôüó/d˙wbˆó1-ćĹ2ĽZÝqÇ]éškţ“:ŰvŰm[0>mÚ´ôío'Ťŕ’/öťř˙Tü?jă7j8żëŽťdí’râýĚo{YŁëŒ˙íď{߇˛jpßúÖˇłefϞÝp=ÍWęýżţőďÔY"Äű}ž˙ř˘ěő'ß­ˇŢ–ydjzöŮgÓţs]ö:´lٲ•ŹŁ•PţóKZ ËÄů˜–˙}^\ć’K.MĄŠkËÔŠĘÖÓO?“Ţx㍆ń8–óä“OlŽ0G´9XÓ \î­mţű߯ʌů¸'NÜŹŃŻ¸ó›ße­ĽśÝömٸŰnť=ţ[źžQŁF5švöŮßO{îšGv€ě¤“NL-ZIÄöć;ëŹďĽ˙űÚěWů3fLO÷Üs_MŸ>#˙Ç? C Ń›îżR<űěłŇ7żyZş÷Ţ Őý÷˙7Ú*ž >ëŹŐ­8â°ÔY˘rQ|A4˝îş˛ö‡Ń’l̘ŃY($ŢS̝;ŻŃĺ;î] çăËë÷źçÖM?˙ůĽéĹ_Lx@Zk­ľ˛0Đ˙xyĂ>-" ôŽw۰ޏÎŮł_kXÇ~pNúň—ż˜6Ř`Bš3gNşęŞŚ_˙úˇŠłÄuž˙ý'§sÎůQĂ´xŸôţ÷8{ěQŮv?ö؍ÂBŃúŽ'źw€5ŠŁĄ“üĎš6LĽ>çŚĺWš)őĽ-fZÖÓ3Z;%]ýé´ÓNor~|¸ĚHúӟ¤vŘ>­IŰlłUš9ó­vQ!%~é~ä‘GÔߞSÓÁ”LrfΜ•>ó™ĎŹ#|?>͘1ŁÉë‰\Ńž%˙ş"`’ ™uԑiذaŠ3Ĺ/ŘŁŐËO˙…/|ŽÉ2-Ů}÷Éé /N55Ëłń+j˛~č1äË´t…ƒ>°~ţ]ŁéýűW§ý÷ß7Q^†šÎ=÷œŹRITüĘ˙ĹdkÄóyß}÷ÎÚ%­Zľ*›ÖĄ™h—tÖYßIŸ˙ü šޝ:őŃf/­›öŮgď‚iď}ď{Ňý÷?PşöÚ볥)_ůʗ ţçrČ!é˛Ë~ß0˙#O:éä‚ËD%›ĺ˗§Ĺ‹;§5Sî˝÷ž‚°i„{ňĂ?ů† œžńŻ&¨tńŮ%>WD;֎=zTýwbmśĹR„fŞŤd•e:–‰mnď÷ŹKZ)uf€˛ÔÖŢÁQľĄŁl;Ă>đţě—ćĹ-˘ÂCˆŠ'œp|vđą)Ń ăŮg§5˜‰€Đמöĺôĺ/­äí~ć™g… :*>„ŸyćéőŰ÷…‚ NžO|âciŻ˝ölS`&Âgœń­ôŠO}şQËŞœ÷˝ďäúὉĘ2f̘´ţúëĽW^™žÇA÷8ޑj/Ým„ é€öO?üáJ⋲Ż~ő‹Y…–ö>|xýkÁ)Y‹\0ĄŘîťOʂ5çž{~ę*t`úíoßčvFeÎđŃ=˘ŇL” ?ňČĂӅ^”UkIüÚuםë_Ó?™UMŠlGť24UÚ.şčÇŮ>Pę,%BšQIćcűHŁöe1ţ˙ţ߲}%ÚL5gĐ AYX&‚7ů>ň‘ڇ~¸ÉŔN\˙÷żv:ýô3:-0ž÷˝ďŚ .¸°Ů÷!‚ŞßűŢYŮë•cňäîms}Ď=w¤rďŃŰű˝âţÓśÖä¨i.TÓZąÍ´L`(Kqmüřu ~mžţô§?gçă ×FmÔ0/–mo;“Îm—~ń‹Ÿ§ßüćˇéĄ‡Îś?>ŔĆAľřŕżţřâ?_Ŕ×ě@Üă?‘…Dâ—ŢŰlłu:ńÄwg­Î<óť-^×äɓŇ/yIúÝď.ËZ˝ţúüŹmѸqă˛öN]!ÚGýć7ż¨.ĎÚ]Dp&‚4›o>1 pŔ~Í}š˛É&ׯ÷Wő÷ÝŻężPš'kk--śŢzŤl˝Űoż]˘2Eđ+˜ Ń–Šœ3áŔ÷Ż—ľq‰ƒů˖դuÖYťţśí”ŢůΡ7jŐÖQ%cĂ 7LűŰőęIóć˝^˙zÓ7ŤFA–8 ă7ĽŽ§wÜ>ý÷żL–9”ˇřßvŢyçŚéÓ§g­Ł2ÓŹYłÓkŻÍNľľuY˟6Ú í°Ăő_üî[˙\Ü á˛Qy(tuh&Ú/ýň—?Ż˙roşóÎťßÜćŚ feĘsŰŻb;vl“ëŠ˙Ľ_˙úWŇťŢőŽtőŐפ)SLs漖ľ5‹śl°z=цiĈ.˙óöł ÓW\™†˘mӒ%KłŞ2ťîşkúŔNÎÖŃŮrď1Ţţöc˛śhQŮ&ŁE‹gŰ˙Ťăń9âˆĂłŰŹßÝ-^ź8•™ÖimËŁŞVÎŤjĹiU㚥OŢinčűć´žEÇ55+îJ@Yř׿ţÝŞŔGž]Üu×mÍ.“ߌ)D­éöKĐć̙“ĘŮa‡UrzîVĹó[š^ěîťďIgœqVĂxˆżřâ‹=STĺ¸îşˇZ׌ťvúőŻŃSĘDwş Ń:ŕfBŤ˙ęt䑇'Č)՞iŔ€ zľčŻĐâď߁˛ŐÚ~/=@šU|énńc˘,Y˛$ődą~˜Ňz3@ˇ>|xúÚמšľeŞŠŠiqů 7Ü0}úӟjqš‘#Gd§UUU*Ň@ąőÖ[7Ş*˛Í6۔œßšéĽvŘÁéůçŸO[nšEÚmˇ]ÓöŰkÇÖSD ž[o-ÝNďÝď>ŽţuŰk5…"43pŕ€Ź}W˙ţýÓi§š 7ëWLsĺŞôRýäz•ŁÄw™+WŽL=QTŕU]ŚmZ›iŤj埪VœV51žúäć†žoNë[4ÄźáqZSłâŽ”•hró͡¤Ył^-9?>äMœ¸iýÁđCӀRk\wÝ ő Ľ˝öÚ3Ao ˝ĺ**„źűÝď)YMě€öK_ţň{ýŻŢT:ZňĘëŤŇâĺ…%f×ÔĽĎţi^˘ź č_•~zҨDe2 *­?˛o˘÷ˆ°ĚüůóSO4bĈ‚śŐ]Šşş˙ő'ľőÂ7OW uožÖć uy§ĹCjbźšÓâóĹZŹáŚÂ °Ćl¸áéƒ|ęL‡rP`͛3gnZýőӌ3ŇâĹKҐ!CŇć›OĚB{íľG ĽAŐU3@ďű8˝KR† –.\˜z’ŘŚî Ëô&î1:Ý:ëŒMç÷Ă@ӆ ¨JsŠŽšV;z×+ PT„´z§÷‰JŘľľľińâĹŠ'ˆ¨´ś:7…tM€ŹŞĘ—kPŽěť@kT÷ŤJĂžočß§*­7BjŚÜm0ĘcXébߎ}œŢiĐ AYPeM‹mˆmĄ}f ëÓÇGw(Gö] ľFŠßPtL}§ ú'ĘŰNT'*X՛ű6˝ZU˘Қ×-,Ó1öRčÁôŸ†ňdßZ+*PŹ3ŹđÝ![ׄ¨2EšZdż´ßć•+öiŐe*C´B1bDˇ~ŒëŠëԆŠăf sĐʓ}h‹ƒű¤1yĄ™!ŐU郓‡&ĘO˙žUé“Ö|›֜ؗcŸŚrä,ƒN]-ŽŁť:˝™=z°ęjeźĄŮw€śŠö-ë Ť=ӎT§SŚ­KŮ`TßôľC†§MÇ:]‘ę÷ÝŘ‡íł•+Â,ŁFJv~…ŠXgŹť;B9•¤ľu ŞZ9ŻŞ§UMŒç†>y§šĄď›Óú 1oxœÖÔŹ¸+@/4ţü´rĺĘ”‡ÜŻ ÚŁfe]šť¸6-XZ—€ň0|PU”ц‰œÚÚÚ´|ůňlhďw:ńŮ2Ú.ĹЧOĎ bUW÷ߣţ¤ś~Xđć骢ĄîÍÓÚźĄ.ď´xHMŒ7wZ|žX‹˙HĹ ‡‹_-Z´(ĺĄ+~MTŽ8ŕžîZ}ëž×Ľ…ËëŇҚş´|e]Z™;ÄŹYUőŮű¤4 ~_T]•† ¨”Ą‘¸ 4("<łbŊlXľjU6ÔŐŐeC¨ŞŞĘ†ž}űfC˙ţýłĄ§…dz#čáâŕűŇĽKł/T€ž-žÜ˜:C€á‡$ĘX_r•bčYD’  â[r(öU(3PŞŤŤU­€.öŃŘW€žO`ĘÄĐĄCSż~ş+COűfěŁ@y˜€22|řđÔˇoßôąOĆž ”(#}úôIk­ľ–J3ĐCÄžűdě›@ůđIĘL˜1bD8p`֜Řc_–€ňăçhPچšŞŤŤÓâŋӪUŤĐ=˘Ӑ!C˛ý(O3PĆâ€} ˖-ˆ•+W& kDűĽ¨*Łş”?črńŁŇLMMMœ‰Ąśś6ŐŐŐ% mŞŞŞ˛VK’‰!‚iQYčf ‰úƒ J@Óf¨(3T*ŠŔ E`€Š"0@E˜ ˘ĚPQf¨(3T*ŠŔ E`€Š"0@E˜ ˘ĚPQf¨(3T*ŠŔ E`€Š"0@E˜ ˘ĚPQf¨(3T*ŠŔ E`€Š"0@E˜ ˘ĚÍŞ­­MŤV­jb<†şşş†şKUUUĂЧOŸlčۡoĂă-˜ŠŠŠI+VŹH+WŽĚB2ĐS䇶K˝WĐLż~ýR˙ţýSuuu(E`ČD@&‚21¨@šĘUF\ž|yV…&B31D€ G`*ܲe˲ƒ *ÉĐŰD<ŢëĆ•g ˜f BEP&†ÚÚÚ˝]ė,Y’˝ŽĐŒŕ T6¨0ńëÚĽK— ĘP‘â}p.83hĐ Źę Pyf BÄ/j#(SSS“ ŇEpfńâĹiŊYp&Z6•C`*@T•‰_ŃÖŐŐ%ŕ-(ĐĚŕÁƒU›€ "0˝\üj63@i,÷Í+WŽLC† I@ď'0˝T~‰y e4÷ŃšéÓ§Oz/ďř ZľjUZ¸pĄ° ´Qź‡Ž÷Ňńžč˝f —É…e|Áíă=5ô~3ЋäžŘ2ň@űĹ{jĄč˝f —ˆ/ô-Z$,Ä{lč˝f —Xźxą_ż@'‹÷Řń^č]f ˆ/đWŹX‘€Î﵅f w˜€2ˇ|ůňlşŽ÷ÝĐťĚ@‹ňđK–,I@׋÷ŢÚ @ď 0eléŇĽŠŽŽ.]/Ţ{Ç{p ü Ě@™Šrđ555 č>ń\k&(3PŚü˛Ö ďĹ ü Ě@ZślYŞ­­M@÷‹÷âńž(_3P†|9k–÷äPŢf Ě¨.kž*3PŢú% Ź,_ž}ŞŇąÇ“>ţń¤ž}ű&čÍ † ’ Rô–ŔLŸ”šššÔŐ-Z”žůÍÓҕWţŁÍa™P[[—ޏâŞlą.čÍşă=:ĐůT˜€2_Äwu%*ËDĐeʔ‡ÍŰyçÓžűî“ŢöśmҘ1ŁłisćĚMS§>šnťíöôß˙>Řč2Ѣéťß=SĽDëŮg§eíĹ6ß|bęׯ_(wC‡MŐŐŐ *–LĽç Ě@éŽvL]tqVY&ßʟN9ĺsYPŚ9>úXúяÎO/ż<˝`ú;ŢqlúÔ§>žş[Ü_Ď<ólz饗҂ Ó˛e˲ƒq0c„őÓĉ›Ľ#F$ŢrőŐפ3fÖß/ĂÓ 'ŸşÂü7M™ňPv~łÍ6I°ŞT—\ňË,@´ŐV[Ś˝÷ŢłÍóťÓÓO?“nšĺśěüťŢőö4zôčźE[&*Io Ěř)”‰•+WŚŽôěłĎŚüăŸÓvŘaťtúé˙ŰŞ/˙#PsţůçŚď|çťéĄ‡i˜~ŐU˙H‡r`ÚtÓMSwy衇Ӕ)SęďłÚ‚é˖-φ¨ŒóđϤmśŮ*Mš4)őéŁ[mw‰đRÎo,H=Ń_˙ú÷4oŢëiܸąé˜cŽN-éę÷ę@çó­0”ÚÚÚŹ]RWşôŇ_Ö_Ď[Ąű¨,ÓÚ°LNToůÖˇž™&LXŻaZŹ3*et—űîťż~x ËôéS•6Üpƒ4iŇ.Y…Ž]vŮ)ŻŞŞĘśkęÔÇÓÍ7ߒč>ńŒżn;ví´çž{$€Ţ ŢŤÇ{v |¨0e ŤĂ2Ó§ĎHSŚ<\0-Ú0ľ§Ź|„fâ˛_úŇ׌E ž¸ŽőÖŸşŇźyóŞŰ >4vŘĄ%Ű.-X° ÝpĂMYĽ™iӞO›lňBÚxă]ořđá騣ŽH˝MźgWšʇwďPş:0sçwŒďźóŽY‹ĽöÚvۡĽvÚĄ`Ú]wݝşÚÓO?ÝpţŔ(– Ú8řŕł 4á™gžMĐ]ýžč\*Ě@čę/ß§L™R0žďžű¤ŽÚgŸ˝łĘ2o]ǃéřăߕşŇo,ĚNű÷ď›Ö^{íf—6lXÖhůňĺiŕŔM.÷ýSO=ž{"Íʕ+ӀŇ:묓&NÜ,m´Ń†Y‹§ć,Y˛$=ůäSé•W^IŻż>?­Xą" 4(­ľÖđ´ńƧ-ˇÜ"őíۡäeŁU]]]bÚi§Óă?‘mĎoÄzVĽ“N:!ť-ů.\XżÜăő×7#;ˇaذĄiÝuǧ­śÚ"3&ľFl÷#<’^z镴hŃÂúűľ:ťl„Š&LX?ľÇŹYŻŚüăęěüî—6ÝtӔ/w{ŁuSÜޙ3gĽG},˝öÚkiéŇĽŮýśŢzëĽíˇßśÉ@TΜ9sŇO<•f̘žÝ–U“ƏŸśŰnŰ,8•óꍳÓUWýłŕňłfÍN?˙ů/Ć?řÁ÷Ľęęę‚e:ňŘv–¸_â>z饗ӂodíƆ Üđx;śĹuźńĆŮ:˘T<Ö}úô­ŹG×?Öo˞ă%śńŮgŸMłgĎN‹/Šżoú¤Áƒ‡¤qăĆĽmśŮ*=şäĺâőăVżN}üăÉîçG™šŚM›Vż˝‹ę×Ó/{<7Ý4îó-=N˝žœxü{ěńěvĹžŻńřˇNý}żUÖ~ €Ę!0ĺE`Ę@mmmęJłgżV0ޑę29QeŚđ:f§ŽÖż˙ę8$Ʌ+šłŐV[6;? ˙ç?׼yó^/˜žté˛ô /fĂřńă˛j6M]Wˆżýö;RMÍʂéˆaÌYé‰'žLGqX}ҤI“J^Wü:úĆoʖŮa‡í˛j=ľľŤęoĎôŹ}Uܞ|8ŤÔ˛ŢzăSW˜1cf6lźńFi›mśÎ*äÄcňôÓϤG}źţś×Ś›ož%xâ Yş|ąLl_>|hÚnťí˛Ę8ąÝłgżšU>Š€É-ˇÜR˙\™ÖZkDöœ׻ޞ]ćoť2;JEÇstĂzű÷ďßpž3ŰöŠj=jŠ Kż~}Ňć›ožÖ]wÝl;_}^zěą'˛€QÜ_a=vo´Ž¨örŰmwdçŁEŮ[lQżŽuę×׿~ŰçeʍČґ*3qýç?×f{ÂZk ˞›ŁF­~ˆJ@Qĺ%ž›wß}oö|‹çyS" ÷kTď‰}!ŞéDĽ—0ĹmŽ}öŸ˙ź:üqYEĄŽXOTxşá†łű>öľ¨ÄűBÜ÷óçĎϞQqč‘GŤnÉŞQĐű Ě@y˜€2P\%Ł4Ţ掿 Zxꊧ˛K´–ůă˙œ ßtÓMZ݆(玝îɘGâ€öË֑/řßyç]فőÎD ¤mˇÝś`™ŠSÍî‡"qÄáÚłD;˘[o˝= ßDĺ8áR",•BJ…B¤żďž˛óÆ IG}TAU¨¤mˆţůĎe!8?qâÄ4jTăpÔ…‹łPĂqÇ˝ł 2JlonżýÎlËUä9üđĂ ś7îă 7ܰţ9vUV9'Bf3•Ąßł@%듀ŻŤż|*ůćÎíx5˜âu >,uľˇzč!YľˆŠ‡žšţţ÷ŤŇď~÷űtÓM7g5˘Ks˘ĘD1B„6ŠĂ29Ńć&‚%!Úˇ‹ĂqÇ˝#vŘĄ9čÉɅ J‰ę“'Ojr~\„ ÂP˛…NGöÝwď4bÄđ´Í6[5ےiĎ=÷,ŮF(Â#GŽ~̘1=u•ęęţi×]w-9/.TY˝ 3Í_¸pAváâę3aäȑéŘcIřŔÉŮşÚŁ3Űöxá…Ňo,ĚÎďłĎŢ%ƒOQídżýöi¸ŻŠŸŁńĎľrŠű:?,“šöß˙­u´GT˝y˙űON¸ýşömT‰)ŹľÖZŮr!ځ5'Ú 5ŐN-B>œ ňYźxq—Ź'l!‚FĽÂ=qßG;§÷źçÝ]R]€žI`ʋŔ ”Žţň}ěŘÂĺš -VňEUîŞ#ňÎw›g XݒiéŇeY›œhŁóŰß^–nžůÖúƒŢ JŽăšçžo¸ĎŁŐJS˘eQTi Ńú&Şź‹ CTĐhJßžo},‹mlĘşëŽËŽŻ”ŘÖçž[݊*Ţ7W#B'œp|VŠ&‚#ĽD+˘ć*ÇDŽŐ7˘-TWˆvOĽ‚)­~ŒsŹ72duXhćĚ%“•cÚŰŽ+§łŰö˜6íůě4[QľĽ)D7n\vţ•W^)˜—ŤíœňĂ=×1˘!ĚŇ^ń˜EđŹT€)'÷xˇt_ĺöšŚlšĺć çŸţ….YOŘBěÂ+%ÚŚ• ŽĐ{ Ě@yђ H;í´Sš2ĺá†ń[o˝-~řĄŠ#nżýö‚ńíś{[ęNŃ%‚3űěłWVÝcúôééĺ—_NłfÍÎZŠD›”iÓŚĽI“vmÔJ)ż:NBŢxă&ŻgŕŔ çŁýʈMˇÝ‰Ę6Ńęgá…iѢEiÁ‚…Ů6ĺÔŐŐ6yŮţý›wDő‹\ĽŚŞ´ET–iŽúL´Ę‰ű'Úuśüűľéů Ҋ+͋6BŃ6* Ńć'ÚQM˜0! EˆĄ+täąmyóćf§ŐŐš}~†AƒVߗD‰íĚ…r—‹TSᤜlE›łÎ#ŹűKÜ_‹/JsćĚkXK÷UqŔŻńüˇcÍÝ7YOTŚÉľeŠޓO>•ľaŠý/‚TÍí?ô 3PâŕkWţbuĎ=÷H—^úŤ†ń)SĘŞĚlťműB.S§N-ŕÄöG‹Ÿ5!Ž;ŒÇíw˘"É3Ď<“|đáTSł"Ý}÷}iĐ AiłÍ6k¸L~Ւ?˙ůŻŠľ–-k\#*œ<účcYxbáÂĹŠ+,Y˛´á|gT´č ű;˛ fˆÇbʔł6UQY(†aŸőÖ[/Ť>ÔŃpQw<śMÉ=G# ÖÖçh.0łtéęçÍŕÁCZź\Šö\mQ[[›ž~ú™Ź ÔěŮŻŚ•+Ű j)LáŸhéűwţžŃ™ë‰PĚ!‡œ… #ˆ4cĆŹlŤŰ4Ë*ęD[§Ś*CĐűL@y˜€2ĐՁ™hżłÓN;dA™œóÎť ţšm`Dňý肂i;î¸]łmcşSřß~űíÓĆoœţţ÷+łƒá<đ߂ŔL{ďëâöD¸íśŰł*9#FŹ•ľÉ>|h9rTVńäꍯItŽGmžůÄŹ’Đ+ŻLOŻ˝6;­Xą* >Ä´6ŢxŁtŔűľX]Ľ”5ýŘś÷ĺ`ŐŞUĽÖ–Z—öŠŞ6˙ú׿łpONQF•† žľ×ŠVadË›šSú6oďęeš;nŮŃőÄkډ'žľp{鼨^5ëÍ*>+ÓË/ż’ =ôpV­kذa €ŢO`ʋŔ ”îřňýcűpúô§?ßxůĺééŒ3ÎJ§Ÿţż­ÍDX&.óĘ+oľnéÓ§*}čCL=M„˘úĂă?™,X”UŢČUœČUӈJüŕR{D›¤\ bŔ€ę´űî“ÓFmŘPÝ#'Ęo‘í€XmȐ!i‡śĎ†A͛7ŻţšůJzôŃÇëŸ%éůç_H÷ßšśM‰ 6aöěŮ펈4räČě4Â,ĹՑŠEő”öŠę+aÔ¨‘é ƒ,– ­˝żfÎlţ9OΈ#ş|=ů"ˆŻwÇ{tZýő˛iq˙ś÷u€ň˘ ”ďŕ  tחďQe&Z3ĺ‹j1_úŇ×Ó׿~jÖVĺĹ_ĘŞMÄçcZ̋eň+ËäÜsĎ}é†nL]-*EDX$†ŠSmą…ĚŠ+˛ #!*ÉäŞĘ„M6٤áüÔŠ5ťž8č÷CńÁţXÎȑMlá…SGE$ˇÍŻž:;šUV~ó›ßf[kÂ5ĺ&Ş‚D‹œťîş;ŤSʀBĽBš_‡7•CéÎÇś)›nşúńŽ@Ď=×|e–iÓŚeUOŠƒRQ'ŹZU›üń&/?wîÜúËżšÚ+wG˪料1czj'žx˘ŮĐWě˙9šŰؙë‰ËD˜&ZšMŸ>Łäeă94~üş ă˗w]x €žC`ʋwđPúö훺C\Ďi§švŢyÇFóŚLy8ţOŇÇ>öŠôöˇŸ q>ŚĹźŚD%ŽsÎůQ—‡f˘R´{ ŃĺĆon˛bE´M‰ŔH„ ÂV[mY0?Â7›mś:Őj{ěń&×sÝu7¤kŻ˝>ýéO—|_k­ˇÂŕ(%ś?ôPÓ÷][lťí6őßęx7ß|sÉ6;&šůć[ł63–ÉUĽéM"-p˘íŇ}÷=Pr™×_=˝úęęŠ)š*+ůŞŤűg§Mľ*ęŹÇśoßŐÁœššĺmžżńĆĽáĂWˇşýö;› IE(ěĆoI˙ü翲ű%_„nr•v"üĄšbŃŞ,ž3í­brŐYbýń,Őmnşé–Ź˘SkD+Ş¸ÍĽśéţűČZ!…7Ţ(ŤžÔŮë‰ĺŻťîşú×˝‡˛`VŠ×™U=űěęęEŃ–Žš°˝Gw˝g:GżôxÝůĺ{>ëŹ3Ň%—ü2]yĺU ­gZ+ďąÇîéîťďÉ*W„\h&DK–Ž2iŇnYp`ńâ%YPŕ•W^Nl°AVM¤_ż~ŮÁú8>}ú[-u˘M̎;6íšçiÖŹWÓ˘E‹ÓwޝUńŘx㍳–+ąž9s^ËÂ4> ťîşKÁă´ŢzăÓ°aC˛ƒň<0% iD•ЁeŐy^~ůĺ4mÚóفô×_ďxť–%ěśŰŽő÷ű˝iÁ‚EéŻý[ÚrË-Ҙ1c˛jsçÎËś7Wéb‡śk˛5N97n\ZgąŮóŕ™gž­üډ'6˙űië­ˇĘÚdE˜ćő×Wßońü1/ŞĐű Ě@y˜€2ĐÝ_žÇő}ň“K|`úĹ/~•…ZĄŒwÜ>}řĂL›o>1ÝrËmé?řÝš‰ŢG}dýuߚđŽPDb(%B{ď˝g(¸ßţöc˛ 2q°?ĽÚŇD@hҤ]UЉ`Ĺ!‡œU˛YślyÉíXk­aé€öKűەŠ3lťí۲ÇnuՋ•é‘GJˇ“Š B;ďźSęâyxĐA¤˙űÚ4oŢëÍ>n“'OĘB&Ĺâ~Œ°Mf"\CˆĘ2kŻ˝v§=śńœšëŽ{˛ŔËM7ݚM;á„w5Tdii~ƒŽ:ęČtýő7da”ŚžëČöšRŠM6Ů8íťďŢéöŰďČöѧžz:ňížűnőˇgD‡3q?FíŢ{Wţ™4i—l^k3ťíśKýí]šľEŠ€XąĄC‡¤Ă?´ ÍZgŻg—]vÎBIĎ>ű\öšçžűK^Çf›mš=Ϩ 3P^f  Äúř>żĺOwˆ–-gŸ}fš9sfvŕ~ʔłßQ‘!ŽG( *ZD; =÷Üłţüú —Ýoż}˛ÓîÍD%‘cŽ9:ŤĘUff͚•)‚‰ƒßăǏK›l˛i8hN,{ěąG§_|) ̟˙zvP?Z :,­ˇŢşYĽ‰¸ÎR" p ǼG™š­#ޝDЍA…íśŰśÓÓ¨fąţúëĽ'žx˘ţ>˜ž]gÜ˙qđÝuÇ×Ďß2Ť:ӛE•¤wžóíYőh™4wîÜŹşLT‰v[&Ź—śÚjŤ&ˇAƒeaŠŠEľ˜hKÔż˙챏ŔLčŒÇv›mśÎ.•.\˜íăÉbZšƍ['xâ oŢÖo,̞ﱽ#GŽČ*,Ĺs˘T(,'ŞŤÄz}ôąŹ•Tܖ>}úfϓíˇß.ŰŻ_zéĺÔűěłWP‹Ű2{öěěńˆmŠj>Űm÷śúçćşéÎ;ďjŐş"uŘa‡ÔoďŁőˇűŮúŰüFý}Ó/{<7Ýtă챍Űߕë‰Çâ€öŻżďśČ*äD5޸ß#ˆŻăĆ­›ŁZ•!ţ7Ä{v |TuÂrU%Î7wZŐÄxnč“wšúž9­oŃóâÎ>55+Z÷Í”Ѝf™ËMqĽ™•żůÍodŐ]Za˝\ĽŤ“O>ŠĹę1]˝(Áěí@%¨ŽîżGýI|áťŕÍÓUECݛ§ľyC]Ţińšoî´ř|ąććeDŢ L´ŚbBO•fžöľŻdUYr˘ŇĚOzq€Ţ \ߍ@%˜€2íK˘…H9*š8p@€rďћkôLýP6â‹řrlË"43p`uşč˘‹ł_ŕ~éK_HPî„e < Ě@)çŔL˜y§šĄď›Óú 1oxœÖÔŹ¸+@XślYZ˛dIÖŹÁƒ§&¨$ŐŐý÷¨?Š­źyşŞh¨{ó´6o¨Ë;-Ră͝Ÿ/ÖÜźŒ 3Pfâ ů>}ź•€5)ޓ Ë@ůň-;”!_ĚŔšĺ=9”7(CŞĚŔšŁş ”?ß°@™4hPşŸ÷âPţf L 0 UWW' űÄ{đx/”7(cńËÖŞŞŞt˝xď­ş ô3PĆúö훜€Žď˝ă=8Pţf ĚE9x%á kyß ˝‹Ŕ ôC† Iýű÷O@ç‹÷Úńžč=f —ˆ/𕇀Îﱅe ÷˜€^˘OŸ>ičĐĄŮ)ĐqŢc@ďĺ]>ô"ńë×aÆůB:(ŢSÇ{kU wň-:ô2šĐŒ/ö }ź§€ŢO`zĄÜüýű÷O@ëĹ{hačýf —Ę•0`@Z8€ĘĐ/˝Ú!CRż~ýҒ%KR]]] UUUĽÁƒ ›@˜€ _üGhféŇĽŠŚŚ&ŤUWW§AƒiÁF`*D:thZž|yœŠ­­MPŠ˘íReT•€Ę$0&İlٲlœ ’DPfŕŔŮT.¨Pšƒš‰Ş3ŤV­JĐ[EĹĹŽ ĘA`*\.8łbŊTSS“ uuu Ę]UUUŞŽŽÎ†ţýű'€ b2dHš‰Íʕ+Už ŹD%™~ýúeďm#(PŠŔ ĐHîW¸Ąśś6 Í䆏!ŞĐäč.Q5&7ôéÓ'"$“b %3@łr!”° ˇ˜ ˘ĚPQf¨(3T*ŠŔ E`€Š"0@E˜ ˘ĚPQf¨(3T*ŠŔ E`€Š"0@E˜ ˘ĚPQf¨(3T*ŠŔ E`€Š"0@E˜ ˘ĚPQf¨(3T*ŠŔ E`€Š"0@E˜ ˘ĚPQf¨(3ŚŞ*űűćiJuuŮß7O{?€ RUőVPć­iŮßě|]¤ff*Dcra™šs_OóçĎĎΏ1"=˛¨âLď%0P1V'b",3oŢź†ŠšóšY˝LďNĚôIT„\™\e™|šiĹíšz#f*LmmmŤŚőV3T*ŠŔ E`€Š"0@E˜ ˘ĚPQf¨(3T*ŠŔ E`€Š"0@E˜ ˘ĚPQf€ .L|x“óŤŞŞŇ AƒŇ˜1cŇĉ›Ś=öŘ=pŔţŮ4ŢňÜsϧ÷źç}ÓŽ¸â/iÝu×Mĺî˜cޑfĎ~­aük_űrzÇ;ޞĘEŸĐuuuiɒ%饗^J7Ţxs:ó̳ӹǞ3]~ů_Rmmm€žN`č° ŚsĎ=?}ăßL555 z2 U&OŢ-vÚiǴᆌęęęFËÜzëíéĚ3ż› 'ë—ZpÎ9?H{íľgÁ´E‹Ľn¸1]xáOÓ…‹Ś_ýiŸ}öI|`€žH`h—ĄC‡ŚˇżýŘ4iŇnéCúhš?˙†y?˙ůĽé ƒHUUU%/ű /ŚŤŽúgš2ĺÁ4{öŤiɒĽi̘1iƒ ÖO‡vXÚ˙}U°9őÔ˙M7ÝtKĂřf›m–.ťě׍ÖýŽw—fΜŐ0ţ˝ďUżžý –ůĂţ˜.¸ŕ†ńŘÎýëŞ4jÔ¨ô׿ţ-sΏćzčÁéŒ3NOŻžújúĺ/“î˝÷Ţ4gÎÜ´ÖZĂӖ[n‘Ž?ţ¸4yň¤ÔQóćÍK˙ţ÷˛*=łfÍĘîĎ#ÖJăƍKűíˇO:üđĂŇȑ#[\Ď=÷Ü›Žżţ†ôČ#Śšsçf-˛b=›mśiz:ňČ#Ň Aƒš]G<.ůË_ÓO1ÜsĎ}é׿ţm:űěłŇvŰmŰhšÚÚÚ,HTüřźúęěô÷ż_‘î¸ăŽúÇć˘Ô’şşştŢy?N—_ţ—ě|ž fĂÓO?Í˙čG?œ>üá&€îÔ'tPT“2dpÁ´{ッŃrQ%ŚTXŚŘŒ3ŇG?ú‰ŹÂIÎ{LN}úźőÖ%ÂS§>ZpšRa‘‡z¸Ń´ äŰkŻ=RSVŹX‘žň•o„eŠEĺÎ;ďJí÷G„ŠĂ2Ŗ.]šžő­ogpŠĹe?űŮ/”źýĹ"8sĘ)_Ęîăb—^úËfŸďœqĆYYđŠ9ąž?˙ůňFa™bńF5˘Rˇ  + ĚÖż˙´ăŽ;L‹ 0ů"í†ňm´ŃFé”S>›N;í›é˜cŽN}űöm˜­„˘bJEB´#Úzë­ ._\)ŚT`ä™gžI‹/n饗…_˘UQSnťíŽôüóϧÝvŰ%}ĺ+_LŸűܧÓŰŢśMŁĺţđ‡?Ľśzúég҅ţŹ`Z´zŠŠ+§Ÿ~ZúЇ>†V0?*ŔDŤŁ|ţó_ îďx<˘ęÍĎ~vaúÍo~™žôĽSŇŕÁoš–,Y’~űŰߏăĹ_Ş_öwÓ˘UՁđ…ĎĽ|äCiܸu˛RT×iJÝEK& SŒ=Ś`<*™äD%‘ßţö˛‚ůŰlłMşč˘ Ҁ˛ń#<üᏥ… eăqřĂÓˇžőż ËDčŸřXzńĹÓ /ź”Ţýîă B)[ląyÖ)‚)9Ĺ÷Ő5×üťQĺ˜SOýZ:účŁĆO:éÝéSŸúlBjĘôé3UËůęWżœ&L˜:th Q1hă7J›l˛Iö8tf€N1lXa%”ĺËkÎG˜$Úůäűěg˙§!,“ŐLŠ+Őüç?×5œ/Ž-›"@fÍz5͜9ła^rrňC2?\؎i=šnÇ"Ôńя~¨Ń´“N:ą`Z>ćΝ›Z+*çW܉ N~X&DĐ$;ůnšĺśúűwyĂřŽťî’UŁůöˇż•~ýëKUp Ţ×óçż^0•tňEü°Lˆ°KTŘiN˙ţóŘW]uuA0(Dh&* |ň{ëƒÝŰ4č(f€NąhѢ‚ńü€ĆłĎ>[0oȐÁiťíś-šž=÷Ü= ŘäL›öVűĄ‰7Ë*ÂäÂ7–yꊧӜ۞­ŕ2뎝nÚwß˝Óc­ŽF“ßş)ŞÍ__sF•†ŢhúúëŻ×hÚŇĽËRk˝ňĘô‚ĐKˆŕH)úĹ/~Ő0-•f̘™Ug)Á3f¤çž{> ˝úękőç§Ľűď˙oŁĺň凍r×YĘÎ;wŠm(%?n¸aVí&'*éüýďW¤ˇ˝më´ůć[doâ|fĚč†óŻ˝VXyeěŘu˛*-ĽŒW˘˜?˙Ź:I˙ţýłń¨sĺ•W5ĚôŃGłŔL~(f‡śËŚĺ<ţřiĺʕYČăĺ—_n˜UM˘:Ksúőë׌é­őÚkŻ5šśÎ:cK.[jz\~ă7jŸ9sVúË_ţ–ŽžúęŹýR[ÄýRÜFiuÖ)šlmłÍÖ m~r•h}ôą‚Ëî˛ËNiŕŔiMčČ}R|ů¸íď}ďűÓţđÇFa™˘Œ?>Ť ÓYZÚö­śÚ2]vŮoŇťŢőδÖZÛ\îůçŸOßűŢ˙Ľ˙ýßouřţh f€ťůć[Ó˘E‹ ŚíśŰŽ ç×^{tÁźŮł_ÍZ•Ş23kVak #ÖjžäÖ;`Ŕ€†vF=öxZ°`Azá…–‰pH\&ŞĚü÷żS˛iS§Nm´MľęcÇ6Ž3kÖŤiäȑ%§7uů¸Ď8㬂Š/&LH'œđŽ´Ă;¤őÖŸľPşéŚ[î‹b1?‚CůUf˘­S)Žš3gNjIlßWžňĹôĽ/’žţ…ôÄO¤Ç2 8=óĚ3ËŢxăÍé°ĂîL{ď˝Wč*Ě2sćĚtîš?*˜íśŰśa|âĉó/^RP&ßíˇßY0žŮf›ŒGXfçwlőŐŮŮerJÖ]wÝ´ţúëgç'OŢ­ašG™šž|ňɂuE{§5eýő×ËnKž;䲡ß~GÁx\Ə_Ýşęšçž/ˇDđ忸8üqő÷űfٲaɒũ9ë­ˇ^ŃuŢYršűîťżQűŚŚĚž=;͟??mşé&騣ŽL_ýę—Ňď~÷ŤôóŸ˙´ ŚLy(t ]-Z”ŽźňŞô|8˝ţúü‚y˙řGłV@9;î¸C;ví‚e.¸ŕ†*19×_cŁ Ía‡Ň躋+Ă\qŕ ç÷Üó­ĚîťżŐž)*Ń<óĚł ăÄ7nÔUňoNM͊†óƒ JűîťwÁüË/˙Kzůĺ— ŚĹř_ţňׂiűíˇOCŘ&Şëä:tH>ź° R„‰Žšć?Š9{ď]xŸF¸čoű{Á´¸Ž˙ř˘f×síľ×§~ôéŔIÇóÎtĆg6jˇaŞ1cĆL2dpč.Z2-úň—żÖP­%Bó潞ŚOŸžVŹXŃhك>0ňEëĽ÷ż˙ätÎ9oU˘‰=řŔGŇŃG‘<~xjú÷ż CQ)ćŔhtŤ+Ăü°aüŃG˛7šáüf›mšufĎ~-ŤD“oŻ˝şśşLTz)vÉ%—Ś}öŮ'í˛ËNiÔ¨Qéä“ß›ľJŠ6GaÁ‚…YŘäďx{š0aýôŇK/ga üVRQ™ĺ=ď9Ša|u [;͙37ýčG¤÷ž÷Ä4zôčô /ŚK/ýEš2ĺÁԜ#Ž8,]vŮś%Äăeśß~ťôĆ Ň5×ü;˝öZóí˜FYđxÜ{ďýéÔS˙7ŤxĽxîüýďW4jůĄ*€î"0´Ę=÷Ü×â2Q1ĺ´ÓžYrŢqÇ˝+ _ÜvŰ[í…^xá…&+–D0äĚ3żUb)Á‹M7Ý4M›6­`úęvM;L›đ÷Ľ_üâW Ó˘2Ě­ˇŢž 9Ń^kɒ%Y`Ş”]wÝ%{ä_ćć›o͆ŚDŜâÇ  +iÉtŘđáĂҗżü…ô˝ď}7 ş4ĺěłĎJ'žřî×7~üřt鼧­śÚ˛ÉeJUˆŮi§Zĺěžű¤FˍąVÚf›­SWŠ–LŸřÄÇJÎËŻŔ÷Ç駟V˛"MžqĆéYđ¨Řé§˙oÎiJܟßůÎéŠ%ůȇš}|FŽ‘­gđŕćŰ'}ç;ßN‡zpjIÜGGyD:óĚ3@wRah“9Dxcíľ×N›ožYVÁĺŔ÷o1đúőë—N9ĺłéŘcNW]őĎŹMĐěŮŻŚ%K–Ś1cƤ 7œ=ôĐtŔű5ź {íľgúÍo~W0­T՘ÝvŰ5ťŢüVC{ěą{Ö&ŞŤ{ě1Y뼿üĺŻéÉ'ŸĘZ+ 64ŤÜ’ďđĂM“&횵<ŠĘ,ŻžújzýőůY@eܸqYŖ#Ž8ź~źt(fĂ 7HüăeéřSşýö;Ó̙3ÓŞUŤ˛ L\öä“ßS݋ZÜ޸Oâń‰Ë\~ů_ŇO<™ćΝ—mÇîťďž>ň‘ŚącÇś¸ž-E¸ç„ŽOW_}MzřáGŇkŻÍÎç¸ýcÇŽ“vÚiÇŹ TTŮčnU°\U‰ó͝V51žúäć†žoNë[4ÄźáqZSłâŽ@“úôYŮxć™i%çOœ¸ivZ[[Wr~uu˙řsmý°ŕÍÓUECݛ§ľyC]Ţińšoî´ř|ąććeT˜ ˘ĚPQf¨(3T*ŠŔ E`€Š"0@E˜ ˘ĚPQf¨(3T*ŠŔ E`€Š"0@E˜ ˘Ěđ˙ŮťŔHÎúîăżŮŞ.¤ëýÜŰů\Î6îŘăŽí˜ŢB !ŕĆJ) $慡H0؎qď˝wűΞłŻwőž}Ţ}Fž˝ŐjWڕvĽ]éűy3žşłŤ˝íŁßü˙ł Ě*f0Ť˜“fŰś€Rł,KĹ@`Œ‹@ ĘÁxăTj@ž̀QČ eŽk š˜ŽBC2„j0ň äažéĚ0Ëĺ žäˆ!4€é`Â/…śgr'8 3ĚRŮĆdH$ĘAśq,Ç“ó˜ô Á`˜`–É'(cÖłmË÷|cmň‘+Вk{ć _ć8÷Řl!‚3Ěnf˜EĆ Ë¸ f=;ëf9}{úq@9p+˸Áłn–ÍÜëőŽŘnƸ˛ľj"4ŔěC`€Y`ꠌ™LH&‹Ľś§ĎÓŸk9ßçĆ3^€%[Ľwť{×{Œ™ű|>'ßČ?ŁĽ Qm€ĘG`€ 4^X&;_ěÍźśśfևe ÄLö| –T3†fĆŇSĄŻ×;âB3Ěf¨0ă…eLEӊÉT˜1ĽcMIŮŮŚŘ™É>?'•ÁŒĽE"Qg|Íăń8ă:fžŽĐ 3ƒG ˘e†eLUó…~¸S­fƒĚĐPš)÷×€ý̘š{Sšk3ˌí0ó˜ ‚d~!7_ÖÓ÷™ÉmĹÔŘŘ0ŁďnŠäA XʗS3cknŰóĚqœô19ƒ1**\zř´a2“é­lÚ1Í431hBx ü˜ą53Ć掷1†ŔĚă¨H٪˘2ąfŢĐPŻ™˘ŘƒĽÔ(F5Ÿô×Fďk€éeĆŘşşş17ŸĎçŒÝ¸c6flÎăážt**˜ů’îöP6%bÍdî|1SĽ+F°e*ďřÉö\“ ˝¸ç#80=Üq6wÜ͌ӸAĆl¨|D_¨@Ůú$ťĽakkkTÉ&SÚ6˝4n9”Ç-ĆëĄÔ/Ŕô1cmécoé2Çč@eĄÂ ,=Œaž´'ˇ8ý•+Ńd%Óńźš‹h2-—¨80ő†ÇچÇށ@j,Ž1**ŒœHŻá‚3ĺĂŒš™ąˇąĆć— ň˜ e5̝-F91/$´2Ů ĚXűÍ{‰D˛–Đ-”yż˝^݁Ŕˆ°Rćy'Œ™Hp†Á€ârÇ[Ü18c1T63T 7Háśe*wĹŞ3Öţ\űL8&ŽxϊĹm‰eÎďŽ˜šßďwB4éÇš˛ ˘äť?ŸjJǏŁ-•Ŕ Ě R˜ĐF9gŠ”)tŸŠ‡G˝'&Ô288¨-Ą=m×öxżúźCŠzb’×ôžNpx’ń$“ü?ł<¸cqňŻ z$<˛““âŢää‘?áS˝ĺ×ĘjżÎl­Öňú*ŐÔÔ8aóüf2&ŚňL0t*ŃdžćBĂ1ůghŃP\îSî2¨|f˜fWX&sťY…B#Ú,™pLßĐ íŃąvőxúeůc˛qińy2ÎmĽţóÚşőÚsy㲒“üQg5š¤îäô´™ş¤D[ňתˆ_őąZRWŻ7,öŞśŚĆ ј×â†gŞŤŤSA–ńÂ1cľj˘Ú ŔT#(ŔLB`]>a™beLť%3™íŚ‚L__Ÿ^ôčA˙.őŐôČŰ׎KVMxT0ŚŘ<žXň7Ť˜4¤›őÇ'ĺK„´¸ŚW—-őę 9^Ő××;Ąb1-›ÜśMš‚3ĹŞ6Ch`$3TlA’r+;™°LžŰMť#1á“ŢŢ^uFt‡wťöŐuČßl)R"diwgŠ*3Őźľƒ úŁ w´hk8Ś˙ˇQ˛â~­Źč=Ť<š_ďWCCƒöńů|ŞŞŞRúĎYhp†Đ ŔÔ¨„ń93T¨rü">Ţk*´ŞLć6ÓvÉeúűű588¤ű{ôRý.ůšÂňXű;-őZjˆËňĹ5]<¨Şćś)ÜÖ*[–l_T›ÂQýó:KA;Ś3ç…uÁRŻjjŞUWWçgLť&cŹŕĚDŤÍš(ĆZ¨|fŔ¤ťŞLśŠ2Ś‹Š&38Ň]ÖN˝Ú¸[ÁŞX*$ăę´ÔeÂ2Ţé ˸L`'8Ż}84“xmŲś"şľ]şeOkšâúËU]TccŁÓŚ) :‡f ÂLŚÚLžmœf:3`RJ–1-—†††ÔÝÝ­P(Ź[<Ű´Łuˇü>[Á,çIe–q™×˜kB3-RÂ3rŸ/ŚgűcúřS>^—ĐŤ:М9sœj3^Ż×9.[fŹj3´h0a ËäłmppРʘÖKw[ťôJËvüśüĘ.ľÔÖW^a—'ůšŞZ:noUÖˇĚÓşÁ˜Žzҧ×ĎłőćĽ{VMMMMÉysH!Őf͌Ŕ ˜R…ebą˜ÓzŠŤŤK;ƒşŠţeůëÂŁZ/<´ŁC˛ĺ–qYţ˜üMÝ w͑Ľď7Śť;bşŸO{­ƒ†Bš3§I ňů†mËˇÚ Ą€Ǜ’Č',“šnÚ/íۡOáXLżńoĐŔœNůóČslŰ畊ÜyŤCň…Źó¸˜7Ś˙z5Ž…ţ€>uDˇ š?žÓŚÉČUmf"Ą€ŮČ#PQĆ LÇkČg˙XŻŰ,wtthçÎ]z1ÚĄ6>ŞĄćNyňČz´w{dűĘ?,ăň7őIy´˛,[{ba}âɰžŘwŢóežoéň­čSČ~ěWcs 8ĚPĄŚëËxąĂ2ńx\;věPWWˇţäۤçŻWUU~?[4ęQ4*UPÓŽŠŞľCvžŻŮňĹôă­Cúކ¸ó™÷ĘźgŽJ Í´ˇˇëuŻ;=5mÚ´yÜÇ|ík׌xĚŤŻn÷1˙ń_O˙÷˙YÓŐW˙}ęÜ÷ÝwżŔěDP€ĘG`ä­Řa™h4Ş­[ˇŞ7<¤ŸT?§ŽÖ}yU•qíě°eyŞ4ć5ę{ó?޲ľ~0ŹO?UÇ@D[ślQ$IíŻ”ĐLkkŤ8`Ujýńǟ÷1™Ç<öŘăă>ć‰'žL-Ÿt҉ČD`äĽŘa™mÝşM[LXŚń yUÓŠÉ DTŠ|uƒyľfJňDőš§"ÚŇ'mŰśÝy]•šI°¤[˛ŮťwŸvěŘ9bŰx™śś6ç˝Éö|.3`\ĹËôööj÷î=z)6 ŸřŸQW$˘x…b✼ţhL•.ŘŇYP;);áU¤żA_y´ZĎtČyÍ{™Ú_Ą™O\›Z~ć™g•HäžđŮÂ1Ď>űźbąÜ×ţÉ'ŸN-/Y˛X‹-@&3`R Ëtuuißž6=îŃőÁçd˘ŠĆĽ=}1Ĺâů…5víłdXĽy|qyŤBykÇ˝ w5)ó)‘\ţîÓ5z`ˇœ÷Ňź§ŠăŠš)ĽŁ^­ŞŞ*gšż@/żź!çąé™óÎ;י éůç_Čů˜'Ÿ|*ľLu‹Oc+\QhXŚłł39uéŢP§î­{Iňě˝˜°ĚŽŢ˜Zk}Ş ä.ťŽXŠ{#…f)kţĆ^ĹCÁä•ű'ЇŠô5H‰ýYg;šüÓjŐĐęt*ľ´´´ ďKžç–ľ˙|™ëšśĺło˛€ÖŹY­GyĚYüń'tŘa‡*ŰkpĂ/--Í:í´Suó͡ŚsĚ1k˛ž?˝ÍÓ 'ŸőS™ç׿ţ­}ô1íÚľűľ÷ŽŮ ó\xáů:î¸cUóz~ń‹ë´~ýKTSSŁŽ:ęH]vٛuüńÇ ”*̀œŠ–ioowÂ27„öęŢúu#Â2ű—ÚúcęJîËńÔ{:=˛<ÓW!ĽŘ,OBžÚÁŹűĚű¨U¤§iDXf˙–ţřr~őŞG]]ÝÎ{ź˙ą“Ť4SĘ*4é•_Ň+¤{ĺ•WŸÉX˝ú¨ätdjßOdĚΝť´gĎ^gŮçóe žÜxăÍzë[ߊ_ţňWÚ´iłBĄ"‘ˆ˘šĺ–Űtĺ•×§>őőőő)żúŐŻőя~ őôô:í˘ÚŰ;t÷Ý÷ęďţî*}ăßłí˜f@QŒ×†ŠťťGw učéú’5vŁg(ĄÝ˝1Eb# …“żşřÚiüő}Ę,™cZ/Eşç(6P;îăď|ľF7n•óڞi:¤fž{îEŁŃQǘŞ-.SůĹTĎY´hĄłžnÝz ŒzLzu˛ŠŠŠą˙şëŽ×—žô•Ôó™ósÎŮşč˘ œŠ0ŽxHŸüägœ ÍXĚk˙Ż˙úŽł|ĐAę o8KŻ{݉jllHc5×\ó €ňBK&U!ŐGĆZ7•::::őd¸GÖż$ËĘ/´‰ŰÚÝSCĐŤĆj<–´×ńϜę2)ɟÍW; Xmň˝ó$ç5Š…jrVŮÉć/ת10 SŐéTWŠŻŻwś×ži:Z3-_žLóçĎÓŢ˝űœ //źđâ¨K遙5kŽvććÓB)ëЧžvÚ4ĽK̜xâÚűL5™˙ţďď;ËćýůÄ'>ŚK.šHĎţüřsĎ=ŻOúsNđČ,›6Kď{ß{”ËĎţKŐŐŐęË_ţ˘ÖŽÝßţihhČyŽßüćwÎúď˙G'L“Ť˜zT˜Ł+,c‚űöľi]¸_ŽyŃi?TŘ ‘zCqí쎪Ťß–íjŚňŐ (6TĽPGsr^XXf˜Ľk_ŹŃ ]–óž›÷ŢUČ5ËTŞŞ4éUf҃.†ŠóěłĎ;Ë őNőă„ö‡`üÉQçLoď”~~ăűß˙aŞ˛ĚG>ň!]zé%#Â2†ŠJóŻ˙úOŠuˆ1-–ĆňĹ/ţ󈰌Q]]­ŤŻţ¸^˙ú3œuóţěgż(f@ŢĆ O¤ď7ílvďŢŁmѐ~|Q–7މJ$OŰŃQ­ĐŢůŠö6ČNżęÉ´ą-Ĺűkjk•âžä;ń_Ďěäcżýd•śôŮÎ{ŸŢꨐk7N<ń„Ôň“O>=bŸŠ8ă~LHĆ śŹ]{\ŞâMzĂTéęęv–çĚiJ…lŒţţ~=ňČcÎrsó˝ĺ-Ą\Lřĺ°Ă}íqzţůrkÚ8esŇ}čCZ6Sm ”3`„B‚šŽ5ŰMťp<ޟj˝Ź@D“c ˇ+Š{í­×Đv5) ¨RŮż"= Ú3O‘Ţ)ůłyköL“‘Hxu͓A ENhfŹk”÷k-A˜ćřăMa^|q݈Š8=öxj9=X3gΜTf˖­jkkKíKŻRcB6é­¤ž}ö9'Ŕe˜@Lfe™LÇwljůĺ—7ä<îä“OŇX–-[ŞĽK—8Ë&ź´qă+ĺÁ'€×ŤÓŢ˝{‡őĂđ+Š7LžŞF|((;îM{2KсZgňřŁňÖ ÉW=$ËS9KÄźJ U+ŞR":ú×0Ó˛Ę+j2Bażžńl\Ÿ>6˘}űöiţüůÎvsŇƒ$ă­§kßDÔ××ëˆ#w*¸˜śG&ÔâVkyâ‰ý­•N8adť# Ů°acę¸óÎ;÷ľĺý™ĚŞ/mmíŠĺ[o˝Ý™ňŐÝݝsßŇĽK5šŮž}‡łÜŮŮ%P¨0ĆUH;Óvf``Pw u¨˝aŠ!Ö_—s_"ęWÔŠÔ2_Ą˝ŚZK˝8ąí2h۔|[âá€S'źŻ%9ÍU´Ż.kXĆe‚?Ĺđj{•ţ¸Ĺă´JoTN­™ŇĂ0O=őŒ3Ôúő/9Ë˗/ÓźyóF<ćÄ׌–ݐŒyÍĎ<óŹłlB=™!›žžM”ů,çRSS­ńÔÖÖŚ–{{{Ęf€c˘-zҗMۛŽŽNm éÁÚ *FdĹT–‰GňŤ¸bÂ3f2uf,˖'qÚA™*4ž@r*qóZÍóŰÉ)ńˇŒ*0b^ŻĺM8í§&ëŚWŞtTË źŢNƒĂďczľ˜B*ÇťĘŒŠóŁýŻłě^ž{îyĹăqgŮ´VĘ´zőQŞŽŽvZ8=ýôpČć•W^U__żł|ŕ¨ššyÄcRË555úÄ'>Ś|­Xą<ç>FOzH&ýu€éE`ŒiźVLéÚŰ;‰Ĺt­ľžhí‘bƒ5‡N SaĆim”ŢŢȄh|Ńäk‹'çqYޘN‘7šn%’ËśĚ˙3asŹsž„%'ů“<ŸđHÉÉĚM Ĺdœ)ćž'&&1gđCĂ?÷$™×ů­§ƒşćô°dZ´haöă hÍTL‡~˜ęë뜰‹Š*cWŚ5“+łRŒá÷űľfÍj=üđŁÚ˝{ÚÚÚF<&ł“ŃÚڒZ>öŘ5şŕ‚óT [ˇn÷˜Í›ˇ¤–››ç”Z2€ ˇáI\wwˇSő㡥Š×ôŤXâƒăˇ˝É›m) (>Tí´FŠt7)ÜŃě´JÚ;_ƒťhh×B î\¤Á‹“Ë 2­žv'§=ó’Çľ*ÜŢŹHg“Ó*Ö_›óŠ13ýčGôď|OŸúÔgľjŐJg2ď­ŠxÓŰۗ:îÍožXÇłF |PaLŠ Db1Ýę{UĹdÇ=JDš­,T–'ĄbúőˁTűŹr’ŽŠŻŻÓ!‡\ĐcrmK÷Ţ÷ž[Ÿűܧ ŽĚg÷ž{îÓoű{Ýu×=Š÷Ĺ´‚úҗţEgžyƘç3mŁŽşęŁN¨hÓŚÍN…œ‡~tDXćňË/Ő'?y•@yĄÂ łXŽÖ:ůV—éëësw í“Ý0¤bЇgouĂÔuńÊUŤX†Â>Ý´%Ź7UżęęęœíŠ2SĚę3'ž¸V×]w}j}íÚăĺńŒë^ťö8ç˜Db8T´pá-]şDăšč˘ œó˙áÔŁ>ŽmŰś+'ߋZ­XąÂiuŮeoVCCƒňa1ڞĚĎ~ö §˛L˙€´zőQNe™ńB<`zäűW+Ď}Vs+Çş;yŇćîä}m›7c2űĚ_3<‘Hô!0ĂĹăq'¨`&w9‹ihhP‰„­ůóçtžÉföěŮë´ ůRô)ĹkŠ[ľ$ŇŮŹŘ`ńÂ"1´kŚ“iIéÍ/¸‘ŻšŞ˜žyFŘiÉ´`ÁüÔöôđKf&W0ŚÔíšĘĹŢ˝űäńXŞŽŽ‘ĎçsĆEź^Ż3w—¨ćӌłw8č œšůŰS6€˙dł;9őž6gLökóDÚd§Í3'ĺXkžšœiŹ}Z20KM6,c*”˜ę2÷u=,cÄĂłˇ“Ë㏨ŘC>Ý˝SÎľ3×Еë:g[o;@š#0&Ą-"‘ˆî÷mWą%b>ŮqîĘąź y‘*3•ˆŔ łĐdĂ&daZú<`ďQ)$ÂAa˜Ç_üŔŒqŰVs Mři2ҀJD`d•+Ç‹ĹՍ¨§ŽSĽRaĆeůJ˜ŮŐ[ĽţPÔš–‰DBł ŕŤRČčvL Ý>´/ů›DLĹ!–ě¨Wćń%ßcŤřU\섥ˇZÎľěďďßżśL` 0Ŕ,3™ĐƒyěĐАÓĘçEď^•B"ęOţ×ösB3%đČnŸs-Í5ěçTÇ“ל™ŠŔ %W•‘X,ŚDÂ֎ȐBľ˝*…DÄ/ŒTŞŔL÷@PťÎ55×Ö5V•PŮÜĄ˙ŚŚŚQűÜmłáĎf@ŢĄӎɸ7´O–Ušß”13™,o\Ľră–áš{mÇC€€J7<ÖßŇ2GÍÍÍNU3™eł-ý˜™Ě'€<˜ D8v*‘l˛şT*vŒ_O2y|Ľ ĚźŘćuŽŠšść[í°˜ÉÜ{c͟L@fHf˙~*̀e˛ŐAL랈 WÔöŤTQ3Ł”¨%“Ń3Đ`d¸ŐÖd>Tž r˜qýá)}Űţíł0Bú/AéËĄPșż0Ô+ů˘* ے÷ #y< É*Ő/§–ٝp–†††R[s}ŔĚŕdĚMľîľłéOf˜ĺň C¸™gb*•a™lYž„Jĺé}Ăm˜L[Śź^ Pá̀q™€„ S˜ůVŤt;F`&ˇt™M]–smŁŃ(a0+˜Ye'Ěj<W´:¤Rąă>!;ËWŠ EÎľ5ĺÓž3•`–Č'üë˜Db¸şIo4,ůŁ*;N–7—RśdŠ'źęGŐäó9×Úë]éÇ|6,Ëó<ů@Ľ0•Xđƒéć›oQGGq*îśśśčźóޤ~đýňűýŔôáŻR`\‘Hęo ÷˲JWuÄNВ)§V˜1ÖurÜk Ŕl÷ĂţX?űŮ/Š–1ÚŰ;tíľ?wÎ €éE`€Y,ߪ3nˆâ•pŻJÉNđŤI.–ˇtfŒ Ăç7wĎMŚ3ĹM7ÝŹRšńƛ€éEK&0.70ł9ZâŔLœv>š”şÓ‘˜ĄÂ ÊYY&Sgg—0˝̀qĹă §˘HŸ/¤’˛Š0““UÚ 3áávXńxi[?Ľëîéîőýşýĺ„ÖŚT8ek~tŘܸÎX™ĐA­Ľý.WŽ,˒ĎçS0PmmmrPǹQ2Űí¸ë‰@ź¤ýiÉ4OiYĂqŸsS4–űűÇŰuÍ=î猠 €™!a[ÚݧääÓ]›¤łVĹôľ1Í6ćűĽiůkŚţţŐŐŐŞššY˜žß1 Ý=-hčČ%5ňL˛ln"ůyzaÇ öôF´°1 Ł–Ô  řŤȟßVI%NäbYĽ}ď9Şűd†§ŠáˇśĽ…e`ćşk“O_˝7 Ů΄fÚÚڄ™Żw(Ž]ĹŇÎŢÚď^&Ę<֜ܘӜťghö…Đ@i˜`Č'ôW0ÂSę 3š•6`bŰŢ<Ž™ük0•e~óœ`ÖxnG˙ó8Ĺއ†Bęěěfś*ż%Ÿg˙řΞžŘ„C3nXÜĂeÎ]íçO[ 8ř­äÍň–¸_M`&§ż5‰"ĺqĆ Őt÷‡¨,`V2•f6ś3o*̈́Ăaać ř<:fy­Ň23 Íd ˘sšs›ç(~Ťů+q[ ˘š•>JTúg¸{}ż`śşw3ĂńĆŔŔ€0łľÖůu܊ş ‡fr…eĚ9ÍšŠ…ßĐ@Ţ,ŤÄfhɔ[Šßš)H+ÝţrŠ??PžÖˇß w6‡#ÂĚ7ŃĐ a0•̀œFľ×™ĄĘUę7§ôaĽőűłÖ^Šn:bą˜0;š!,ښOyÜž¸¤šŠĄÝó%ť|ŞĚ 훧rŇľ}JĹrbÔĺőó€Ęć†fžÜbB2ĂŰÜĐĚ1ËM˜fxˆ° ˜T˜(m˜Ĺ˘#SnVi+Ědž÷ś]üç;Œ<€Yl~äóqďl“ťŇ̀”Ë –SŽŔ ȟ]ę_čɔ[‰3—Ö*AzéœCřŐŔěuŘܸ ƒaöÉš‰:A™á°L4ľ° ˜*üŐ”‹ŔL.ĽŽžăń”žźĎëăvJł×+‚T[[+ĚNšB3„eŔt!0ňfŮ%U˜C‰+ĚřJ?pŰTWĽŤĎ¤ď€ŮçŹU1ÔJ`ŚŽŽVÁ`P˜˝˛…f\„eŔT#0rĘlËăUŠ3BśUځUďýVxéÚVýĹjŔŹązABXÓlW]]ĽććfŮB3„eŔt 0ňćUiű­[úšçd—60ă-cMAhéăçÎĽŇ €YÁT–ůĚÍvڞĚÜšs¸L0ćřuŞö{œéxÂ2`ř0SiĆśmí„Â*ËKKŚ\ěˇdŞö ŕz˝^MSićő‡…t÷ú~ÝţrBë÷IŃ8!•Ícٚ_'67Ž3V&fm&3Žŕóů T[K&d×Rçי‡6 `ş˜ăňz=J$Ş GÔë ¨T,‹ 3šŘ‰Ň˛Îőf̀ćdX”¨iŞŤŇĽkÍ$€)EK&f|B c ‡dšBĽŹ/c*ĚĚÎ;ďňaÇKřŢ$/ýŞúáŔŒ{­łfQ0{´śś¨TćÎmځ0.7DąŔ´ĚI”°e‡ŔL.‰V˜ńúĽ[‡Żkf`† `ś:ďź7ŠTÎ;ď\`zђ ŒbBśm§ÖÝĹŞş&=ŕ‘˘* —–LšÄĂĽ{oź~[-nrŽť×[Â@äƒ|ż3żůć[ÔŢŢĄb0UkLçxż0˝̀qy<'Ląhn‹ŞĂíŠĆT™œb% Ěř=śZćÔ;טŠ2 óűýúđ‡˙ƙ0óВ äĹä(ć̙ŁÚxXĽbyiɔK,TşŔLŁgHŐŐŐňů†ŤËäš!X*fąB‚Á`P>ŸOM=C’]˘°„eSe& Ë—°U ŸtPuŸSE¨ŞŞJł7L1ˇ?Ą€ĺUŠ˜ÍV‰z`%yƒśnăĚf˜%&ŰfÇ ĚRߤşŞŇT;1<ţ҅C*U"Qş‘×cëč•ÍÎľ7˝ŮÓĽhÓf3 ŤláŻ×Ł ćŠ1ŇŻR!03Z"R˘÷$y‰ŞO-͍ Š.f3`\nx& ŞľľUŐíůlŸJÁňE…‘˘CĽ ĚřŤm\߯úúzçÚT’łAiţŇ*† ?Řv~-–jkk588¤•C–:V$´ˇWEG…™Ń"Ľ Y–­ľË}ÎgŔmš…™Ľ˝˝]ŻžşÉYž3gŽ>ř 3 Cz€&3LăóůœśLK“xßé×ŢDäÉ/l“˙ °eůc˛ŁüšbXިń"żÇIŻ´H˝Zž¨UUUAy<# ŚW‘)EE™x<ŽuëÖkăĆWÔŮŮŠp8⼎––tЁ:ě°CG˝Ś| ęšçž×Ö­ŰÔÓÓŁh4ćœ{ţüů:đŔtČ!çý3ÝtÓ-ŠŔ‰Ëçóęxżü~ÖÇôööę˙ţďgŁśŻ^}¤Î8ătgšŁŁCżřĹŻ”‹ßďS]]–.]˘ŁŽ:RÍÍ͚ó?űěóÎň‰'ŽÍë1\›Šš6€éĹ_˘˜E Š&“Kuuľ–/_ŚęőϨj^ƒB‰âW?ńúي˜qŘńŇT—ńVŰ:ŞŠWsçŽtŽŠ1™`L!íëëӟţôguvvŘnŞ îĐöí;ôôÓĎč’K.rÚEÂ(nżý'ˆ‘yî͛ˇ8“9÷Ĺ_čTLšˆX,ŽW^yŐ ŽdóňË4Yćőwuu;Ó /ŹÓYg™óůƲmŰöÔ˛ůw;ŽÍřŠumÓkbˇ†€YÇ D˜?d›é€ĽĹ-•‚'PšóV˘h¸4-Şźą˜NXP P0Ěűq“­6“H$tĂ 7Ždƒľ´4;•;\&Œ`‚…źLűĄ›ožuD cŢźšZąbšjjŞÓŽëЍ7ŢŹÉx饗sî›H(ĂTYih¨wŚÚښďłyĎîşë'ĚRˆţţ~ç}4Ě{ČY6Á†;ďź;uî˝{÷i׎ÝZ´hĄňU__§žž~gyçÎ]N Ĺ´ćI×Ö֖ И'ćߋii4žNXŤŁ^ZŇíˇßé´.r_ży/ÖŹ9ZůJŻ.łtéŇqŻ%×&ťR\ŔôŁÂ eźŔ„Š0łrĺ ÍŮŐŇĹŻ€byă˛[ńřpP¨Ďęœ9MАˆ 0˜ÇŚżśÁÁ‘Ą†ćć9*„yM˗/Sw÷óÎş `wÜţ ‡yž 6ŚÖMHeŰśmš¨h4:b}îܹʗy-éϝO`†k“żÉ\@y Â pږ§žž>ůęĺŞ~)˘%­ŤÔ0Om™˘Ą¨ŠÎŠëuóťœv7ŮBĽlÇd,Y˛XGq¸3™€CŚÝť÷(ÚZźxąňuĚ1kœ@‡aÚóÜrËmęííuÂ;věÔ­ˇŢ–:vĺʇĚyVŽ\™Z7m‰L›—yŽôŕNJ˓)ü߆ c˜j/wÜqWj›š^ŤV­Ěűćuší†LXĹü{×f|Ÿ6€ň@…PˇĘŒiË´pá­ÜřŠBö€ŹD˝lOńŞĚxƒaEe*XLMŤ r4ÔR1ůŞĽÖDżŽ^VíTđÎöŠjÇ4žP(¤;î¸3ľŢŇҜ5¸‘‹ …üĹ_\ŚťďžW{öěŐ+ŻźęLé|>Ż;ě0vÚ)*” e,^źČ ~DŁĂŸőőë_J…;Ňۙ×nIůVašďžœ)SCC˝VŻ>JGu¤Óş(_[ślM-çS]f<\›â]@y`d€Y¨X‰şşZ§Rƒo}X-)nK&˓(î9+Š'Şx¤ˆ•{’—<ëÔ]Ékś,kőą>ĹhÇ4ČřÝďţ îîgÝŢôŚ7|ţ`0¨ůóç%灏ű›ššœŔÄD^w"‘p‚ŤV­Jm{őŐMÎ܄/6mڔÚ~ŔŤœă'Ëź/Ś:JGGgAŰž}GjŮT‚šěkŕڌ6Ńk(T˜)nő˜lëٖM•S˝âŔÍ[ľ16¨€Ő ˆ]ꐋŻ*ŹhÄŻŮ( Ť˜üŐRs|@ŤűÔÚÚę„ŒRaňŃ××§?ţńuuu;ë^ŻW^xš›› 9Sšäü“"‘áVV&ŘąlŮ2ŐÔÔ8íyĚţööÝsĎ}Ú°aŁ.šä"ů|…˙:|đÁĽ*–ô÷¨ťť;ůœ‘T $㠃T!ĚńŚBŠËź'ŚBŠi#dŞĹlŰś]]tA^ŐbĚk1?ŤaŢËôóŠkSÜk(fŔ¤466$˙PźD;žÚŚŐg‡ôÄK~ÉĘŻŐÉxźUCŠöÖi6 ą“啢ƒ˝aU›VŽ<$yÍU Ĺ՘°ÄŸţôg'|`˜ ĹœŻ%Kr§bČÍ7ߒ d˜v9—_~Šęr™ ĹmˇÝá,ďÚľ[=ô°N?ý4Ę#ŞŤŤ444|L•‘pxŔiîÜV'PbÚĺË´73­}Ň{ě1şîşëŐ××ďü|wß}ŢűŢw{.ózÜ *ćź ž\›aĹź6€ňAK&fŠ|+‹¤Żg[ŽŽŽÖŞU+´8ů÷羗‡4ˇŽxż^Xž¸<ţŮזÉňÄ(bĽž`BŤ{tđü€vđű‡ŤöŒwms­‹ 3üöˇżO2LŤžË.{ł–.]˘B™s™Š"ŽcŽY3"arČÁNK ׺uë5ŚőŠdâ2Ýť÷¤Ö=ôCUU•óš]˝˝}ęęę÷qŰśmK-O´ę ×fl˝6€ňA…0iŚĹůăńŔË/Šń ƒęxŠV oqŢę!%˘ő*Š„G‰ädÇ|JÄ=RÜ+ŰNŽ'ˇÉ™[rjăؖ3umß#ËcÂ"Á+ůÇx×JνɚYNÎý^§MÇçuöC,2¤bń×$˙3Ńé‡u$ŻŃŐ×齜$SQäŽ;îJUB1UA.˝ôľ´´h"BĄ‘yň „Ĺbq§Ňˆš~…:ě°CőěłĎ;ËťwďvÚţ¸ç/´ĺĎXŇŤŁąŘř˙Žśn\`†k“Ÿ‰\@ů 0Ŕ,fţ€lŰö¸ŰÓ׳-›?jŻ\š\[ślŃśGCZ˝ÖŤg^)Nk&oučľśLV9ą-ĹŁ>Ůр& “œěxá|ˇćg°_[N$Ďc–˘Yőř|ňů}ňüň}ňŞÎ2ŘYœŔŒ'ůăĆÂ1˝qQ›V-] Ĺ‹;8ŒÉV—™Lՙ'Ÿ|J=ôHj˝ŽŽÖ d455ű؞ž'ĚŃÝÝ­ŐŤŇÚľÇ;Ű[[G†9žyćY­ZľRľľľŠmŻžşI{öěM­77ϙP Ø;wŽóřÎÎ.§şˆËT`IΉ2˙Ž6n|EëÖ˝”ÚfŽÝxí´Ěűăžt1Żł“š6Űśm×˝÷Ţçźö3Î8]˗/sśsmĺˆŔ ( óő5kŽÖŕ#jcGD‹šÚŐ5ůŔŒĺËŒ*Œ{Ź ĹÄĂA%LH&b~Í)M+ĄÜĎSÄT™ ÉÔÔ0ĄŻž Č_t–Çĺ‰(N¨<¸ćŰZ37¤C=.kX Tí–ryöŮçF2ŒĄäűuÝu×g=ŢT5šâŠËSë<ň˜ÓfÇ]^šr…SᨚšŮŠ,˛~ýpˆĄťťG×^űs-]şÔiŸÓŮŮ9"a~î“O~&Ă´÷ÉüYŇŰôâŃGÓSO=í,›@†yOÜ /.óóc˙;0ĄײeËTˆÉ^›Űoż#ŐÂéÖ[oÓ_˙őœeŽ  ˜YZeĆX˛dą̛§ŢgŰTózŻ:{jJLžM‰ˇv g`Ǝů  ĚD*Ȕ’y_báˆ3 őö;hŐAjŤäőgĎDŠS]Ć_kËˆč‚ƒ÷éŕƒQi$ߪ1Ľ¨.ÓŰŰ;j›i˝“üżŹÜv:ŽĚ BúgôŹłÎt^Űşuëőh4ŚM›6:§ßďKűz­Xą\“a?ühę5ř|^pŔ*MD8ů1S.‹/Ň駟Şń¤fÜ /ů*ćľÉźNgĹľ”3ĚršÚ2M„ßď×ھNJýćŰÔńŔVżŢŇëj”đN.4ă­ ;•fÜ@ŒmÚ- U)ŽR"šGՖ2a*ЄúĚ4 oŔ§`m5Ő˛<ŻP-›WëTŰpŰیŐ~ŠœxâZuuu9ᎣŽ:rDČ´Ĺ9űě×'ˇáT3Ůąc§úűű‹Ĺ œJ'˖-ՑGáT6™Źşş:'$ś}űg}ŐŞUÎżb0?‹ŰRéŕƒĘŤ:Š Šlßž?0cZM%tšçž{˙˙äĚ3Ďąoś_@ůÉ÷Ż$VžűŹ<ćVŽuwň¤ÍÝÉűÚ6oĆdö5˜y$}HĚpŚÚƒůc´™ÜĺX,ŚĄĄÁäËm͟?O1V`&s_úzŽĺM›6é‘G×sóƒŞ9¤FĎoő%˙×zrm†˘}ľŠő4*6T­hrRÂŁRëÚžGĽfB+Áşëkd[CęÝŮŻÉđřM0'Şľs:uö˛^˝ţő§çŹ.3VxŚŐePZťwďŃo~ó;gšľľEoű[ŠcďŢ}ňx,UW×Čçó ˇâözšť ŔlřONÎĚ~z_›Ç3&űľy"m˛Ó晓rŹ5Ď\Î4îÝâT˜Ž2“Ť5Óʕ+ľo_›â›śčĽVŸœoé•}žäAŹdcÂ11żB-˛3+°aŢ3Sq&ÔoŞÎ„dy‚ţ-9_LóC:ma§VŻ>zBaTŚ-[ś¤–Mľ[éoÍ-ßĘ#™Ç{ě1jŞŻÓâuƒ *Ş%MĘ#Ë;ęLŠ Ô*´wŽbCUňV iŚňxcčRx°'ůs†ňŻř–ńřcŞMDtéŠ=:`Őrxŕű÷ĄşLerŰ˗/ȍ 3ŔQH•™\•eҗ€Î>űőşá†›}lP:ÁV´śF{ăy=‡ő)ÜÝäĚ]žšA§%“ě™Ü0ď[xpŔYNÄl ´)P‘ŻŞF‰ČřżŽ™‹Ç“7ŐíŇâÖwÜąNyŕ|ž{ŹuTގźĺ/ňC…0ŽB*’¤/×ÔÔčôÓOŃ\ĹUýř ć6†5'0~ˆ#ÖW§P{ˈ°ŒsnOBž™XeĆU<’ą)2×`WŸ<ÁĆ,͓|ť˝Á˜CQ]žr7zuÚi§:ĽÔ!EhĹDĚ$f@ĘXĄˆń*‘ä b,\¸P§œr’–Ú yТććVy˛g@…;ć(ÚW—łŠŒżv0yţ„f óVE˛ďLžGƒCÉßؒű˝YŢ0§˛LXថ.[ľW+šâ:ăŒSŐĐАvţɡb˜ìŠUu$}ßňĺËľfÍj­ŠÇ{|@s"šW푝ŘŒó)ÔŢŹD8¨1™*3ľ3¨ĘŒ'˘xtěP¨7ŞX¸Wßţă,Żůπ"˝Cşhe‡h ;Á¤–––ýnj–)¤A0ӌßŕ5&8aŰvÎmŮöť?ü0% éšôĘcj:ڒĎňjç€ Î˜Ę2ÍR<ż,ŻŻzPąĄ*ŮqŻ*š×„aň:4J$Ţ>ëëJ<ŃPŹhTWÜŁ›˘:őԓľhѢÔń`rŁÂ e2a‹ąŞšqÄá:ôЃu SĂÓ} &çËęlyűëóË ŸŘV ĄO-ůÖ$âʑ/ĘĘT˘‰Gűîk“7Ň;íցM|ňIZ˛dÉţSçŮ.kŹmůě¨Tf@V…„(ň h˜ĺcŽYŁc]ŁĽV\ ÖőËŠjŒľ6÷9A˜|yüyŤBŞT–7ŽH¤ Çë=lďU­Âzßęn­˜“ĐgœŚĺ˗ĺ~žN…> Rђ Ef;Ś\­šĚňĄ‡˘ŞŞ*=ü𣠟ҍő ë4ˇĽ_Ձˆv훣x"żLŻżžOv4 Dź˛2Ŕ–ÇV¸/˙ 9Ż%ËV˙ŢA-o˛tĹ!Ím čôÓOUkkëČsQMfźu€Ů‚Ŕ Č)33Ţž|C3ÊËU]]Ľűî{@{úôh[ľŞ”–ÎoמŽ&…"˙úlůë{în’Óă¨"؊Ç•ˆçWM'PçQ¨łSńhL'.•ŢtPTÍsšœ°L]]݈c ˌ‡0 ˜ÉhÉĆTh˞|Ű3óçĎ×9眭†şœRí‹}JD˘ZÔŇŠš =ňx'•ŻvP•Âă‹*2Éă8Kţژzwě’?Ö;Žë‚CbZşd‘^˙ú3F„eĚűZhX†VL`6ŁÂ ˜”ÉVšijj҅žŻ‡~DÖöjßÖŤgëTŰ,|auÔi \3ćkđŐȎúUÎ<>[C=cdIÁZKí튵G´bŽô–5śšk}:üđÜÉăٟyžHŰ%Â2`ś#0Ć5VkŚ\űÇ Íîş×ëŐ)§œŹÍ›ˇč駟Qó@Ÿžč (´ VMŐ}Şö†ÔŽW4îĎţüÉ)ĐŘŤpWł1ŻĘ‘•|YC}=ămT ÖŁČ@Żzv$ćäúĆCĽ×­šľvíqš;wnA•d ËĚf@^ŠšÉ\7ËŤV­Tsó=ňČc:ЧGÝí]z4Q#ßiN°Ká¨_ąZĹě@–`+ĐÔ­pW“ěxy…fLA˜đPOňue˙|՞äžőîęvÂ?kIç*5Ő´xń"­Ys´ŞŤŤG<ŚaÂ4`ś 0ňVęЌaZ4˝ńoЋ/ŽÓŤŻnŇ9CƒÚ°3Ź 5őň×IőŢEâ~…ՊY#[0Yž¸‚nh&QĄ“A‰„{$Fí Ôy őŠwłž´IşŕPiy‹W:ôĐC´lŮŇ-˜†ĎIX`2̀‚LEhĆDŽ:ęH§âŒiŃTÝŢĄƒ‡ş´nOüuňŐ'ąŁŠĆŠZA%,o\Á9Ý w—AĽ ÷*ŽďßäľäŻąéëSďŽ~g۲&éôUŇá źŞŽŽŇňĺËtŘa‡*ĚM0CX`$3 `Ĺ Íé-™Ň׍ÚÚZrĘÉÚąc§Ö­[ŻăއtD¨[/´űô’U'O˝%,ŞD|@1Ë/ŰTÂx-4ÓĽHOŁQżŚƒĺ•ƒÝÉçOţ<KÁąÚť4Ř1 1A™ł”™ďuZ.ľśśčđĂsŞËŤŠ a€Ń̀ )Fh&ŰślëK—.ђ%‹ľmŰvmذQkŤuT¨Wëş-­‹Ö*^S-KQŮĄ¨d{÷űeů 4t):PŻx¨ZSÉňĹ엯*ůrüQ św+ÔsöUűĽŁ–JÇ-‘VÍ *8ASMgŢźyE Ć–ȎŔ (™\cźLścLŤ˘e˖:Á™_щő Šo°GOuUiS´ZvurІG’Sňž~Y†ä j“ç H‰´iJž\Ż×+O ůsÄ5ĐšGĄžىá×ďIî? Ĺ֚E–Ö,ńŠś:ŕećĚiŇA¨–––ź/…„bËäF`€ 5^…—ry šŽÉ7$“m›œŮšs—6mÚ¤ęAÓW(4 ś=Ö^Ľ]Ń*ŮţäŽ)1ŘŠxźS‰xň9ĺ‘'P-o (ŻŠDăőÉňx’göĘJNćŠ,™×6üܖIť˜-əÇk’1ĂËR\‰XX‘Ą v&ϏřůŞ’że­jľuČü>'$c´´4kѢEZ°`žSf:‚2ů€ěňŠ *PăU›ÉŹÉˇ˛ĚXǚPĘÁä´7tÚ5utt*Œč´é4ç1qEŁ˝Ĺ´ąÓŇśnK{ű}ęŒű˛}ŠŰ^%ŹáJ3ržfřš^[óބjürŚĆ*Kóę=š×ŕтŸł řFa̲ É̝;WóçĎs*Ët)4CX f¨P#ĂfyzŰ3ĹlŃän3 Ů^[[Ť5kŽvöĹăqíÚľ[űöíSOOŻ<\9ĄA:!ő(sŽhňřˆFkĘú:łŠŽŽV}}š››ŐÔÔ¨ĆĆFçŘąB*ĹЌˇŻc0–ýă+ŒľPůĚPAĆ •”‹É†fŒÉgÜ}>ŸO˖-ŐŇĽKRŰMűŚööuwwŤŻŻĎŠHĆœpMśó˜™LŘ@Ŕďn‚Á Ě1S]]­jjjœcŇ_ÓX?{Ąű&SUڐă0śBotĺ‹Ŕ 3@zp¤ž çš1Šœď|†iß´págď5ŽĽ÷y˘Őa&[UŚă;†Ä8 3 fSÝÄTH‰Çňůź*ů„fĆ;n"™Ě‹ą^C)9JQifź}9c3cn†[aĚ f˜̗u‡ĂňůjT.ĆŞ"SČqŠF“š?Ýd*Ëäű9n˛ű =ă3cnfź…Ŕ 3 *˜ů˘žţe}hhHľľĺ˜qRmƘLpĆ5]•e&ň\Ĺ Ęz,ĆgĆÜ ÷Ś5Ć_˜ĚP2(Ă_ÖĽX,ćl/Ç/íůV›ÉçŘąZ2e;fŹăŠ­˜U`ĘL/3ŚdĆÜź^Ϩ 3ŒÇPŮĚPĄ2ż{˝>%Q§DlUU•ĘUžŐfÜc|ŞĹäŰö)ÓD‚4 )UK%gJĂmÇdĆŢŇ1@ĺ#0@3wľ˜Ŕ‡™{˝^EŁQő÷”u`Ć(¤ÚLžÇO´˘LŠ7JY%†€Ň2cm†{s[2eVš•‰Ŕ &3<âöM6_ÔÍdJĚÉç+˙˙™/¤ÚŒ{źQH['×T´dšH€eހ¸ăléa™ôq™ĚuPYˆŔPĄ˛}A7!3ďîîQĽ˜ČŔ‚ű˜BŤˇŒ5ă<9G!„˜:fŒ-}ĚÍĹ 3f¨ Ů*˛¤W˜1_ŢÝ;_ÂሂÁ€*EĄmš27‘Çć:O)Lćü ŔL-3śćV—1cnŮ*̸ť 2Qa€ ”ţĺ<łĘ‰ßďw杝S҆¨Ř&s‡ÎD+ž”B1^ w+L=3ŚfĆÖŇÇÚ2Çyˇ ň˜ ‚ek äŢő2ܚŠ[•ŞÁ—ÉśNšĚóă|˜zfLÍmĹdĆÚŚb| L=Z2PaÜśLéí™ŇŰ2™mćΗD"ŽP(ʁAŐÖÖ¨’M´]Óxç+' ´L?3–fĆÔ|>oŞşLśvLé•f@e"0@Ëü’>˛5S@śQooŻź^ŞŞŞTéŇŢJl7• ƒ*ĺ! ˝6–ćuĆÖrU/f<€™–LT lw°¤ˇd2w˝ ąž ŚŤŤŰůÂ?“Tęƒ+ĺnj™1´áŃü#Ćب.ŔĚD`€ —íˇLlfhf``@3Q9‡PȔ73f––ÉlĹÄř3-™¨PćËšiK”ţ%Ý|‰O$Š/ô†˜‰FŁęííS$QSSӌţrŸíg›ŠN ˜T3^ÔÝm*3‡ą43Žćóůœĺô°LfpĆ`€ĘG`€ =<ăeҙ/únhĆ ěŢ˝G--Í ƒš-ňÄČŹa`f ‡ĂęččQĽŮmÔ9’`f"0@qƒ1ŮÖłU—É|ŹŮn*ĚÄăquvv9ASmĆďçW3W4sŞĘÄb1gŹĚ„d@*“+,“>ޖ9~Äx•‰żŽPáň ͘ułÝ0Uè€;ľˇˇ; őÎ>žŕ`&1cgŚ˘ŒiWnn$3Ěx˜š™Ě­Ěœ)$,**Lf•™ĚmŮB3nť&wŮ-1kZ4™cÍÔŐŐíě7ƒ555 Î1  ’˜ń/Œ ‡#tn3ÜöKfĚ̌šĄwťť\HX†ą3**P>ĄwŮ|Ů7wÝĚÓ5î‚8p—űúú’“F=Gú9ŇçŔTrƒ*™óĚý††17ŠĽcŇĂ1és÷ńéç ,ŔĚC`€ 5^h&ý {z€Ć­6ăgÜu3X`˜m&43ÜÂɖűnČĆ=ÇXŇ Ć Ľdށ osţ돝eÜc3ƒ2ŮÖ3ĎKX€™‰Ŕ ,[€%WhĆýÂď†dŇŰ4Ľos\îöôç €rmü+[Ř%=“ylz Śą*Őd[•‹Ŕ 3@fľ™Ě ť?}P ˝MSúă‡+Ë(k@&}›{0Üq.cŹĘ0ŮÚ,e†gr=6af3Ě…´h2܁ô 2frŤË¤‡d˛…gŇŰ<S)W¸eŹśJ™hň­*“k¨lf˜ArľhJߖë f@&ŰšŇ÷Ó-ł“4~€†  0Ě0ĺŞ6cdgĚÜ´WJ_ŤSć ÁXá‚5˜ˆą‚*šöĺÓZ)˝Sžç3f¨\b˛mĎlϔmP![ˆ&}?0ŐĆ Ç¤o/¤z ă]Ěf˜á˛U›qˇ™á—ĚíŮ*Ëä;h@…LÄdB+šZ.eî/t˜YĚ0 äŞ63Öž\ ™Aš|ž(śń‚1šŽ/t˜™Ě0‹äŞ6ăîK7Ţqă "P]“1ŮK1‚4`ć"0Ŕ,3Vľ™lÇšĆ:žp ŠmŹjÉŮ|!(ŔěF`€Y*ßŕĚXÇ”ŔTrÇŁ˛…]Ěž|B0e€A`€Y.[p&ß ƒ ('™ăZéăWŒe€tfŔ„P]Ӊ ˜ 3ĚršzAçSq†Đ ŚCćřUúölËĆXíœŔěC`€Y*ۀBތDH$*ä\@ąek/îňx<#ÖӏIÉœf™|‚2f=Űś|Ď7Öv Ů-fĚ)WĐ%ó†/s\fŔ†ŕ p˜`+,ă(˜őx<ĺôíéÇĺŔ­,ă_ĚşY6sŻ×;b{śŔÍX!0s˜`/(c&’‰ĹbŠíéóôÇçZÎ÷y€ńŒ`ÉV)ĆÝîŢđĺcć>ŸĎ ϘĐLfŔ&ýg˜=Ě0Ăĺj­dL@ĆeĚän7Á`@~ż?9x`, P†+&›)Žh4Şp8âŒ}E"gŒËŒ}™Éhrg `v 0Ŕ •ŤŞŒ[MĆ ˜šaęęjR@ĽŘÉăÜVSS㌇™ŔĚŔŔ s™;™ýnŐŞÍ0ű˜`ĘVUĆ ˜š ʘɏ›;ięëëœÁ`&2˜ŞŞ*g2ăb}}ýŠ›É̸˜™L8&[p†Đ 3flAw2™p8ěÜ=cÖ“ƒAł… Ç47ĎQ(VOOOŞs083–GœŔŒÇăq1fžŽĐ 3ƒG ˘e†eLU˜1ËMM?3ŚćޔfĆÚĚrú˜ĚPA2ż›/ëéűĚäśbjnž3ęîc3cjflÍm{ž”I“3ŃP™hÉ@…KżťĹ´a2“ĎçSUU•0RŠ/(ż 03˜ą53Ć掷ůýţÔŘc@Ě €Š”­şŒ)kć´b$šŞršÓńœ( 3Ɩ>ć6V•Py¨0@3_ŇÝĘŚDŹ™ź^݁€f›r §dž.î@¨ fŒÍŒľšănf\njř–MŒńPů¨0@ĘÖ'ٔ†5ó††zÍ•XɅę3•ĂŒľĽ˝ĽŁĘ •Ŕ ,=|až´'ˇ( j&›IÂ3ĺmxŹm`†ąfZ2PaÜ/äé_ÎÍÝ,fňz}NIؙ¨ŘĹ:_ąĘﺯ‡ržĺÌľ™17ӒÉmÇäŽË™qw*f¨0™Ałnž°555šIŠq×Nú9JqPąĎϝJĺĹs3cpŮĆć@e"0@…rCćΖáŔŒiÇĐL0B'Ĺ Ď`ú šŮŠ*3ŒŮ03В € ’ţEăŽÇ™mf¨lf¨`nxÂí\IJ”)u[§BA Ä„!80u†[˘'RË ň˜`F˜ša™|Ž-u˜&ßsŒ^É7<3‘ŕ Ą€Š@P€™„Ŕ ˜2Ĺ ĘL&HcîJŸŇ[[eśš2L Ĺ Ľ¸ËŚwuú”íůrYň ĎœĄÚ @aĚPA˛@*ĽląŞŔşßŹÇăqgŠĹbŠ@LąŢ77@c&ŸĎ'Ż×ëLnëĚcs˝Ţbg͔N%Ď€‘ĚPĄ*é‹x1Â2…ěsĂ1nPĆÝoś…cQmśiK|Ÿ6G÷j[˘]{í *˘ŃPr>ŕ‰(lŜÇmŸjU+ *+ šä|žŐ¨ĺžV­ô/Đ ß<-ńľ*čó;Ďe˜ĐŠœqC4éŻs˘ÁB3ĺ1*P2Ľ ĘdŤ$FÉWLŤ%łź/Ü­'"ŻčŠřf=§mÚiu)šw˙­×ŚbV\Ţp–œ"ÓO^-ś›t”–éXĎ 8PóŞćČď÷;íšÜŕŒť>VKŚÉ„j =`ś"0Jb˛a™|ˇ§‡dÂá°Bᐞ˝˘ě—őtbŤśyڕ0é–fGbŠkŤŐĄ­ęПí§ĺ [ZšŤcŹe:Ís˜Ž ŽRU°JÁ`Đ Ď˜ŕŒ™ŇžBƒ3T›˜83 čň ËZU&[P&‰8S(ŇÖÁ=ş3ąNˇXĎh—ş‡ňhZ˜€ÎfkŸ6kŸ~—xBs‡ęőúĄĂužľFT-Tuuľž1Ą™@ ŕýˇîĐăÖ&ÍdíęÓZ7ęű}¤ű­˜Żććf§UÓXŐfÍŽŔ ˜°‰„eĆŰ‹ĹÔÖÖŚžţ>ýŇzH×ëQEÓlńŒśęJë˙ô–č‰zŰŢ׊q ^sçΕĎ7ük[fŘeŹM„f˛#0&¤a™ÁÁAíÝťWťc]úŠő'­ÓNÍFaEu­ő€ľ_Őçú/V(ŇüůóUSSăěϡEĄ€ě<(P1Â2fÝÝfćŚýŇŽ]ťô@ü%}ŘúÉŹ ˤŰ`íÖGŹ˙Ő=ńuÉ÷fˇóĽżgcľľk[!űf"*̀˘Ę7,“žlŞĘt÷őé˙Ź{ők=&[„8\ ëßôG]lďĐ;ÎT$Ńźyóäń 瞳ľh*´Ň ŔlC`dʊ$…†eâń¸vîÜŠîđ€žhýNOi‹0š ýŃz"ůî´éŸú.uB3‹/–×ëŢ?ÉĐ 0ŰВ 䭘a™X,ŚmŰśio¸[Ÿ´~NX&ĎjŤŽNžWťÂÎ{FSű&۞‰ÖL`6!0ňRh bʇ z˜ŔǎX‡Žś~ŚWľWČĎfľ9Ą™­ąvmߞ݊6ăĘ'43B3`ś 0&mź Fúş x˜ ÇĆř]eýL;Ő%f†Ťňźߍ;vTi†P €äŔ8&ÓĘ'ł ÓΝ;ľ#ŢŠ°ŽW—„‰1ďÝg­ëôŸńwĘÚaiɒ%ňűýÎ>óž[–•óącí﹘^O?ýŒîšç>íŢ˝[>ŸO+V,×ĺ—_Ş––€ü˜c*4,“ž-}9‘H8ŐPÚc}úGëׄeŠ [ƒúGýF_˝Sž]ť´téRy<ĂӃ/ŮB0„fĘÞ={ő™Ďüƒ6mÚŹ7żůb}âËzœ ›}á ˙˘ŰnťcÔžK.šH 0f@Ńä טíŚ"FOt@ŸˇŽ×u ĹąŰęŇ?čzýGäňîÚĽE‹ĽB3éĘ5cZtÝyçÝş˙ţôŇK/ŤŁŁCąX\--ÍNő”3Ďőö럭ßéíŠk“öé‹ÖďőoCoQ[[[*@‘’o=ÝTl~ř}őŤ˙Ą;wÚˇk×ngzčĄGôÝď~_W]ő1ţ›TIN;í, 9Ë÷Ýw§jjjF3gNSjٝFcBEżůÍďRëW\qš>đżtÎ×××'P83 `ci2÷÷ôô$˙¨ßŻ˙Ń=zNۄŇxF[őcÝŤżî;K@@sćĚqś|™ŽĘ3wÝu>űŮĎ+§ś566hńâĹÎś={ö$?;˝ÎöŽŽn§‘ ‡źő­Wh&yßűŢŁH$ŞM›6颋.ÔŇĽKFł{÷…B!gšŽŽVW_ýqů|ĂżĆWWW ŽŔ ČjźPLŽcӗMuŽŽN=bż˘?ZO Ľő;ëqŠ%:ĽóUUUĽÂ饘B2Ľ ӘŠC&ă†e>ř }âÓqÇ;âůž~úýđ‡?Ňc=áŹýëßÔI'¨ĺ˗iŚƒúťżűđ˜Ç ¤–,X ˀ‰c´Œ2™VL.†0íö&ztuŁlĺŔÁĘ÷řݤU‰yňˇůœj-^ŻwôqÓܚé†nLULY´hĄ~řĂ煮śvÔqÇłFßţö7őˇűwzňɧœĎÔ/ů+}ć3ŸŇleÚ6Ŕd™ďWŃhԙť“ůţ—H$„É3ßÝĚwióÜü~Öďč˜>f@Ţ iĹÔŃŃĄĄHX_ąţ¨^ SŁ_!ç=ż&ň.ç̝;פ+§ÖL/żź!ľ|ńĹf Ë¸Ě ă_ţĺ{´k×.gÝüL™N;í,§š‘iEőĐC÷*‹éú룛nşEŰśmwÖçϟ§OůÉOëţűLm3mŁLőóSáeǎáŘď˙GíŢ˝[ßúÖ7RďŰŃGŻÖ_˙ő_9Ë?řÁRçx׻ޑźŐŠcƓ~S…ćJísˇćućú^pÁůNeă–[n30cŞď¸.źđʂ3Œůîc*qšŔ ʗ 2™ÉfĚ /Śň ŚNžąňÜgĺ1ˇrŹť“'mîNŢלy3&łŻÁĚ#‘čţż"0Cš=ĹÍä.›v3CCƒJ$l-]şD“1Vľą3™­˜L…‹ĎŰ×ë1˝*LŸăíUú˛ç­N‹ž–––ÔöôPLf@fŹŔLąÂ4şě˛ˇ8Uˆ jůđ‡?¤łĎ~ý„JRť-™\gœqšžň•/h4˙Nžüĺw:Ü9MúÍoŽÔ1Uežöľkœe"ůô§?é´_2aĂ|ÖMus.wŕůęŤ?ގżý­cžŽűîťÓ .eĘՒŠĐcŒÍ›ˇčŠ+Ţî,›÷ńöŰoĘúœƒƒƒ:÷Ü SŻíwżť>ď6Uʛůîc~ç7Tó=Ö|ŤĹ.ŚŠ\ëńXŞŽžFfœÄŒ˜šť ŔlřMŮrӇ˛÷ľy{=a™2đ„ľIÚ/;×$=P’ëúe[/…ććf]sÍ×T__çŹďŮłW_řÂżčěłß¤ŤŻţ{'´bÂ1oŢ\}ůË_uWžČúüç?ëTˇ1şşşSá—Xţţ÷˜Zżęޏę˛Ëޜ Ëf좋.Đç>÷éÔśüŕĘâŽÍ•+W訣Žt–MyoˇŠOŚťďž7őyXłćhÂ2Ŕ 100 îînÂ2Ě\;s Íľ@é˜Ea‚===ę éűşS(ßŐH^“ŢŢŢ) Ăäë¸ăŽŐ/~q­ÓÉ ¤˜2Ô÷Ţ{żSáĹTJyó›˙Bßü桾{÷žźĎűÖˇ^‘łJyž÷ž÷ÝŠő;î¸kÄţGyÔi'f˜Ş7W\qšršđÂóľjŐJgšŻŻ_?üˆĘÁĹ_˜ZžéŚ›ł“žý’K.€ĘfÂ˙&d‘~Ł*›š–ćššk €ŇĄŽpä Sä[]Śżż_‘HT7ŘOŞM}šJVwTęŒ(ąť_v{Xę‰$_PTv_r{oDö`\Š˜)1ü€đkËU^ɟ–ŽMţjTă“Uç—ę’óÚäźÁ/Ť%(knur^%ľe*'sźO˝úsâi˝-|Šs‡Z]ÝpUsíÜKéËŮÖÇŰ>Q .pŞÁ|ôŁWęöŰďpB'Ď<ó\ęnČ;vęÚkŽëŽť^—^z‰ŽźňołśJw kÇÜâ‰ű÷Ż_˙’‰D*°óä“O§ö~úic–R6ďƒiý´iÓfgý‰'žr3ÝÎ=÷]sÍ7œđ‘yMíííjmmMíokkÓă?é,›÷ň o8K*—ůÝß|ÇĚăĄĚ÷řŞŞ* ř̀I3A Ćˆéˇz\%łĺŮ2 ŘŚŮ[’ƒ[űdo˝kPŠ&TLăÖai Čł¸FZZ+ki3÷.Ż—˝źVň/PR,żŃŁş8zœÉAÔÚÚÚ˘†^ŠÁTsy÷ťßéL&,óÜsĎëž{îÓ]wÝ­}űڜvGŚMÓ3Ď<Ť˙ůŸďš1!œą466&߃šäçuĐ ËtuuŠĽĽĹ١oßžÔq°Jă9đŔSË&ˆRĚ{söٯ׍7Ţěü|ˇŢzťŢůΡ§ößrËmÎvĂT÷ŠŽŽ€Ę488čL˜ŮL Ę|ďŽŔ ˜tu–1ŐenN<ŤNŤ8wśYşl“˝Ž[öúäôJoу1ÖQÂTąIž6WÜüÇď‘u@ƒŹƒ“ÓA ňŃ,­Ş—=Íi:’×äVűY]9ŃL5ĄŁŞĚd :ţřăœéęŤ?î´MúĘWţ]˝˝}Ú°aŁžő­˙Ö§?ýɜĎgŃc3†9Ż˜1-Ĺ\n%žąÔ×ď?ŚťťGĺ´Y2ăć›o˜šéŚ[F 2™ďá´`š=Ěwyó}Üý>€â 0&Í Ô…˘aýZj˘,“…yŞCą‡÷Ę~źm¸ŠLĽ‰&dżÔíL† ŃXľ>YŤ›Ľ5-ňŰ*Ô0-š_ُčźč1Νi•2Ŕf‚9çœsśš›çčoţć#Îśn¸QŸřÄÇä÷űł>Ƅ^ćΝ;ćy{zzSˍ Šĺ††ýËů”4ďëëĎzžévĚ1k´dÉb§ĽŐK/˝Ź-[śjŊĺzőŐMÚ¸ńç˜UŤVꨣŽ€ĘCXfvrŻ9Ą€â™ćű@ĽČU]ĆÜĺ‹ĹuGâíł&Xeă…nEŢy"ŸxD‰_oŽĚ°Lö@L‰‡÷)ńÝőŠ|đ~E.şMń/>ŁÄ]ťe M]Ŝ˝ÉksWň™k•^˛;×u-•žž>­[ˇŢ™^yĺŐźsěąÇČçÎy‡B!ľľľçâˆĂĐŒëŘcפçĹ㚯‰yî˝÷ţÔúqÇŁrrá…ç§~śűî{Ŕ™ßsĎđĎnÂGçŸ˙&¨,ćÂ0ŸóYŔ䘍F“SL[cmzŮÚĽ‰ˆ~íY)\ú°HY2-œžhWükĎ+rÉmŠéŮOvČ*QĄ—őÉk´-y­Ě5K LĽXĽÚÚgŮRţç~2ćń&˜ň­oýwj}Á‚ů#Z'eúÝďţ Ýť÷dÝ×ŰŰŤŸýěŠőłÎ:sÄţ“O~]ňÜőβ9Çoű{ĺróÍˇŚŞĐ˜yl&SéĹ5Ő–sŇI'8Ë/źđ˘^|q6lŘ謟~úŠjnn€ĘažSäÓ:łƒů,L×÷z€™„Ŕ %ł‚HŽś=Śp"‘Đm‰çdŤđ”‡ľy@ö+˝BR8ĄÄm;ťęEޏK‰_n*zŐsîH<ď\ł|Ű2ťM“ŠnňÎwž=ľţӟţL˙ř˙ŹM›6z^Óśécű„NqĽ?6›p8Ź|䣣Îg*ŰüÝß]ĽÎÎ.g}ΜŚQm‰Ěkűëżţ@jýškžĄ?ýéĎÎű•ţşnşé}éK_Iműŕ˙J@`ÔkijjL-›ĐĘTťř⋜šyÍćgŮżvL@Ľ!,ƒL|&&Ď'0kM6 a3ŃXTwÚ/JVáOźÚ-dąoHńďŽWâ˙6Ęş`Š|oY%{~•Šáű˝/vŚsíĆŞÔ2óŮIŻ Rˆ÷ž÷ÝzęŠgôÄO:ë&cŚćć9š?žSyfďŢ˝ęéŚ2•QŢň–żóÜüŕűőĂţXo{Űť´zőQZ¸pöíkÓsĎ=ďTDr}ęSWŤąąqÔăßúÖ+ôđÏčÁv^ÇżţëżéG?ú‰9ä`g˙ƍŻhűöŠăO8áx˝ýíoÍúZN:éD§âń™Ď|^§žz˛óž}öYŁŞŰ”Âgœ–üœ÷ŃüüĆÜš­YŤá(_n+d ŰršśśV˜*̀ 1•<âń„ž‰mŃ>O&Âx…ÜěÁ˜żŢŹČŰîVěŤĎÉÓÖdíI^ŤçăۜkgŽátƒúĆ7ţSW\qš<žýżŽšę/ë׿ä´J˘Ę/ďz×;ôŐŻţ›źŢą?3&źrŢyç:UažyćY'ˆóä“OĽÂ2ć\˙ň/_Đßř†Ź7–kŽůš.ťěÍŠm;wîŇ]wÝăLéaSŠĺ›ßüúˆŸ!Ý>đ—š7oŽłl*úÜvŰşőÖŰu÷Ý÷h*řýţä{ńŚŰ.şč‚œŻ@ů1ĄsЍůlŚ˜8*̀1ĺj× …œůƒzYĺ=˛YqŻ%ŋŰögSĽÎ/ŤŢďŹÚ–%Ť.íW Ąxrr¸ĺŽ=“•œěXBe%ž}Óv…ďÜ)Ďe+ä{ĎÁ˛k'6ş?ń˛Ž×AÎ54á#˝bĚdŞÇ䍪ŞJŸţô'€ËíˇßĄGyLťvíRWWˇŠ1-“.\¨“O>ɊȲdÉâźÎk^÷żţë?iíÚăę.›7oV8Ńüůótâ‰'čďx›VŹX>ć9L¨ćsŸű´Î?˙MúĂţ¤§Ÿ~ĆŠRc˜ -kÖ­K.šHÇwě˜ç™7ožŽ˝ö'Nś|Č9‡ ą¸˙vŚ‚ůŽťîúÔúEю ¨$éítlĚgd2dfł|˙bĺšĎĘcnĺXw'OÚܝźŻmófLfŸůMЉD3œic fr—‡ď6T"akéŇ%/[KŚĚmŮ3fŢÖÖćŢ3đ-móuj˘â_zF‰Űvj"ŹZŸ´ŹNÖŇZi~ľÔZ%ĎÜ*Š%(kNr^ŸÜ_[x>؊$d÷Ǥžˆěްěö3—™ďNV39NS°Ś! ߇“u~a×Űľ2ŢŞŸÔ|DUUAľśśŚÂ1é!™ĚŔLśMŠC5ů:í´łRw\Ţ}÷mŞŻŻ†™Ş6ŸűÜ?:ËÇ{Œ~đƒ˙€Ę‰DÔŰŰ+`<&0„Ň2Ug=KŐŐ5ÎÍ6f\ÄÜôcćî2łE ŕ?993$é}mϘě×扴ÉN›gNĘą>Öv„´š_ń{w+qŰNÉ´oš¤ÄŤ}Šę6…x.ąmÄľݚ g*Ăoű{mŰś}ÄśóÎ;WW\qšTŽP($ ć3SWW'äŔ (X,W4×.oP •uňŽ^Öáy†`Ěă.^Ą‰ÚßçĚÍ‚Y_—M ښŠŘRn~úӟéóŸ˙çŹa™Lćťä}÷= }čJ˝úę&aę”ăg œ˜qĂ[˘ă’M7SÇˆËł/,ĎÖYűFO;Ľś°sœâÓą­äë=už|ß=EŢ=VZR›ű`%ß§Ž–ÝĐDmŽfÜ`z™ď܉DBĺä÷ż˙Ł~úӟgÝWSS­yóć:ma3uvvé3ŸůľľqĂÍT1Ÿ\7Ĺ`4Z2G>ŐDĚ1n¸bKźmÚ“°㲡ö+ąľOöśiߐÔ–Ý’ÚB˛&iČj&§€ÔZ%-¨–ľ¸Vž%ľ˛–ŐÉnôŤä,ÉsćByN[ űĎŰ˙Ů+˛÷íß˝ŞŢiă¤ă[4Űű3ů´V*‡öK0“•[…íŰwč‡?üń¨íçŸ˙&]qĹĺZşt‰łn‚=ô°~ň“ŸjëÖmŠăşşşőőŻS_ůʗ„Ša>CŮLSĹ /}č_ŇőíÓĽÇÍŐ÷ŢwˆžÉÝť‰%’ç|Yż˛MWœ0OßߥbxP÷NĽ}vŻŚ’J(ąŽKöúnŮÉyâĺŢá€LąőFd›iËČÍŠűłü˛n”uPƒ<Éšçđ9˛VŤ$ź–ŹK–Éń2§NźmHž…5E{žÝv3çî3(ĺöýĚ´bŠD"#ś}ôŁŃĹ_8b›ÇăŃŠ§ž˘ăŽ;VŸýě?ę…^Lí{üń'őÜsĎkőęŁRŰţĺ_ž¤űď0ľ~Ůeoև?ü7ÎqżüĺŻôŇK/+ŽhţüyÎ9/˝ô-^źhŹ—ę„v|đaÝyç]Îăťť{ä÷ű 8kÖ­ /<_+WŽČúŘĚ×sŐUŐœ§uëÖëşëŽ×‹/ŽÓŕŕZZšuĚ1kœ°Đ˛eKUŽŚű3ôÜö~ýřţÝÎňľíQ÷`L×}řˆ ‡fLXćíß}QzşÝY˙IňÜ>{ąÖ,ŤŔd˜qKCŘ!•’•°Ľ—z{tŻěÇŰeŻďIŽú”AYęިě'ڝ)őjćUËłŚYÖęfyŸ+{Qq4ŚU“˝´FVr*fÓ¨^ :ór+÷ łU9fúűűuß}ŒŘv Ǐ ˤŤŽŽÖß˙ýŐúŔ>4"hsÓMˇŒĚdsë­ˇë?˙ó˙¨€k*ܘÉ<ţSŸú„^˙ú3˛>śŤŤK_úŇWőěłĎŘn*ŞšŠ7fúӟţŹK.šHúĐĺóý§sxŕAýëż~yÄwć={öęć›oŐ]wÝŁĎţ3zÝëNRš™îĎВć Şźę żŽži×ŰţűĹ …f2Ă2†9÷’ć*Ăäęŕ€YǸ Y%*<}âúMŠ^z‡"z@‰Ÿl”ýBWy„erŮ7¤Äm;˙ĎçyŰ]Š˝ç^Ĺżť^Ö Ý˛Ęře÷yÂΜŔ ”‡r Ě<őÔ3Ł^Š3žE‹ęÄ׎ŘöřăOŒů˜M›6ëżţë;9ŰE›đ͗żüď#*׸úúútĺ•–ÉdÎý‡?üÉ ĺŒgçÎ]ÉçűZÎďËápX_ýꨣŁCĺfş?C-u~ýúĘŁTíß˙ç'74c0ůĘ–1ç4çn­›‚vŮ`V 0Ɣ9X• Ěxb*…ř÷_RüŰëewETŠě-ýJür“"~PŃËîPü[ëd˝<ľ-Źňö_ĂĚŔ\”€Ň*§ďc›7oąœÖFůXťöřë==˝ęěěĚyü3Ď<ë„bL˜˙÷ÓWžňE{î9#Ž1ďMfăßř–öîݗZŻŠŠÖ_ýŐű’Ű˙S_űڗsZ–•ÚÇwŞœ“顿ý˝SćźóÎuÚ3˝÷˝ďRkkˈcĘ7ĺŚ>Cg>GřŘę ‡fr…eĚ9ÍšŠ…–L  n¸"\ŠŔ̎A%ŽŰ¤™Äî ËţőfE’“ľŹNÖKĺťh™ěşé˙5,fšwYLżrŞÚŃ12ŕŇÜřÁ÷ë-oů‹Ôş Ý455éWżúujێ;őâ‹ëtä‘G¤Öď˝÷ţÔ~żßŻkŽůš:čŔÔśc=FóçĎÓ~đŁÔśëŽť^§Ÿ~ŞĆň…/|N§žzJjÝoŢ˙ţżVwwOjŰO<Ľwżű*'ĺňrC3oţćsŠż&š1A˜_ţmîöL„eŔT˘Â (ˆ{ŁRŘ[üż‰÷$˙3sŤ›ŘŰú•řîzE.˝]ńNÖŚM§¸5ü^u÷Őf`v …B#Öëë땯†††QŰLŁ\LçňË/ľý]ďzťŞŤŤGl{đÁ‡SËwŢy׈}§žzňˆ°ŒëŇK/qž 6ŽYńć€VËćg:÷Ü7ŽŘÖŢŢ.äf.żĎ¨4c‚0&“­ŇLްĚď ˀĄÂ eÚBĽióTv %nÜŽHrňœ4WŢ÷"Ţ(ĘEUUՈőţţ~卯ŻoÔś`0˜óřŁ^-Ż×;jť šyäázüń'SŰöěٓZŢ´idۨťďžWš X߲ekΊ7˗/Ëş}Ѣ…cžŁýZhćŇ´J3nh&˝ŇĚXa™ł ˀ!0 bÚ~›ő(Ź˘JˆřżźV‘O>*ľ‡FďŸW-Ďq-˛Žœ#OrĐÄZY—53™ř‡HžoA•,39r`ĆJŽçŘŰű•ŘĐ#űĽäôl§ěW{Ľx‘'ÉÓŘwěTřţ=ňźóůŢsŕ„B?ů Ƈď ,×Á4˜mĘŠčąÇŽŕůĂţ4n`fϞ˝zä‘ÇFl;ţřăĆ|ĚŽ]ťĆء{Äúœ9ű+łfV­y˙űߍwźămšÍĘšŠlŽĐL:Â2`*˜٘ÁŰśsî3‚‰ŇüaŻŞSŕgg*ţç­JźÔ+˓|ÎCĺ=qžěe5#ŐÔ˛MŽdy<ÉIç,Ţ8WâšNُí“ýprڙguœą„“çüńĹ6öČűĽă“o€J˘&pćf <˜vGŚíQ9¨ŻŻ×i§˘{ď˝?ľíĄ‡џ˙|“.źđüŹ …Bú˙řú¨ę-çŸ˙&ĺůç_T__Ÿóœé:::ôŇK/ŘśhѢÔňŠËőđÏŚÖ×­[ŻŮ.Ÿ–YÓ)[hĆEXL5ţ: â†+ŞĽËÝÚ5^y޲Jž/Ź‘÷ókäšb娰LŮ0Żő¤šň~ôů~ůzůvŚźs¨ŹUőšŹÄý{•¸wˇJĽ.>~`ڜďL€™ŚÜÂďyĎťä÷ěÇüo|KßüćˇGT~1UhLŚ}ěj§mS:SŠf͚ŁÇ|´ůÎwž7âćsÎo}ëżGˆ^÷şSËgŸ}ֈ}=öĨç7věŘŠË/ŤŽźňăúú׿Š?ţń†˛ &[šf 74c2.Â2`:PaÄx™ŤMţˇCȰŹÖi§d&mîSüś˛oÚ!ťkbíŤ÷ě‘ç̅*…çVĆ`ĚĺöýlůňeúŔţRßýîFlżá†ŠžžÎŠ ÓŢŢ1ŞŞŒaÚ']}őUĘÇwÜĺ[N9ĺuNpćžűĐ+Żź:☼K—čđĂK­› 3'œpź”1LČ泟ýG]~ů›uĚ1Ă-Ľ^~yƒ~ýëߪ§§×™LŚ#ř㗜őž˙Py(a0ľ̀1eśgňů†}XkĆą˛ŢŠ6Łż:D‰ťw)ńű­˛_č*čV÷Ă6ůXîűî^ÓÔsRUŚEf5—rpů嗪żż_×^ű‹Qűúúú)–ůĘWž¤ůóçiJoxĂYZšr… u晧;–Ÿ˙ü—zá…“ďAÄ ŇwÜąN•›… ä|lkkŤţß˙ű=ůäSşíś;ôꫛÔŢŢŽX,ކ†ztЁÎë?眳gô÷)ž+†Ŕ (ˆŽXœ/ŻíQܚ݁† ;¤QžŻŸ(űá}Šg˝ěm%Ź-É{ĺá˛.Më+oÂҊęáŔL9Ý}fZ̈́ěL€ĆLć=2Ą †3ŠŚRށĂ|<ăŒÓœŠ=ô}ń‹˙ʉ07Ź]{ź3ęŸţéóywîšç8Sš2ŸäŔ p˜ś/ŚĺM>Çř|^Ő×ÔŞe°JűjUNŹţ˜ŹÎˆâ!ŮíCROTŠÉˆIƒÉ)‘ĺgŹőÉ xĽşäŻFs‚˛’“§ľJZP#ťş´-pŹ×͓˛oŮĄÄ˝{d÷Dd­¨“ďҲmTŠ´ŐŞŽŽÖš–ÎëH^Űq_kÇL” ˜>󳽢L!Ü*)))Öżőp™÷ "è:đ+XĹóĽÚÚ:íŐĐO‹´IŞŮĄ¸u;d˙ŽBZYidŤŤ¤zťşDEŁfúŚÂZľŐ\Fe)nBžló7)_Ž”îÓÖ({ÖXŻq°oŸufEÂ2Ńẇ„f€žÁ|V#0ƒHP] rŒ¨Đ …Ó~)ŘńŽŞ$“Fę Ç9:!Wç|8űżWĘţżuRu“şťCŽď*­Šĺšď7$^ń“ú(nF –ěDugćŢNNa-űV˜‰4$ӑP a™č"4ô‰‰‰ÖdZąĄ¸Ţ/ˆ Łé bńńńÎ?ĘŰ48ťżúŐf¨(}‡˘­ůĄďÔňÄjńĆľ|V,9§–ż#Më+ŰěBĹĐĎ9jĹÖMQŇż&S…9œƒi Ökš;˜VB„e˘ĎÜSóšîŽ×@ô˜VČfó^@ä̡p*ϸŽ1Ľ~sr˛5rcnÔ3q9^X§Xähn‘>-RłsŠËMVü‰C”đƒjÉî>˙ě^•ŁÜa9îę2áT‰‰v{&Â2ÇÜ[z׹Ď|f3SOüütë­ˇŃázŸ r|ő´‹ůƒź™X7XQW×,GMłbŁźAöGWŠá”wdżíKĹm­Sw0š~¨Őśgw…*Ě7$M…tsoů*Đ3¤ĽĽ †÷@űQaäYqơúŒ ËŘlńš”šŤ#<źÍů&X3oŢ|mذQUUUÖ˝)((ĐÔŠ“Ó”6s柊7ŢxËZîßż@7ßü ëożýŽślŮbm/,,´k̘Ń~Ÿł)Ľž`ÁB-^źDEEEŞŻŻWffŚöŘc”:hچ˘h1÷œŔ Đ3¤¤¤XĄřÚÚZĄ÷2Ÿ[Í{G`€^,œöKĄ˜śL™™:°q”>¨_§Š”:őVŽÂ4Ů.Ł„ FËţîfľ<ű˝kŤCŸW֠Ζ[Ÿ˘›öPFFşőšuT{Â6ŃŽ.ĚńÇŤĽKżĐöíeÖş ¨xfš››őĚ3ĎiáÂĹ^çUUU[ÓŞUŤőÉ'ótéĽ)''Çďc˜0ʢE‹őÄO{ý­\šĘ:˙œsÎŇ~űMő:§źź\>ř°6mÚěł˝Âz.‹}ŽŮłÔ1ÇĚV4tĺ=ĐůLXÂ|ţ¨Ťë˝Ÿ˝{3óyŢő%t_7mř†!Bľë1Ľ€‡ Ź[ ’#1NńG*ńуdűí$ĹČ z|Üč,uś›‡jđŔA~{œ{}ŁY…ŚŁáŹH˜Ş*űî;νnŞĚx–.ᅗźÂ2iiŠ5j¤rsw…cLŐn1á̡:˙űßÜçfeízÍĎúüó˙ScăŽJCć:žaó÷ÚkOM›6UýÜç™ 6Ÿ}ś@ŃЕ÷@×0•^ŁńEÄóš›×ŃC…ĐnŽ 5fĐfŕŔţÚÝp}Ô¸NŐIaś#ęáqRüĄd;d€ěs6Şĺ_ßľŠ&7*K GŞ3ë€d5$kúŽá¸o÷ jWˇc2şşÚ‰+„âbŞÍ˜ŔĐśmEš;÷S÷vÓ é˛Ë.śJZ›÷łiçôŢ{Xű6nܤůó?Ó̙3Ú\żŚŚVcÇ/žĐj e1>ú¸–-űĘÚ__ß ďž[iľˆ2Ěu\a›-^×\s•FŒn­›Ç}â‰§Ź 3ĆkŻÍŃ´iűuřu˘Â Đ3™ŕ„ůź@{ŚŢÁT•Ą˛ @ôQa€^.Đä#ůC˝9633Sن Óô-CoVpćŘÁJ|f–l—ąB2qĂ2Úp%ÝšżZ’;÷Ÿdn˘‘C‡YŻQ¤Żk$ŰťßÁDWľÓFÉÓgœćî˙n~6ÓÎ)''Ű˝ńâ%ăÄO°Â2FBB‚fĎ>ĘkYY™ßëLž<É–q=î 'ç^ŻŹŹŇúő˜Ď<ţވ˘g1Ż1a€ÎA…W5™@Ëfđڰp\7L nReR˝ŕ͑ŻřsFY“Kg×˙ČŠOŐôŠa4v {€-P ŚX „Ë÷›–IIIÖ|ëÖ­îmŮŮYm*ŃŘl6˝‡ťeÓśmŰH~~ž×z^^Ž×zcc“{ŮóqÍľ=[BůSRR˘aÆ 1áŢ7-hľ“El2ŻŤ ˘9:f@T˜°ENNŽF ŽŁ×Žş‡Ł×˛^óÚô´@L(EEĹ^ëŽp‹iĽäčۘž}ákkëdˇŰýî=5ç×ŐE"ŤŻ't 4¨0Ÿů\-xűĚki^SÂ2‹m݊1Áś‡Ş2cžŮ6bÄ0MظIKʡjeîva÷ŮłŹĆ×jذ!^-‡\‚U—éŒvLńńńjiéěš:­Ěă|ůĺWîő~ýúşĂ1ééťJY›oaúSSSă^NMMąŞÎt„9?%%Yőő Öú”)“tä‘G='++Seî9€ŢÁ˙“““­j›Ž–´ˆ-Ś2ŞŠKP kđŻ.Uyyy3f´ŽýśBkł¨)žkđ–ŘbÓěőٜŻĹĘĎĎWwЕn^ý mß^ć^Ÿ6m?÷r˙ţýőŐWßX˕•UV%ĎśLŚĚʕŤźŽ†‚‚­_żÁý´˝ŽŠ*ă 7ECoŤ*ôv&h‘••efęęęÔÔÔ$t‰‰‰VUW+at žr ,áV UĄÄTŇ:t°Fd ԌÍC„Ýc挥•aŞË uWGٝŐeŒÎ¨vb‚'ښLssł*++ľ|ů =đŔƒzűíwÝÇôíŰG<Ó˝>uęŻk<÷Üójhh­üb*%˝ňĘkި¨ô8~˛˘aňäIîĺe˾ҊßzíŸ;÷ÝxăMúÍo~݇zÄÜî(*Ě˝“ ^dgg[S4Cůˆ.óÚ¸^'Â2] 3 ę̡ŮöŮgom˙¤\krĘľ!łRč:…;˛tĐśĄÚűŔ=•™Ůńś>Ńb‚;ŃţvămˇÝtrr’.şčŤ,š‹Šě2cĆúä“yÖúŞUŤuë­żÓ AƒTZZŞ˛˛r÷ąƒ Ôôéű+8`͛7_ŰśY!ŸűďPŁFT^^ŽUĺfÝşőÖqŚ2ŽŠFcž]ŘQm% ś™Ę%f2-jÍLĺ󚏍Úĺ›ůRƒy=L8Ćós*v3 $SYÄTŢđˇhyŕŔ1t¨~°˛^˙żHľ ”î ŠÍ :mĺX6Ü €¸t´şL4˜A3uŐŔŹ ť\tŃůęׯ_›}§œr’UÁĺóϗZë55ľ^m˜ŒÂÂAşôҋ˘Ö;Ţ †^vŮĹzđÁ‡­ĐŒů]1a_C‡ѹ瞭ŽrÝo0ĚgWHĂTë4Á3wMć3 Ašč0ŸĹĚçkó%×d‚2|Š {!0Ü|ƒ1í9Ďľl&Nœ ŇŇí:yő^zzĎŻäPä×Fřâœ˙;iÍ^œÜWăÇď˛SD׎RĆ<§Î€MLL°ĘX2Řúů'L00b*/¸ŕ<Ť=ÓüůŸiÆŞŽŽśŞş˜ę.SŚLŇ~űMľŽ‹Śž}űęg?ťA ,Ԓ%_¨¨¨HľľľÖ㚀ÓäÉ­ÇĆ *ąq…8€Ţ,Üż|ąš/.Œy\€u×ď1wMśŰl>“Ů—e捍Mó@çúƗ™\ËÍÍÍŞŤŤUK‹CƒŞŁ‚f|÷yŽZ6€>řXs żŐź…Î3cËÍŢQŸ ZŻšƒ6¨)ŢŽŢ$ą%^37 ŐĚ­C••žŠéOSż~ýźŽiOXŚ;ˇbčJf@D:34cčˆ#×âş+yK˘&” ЛCWiy~‰zƒŃĺů:fÝęӜĄ…4yň$Ľ§§{CX c̀¨ 74c¸śůîOMMľZ4­Yó˝–/_Ą3W§hEI‰ŢžJÉőꉲ’uÔşQÚ§źŸ233ľ×ř=5räˆ6툢–č̀ˆŤ2h¨mž!ŮcQ*,¤ožYŽäőÉš,O‹únÖüAU•Ô ž Ť!Il˘)%•™”ŽÂQƒ´Ď>c#Ž*ÉśHöôDf@ťtFhĆßşŠ6cÚ \¨Żż^ŽěŞ í˙EĄ–ĺnÓÜ ڞZŤX”Ӑ˘ýˇjż’BĽ'Ś*ťośĆŽÝ[ýűD­Š a˙̀vkohĆ’ńמР @ůůůÚ°aŁÖŽ]§ŒŞtMřj –ĺnŐâ‚-ڔU%‡?—î ÎůżÁUYš\4PăË(-9Šʌ1Ü %$x˙Ó,œL Đ a€Ŕ̀iOhĆßöp‚4&PbÂ%C‡ŃÖ­Ű´zőjeWgj˙¨ĽR_ćoӒ~[U–Z§î$Ť!YăJ ŹśKý[˛•œœŹŒ‚ >LC† –ÍfksN{ŤĘŰî~€žŽŔ č°h…fümó¤1“ÂÂA8p€ślŮŞőë×+Ľ"EƒŞó5kű(}Ÿ˛]ßäkmVšŠŇwČŃĹů8çSí_“Ąa•šÚ§˛@#ę󕔔¤„”ĺććhȐ!Öso{nŰ-–Ŕ ˆŠpB3F¸-šÂŮf'&83hĐ@ŐŐŐYá™M›6)˝&]űTVóö&UŘkľ&­TŤ3ˇk}V…JSëŐߢhŠo‰WŸÚT ŤÎŃČę<ŞíŁŹř4Ť"ŽyŽŠůŠ0 żŐv)==˝CĄ˜öeÂ= 7 0˘&Th&Ř1áT›qm3|Ă4iii5j¤FŽĄ˛˛2kűöíJŹJRߖí_9J-ĺ-j´7ŠÔśCʼn;´-ŠZĽÉ;TžT§šÄFŐ&ÚՔ`—]-Îyk¨&ą9^6Ĺ;ç6Ľ7%(­)QšŠęӐŽM™ęۘŠ>ö %ŮwUŒI‘˛˛2•ŸŸŻţý ”››qЅ° @ç!0˘ŞŁĄ#Te™PŰMPĹLf_SS“ĘĘĘUZZjhjjjUčHVĄ=_ŞSëä!Đs8‰wîłĹ)==ÍzĚ>}ú(//W‰‰‰AC*ŃʄÚÉ1˝ bT8Á”Ý%ÜЌIľÇ{†AüíKJJ˛Şź˜Éě7“ißTSSŁ;Ě´ĂZollTSSłš››ŐŇŇ"ťÝn]ĂfłY•cL{ĽÄÄëzŠŠŠĘČČpNéV‹%łn+T0%Zš`ŰŰ{Âǘ ąŔ 1Ć7LŇ]?œ‡艤ÚL°íĄöšö›É„\ĚÔŻŸ‚ě9GëřöbËěžă-Œżť̀N*ŔÎqí­,ă)ÜǏ–Ψ4j_{Žč­ĚŁźCfš{śg2:ZmƾϪ g°ăÚ#’pJGÂ0„evˇ]ă.ŒÁűĚCüJ|Ă"=ĄE“ŃžŕŒçţ`Çř×YÂyŒhe"=á ՝1bzׇň––Ůl6uWáśh çŘp‚1‘śfę¨hV!(Đ=˜17ƒ1z3ôńńń˛ŰíjnśwëŔŒK¸Őf\ÇáV‹ioU™HŸO¤:ŤĽ5ËŒšf ôfč̇uœ¨ŻŻWrr’bA$Őf"9>ÜđL°ó˘Ľ3ŤÄ”čfĚ͌Ĺ˜ gá˙łĂĚuĎëľľľŠ5ޟ!ŇăĂmkÉńéăľçšuŐĎ€VŽ17חÖ› g Â 1ȡĽQë‡uŠŠŠÉꊋßv‰¤M“ç9F4Ű)şV4B:ť­˘ĂŒľ™17›-žÍ˜c5Ä6*ĚŁ|?Űl Öśşş:ĹŞö~C'š•d|ŻŐ×lďůčZfŹÍŒË˜ą7OŒŐűĚĂ\e`ÍÜfłYŰ*+Ťë:éęVLĄžCGŻ€ÝĂ5ÖfĆŢ<Çâ@ěŁ%1ơ ‘+Ta>¨›ŠššY JNNVŹó ‹DÚŽ)Đu˘q˝P×îN×@ű˜163Öć–ńťáËNÄ6"°Ä(ĐZŰ2•••Ť§‰öD ÖK‘NŃ~>čĚ›ç˜› ă8ô fˆ!ţ>ˆ{V˜1ŢÍźŠŠIľľuę‰:#ʞťô¤Ÿ '1ckfŒÍsĚ-Đ8c;Ä&3Ä ĎçžO­yII‰ZZZԓĹbŕ„ @÷fĆÔĚؚçX›ď˜ă;Ä>3Ä0-‚LOeW™ŘŇŇRőŐ*ŠŁşëó€fLÍՊɌľuf›n°ű˜ Ćx~‹Ĺs›Ť-“ë›/6[źęęęUYYĽŢhw d0xŰĚXšS3ckŽę2ţÚ1ůŁą%A fů Íěj͔$‡ŁQJH°)==]˝¤ŚŚĆK3UeĚؚż/Gń%)z3Ä óĄÜáp¸çŽmŽ–L.ć[0ŚçriévkĐ Ж ˘1´]՛mVeϖL.T— g %1Îß7\\eb[ż ÓZ:Ö|௏Ź€]̘™oXơŐečy¨0@ŒňŹ2ăb>ěŠ2Žô†+0ÓÔÔ¤ŠŠJ544¨OŸ>îý@oÔZ™šTuuőÖX™GKHH°–=Ă2žÁƒŕ ąŔ =€gxĆ_Ć|Đw…fĚŔ† ŐŻ__ĽĽĽ čmjkkU\\âUĽŮՆÉw"$@ĎD`€â Ćř[÷W]Ć÷\ł˝ąąQvť]%%ĽÖ@@^^žRR’ôtőő *++łžXfĆĘLH&))ÉŒ –ńoó Τ 6˜ ƅš1ëfť‘œœŹććfk2EEEÖŔ@nnŽRSSiŐ€Ō‹ŐŐŐŠźźÂú"™aĆĂLUfWefπL$aťĚc|ŤĚřnóšqľkr-ťJ̚ŔŒ9śľ_óvkżŮ—žžnUqőlf ąŔŒ}™ą.óe1SMŚŚŚĆ3\í—Ěx—s{šśť–# Ë0n@ě"0@ '4ăZ6öÍ kÝ5hŕúđoÖÍ7kĚ ‚Y6óĘĘJç¤6áy Ď9Е\Aßšď~Æ1_ó Ćx†c<çŽó=ŻAX€ž‡Ŕ 1*ThĆóťg€ĆUmĆœq­›ÁĂl3šÖNšÂ˛q]#‚4ˆ†PĄß1°ÖmÖ˙ľÖ]e\Çúeü­ű^—° =b˜żK ĐŒëż+$ăŮŚÉs›k ÁĹľÝó1Ä ;đ7ţĺ/ěâŒń=ÖłS°J5ţÖ@ě"0@ŕ[mĆ7HăÚď9(ŕŮŚÉóüÖĘ2ňńÜć:Ř\ă\F°Ę0ţÚ,ů†gë‰° = zˆHZ4ŽĎ 2frU—ń Éř ĎxśyşR pK°śJžh­*hˆmfčAľhňÜčżo@Ćßľ<÷ť›o &×6ű ĘOfčU›1|ƒ3fnÚ+yŽkÇä;H,Ň} g"0@/¨ÚŒkŸ§PDžD ş :˘Ł!–hi@ĎE`€^&XľÇšD€a ])Ňń(ĆŻčÝĚĐK…œń=ŢUd°;t$ěBPfčĺ" Îř;čîËž̋瀕cĐ’˜mř$ @, ÂE`„j @ ş-f@‡1P€XB`˝ ô*fĐŤ˜@ŻB`˝ ô*fĐŤ˜@ŻB`˝ ô*fĐŤ˜@ŻB`˝ ô*fĐŤ˜@ŻB`˝ ô*fĐŤ˜@ŻB`˝ ô*fĐŤ˜@ŻB`˝ ô*fĐŤ˜@ŻB`˝ ô*fĐŤ˜@ŻB`˝ ô*fĐŤ˜@ŻB`˝ ô*fĐŤÄ ˆqUUUš;÷­\šJĄPa1măƍşě˛+U^^a­ŸţšşňĘˁ༺şZGqtĐc•——ŤhćĚuä‘G¨oßžBç8ę¨cTYYĺ^˙ŐŻnҹǣŽâď=qǡĩžwÖYçjíÚľîőłĎ>K×\ócEŰ /źěËO<ń”.žřB%%%Ў 罳ťß_ž^yĺUýńˇš×ÍkćĚyUDąŚŚ&[Ó_,ÓĂ?j!N:éD!šŤ~ýúéç?˙Šââ⁒iť4pŕ kŮTFŠŹŹ°*˔””zwÇwꀌ[Ą Ť˜ę,ˇŢú+„‹Ŕ éÄOЌzmknnÖÝwß§çžű×ś—_~U—^zą€îŠŔ h—„„]{íUúřăšÚşuŤ{ű—_~é÷ř––ŤeÎ[o˝ĽĺËW¨ŹŹÜŞ RPP É“'éä“OÔȑ#JYY™ćĚyĂů¸ŸhŰśmÖuŇŇR5tčPŤşÍ '§üüü ×¨ŤŤÓŤŻžŚ?üXk֬ю5JOOӐ!C´˙ţÓtĘ)')//ŻÍyßżVgŸ}Ž{˝oß>Î럤††=őÔ3zç÷´yófĽ¤$[×:öŘŁ­°Q||źűœŻżţF—\ršßçuýő?u/ßyçš>}ăp8œĎőtŻűčĄëOú?żÇ766jöěăŹZ.]t.ťěíżüĺÍúŕƒ<Öo´î×W_}­'žxŇů^úJ55ľęÓ§ŚL™Źţđ, 6´Íuţűß˙YՍ\ čŻ_üoŔýGu„~űŰ[UTT¤GyL ,PiéveggiĎ=Çč´ÓNľŢÁ|úé<˝˙ţÎçřľĘËËT_ß ŹŹLë}h^ˇ“N:Ášžĺ>ţńǟÔ}÷=ŕ÷Z4Ë˝üńÇď[żžĘËË­ ڂ ľ~ýzUUU[Ç 0@ăÇďŤăŽ;F{wşB{wř°:‹ Ě˜ŕ‹‹yî&4ăĎťďžëľ>qâ 8PÝĹƍ›őë_˙Ö+,ăÉülżýíďURR˘ŽhjjŇĎ~öKݰŒŻG}ÜŞ"ăëç?ż)ä{Ů0•WĚą+WŽR{˝ńĆ[ÖűĐ7,㏠ýýďwŤłDăwÇ玞úÚ6aOćžöŮĐ٨0Ú­¸¸XK–|áľmĐ ďęˇÝvťśnÝć^7í[Î;ď\M˜0ŢŞÄbÚ4™ę2&0c˜Ŕ̙35kÖ!îsLčŕŢ{˝Ű٘ö7§œr˛Ő făƍÖ5LĽ —żýíN͘q€ť-Ž Ҙ0†yL—ÁƒëüóĎѰaĂŹś7ćŸ}śĐ˝ßTö0mfúőë'Ěă˝ţúëüăŽ;Ú ™ę"ŚŐŒ'Sä’K.´ŞžŒ1\˙üç}VŘćG?şÚë8SŐÄՆÉӖÇ_iѢĹ^Œťďţťť‘ŤBŒ žÜyçß˝Ž3fŒóýzŽŐ–Ę´“úĎž÷ G˝řâKÖű9Đűľ˝˘őťs÷Ý÷Ş˘˘ŇëÚýtěąÇXí°L…Ӣ˟t63 "ŚúGEE…–.]Śx°MŗYłfš—Mĺ˝÷>pŻ›0Ŕ}÷ÝăüĂ˙h÷śŠS§hŔ€çÓďso{üń'˝3O>ů”>p1a™‡~ĐúŁ˝‹i-tÁŤşz‡ľn‚ďžűžŞ1Ţ~űŻÖQƒ Ňż˙ý/edd¸ˇÍ˜q nźńš;÷SkÝž}öy]s͏ČčŃŁu˙ýwť?řÁ)1b„|đ!÷1&p`*t˜Ÿ5--Í N˜ŔŒ/łÝL‘2ío<3Ÿ|2Ďzîžm Ě6ĎJ%&¸4kÖ!ęnţřÇßëCv…}N=őy潪Á,X°°CăôÓOÓ 7\ë^?óĚ3tÝu7háÂĹîm&ăyWŻ^íuž}űčúëŻqŻ›؝wŢŽ_ýęV 2Ôů>Ś=öŘĂÚg‚#fň ¸˜×ܡe—y­LK¨őë7:§uÎßłFÝu×ßÜǙ@Ő¤I5{öqVĘ0ż›Ë–}Ľ#Ž8Lэßó;ŕů߂֟ÁüžÜ美 ™ĘPżűÝ@g#0BúéOÖq#GŽôŞlňć›o{í7ű<Ă2.&źđđÏşŰ;}űíˇÚž}ťňóó­0€ŠBăÉüaÝ3,c˜?â›íŸžDŁFŇ{Œ´.o˝őŽ×ńçž{ś×ü ÓÚČTżqýŃß0my‚fL• ß°ĂŮgŸŠýëawŐĂTăé,łf˘;îř›űţ™š •Ěœ9Ă}Œo;Ś#Ž8BÉÉÉęNL¸Ä3,c˜Ę-Ç{ŹšréhK&SĹĆTüńÝvÖYgzfLĹźMĂ÷uŢž˝ĚވâůžĎÉÉŃÝw߼Ž2×q…˝1ďפ¤Dw`Ć(//S´EăwÇTŸń ™}ž×9ć˜ŮVUĄeËž‰Ŕ ˆ ÓZĺŽ;nSBÂŽ^řVäxűíw˝B$ž\a—ďż_kf6mÚÜŚŠÍL÷{K.šČšüń}.O=őŹŽńĺűXëׯWssł×Ďĺiřđamś™ÖK}ú䍤¤Ô˝Í3ÔmćńfÍ:TŻ˝öş{ۇ~äĚÔÔÔxľî1Ž?ţXu7Ś"‹?ƒňZ÷}ŻD*??ĎÝŞËSaá 6ŰęęvUĺ™6m?ë}`ކ Ôüň—7[Żő¸qűXŸŃŁ÷ĐžűŽó{ýŽ0ŻĄů0ďGÓ˘j˖­Öűˇ˛˛Ęë8óœ˘-ż;[ślöÚgÂZSŚL–?Ś•@g#0:Ě´2­iŇÓÓ˝ś—ś9öwŢS8***­šżj"ýű(Ś˝ŤU“‹ieŚpTVVZáimď,Ś%•g`fîÜOÜa…?ţÄŤşÇđáĂ5věŢęnşę^ś÷q ôӟ^ŻżüĺŻ^Á”ŇŇíVĽ3ŚÚŠŠntŃEhňäIj/.3mŒţ÷żŹöPťC´~wĘĘ*źś÷éÓ'ŕý.(č/:Ҟ{îiU}0-ZÜŚúĂŔڄe:ŞąąľZE Š4‘čč5|[ÉtG&ŒˇÚRmŢÜZÉŁŞŞZ_|ąĚŞâńţűď{{üńÇ(6›­ÍśÚÚĐsjkkźÖMŰŁXwŇI'jôčŃzěąÇ­Ş=ţŢćýf*°,Y˛T7Üp­N;íTEĘ\㦛nq‡p|ĽŚŚjŸ}öÖęŐkT^^ĄÎ­ßßëťngTÉŔŇ%—\¨3Üš|‘Žťî}öŮB÷ţ'Ÿ|Z't‚ňňňźÎëÓÇ{ýŠ+.Óœ§Hôëׯ͜mۊ”››Ťp™pAzzšjjvľňů׿°Účô$ŚĘĚ?˙ů/÷ş m˜ö@‹ďjŸcŞz̞}”"aîŸg+"ă믿ёG𜢢"Ż–TFNNtŰí.{wnťíOVäťďVjůňĺúöŰďŹ*0ć˝ébB!wß}Ÿ;lV›ßPćĚyĂ+,cÂFÇœ\3mŸĚdsÖYçvj`&Zż;ůůŢżŻĽĽĽjjjRbbb›cˇmŰ&:[ěÍtš˙řG^ŐBjkkőŕƒˇ9nĈ^ë_ýľ"UX8HÉÉÉ^Ű>ůäSżÇŢ{ďúÁÎĐĎţKçóyČ uz._}ő•zšcŽ™íőş˜ŔŒŠ2SWˇŤ́N8źa‚ŚŞŠ'ÓţiÆ ĎšďžÚT 3fŒzós™–Dfn‚#gœqşn˝őWzńĹ˙ęşëŽö:քjžůfš"eZjy:眳őË_ި™3gX­ĄĚkbřVńé ŃřÝ1Տ<™űňŮg ükZˆĐŮ̀ˆíąÇ(uÔ^Ű^yĺU­]ťÎkŰQGéľ>oŢgV›_&|0{öąşč˘ËôÇ?ŢŚ˙ţ÷˛ŰíÖ>Sáâŕƒgz˙Üs˙iÖزe‹^~ůeŤ%ŃGÍŐ#<Ş•+Wz<ďçűôÓĎŞŹŹŹÍsy㍷œÇŁŤŽşV˙űÝúđC˙-q:Ęxđ¨Í‘﹁ZD™ ĹäÉÝë˗Żp>˙˝Ž9î¸cŐGu¸Ďs­Ő•W^Ľ÷ß˙ĐýZćţßrËŻőÖ[ďx߯__Mš4Qąěž{î×xž9äpvÚYzöŮ˙xí7ŻÓĄ‡Ňć<ĎveţÚRŐÔ´ ˝TVVy­›śgžL ި¨XÁ„óŢ uL4~wŚMŰOIII^ǛűYUĺýsžôŇËVĹ:-™@ť\~ůezď˝Ü\7Ő6îšç^ýőݎť1b¸8`+(ă:ćşë~˘łÎ:CSŚLśÂ+VŹĐSO=يŠJk2,?~_zęÜ×9çœZÁ WK ;jtńŗéä“OҐ!ƒľyóýď/8˙ř^í>'33CGšëý&źóřăO޸¸ÄZ/-ÝŽ /źDgŸ}ŚU=Ĺ@.\l]Ç<Îâş[SjjŠ9ä`E›ůŮsssźÚé<ôĐ#Î{PnU„9昣ݕ`RSÓŹ{ăň /[ŰFŽa…—<{ěąZ´čskŮü/źđ˘{_~~žóő˜Žö0÷úĺ—_Ó÷ßďŢś}{™nşéĽĽĽŠoßžÎç]ëžżžL ăşëŽ•ÍfS,KH°i͚5îuSĹČźV&$cŢo6lÔĂ˙ŰëÓÎČ´PrńWÝçüł<đëZguŚľ­˙Żc{ě ZmĚďÜÇĎŐ]wÝ­PÂyď„:&ż;ć=rřáł4gΛîÇYż~˝~řĂóŹ÷zvv––-ű’ę2€.C`´‹ůƒž ľ<ýô3îmŸ~:ߪz1yň$÷ś[nšI矑JJJ­uóÇ~óÇ3ůcţ°ţ‹_ÜčľÍŽşęJŤj…Kuőëřţ˜€Ć7ţLîm™™™úÍo~­ŤŻžÎ]ĹTç¸óÎ(ӊćüóĎUg1á•×_Ă˝žvíZÝ~űߏĺ!C†č ƒZ+ëŒť—śnÝę>nŐŞUΟĺw:öŘcôŤ_ÝäuÍC=Xwܑn…Š|}ôŃí­˜ę wŢyť.˝ôŠ6Ą˜0á‡@ޏâ2͚uˆbÝšçţPo˝őśóľŘf­›X°÷˛qůĺ—z˝‡ Şx˝žsç~jM†ŠdŢŤGq¸UąĹĹ<ŚŠÜâɄŽhUW $œ÷N¨c˘őťsőŐ?Öźyó˝Â9ćż ž÷oÖŹCŹ€‰–L Ý.¸ŕ\Ť˛†§üă^9÷şŠ¨ńđĂjß}Ç…źž ÜwßÝ>|X›}gžy†ó÷7+999č5Lŕć׿žEGqX›}Ś%Đý÷ßcľ ĹTŔš÷Ţť”’’˘ÎbžËʕŤÜË矞ßçńő×ß´ŮfîĎa‡ć÷š'œĐžvL.ŚĺÓc=â÷ŢúÓˇoýĺ/ęÔĐQW2­•îťďŤŞJ(ćőşţúktúé§ym7aޟ˙ü§JHđŸ[_ľjľ57a*ßs}]}ő4qâř Ç„óŢ ç˜hüîäććęž{ţá|ő xŽ áůśr 3Pa´[VV–†¸çžűÝŰžűî;˝ůćŰ:účŁÜŰúő맸W ,ÔoźŠ•+WŤ¤¤XMMÍĘÉÉ֘1Ł5sć ç9ł•˜˜đńŽ=öhMŸ>Ms查>šŤ˘˘"•••[­_† Śý÷ŸŚ“N:AůůůŻa‚;Ď>ű”>řŕC˝űî{Ú°a“JKK­Ę+&Ü3nÜXŤ•ÓôéűŤł™űňčŁëąÇž´*o˜ŸÇ0Ď?99É}œi‹cBG=ö¸žřb™Ő ÉcRSS­8žá‹ăŽ;F/żüŠ×6ÓĘÇT­é(zřýďŤ .8ßş‹-vž–%î×!?żFŽŽC=T8˝SGťĂ€ýŻŮCÎ÷ĎGúđĂőÍ7+TQQá|/7Ym…ŹiÓöł^ƒ>}úř˝†yŸ>ňČżôÄOjéŇ/Źś\Ś‚O˙ţýÝ-Όn¸Öy­Šz饗ľ|ů UVVY-žĆŽÝŰ íˇßTçkńAŸo8ďpß_ŃřÝ5j¤óç~T/žř˛ŐŇmóćMjiqXíŸ~đƒSŹ˙n|ôŃÇ łĹEá¸8?ËÁćqÖ]SźÇÜ5ŮvnłůLf_–™766Í´m[‘N:é^Űnžů:ţřăĐII‰8g-ΊjçÜî39vÎ[<&‡ÇÜwR€ő`sße_ÁöY¨0ĐØ*!žL›ŞĂ›%´"0Đ<đŔƒęÓ'_UUŐzöŮçźöwÜąVh­Ěĸ7ęŃG÷ť/77G^xž° €÷ŃGűݞ™™ĄŰożMšššŔ.fb\SSł  ˛˛2ĹĹĹŠ_ż~:đŔtÎ9g)??_đ…ăâü,›ÇXwMńs×dŰšÍć3™}YfŢŘŘ4Oč4II‰8g-ΊjçÜî39vÎ[<&‡ÇÜwR€ő`sße_ÁöY¨0€^…Ŕ z3čUĚ W!0€^…Ŕ z3čUĚ W!0€^…Ŕ z3čUĚ W!0€^…Ŕ z3 Ă‡€Î'€h 0B"€î Ô8.3  2ˆEžăZh@ f€%Ґ ĄěNá„a<ǰĎOfčĺ_ ÄšŔî`Â/‘śgrOpfčĽü (dhiiĐřNJxŒgH†ŕ 0ĚĐ˄”1ëţś…{˝`Ű€p ´Úîű…/sœëX!‚3ônfčE‚…e\ fÝnˇ[ëfŮsťçq@wŕŞ,ă ž˜ułlć6›Íkťăňת‰Đ ˝zPA3™Lssł{ťçÜóü@Ëá>.J¨‹żJ1ŽíŽ/|šŽ1ó„„+Vľ™úúzk̈́fL‹&WľĂ38Ch€ž…Ŕ =€oXĆs2ĺeMXĆ,gd¤+==]@ogB1ŮŮYJH°iǎŐŐŐYĄS…Ćh\B3ôLfˆaÁZ0y†eĚ|ӂ)55Ev1_0‹ˇY-šĚXšaB3žhŃ@ĎC`€*,ÓÜÜŹĆĆFÂ2@Žą3š1cj&“ŕýg4ϐ Őfˆ}fˆAĄÂ2vťÝú`o晙„e€ĚZK‹]ŐŐ;ÜĄ›Íću Ąz3ĘPaSQĆ´b2f’’’Ź’˛B3ci V`&>>Ţ Ä˜š'B3ô ń1Í7,cŞĘ˜ŔŒYÎÉÉ€đ™15חŇĚX›Yöƒ=bˆďróaÝsŸ™\­˜ňňrŰ|ű@pfL͌­šÚžűe<Çä B4Ä&ţŠ@Œóüv‹iĂdŚ„„Ľ¤¤@äĚؚcsˇQa€ž‡Ŕ 1Ę_uS&ÖĚiĹtŒcós VeÄ3Ä0ó!ÝŐCٔˆ5“ÍfSRR’´Ÿc3cmŽq7Ďą8űĚƒüőIv•†ÍĘĘ€Ž3cmžcož¨2@lKˆYž˝“͇vç%''+–đœö‰‹‹:WëX[ë؛Š8ă‹cl€ŘG`€㠘xöM6ßf1“Í– řřîY@Ž`LtşŸ ÖDk3cnŚ%“3랡Â3Ä.Z2c|ƒfÝ|`7ŇŇŇÔ]xVż!,Óu¸ďŃĺs3cpţĆć@l"0@Œr"Ě7[Z3ŚS’v7‚Ý Ż@Ç´Žš9ÜUfo g %1Äóƒ¸ďrK‹C6›MťݟçkD™`€đ™173öllŽńbbo@Ĺ|łĹ0=”w÷sén×ë)˘9č @ř\cnŽ18ĆXˆmfˆAŽP‰oů׎ü€ŢŃ` Á˜Čş_í}Í]×cP 8Ďń×xœŮF`€ŘF`€ć =¸z'wőăvö9Í÷žF:HĂŔ@h­-Ń[ÜË ö˜ GčžaZ6…'ZĄ•öTŽ!4‚2ô$f@X" ŞP&ráţüá["mŐE‹&Л˜ †ř Utˇ I8χ˛ľíçďޅ šPA :ba|„‡Ŕ 1Ş+?ˆG#ӑçŰŰ" ˇ„SM&Ü 2„kBc €ŘG`ŐѰL¸až‰łK°{Nŕ%Řqá ć0ŕz:3  Ž„e:łâLoć{ßÚSQ†Đ čí̀v –iiiQSS“š››­mf˝#×í­Â ŽÄÇÇ[Ç&$$(11ŃZ|!z33ŔŻöVˆqmohhPccŁB]‹pLhţ°‹+dććŢ'%%)99šÝĄB5 §"0ÚhOXĆs[uuľ5mh,Ѣ¸uú>ŽDqujR‹ŹŁ;CÖJœ;çň™ďşd\řÇşŻçóXžŰwžďąĎęXšŁÍsđ8?’cĄžƒĎů~mݗäœr5&-MćähxV–233­)P‹&B3 7"0@Œń Ťtu…–`a3/))QYUĽŢJüZ‹×{YşMXĆu]}ţƒ*ÚMay<ë<śőÚ ÎĽmMΊJs+Şu@V–N雯źúzőéÓÇ žř ŔŠżą9ĆUˆMfˆQÝ­•‘y>ĽĽĽVXćŠäĎ´6ž4@ĽuzXĆ˙|×ĂG\Ő%TFŃËÄy‡eÂ=ÖcÝ4gú¤˘JEMşrçłs…fĐ1´ öĹ ŔC°űÁŞËTUUŠśśNo&~$,FĆ}e˙•pÂ20‘IX&豊<,ŁŽ…evm—VÖÔë…âíÖkc^ŁÖk~ýaô4f@ťš‚ÍÍÍV cł˝LŸ'lčXX&ěHr?†çźM(EŃË(°L Ç –‰´ M€°ŒëźO+k´ąŚĆzĚkŐz-B0 ÷"0Ü"Š2âš^[[k­n[ďd €ńšŤuYX&ĚL$dž–ńŹÓĽaydî–1ŰZZš_Qc˝FćľÚuożŚž؀ž$AÔĐĐ`Íר¸uC°L–-]łłÇkrÚőOĚVr|bŔë–7×čŸ[?Ňç;և–Q$ašça‡eÂŽBfXĆă9ťśí×§żŽŢ{źň“SH˝ÝŽÍ55ZX\˘—ž_§ĘĆ&ża×óűŚŞĆÚâz­z3*̀BU"inś[ó Őz„6Ě˙ń”LË­ š@§äî§ĄÉ}‚†eŒÜ„týhŔĄ‘…eÂŽBłëř ˇh†e<.ëç˜ëÇN–1Rl6ĚĘŇYŁFęŃYkF˙‚ß6,co{Sëkäz­ÜA•€ž‚Ŕ č°p…,šă%&,s}Á1J ’ń•şł ^X•Z:#,Öą ?,ŁçůěóŹ “oS$Rt󔉚1 ›ççŘ9ov?/ĄĐ똖@!ŠH* ”˜6L?î{¤"eˇ7kcé– áϰL˜-:%,ă˙1ý†eÁĂ2fžąhŤőłGœ}ă„qĘNJn–Qˆ|L¸Ż1AĐS$ <Ö˛o D­A“˛'+)>ÁëزíĽÚąŁJ---Ż_ĺhĐ›žÝy’Ÿ°LŘ-Â ŔČ#[â'nXĆá÷ů†slëěďW묚ĘIüOľřřxedf)/ŻââZĎON°é´‘CőĐňŐmĂ2汜]Çz.ô6f@ů„OvAHßĂë¨Ň˛=Uń™–ÚˇŞNÍ>Ŕ¨“Ă2Â1Žö†eiXŚőąžŞŠŃWkÖř;Mł%hZV†.#őíÓW.‡,ĐżžY­6aŔ…–L l![ňř ˘mŮ é^‡ýŻâsÍłoˆ<,îąόW‰‘çóőLűĂ2Š  MŕÇň–1Ë5Ív˝_VĽgÖŹ—§ÜÔů Ë8‚W“ĄÝčM̀€‚…(Ú´c˛řŻęb‹÷ţ'Çü㠊(ăT qŹ#ĚL$dž–‘gX&ŽÓÂ2žÇ~PZ)OÖ˝–ń˙şľE€f÷x≧tčĄGčôÓĎÖʕŤ:-™@TĂţZ ů Ť˛Œü…eü‡c:?,ŁđÂ2‚*í ËČC€ck›íň+Đsč ó^‰‹‹ÎľűŒŐÁäœf*!!ś˙ů:gΛúőŻk-}ôQúýďăŢWVVŚüă^ëWWďĐ=÷Üç\żS ú̀ńŽXŇ6,㐟pE€j1že"j*㺎Ç㆖‰Ű=a™0*ŢČďý –éŹĐK{ÔÖÖęďż[/˝ôŠZZZźö577ŤŚŚV6l´‚&ýtă?ąÂ3=QJJŠ5ŐŐŐYëšššƒ–L ş|Ă2އř Éx‡O˘–‰´R¨ŒÚ–QđçŕyÝ0Ă2‹Eš˛Lg(..Öyç]¤^xŠMX&++Sé^ۊŠŠő“Ÿü\÷ß˙OőDiiişëŽżęCŇŠ§ž˘n¸V sPa„Ĺť’L€”FPźć!áWjQˆđI'„e"­B*äXE–iŰÖĘs›ďąťŞÍteĺSY檍ŽÓşuëÝŰöß?yćéš4i˘1L›˘?üX=ôˆŠ‹KŹm?ü¨ŐŞéôÓOUOc~v3€ÎE…Eţ!öćf÷î娅eB…O˘–‘ďóU—…emžŻ<žCœ˙űëul÷Ť2sĎ=÷ëűď×ZËńńńúÉOŽsnťK3fčËyyy:唓ôôӏkĎ=Ǹˇ›6NEEEh*ĚżV‘ z’ů?m!ëK7khßAÖ!fšmřÄ3¨˛ťÂ2 –islđöP!ŤĹČßóm{Ź˙°Œ÷c­+ÚŚaýűť—ƒ‰ÎŞ8łeËVý÷ż/¸×/żüuÖAĎÉÉÉŃ}÷ýC§œrş***ŐŘب'Ÿ|Ć ÚxşîşŸč“OćYˏ?ţˆFŒާžzFo˝őŽ6mÚl÷îťoX×ó´~ý˝üňŤúüó%Ú°aƒę딟Ÿ§ÂÂBtĐ tŇ ^Až@ćĎ˙Ěj1őĺ—_О˛J™™7nţš?~ߐç{>˙;îřł9ä`żÇEëůĐ[˜íÖ6Tă?óhŐý fokőÍ+ÂŻę$,“aKÖ¤ŹÁÚ/gˆ Sr”›˜ŞĚ„dugU*olĐúŐúʍX‹JŠľŁąŠCa3żoŝłc‡ľúäĆň°Â2]Ů~É׋/ž¤––kyäČşŕ‚óÂ:/++K?ţń•zć™çŹu ŚŽŽN—\r…žýöť€Ç˜űpď˝÷ëńǟr?'—mۊŹińâĎőä“OëÎ;ďИ1Łý^ÇnˇëOú‹^zéŻíĺĺúřăOŹĚM7ý\IIIęˆh=_z;3 j`V´”ęöQ ¤a™”¸Ýooý ˙xĽŮK˛’’ŹihFŚę?P vť^^ˇNĎ­^ٚf{ťÂ2ƗUőşńë-a۸*¨ÇŹl6[Řçž|ň‰ÖŽř—–INN֔)“”ŸŸŻ;v(!a×?ďźózúégÝëý4uęeggŤ¤¤DóćÍwžSŁââÝpĂĎôÜsO)##ŁÍcýć7ż×oźĺ^ĎËËŐŘą{+%%EkÖ|oľŸúóŸo×i§ý@­ç @oG`D‘ŸLŔH‘‡eFĽöŃ/FŽźÄžŃj&ŮfÓé#GjÖ Aúݢ%ZYY~Xfg;'‡O5żÇvٰŒi‰d$.‡zˆ:ËŇĽ_Xí‰n˝ő+PâkĺĘUîj5Ə|…Ő:)>>Ţ˝­ŹŹL—_ţc­]ťNEEĹzőŐ×Ű´úřăš^a™ .8W—]v‰W5™>řPżúŐo˝/RŃzž@Š@´tJXŚuuZöPýaôą=&,ăŠOJŠî8`šŚô ?,ăđ ËÄů?Öwűnśuë6w+!ô0 ż:ËđáĂôç?˙Ÿß°Œ1xpĄţú×ŰtꊧčźóÎхžď>1ňňňt鼝×,XŘć:>ú„{ů„ŽÓUWý¨Më% úőŻoVGDëů*̀9ŽG„ Ë(°LœF¤ćëşa+)>üÖ=ą&ÉfÓ/'OĐO?]¨ďĘ+ť4,c^Ó¸¸Ž Ԙ–H.99Ůmž^yĺ5}öŮóӟ^o…Dü1íž|ƒ+žRSSuĐA3­)˜aÆş—KJJ˝ö덯žś–Í=źâŠK^çČ#×C=bľgjh<_ЊŔ ˆ"ß 2ţÂ2ţŰ- ˤŮuÓČ#”ßó˙ْŻ_M™ Kß˙TuÍv KÂ2ĄrNťA¨Îˇß~§ˇß~7č1W^yyŔŔLaaĄÚ˄ˆśoߎőë7čšçžwoŻŻŻ÷:nůňîŮčŃ{¨_ż~AŻ;sćŒvf˘ń|@+3 j˘–1NěˇoLľa*//SIq‘*++ÔĐĐ`mKNNQvvŽúöë§ÜÜź ç÷MMŃŠŁ†éńßďÜâ}?# ˸ŽŰy~7žžî^./ݰÚ3Ť2J°ĐM||x?łyŸžD‹-ÖęŐkŹ@KQQąšššBž[ZşÝ˝ěYŮ%ÓVŠŁ:ň|@+3 Š˘–q]Ç)#>YÇ÷ŤXPW[ŤďVŽPeEE›}ľľ5Ö´uëfĺääjô˜=•š8ôƒ‘ĂôÂę ÚŃd÷ Ë(°Œďëąű 8Ŕ ȘЇ™śm+˛śůsă?ą&OćœéÓ’ÝnˇÖSR’Ő&xň‡?üI7nňť?%%EcÌ֞e_úÝ_UUĺ^ö ’‘‘ĄŽččó­̀č #,ăî‘çđŘ79{°Rb “ É|ýő2577‡<ś˘˘\K>_¤}ƍˇŞÎř“š`Ó~}őţĆmň˄şÂ2ňœď^III>|˜ÖŹi­ óÁę‡?<+ěóM%WXĆfł9ďaśÚ덯žÖUW]çŽĚ’••Šý÷ŸŚqăöą*Á <ؚoذQ§žzŚßkx>~uuľBń ŘěŽç Z˜Q:,ăđ–ńü˜š=DݝŠ,nXĆĹűő×_jҤŠJMMő{Ěôţ&0S4,ăoťß°ŒWőžÝoÌ݁™W^yMgžyş~ Ç{ď˝ď^9r„Ő^=ôˆ;|rčĄëwżťŐďëápž{ůůťZl™ÖHĄŹ[ˇ^íç ZĹ Zvţ>찌‡eĚąƒSsÔÝ­\ůmDa—ćŚ&}÷Ýň€ű‡dĽG7,ăčfŒ“O>ŃjËd˜ŕĚż˙ýXXç™ę,Ď<óœ{݄F:âťďVş—o¸áş€áĽ-[śźĆŘą{+.ŽőޚŸeóćŔǚ Ë'Ÿ|ŞöŠĆó­̀¨r8`źś‡qlnbšşłňň2ŤĹR{™VNćţä§$‡–Ů9ó×~ІeŒÂÂA:é¤Üë>ř°ž~úŮ çÔÔÔčć›mľd2ŇŇŇtꊧ¨#\ĄĂf üĎâçž{>ŕžž}űZ-‘\î˝÷ţ€ÇžţúVť¤öŠĆó­hɢ&dXFá‡eLŇ#ݖ¤Pęľfő*••m—ÝnWG˜ś@ššy>b”ČĽ¸¸ČďöŤŻšÎůźuŰm´Öţ󛔜œ¤ť˙ń÷6ǖ”[é+3)1̰LœwX&D°Śť¸îşŤľtéZťvZZZôˇżÝĽO?§3Î8MS§NqWO1UeŢ}÷}=öŘ^Ő[~ý뛝÷-W1jÔHçkXb-˙óŸéć›áJihhĐ_˙úw͛÷YĐë\pÁšşá†­ĺˇß~WyyyşęŞ+•’’â>Ćü üămęĎ˜Ń,,㮆:,cŽUńe/^hľ7Џ)--ąŞĆL™:MÉÉ)AŻŞŹđť˝Éů|VŽ\ŠnřŠľnB!{î9Ćﱦʌ?îŸ=TXĆóčÇv'&tĎ=׏~tÖŻß`m[°`‘5ŮŮYVŤŤššZŻóLűŁË.ťX‡>Ku晧ťĂ%/żüŞ-ZŹý÷ŸŚŒŒ ;÷ÍWUUľöŰoŠ.\đ:4SGu„ŢzëkýŮg˙ă\~[űě3Ö ÍŹZľZëÖ­WRR’ŽšćÇúÇ?îU{DëůZ2€h –QÄa™p*˘˜Ę2Ń Ëx2A síPLEţô§˙ÓđáĂŹ Œ™Ě˛Ůć˙ő (œ°LDUhş—‚‚=ţř#:ůä˝*Ľ••UmÂ2yyšúűßďĐĽ—^Źh8ŕ€éşúęš{˖­zᅗœĎéI˝ůćŰVřdß}Çé–[n y­ßţö×:î¸cÜëĺĺš;÷S˝óÎ{VXĆ<Ć-ˇü2`pŞŤŸ/˝f@tš0žMڄbB‡eaTD1m˜:KYy™ÚËÔĆ1•P\Lĺš{K€ƒCüœí ËČűŘnXaĆ%==Ýj-tÁçiΜ7´hŃçZˇnţ0Á’3f´fΜĄŮłôjs 矎Őę?˙ůŻ>˙|‰śo/SBB‚ŐţČ<Ţ)§œ¤;v„źŽ9ç7żů•UůćĹ_ÖW_}m…~˛˛2­˅žoUœY¸p‘:"ZĎ€Ţ.ÜżœÄ…š/.Œy\€u×ď1wMśŰl>“Ů—e捍Mó@g‚‡Ăš\ËŚJ]]­ZZ<¸PíáđS~Äw›kÝsťkyëÖmÖü†Ę7Zˇ{VˆioXĆ9iżóĚ's?´îCg0!„gô˜E 獜śśÍö+Žüąžýö;Ť˛ŒájÉôŔým[ń¤ĽĽkę~űű˝ţĎčŒŮš:,×6,ăœ?vČ ëĐú[sĎPk9Î'Ŕç'Đ*äĐĂlܸIńńqJMMłĆĚřˆÍfłćŽez‹¤¤Äœ3óM᪝sťĎäŘ9oń˜sßIփÍ}—}…Ź˝OK&U‘…eÜ'É7,NŽ777O%7/?ä1ŮŮ9~ˇ'&&jôčŃúŰßî°&łlśů˝FNNŔë{U‹ą–Ű–éŽfvZ2€¨‰<,×&äI¸cřˆQި(ˇŞěD“ ˇŒšGČăúö+ĐÖ­[Úlżű÷ZđŸ÷źFżž Î7^XĆ˙f@ôt0,ăđ Ë8B‡fŇŇŇ4eę4őíŰOś„Žç€Í5Lfň”iJNNyźŠp““›ŤöĘÉÉ ~žŁýaa€€¨0˘+@H&dXF;×=Ď CrrŠö;NťË˜1{iÉç‹ÔÔÔŃy Śm“óܐ‚ÜĎHÂ2Z2¸QaDOˆŠ(AĂ2îcĺql÷—’’Şąűěk`ÂeŽÝÇyNjjjđVęQäaŞĚ¸˜ŃŐᰌOkڐŁI“ŚX-–B1ÇLš4Ő:'ţĂ2qĄĂ2ŽóýlčíhɢǏZŒop#DX&Ć*˘¤ŚŚiü„I*//SIIą*+*ÔĐPoí3mٞsrÔŻorrC‡j\:– Pmf@…ŔjŮäŘ“››gMQnXĆëœÇŔBK&=Ń ËP%˛°L j3ÜOĐEĚřÎĺ˙ţVšW~Ź‹ZĄĆću”š†š–šćeÎk;ăQB`D—oFóˆÂ2TDąD),ăŕ~€NöĺĆzdîVíh°ë‰yŰtć}ßt(4cÎ=ëţoŹk™kţŰyíeŤ f@ôř Ë8|Ă2Žő™óm!m­qX†ű :Ya^˛˛RlîőWż(mwhĆ–yeiŠ{›šva^Š˘Ŕ ˆ˘Ą˜ a™8Â2a –qD–aĐ%ň3őüU㔚¸ëĎOí Íř ˘kšk÷q>@4˜QăÝnЃa-„ä§­UäaŸ× ÍÚ;W/]ťoťC3Â2ćšćÚђ €h 3,Ł(†ejkv¨ŞşJ ő˛ŰíęÎl6›’“S”™™Ľ´ôŒ0Î𾟻îĎÎ}„e@7ä ͜tחŞkj ɘЌ Â7aЕ¨0˘+Œ°Lې‡Għ˘JŔ‡q´¨hŰmU]mMˇËć9Ö:ŸŤyÎf2?CH^a™ĐĄŁ€aB3  ™€Ë‹>•fLĆbüUš –y‘° č$f@ôx´ Š,,ă’ńŮHqń6+|ŤLeœââ˘ŕ…Ë8"˄¸QwX˜Ą™`a™ĂˀNB`DWĐ6Aá‡eA*̘°ImMě†e\Âů9:–‘+,C…Đő…fθ÷k+(c&łLXtľDK¤a Ë)‰RU]ĽîÄnoVyy…ęęęäpřâqqqJMIQvNŽwýŹşşRiéé~Ď /,Łŕa™0+ötWhćäťžT]Ske™×–mˇ‚2ŽeÂ2 Ť˜QqX&蹁54ÔŤť0a™M›ˇhńÂeZłf­ĚĎ1jÔ0MœÜ 9Ń ËPdtŽĐŒ ȸ–ť=Q Ë8bŞ"JŰçÉŃ„ Ŕ Ë(H°`÷2Á˜WŽßWĂú¤X“Y&,ş-™@y`üm뤰Œi“Tś}{đöFQ`ł%8Ë{đĆ´g5j˜ť “˨=†źNJjŞÂ$ăç~:|+ô–ÝÔ!{ćjŐ_Ś `w!0˘Ç3,ă7ă–QŰ6Lžó0˜ĐĘ Aƒ´;dçäjň”ńÖňęŐ돚 ĐLœ4Îďńśřxĺćä(m0ę@X&FC3---VĘĚÎŇĚ{“xçű%..ΚŰl6kŢ4´4ŤŢޤFGłšZějv8_! âœ˙Kˆ‹WbźMIq Ją%*9ž­˘‘G5‘‡eچdb­"Jbb‚ *==MS§M”#@ #.>^ŠŠŠVXĆÂć–ńs…eüÎcHSS“;(ӛš~~s/Ě=qgŐŐZœo´ęćzŐŘÔäčÜjNč˝LđĘźżšœďůZ5JÍÎ˙ÎĆٔnKVfBŠâ㨘 :̀č ęˆ<,;5­šúô飨ë@XĆŃćţ*&˜Pˆ™ŕŸ ИÉÜ#šéŞŕLeS*›ë¨"ƒÝÂh*šk­÷`vBŞ˛Ămk˜Ńă7ĚŃΰ —ß)PřH…eÝ<€dB ˝ž˘L$\Ux’’’:­U“i˝TÖTŁFçŘÝL`Ëgj[•—˜NŤ&Â#ˆ˘h„e´ëŘą˝6N-IҲ­ńŞoöLIIph\ťÎߏYá†BľľňŠ‰Ý°Lssł–AäLŔ¨žžŢ Í$$D÷Ÿö;š´˝i‡€îƸś5T*?1C É€ö 0˘§˝aĎ@‡żM7fÂ27ž™˘ mŸo˘-NWœĽŁÇĽZ÷䍯kő›÷Ťő§#k•ŸF$(ša™nz? ËD‡ëF+4SÝ\oU–ş3č2Ug2R‘"0˘Č7,ŁđÂ2­…Ú–ŠŤŤSyY™šívu&›ÍŚźü|ĽŚěú㏊,ă/,c\~pŚÎžá^?ozŚ5|iłŽ?°AĄt(,#Â2˝M´B3ڞ aÄ ó^sţJ3"/€(i–‰ó–Qa™Be]–1ěÎÇ(Ű^ćľÍ´a ä˜qimśëÜě/‡esOÍ˝m݆–fÚ0!ć˜÷Źyď@$̀( 3,v°&ś9üt]jqČŞ†žHĂ2qAíNËtžŽÜ[*Ë VńŢ)Z2€č ;,Ćą„VŽ×śqýíZ´É˙?ŠŢřşÖ݆ÉeÎWľ? ĚçnXĆÁąťWSSS‡Ş  8soÍ=NLLŒčźĘŚ:5v°JÇ;+ęĆ×ďUy]•ľž›šĽĽ×?ôœ'—źŠ[Ţü§{=-)EËúŒ"ąźh]üşć­űJ%5eJś%kxţÍ3]çO>ĆyÍĐíz~ýÖżôřçsźś]:íDÝ|Ř~vŮ;úĹë÷ym›R¸—ţ{Ţ­ĺ9ßÎӏ^¸ÝďšéΟąf2r’.ß˙$őËČU(G>x­V–ny\°çÜxďĺÚ\Yl-?|úÍ:lÔľ‡yďš÷pvbŞ f@tů`ä/,ç˙XßíŘl6ŻpLjJŠ ¤ÝáěńÍZ^œ ?E=ţůQľ5?zŸÖÖL&@óôgUú㑻6?K0a`ą–1L˜Ł˝>ţxŽžţżű”­!CkâÄ ÚwßqŠď# Ě´89+›ëÔ^uM úýť˙ÖÓKߊčźâĺşíƒ'Տ,|UxďQçϰ+„ŐĐܤe[VYÓSKŢŇÓg˙VCr Š×–Ş›fŻ¸¸śżCŻ~ó‰ÚŤŚą^kśo˛Śç—˝ŻçĎű?é;DčóÎLHQ|\ϨR s˜Ńă/,łłUPÄaGëŠţţ왜œ˘ÚÚîŃ~c`V‹n?şN/MҲ­ńŞkÚőŒ›ěÝó~•5Ľ&:4a@‹–ÉKŰ2?‹?戀E–ń¸`7Б°Lčk7Ť´tť5-Yň….ԅž§ž}űŞ7Š$4SÝ\ď|‹´ďMb‚*Ç=ňS+üa$ÄŰÔÜ^%SŐĽşĄýżËK6§ß˝űˆ{}tŸ!:hÄD•ŐUęoç[AžM•Eúń‹ˇë• o÷| fkuŠm\Ąý†ěíľ}{mĽ>[˙MŘ×INHÔŃ{Nˇ–›[Z´˛xƒťZLUĂŤÂÎóçţ_Ř×ŰŤß0f÷óťŻ7oĚ{Řź—Š2 f@Ô´ţš=:as^uSٞ“ÚÚZUôz™Ééúű ×{műÝ;č‘EŻZˋ6.WmcCX­ŁŒs&ÍÖ'%´eŢËf„ƒŔ ˆ"pF°Œ˙šźÂ2f^ŢĐŕ70“–žaMľ5;ËŇÍϑ–îw_iMS›śVBFţćmÂ2Ý ÂLKK‹5EÓĎ~vƒ čďüyÚąc‡6oޢšs?ՊßZűőď?Śoü‰’“Ă #ôŽűŞ-UCKłš 2Ľ&&ëWG\Źł'ĄˇW.yźiIôŤˇ´–ăăâő׎ŃĹ˙ żÂĘŽëěj#uČČI1špOĺ§g;—*Źő ᷜÚčX˝şźľĺŇß~ŚßuŠU9ÇĺľĺťÚ1Mq>ÎŤË#oĎtꞳ܁Łž9üŔL8Ž{ĺNw čˇG^ށY}ô—ŸÔ÷ۡč×G\¤ó§cí+qŢó<ŢţnĄ6W+і¨}úĐُÔń{Ďđ{íHĎ1żŸţ†žYúŽÖUlQvr†Nwˆn8čLE›y/›÷tr<uÇ("ˆž0Ă2ża™śa› ;Ş54#ÓďCőëW âbĹlhƄeú:†@ÖWÔď\ŠóŞČNXf÷W˜éŒę2Ś‚ŠŤŠJ^^ž5ˇ^~ůU˝űîűÖöââ}ôŃ\yäámÎ7ÁšyóćkÆŞŞŞRZZš 4uędç4E Ţ˙\ž3çM˝ńĆ[Ör˙ţşůć_X×xűíwľeËk{aaĄőXcÌöűœMŤ¤ jńâ%***R}}˝233ľÇŁtĐA35thôZę˜{*0SoďX›,[\ź^ťđŻŮ'ü*>ˇř¤ť*‹ YL4Zí1uČ^úßWXË 6|#{K‹l;ŢĺEëTV[e-g§dhLߥa_×T˜Ő§PŤK7Yí>YťĚ äŰŞˇ[mšŒôäTë?Ş]™ŐĽÝËĂó*/-KĺťâőVEťO0ęË­ktŃţŕő͍šżţ+kzoő"Ýyüu^­ŹÚsÎľŻÜŠWž™ťëřŚ2Ý?˙•×F^U(ć=M`@(Œ"€(ÚUɤŁac~q‘föč˙‘œ¤/( ÚšUWWŞĄĄžKŰý´‡ÍfSrrŠŐ†)Pe—O֙?ôG/,ăč&fşĘńÇŤĽKżĐöíeÖş ¨xfš››őĚ3ĎiáÂĹ^çUUU[ÓŞUŤőÉ'ótéĽ)''Çďc˜÷ۢE‹őÄO[4\VŽ\eÎ9giżýŚzS^^Ž|X›6möŮ^a=—E‹>×ěŮGę˜cf+š獎fu„ FD–Yśe•UmÄ0Á”ŸzޚZÚ÷N7KŻ-˙Ô ´˜°Ć9ĎüFÇîu€”yxáŤjq´X•aţ0űrĽ'Ľ„}ÝF{“9Ů ĚŻ,ŸëĚźžâSŤÍ“1s؄°Ž×ě|Ż,ÝüÝÎk7;—WęŽOžłÖMuž?}Ľ:ÓłËŢľ*ůĚ>Q™IŠ*ČĚӎ†Z]ńżŰÜÁ—iCĆę¨1űŤźŽZ/žŁĘúV…šqýGęâýN°ŽiĎ9/3×+,3":Nëʡę9çó˛…tľGGßÓz3 zÜa™@m‚B„e´knŽ]XRŹ:ç—Sm˙ɒ–žnM=I]S‹>ŰXAXfç,hXf÷W˜qtajÇTUŮwßqúŕƒŹuSeĆ´lĘČȰÖ_xá%ݰLZZިíۡ[áĂT1á–n¸śMĽŁśśV˙ýď Öš p>Fąś1ĚĎúüó˙ӄ 㕔ÔÚV̄t<Ă2ć9š*4YY™Zˇn˝ŠŠŠ­óL›źź\íż˙4uT8÷źŠĽë‚fÍÎÇúŜűŹ ‹që)39MeuUj†yôô[ôŕ‚—őˇŸuW9q1ጿwľ&ŁH˜{rüSő/çuˇV.P“˝Éj=4çŰůîăfšŹí5•!ŻWQ_­“űE›íS ÷Ň_Žýąő<#ńŸ/ßÓ˘MËŰl/ČČÓ/gßfťiUő迲...~][ŞJŹĺ™#&ęą3nąB5Ćᣌč¤Gnƒ˜˙’.šzźŒúďWD|ÎSKŢt?愁ŁőŸsţOI;Ÿţöń3úÇ'˙Q´uĺ{@ě"0˘ŞCaŸck›ôâÚľ:{ÔęMžYVʚ{a™¸Ŕaí\ďş˛ÂŒQPĐĎkÝT›1™mۊ4wî§îíŚŇe—]Ź””+`bÚ9˝÷^k›Ÿ7iţüĎ4sćŒ6×ŻŠŠŐŘą{éâ‹/´ÚB™@ĚŁ>ŽeËZőő úV‹(Ă\Ç–ąŮâuÍ5WiĈáÖşyÜ'žxĘŞ0cźöÚM›śŸW[›öçž7;şîuůׂW´˘xľ|đˆI:nďęˆf{ł~űÎ#zjé[îާďˇo֕/ܮێý‘őxᲡح0Knj–Ę몜żuZşy•ö.Ś/œsĂgÓa{LŃ3KßQ{-Ţ´B§=qłţ|ěuÄSĂ>ĎTé1“/źń˜9fĎźÂ2Ć{Ť?w/Ÿąď,wđĹ?pî3DߕŽWIMšž+YŻ=ű ‹řœ=œë‹7}ë>ćŠé'ťĂ2ĆĺűŸŹűć˝ ć–čV„éĘ÷4€ŘE`DMÄaK c[÷ý÷űďudá`őI żJ,+ŢѤçž,‰^XƧ Mo’––ćľŢŘŘhÍM%Ogœqš–1L@Ĺ´súüó%ިh­˛xńżăÄO°Â2†ŠB3{öQîŔŒQVVć^6×q™lĺ§e‡UŧOzŽ_űo÷zIM…^řŠ˜˙˘ś×VęG/ÜŽW/ş]{öíœ×ť_Fn›m[*KÜËW˝ôWk dsUŠ˜‰ôœ<çýń 2ńůůL›ŹÁ9ý´śl‹˘ÉŃ˙ƒ bf@tů Ëě×§żŽŢs˘ľ~÷Š/´ ¤(ŕą­ ć˙´?j›íşuŃbýí€éJśŮԓ54ˇč–ˇ×9˙(ßQXćŔa™şqÖkó_ŢߌOżŻń{locZ&yrľFÚşuŤ{[vvV›J46çűlôč=Ü-›śmŰŚ@ňóóźÖM+%OMîeĎÇ5×öl ĺOIII—fşĘ]Ÿ>§úŚÖĐRvr†ţřţcî}eľťZ2Ő6ÖëĘţ˘Œä4Ý~ěUŻgÚ8=űĹŽę.wžp­ŮZEĆ՚čťâúđűĎ­ &÷Ď{A÷œüEâäqť3ŚRJ]sŁ{߉{ĎT{őMĎŃ/=OK6}§…—[힞úü-ý>ĚŃ˙ÍžB?œt”şJó5éźsˇŘ=̀č €šnŻIĘNJn]Ţ{˘ÎúčͰÂ2Ž–MkŞŞőçĽËô‹‰ă{lhŚžšEż}o˝V”ÔF\YćŚĂ('ľőŸu7Ţ_Ç<¸f×ß ˝Ží]ŠŠŠ˝Ö]áÓJÉĹ´hň'==Ý˝\[['ťÝni|…Ű2ɜ_WYč ž>ňB{ÄYՈ:˙ RUWă^.ÚQŚ7žđXłĎTŒŃąцňmjnąť×Gćjs̨>…V`ĆX]şI‘š>^---ę ćqžürWk¤~ýúşĂ1ééťZ5íŘąĂďů55ťÂŠÎ÷›­ƒA-s~JJ˛ęëŹő)S&éČ#zNVVŚ:ĘÜóPââŐä°Ť;Ű\YŹ~ö˛ňÓ˛tůţ'[-főő:ćľĺŸęĘNqŻ×66č˝Ő Ýëłň)ˆ:qěAşçÓç­6OŸŽűŇÚ~č¨ÉĘLNSG˜UŽ^ę^­ŽtčČIúdí2ků™Ľo;ΙJˆo}Ÿ›Š7w|ô´úgćktŸ!š6do%ŘÚuÎäÂ1îPiA5kÔ%'´ś1ť{ŢóVőŸh3ďi…Ŕ ˆž@˜ ÇĘűX?a×|ee•.y˙0|ˆÎ=Bi ąýOSUć_—ęÉĽĹÚŃh–Ůy‚ߌżűç7Xłť…[%^ý mß^ć^Ÿ6m?÷r˙ţýőŐWßX˕Î÷”ŠDăٖÉTƒYšr•×ńŃPPP őë7¸cŔ€ś×5UeRR˘ çž'ĆŰÔdďüŔĚżNűeŔ}ëʜ鐎´–Ó’R´ü§Ďxí˙Ń whŮÖÖפąĽY?;ř‡ę—‘ŤŁ÷œîŽTó—ŸÔWŰÖhĘŕ˝T]_Ł—žůHkËvľÁşpęńj“vf<™ H$ŞjtŐKm]qţ.–Ô”kÉć•VČÄ}Í´xjS÷Ľ?{ŮŞöłxÓ ňŘ/tźó9´8ZôúŠOőĺÖŐÖq#ňéÝËţŃîsΞx”;0c^ĂŁţu­:NߗoŃgëżś7ž•‚˘!1žgˇďf@TšĂ2–pÂ2ţĂ1žsW••zçö˙łzćŹŰ¤Š}ľżs–•ĄÜ”de'%Ş;ŤŹoVY]łž/ŤÓ§ëŤ4C•jZ|*Čř ˨ăt˝ĎQ7Ş0cr0Ă\ĎT“1“Š łyó}üń\}óÍ ÷1}űöŃÁď #L:Eďźóž{ýšçž×ĺ—_˘äädçýuč•W^SEEĽÇń“ “'Orf–-űJ+V|Ť˝öÚÓ˝îÜOôüó/(//W……ƒôĂžĽÔÔTuD8f’âTŤFug[ŤKw-WíZžýŘŤTU_cU~1mĽć|;Ϛ<™öIˇqąfŽŻö0möé?B_oűŢZĎHNÓaŁŚFr 547éľĺŸÜÉ~'ę Օ˛S2tß)?ÓĽĎ˙Ůů߼J+ěâ ź¸ä§eëޓŞř[ÚsÎIű¤÷V/ŇŤ;ţuĺ[­É8}üáúbóJ­,Ý h2ďi…‘DSąÂáđ_ŽÄkłoľżÇĆ„ř†e<+Ş87ěh˛ëýŰœS‘ß`|ćAŰErlĐçëq~Ŕcƒ=Vˆ°Œü?ßśUęńŻŤ*ż˜śDMMMŠŚŰnť#čţää$]tŃVĆĹTv™1ă}ňIk°bŐŞŐşőÖßiĐ A*--UYYšűŘAƒjúôý °żć͛ŻmŰŠŹ€Ďý÷?¨QŁFZSĺfÝşőÖqŚ2ŽŠFÓѰŒN+Š[˘ýŽ8Quóaę7o?¤Ü´L]1ýd÷v^yęěßę­ď>ÓKß|Ź/6ŻŇöÚJ%%$Ş0ŤŸ’9Ę1*Ě0Uf\™ŁĆLsˇjŻ„řŤ˝Ôř{čě‰Gꐑ“´;L.ÜSs.ůŤ]üşŢ]ľH[ŞJ­˙ž›űuŘSté´­LGĎšëÄë­óž]úŽÖ–oś‚7g9îk<]G?t˝˘ÍzO@áţu$.Ě}qaĚ㏝Śxšk˛íÜfó™Ěž,3ollňţ*)=ŠŚaţ0i&×rssłęęj€whđŕBľ‡żŒď6Ďuײkžuë6k~ĺŞĹ;đ~Ě9âDŻký櫊8,nP%ܰL$Ç Ëř9żÂ2ÖŚÇÎťvŒ<đˇU~Ă2ϝždÍ]­€\AĎŔŒoxĆ_˜Ś#ÓrȄEÚËT1UXÂaÂ.]tžúők–0Á§žzFŸž4ŕůŚĘËĽ—^¤źź<÷ś9sŢÔoźĺ^˙Űßţ˘ÄÄ]œŻ­­ŐĎ~ł{ý„ŽÓGć^/))у>l…f:tˆŽ¸âRedd¨#Lu™pŰ;mŠŻP“ŁóŰ2-1ÎŚ)9€h۸q“ółvœRSӔ`˜/ޘšk€Ţ"))ńçĚ öWíœŰ}&ÇÎy‹Çäđ˜űN °lîťě+Ř> f@tů „˜€„gk˜ŒÄ$íh4•F‚`b,,ŁŽË´îÎJöŒ1÷Ú_X&PĽŸŽf:˜ &11AŮŮŮ2d°ĆßW&ŒؒȄ\.¸ŕ<Ť=ÓüůŸiÆŞŽŽśŞş˜ę.SŚLŇ~űMő ĂDCßž}őłŸÝ  jɒ/TTTd…lĚ㚠7“'O´7ƒl‘\#Ý–ŹŠćZąÎź— f@ô„457)9i×14XĎŻ]82|ŇYayIX&‚*4ţçňËh×ÜXŚő1NçÝú¤Ń´<ęŚaĂP:Җ頃fZS´Œťˇ5…ë˜cf[S iiişűî;ƒ]BIIIš9s†5uŚHÂ>™ )ŞlŽsžeBîn+Îů?ó^€pÄ  üśćńT)ŞŞň:äüŃ{ꤥíJ3~Ă2AĂ'‘„eźžmDU]B`pŁ˘ÉŽ'7mo] €Qŕ°LŔŞ.Ą0ŽËE5,Ł]× qěßçUé˘q5ĘMQ@ viKľ´´HzkuźŞâ‚<_>2á¤ÖŹtWV’ ĹđhllÚ/Za—Ě„çť'NۛvčŽLeÂ2ڋŔ °‡CŐTšCń)ŠR›đÉŽH;ě-zĽ¨Lݍ<`°ĆýTŠÔ„eÂ=6ܰŒv];œ` Á\˝ÍĆsöźv…eĚc44FÖ +Îۘ ‡i#dB3‘śěęí\­­:҆)DHŒˇŠŹŠF-Íş‹¤řŤ˛ m˜t-™@@Ážű\Ë ĹĽj–qÄlÔްŒg˜p[ E=,ŁČÂ2ŽđĂ2a`Ü ˘{ZWoo=ĂĎëćOWWĄ1””%&& á1÷ĘÜłÎ˸˜@€älĺ$¤Yg€ÝÉźÍ{Ńź' Ëč(F@ŘU˘qmŻŤWăör%ĺĺľî–ń_ŠEîó<ç^a™°[ …€ńvX&ĚL$dž–ńż/PXĆhhhQźŁľBH  LwiÓdB fjjj’Ýn§âŒŽąŮl],ĘNLľÚ4U7׍ĆŢ &‡]@WIŒł)ݖl˝ăťQK9ŕ˙Ůť8šĘrŕϖl’M/’zoŇDş‚(Š˝!zőÚš¨Ř˝vť÷oAąĄ`E‘VzďEzé˝mýĎ{’ł™™mÉn’Ůý~ďçÜ3ç=gÎĚΙ ÎťżyŞ›Ŕ °Ţęęjł`ĂčúúXňÜě¨Ůu#Fô1,ÓSřd€Â2˝ Şô!,} ËD§ç} Ë´÷–im‰Xś˛5& kĘśÓľŞyp&˝ŻňŕL e ľM Ȥ0S”Čj2=>—ÂóHÁ™´Źjk‰•­ÍŃÔŢÍm­ŃŇ^¸>eő`]¤*2ő5ľY;°†šúQ7L5`@˜yÖY^YfřđáŃŇŇ3F6Ć˝­-ŃôÜŹh˜2%j Űë–‰u ËDÇşb&2,}¨BÓůą*`bÝĂ2-ÍËWľfƒ;Ž]T¸^“˛k•]%UR@dc†D¨,„¨fţúdzŰŞ§ŇqŮzŸÍ&gÚh]ş4ÚVʈhk]ioď{XڤKoĂ25݇eúÔŠa™âPKĎo˝Â2˝:vőHľWÚŰj˛çŘÚ\Í-Ť4ľ5íqđÔ%Ůaůľ*֛kÜÝ8@ľńľP`˝¤E}}}46ŽŒ§M].ŽóímY`Ś­yeaiŽÖÂŇśfIá‘ö’KÍÚąŽPHM”„C*uuŸŠçY\i_sßlłä<ĽĎŠň}j:2]ß§(tSö[ąbElh*Älú\#€žKsmi>%Í˝3ÇŐO`ŞX^6­ëę겹E‹ÇĆ$”ąiq=Ö]>זćފçâ€ęçżčPeĘůvú ž––––XľjUllĹM66Ż;@˙HsliŽ-Ÿwëj^¨N3PĽ*}@ŻŻ_ݖiţüąŠ)r˜PX?^O€•ć؊çÜrća`p¨ j¤âíííĆň 3éĂ{úÖKsss,_ž"GĆŚÎ䛚4ˇ–ćŘR+Ś4çVŠÂLÎüT'f  8/Ż02lذl=gΜhkk  ÷ҜZš[+žk+ŻđŤĘ T?¨b•ZňäßzIˇçΝ@ďĽ9ľźSškÓ'¨2Ĺßb)ËŰ2ĺß|ŠŤŤ+VƢE‹čYšKKsjin-Ż.SŠSĽ9: şĚ@Ťô햵­™˛oŔ,\¸0–-[@×ŇZšKKsjin­ťš7 úŐPu҇ňöööŽu>–ˇdĘĽoÁ¤žËsçÎËśG@Š–IshkŤ7×e•eŠ[2ĺT—€ÁA…¨r•žá’—‰]ým˜ŐĽcÓţE‹°Vš3+˔ˇbR]f JW™ÉĽńŠ˘Lţ>É3ÍÍÍąpá˘XľjULž<šc? EŤ+3ύ+Vfsei­žž>ť]–)Î$‚3Pýf`(ĎT ¤úyh&M<ůäS1eĘfŃŘŘ0Ô,_ž,UeÎ+3dú–Ş—Ŕ T™ň*3ĺc•B3yťŚüv^b6fŇąŤű5ĎËö§}ŁFĘŞÎä=›MP ŇÜWšëJ_KŐd–-[–́%yűĽ4ߕćŔňyŻ|<żÝ—°Œy3¨^3P…zšÉo§űi’ ßÎ' ň˙i;}ł&M"¤Űi˝hѢŁřĹkؐň Jůş|’‡aҗʃ1Ĺá˜âu~˙âsËŔŕ#0UާĐLńöâM^m&ÎäŰi˛ Ic)@łş…S{䑇lňstG€ţĐS(Ľ|lőXö˙łíź˘L~lyPŚŇvůy…e`p˜€*V)ŔŇUh&˙ŔŸ‡dŠŰ4ĺ š|źř1bŘTš˙Şv)Ɣ[Ü‚ŠťJ5•ś€ę%0ƒ@yľ™ň MžżxR ¸MSńýWW–‰Š™âąü8ŘňyޤťĘ0•Ú,•‡gşşo1a\f`čK‹Ś$Ÿ(Ž “–źşLqHŚRxڏÍlH]…[şkŤT^ŚˇUeşŞ›Ŕ "]ľh*ëęy@ŚŇšŠ÷ŔĆVނ)Ť´_P(&0ƒPWŐf’ňŕLZ§öJĹŰÝľc*Ÿ$č.<#XŔşč.¨Ň՞޴V*năÔŰóƒ“Ŕ R]UˆŠ4^ޞŠŇ¤BĽMń~ŘĐş Ǐ÷ĽzŒů.f`ŤTm&OĘĂ/ĺă•*ËôvŇ@…ÖĹú„VşjšTžżŻű€ÁE`†€ŽŞÍtˇŻŤ‰…ň Moú[OÁ˜ŽŽďë>`p˜€!¤Ťj3ůžb=×Ó$‚ę2Źő ąôGźf`ˆéŽÚLĽăr} Ŕ˜h`Cęë|”ů+Úf`ˆęmpŚüřbŞČ°1ŹOŘEPHf`ˆëkpŚŇ}`Sg. (&0dŠ' TŽ`0’ş"0tR>‘ @@5zK`čQO 5l1@˜֛‰ މŔ CŠŔ CŠŔ CŠŔ °ŢÚŰŰZMMMô G1l zš§¨zK`čD@€jT>Ż%@tE`Čô5$#TŔĆԛ0Lń–đ PL`†¸Ž‚/˝ ÄͰ1¤đK_Ű3ĺÇ Î‰Ŕ Q•&ş›dhkk ŘTšÇŞ­­íň˜âŒŕ ĚŔӛ LÚŽ4ÖŰóu7˝ŃU ĽŤńň/|Ľăňc+…dg`h˜€!¤ť°L>Ąś[[[łítťxźř8Řä•eňŕKÚNˇÓşŽŽŽd<ÍqUjŐ$4CŔ =eҒB2---ăĹëâűwuťˇ =é)ŔRŠRL>žá+?&­ëëëłđL ͔lŠĎ!8C‡Ŕ r]ľVJ) “‚2iÉÇÓÄÁđá 1lذÂäAšD¨1Q@UX]19-­ŃÜÜŤV5es_MMMŮWšűJK Đtœ1CƒŔ R]U•ɍɤ ƒ´NŇ$ŔčŃŁ˘ĄĄĄc˘ŞÍęPLZjł/„566fóa)0łlŮňě dů’öçUgT›€ĄG`ĄJUeŇÄ@Z§ LZŇvú&͘1ŁłÉŒR fĈْćŖ,YÚńe˛4/––ŽŠœš€ÁK`‘JA™|I™UŤVeߞIŰăƍ+L *R8fâÄ ąrĺŞX´hQG5ćáĂWϓĽ€Lž$ŞÍŔŕ%0ƒDqX&żW•IúSX&­Ó7iRU­—ŞŇÉ&gŐfVŽ\™ÍŁĽĐLjєW›IŠƒ3B30¸ĚŔ P–)^RyŮ–IˇGŁF ęR(fܸąQ__K—.‹+VdĄ™T…&hň€ŒĐ N3PĹşkÁT–IđS Ś‘#G°Vú‚Ymm]Ö˘)ÍĽ%)4SL‹&|f Jő–iii‰ŚŚ&ačA>w–B3iN-bęëK˙ŒV’QmŞŸŔ TĄžÂ2­­­Ůű´3f´° ô ÍĄľľľĆ’%K;B3uuu%ÇÍŔŕ!0Uڧ°LŞ(“Z1Ľ 3 YIY gi.mŐŞŚ,0S[[›bŇş˜Đ ľTľň°LŞ*“3éöřńăč˝4§–)-ÍľĽŰĹspŔŕ 0U¤üyú°^ź/-y+ډ'túö Đ˝4§–ćÖňśçĺA™â9šDˆŞ“ż˘@•čęƒwńˇ[RŚ´Ô××Lj#čť4ˇ–ćŘňůśž*ĚÍ@ő˜€*UŠşL*›ÖZ1ŔúIslĹsnÝU™ޏŔ Tąô!=JÄŚĽŽŽ.XwiŽ-ÍľĺónĹsq@ő˜€*Pţ!źRŸäź4ěŘącXiŽ­xî­XĽ9: zĚ@+>´Fbřđ᏿Ősmk3孙€ę%0›¸ňŕůvń‡óôm–´ÔŐŐGm­˙ź@HsmiÎ-ŸKŠç庚ť6}ţ˘UŚŇ‡đÔC9ill  ˙äsniN@¨Rů7YŇ7[VfR;چúĎę9ˇŐ_ZKsqÚ2Ŕŕ 0U¤řƒxůíśśö¨ŤŤ  ˙¤9ˇ4÷ÖÝÜP}f`ÖՇíňńźręŠ ôŸ|Î-ŸƒËővîŘ4ůŤTĄüCwyůךššúOńœ[ń|œ` TˇúŞVţĄ<ď ôżŐ-ŃŰ:nŐO`Ň``™ƒ€ÁD`€!E`ŞDqäňq`ŕu7?WSS@ő¨  * ĘŔĆanŞŸ 3 )*ĚŔ&ʡT :™Ű€MŸ 3 )*ĚUoĺcĹź?˙9V=ůd ¤– bţ_˙Koż=¨^3@U›{ŢyqëÎ;ÇýŻ~uÜşÓNY e ŹxčĄěqî;ţř¸cß}ă‰O:¨NZ2@•)ďŹ2l|)H1çÜscáß˙+x Z.ŒÚ‘#ŁaóÍcôÄėż<&żöľQÓĐPńţËďš'nŰsϒąý{,FlłM vˇď˝w,ťóÎčŤç]}Œ9đŔěöÓ_˙z´77gˇŰV­Š§żń˜řŠWD{îĚ3ŁyΜŽí§żů͘ńůĎGíˆŃ*˝Z˛$ęFŽMÝÍ[nŤžyŚc{‡3Έ-Ţ÷žď÷Ŕë^s˙řÇXă^řÂŘóŸ˙ŒMÁ“'GóźyŰ;ţâąůŰßŔŕQinŽŚŚ&€ę#0UJP6ž–ůóăя|$ćœsN´ˇľ•ěk]˛$V¤ĺá‡cÎo~M›Ű˙ű1龯 úWĂ[tť=PS?qbÔ =ćć úiÉë U•šc˙ýcö/Ů),SIÓłĎĆýŻ{]<ńŮĎýkťÓOą‡u1ţČ#cŰď~7ÂÔ| Śźő­Q7fL4îşkěrţůžM P•T˜€>jž;7î}ÉKbĺcuÚWS[ S§Fë˛eYkŚrO}ĺ+1bŰmcówž3člôžűfᗞ¤×87bťíbŻ˙;Zj˝´ÓŻ~ôŸ /y4lše§ńÖE‹bÖŮg—ŒM~ýëŁaÚ´NǎÜa‡č+čŁG?ôĄNa™á…?úouꩱٛߜ+’Śgž‰gţß˙‹gż÷˝hom]{˙8&˝ć5Q?aB VmŤV­Sť˘q/zQlűíoCĂćo{Ĺń•?Ü)03탌ą‡ýAK&čƒĺ÷Üs~űےą‘;íĎťńĆŘüďčË$ Ó§Çś˙÷ąĂ\r|ë’%1ë§?uľęЧâ‰O:îŘoż¸~ěظśĄ!nš:5î}éK㹳Ίś•+{üîwÇ­;ďœ=tŽôłţç„bÁ%—Do,úç?ł×ńćÂuMŻUúYŇű¤éšçbSłŕňËł÷Ŕ­…ßˎߏiÓâŢc™?üaVýŠ;ý}ýĘĽŔ\ńű({O–ý‘,ťëŽěŘŰ÷Ů'{ŚŸă†I“âŽ}÷Ç>ň‘XńŕƒŹ;f fýüçíík ěŢą0VŠUL.ľ_J¨_zűícó/˝4ŚüăŃWéőż˙ýŃśbEÉx .4]vY,(,)łËţc8 â9fýâńčÉ'Gëňĺ%ă­ÍÍąěîťłećgdĎ{‡ý(j ¨ďÉC˙ýß1ťJÚĽĘź .Č ímmă+~vŽď~ˇÓϒŢ#ó ?Þ×\›‚ô;đŸ7ż9 ÷tÚ7sfś¤0Mj‹śËyçĹŘCét\_żr)(WţZN˙ČGb‹÷žwí@áߗ”ÉŽ[ńż5-óçÇŇ´ţ-IűˇúÂbĆç>@ߊ0}ţŕ^,…R*ýá˝ÜŽgŸý‘>_ŚôŁŃWĎ|ç;YĺŒň°LšUO<÷yd,ťăŽNűfŸsNn)ËT2ëg?ËţpߓĹW_]5a™$ľűIŐUŠĂ2ĹŇkóŕŰŢMĎ>}Ń2o^Ü]xÝ+…-ĘĽ*6÷źä%YľĄî<őĽ/•„eĘ-üŰ߲jC•Ü˙ş×U ˔K“{Ž:*Z/î´ďÉÂă—<Š­zć™ěľęMĽ›ÔV¸f÷}tŰLšœI՘V>úhÉř@\żbéš=|ŇI%c)”ľÍˇžU2öäż˜ľq+˔KŻůŸ˙|ĆúN`zŠ˝ŠŠS”‰Ç׍űŽÚkݘüş×u,˝˝_.…_žřÔ§JĆĆżřĹąëŸţĎťţúŘńżˆĆ]véؗÚΤ CńÝS¨ŕŃ}¨äŁ÷Ý7 đě{÷Ýąű%—Ä„—ž´djűÓôĚ3ѝW\‘­Gî¸cLýŸ˙‰éűXL*üŒ›Şŕ€ŘúË_ÎŢ×Ë Ë´}(Śźő­k÷ďťo´,X…Kr‹ţőŻ’s ÄőKRřęžÂď`óźycĂ ×uˇżţ5ęF*96kĘŤ?m˙Łea´$…œv:çœŐ; żkŁÖ<t kč čĽJ­ŇĐZ ŻĚ˙Ë_JĆś>í´Ž°LÇs?> EW YP˜6yrL}˙űť°ÚÚ¨1˘#0“4ϞÝí]Ň˙ˇűŢ÷Ö;,“,šá†léN őŹO`fÔŢ{—„e’úI“˛ N &ĺV=ýtôE<Ę-ţ׿˛Ş')ˆ”KŐBŇŇ[é:WżIŻń6…çX˜IšŠžkzÜâ瞮ĎÔ˛V@ɘź {.y… ČZxĺ•1ůoĚśçW¨‰ŐĄŹâ°L’Ű~űŰqO~ځ0ţ¨Ł˛Ľ;u%Űĺď끸~ŃÚ˙)źž)ÄÓńb‡JśŰĘÚődâ+^łýëŽíTéçś=÷ŒĆ]wŃĎ~Ô˝ß~1怲PRoŒŮ˙Nc)řÔ°ůćŃ4kVÇXqKŚňJ)éyüçÍoŽJň°LÇ} ď—<0łŞđ~(ůůÖŻĘĽSjwÔÚÇ×k ¤j+Ť}4–Ý{oŹzüńXőÔSYđeáßţVz`Ůűz ŽßCďzW§ą ‘*ŢT’ŢƒŠľZqŔćéo}+fžyfXJmœF–t{Ä6۰îf —†mśYVá#ľĹÉ­zňÉhMkZ,›“Ú1őBóÜšĽíí1÷źóbć‹ţýďčľe•;6u5Æőiźˇ&żá 1ĺâ‹cvYőĺ÷ߟ-ńŤ_eŰ)x5ůľŻ­žřĹ+ĺÔt̨é&°Ńď—~)iuŐ~,ýN4L›+|06ŚUO<Ϟ~zV}§eţü荁¸~•ôtŮŠđ8÷źä%Y Š\ë’%YőŸ´äRđkÚ)§Ä)”SŁ!ôUm˝’ÚĽŒÜi§’ą—^ÚŤűŚ sĎ?żc™ŃEŃ[íííąŽÚVŽ,>Q<đú×Ço|cŰLj“ÚÚ¤`ĐĆ2ýŁC ĎłťeüFn˙ÓĽšš,ě°óoc:¨ËCjí5űÜsăö˝÷îąýÔşč—÷KĽstwŢŞ ´Ĺ×\“Uƒyć˙ţŻsXŚpFlˇ]Œ{ыş?Éş~˙yË[J/ˤj6űŢ}wÖFkؤI]ˇüžűâá÷ź'ű}Žő¸ć0TŠ0}0ţ˜cVW›XcÉő×ÇŇ[n‰ŃZç{đďȎˍ=řŕ.[ܔKŐ;ŠŐ64ÄÁŤVE_Íúĺ/cî˙Řą]S[›żóY+šÔnfř–[f!ŰöŘ#šçĚ ÖÍfozSś¤ !Knź1ťîKnž9˙ë_ѲhQÇqЊË#'{ßv[ô§ň÷ËřŁŽ=ĘZ/ő¤n̘¨kl,Š2ł˛ŹESŽ˝š9šž}66–Ô‚éÁ˙úŻŹ K.ŰŚž|rŒ;ě°ŹÍQj•‚jŠĺXOúú-ż÷Ţxü“ŸŒíž÷˝.i˜>=ś˙ácťÓOώ_Zxüô<_w],ťóΒcSŨů'ž?>€ŢSaú`ó˙ţď’íěőo{çÖGEf}vIX&éˡGţŕŸŞŰäښšbé­ˇF_Íżđ’íéŸřDěpÖYY`fřŒ5Z/Ö]Ş@’ŞÔO˜Ž=6f|öłąŰ_ţ̜›Ľj E–Ţ~{IĐŁ?ŒÚ}÷ŇÇ(źWR¨ĽŻĘŰ •żrŠMPyűŚ )UoZůčŁŰ)čóźëŻiř@Ka™¤ˇďëţž~Î7ţČ#KĆR먅=„˜Rk­–9sbԞ{f˙îl˙ŁĹ>wÜ{]sMԖľäZôŻĐ73ĐŁöÚŤÓÍSˆ;8 ćţţ÷%Á„Śçž‹Ç?ń‰xř]ď*9ž~âÄŘâÝď^;PĄőK{Q˖TíŁźÍŸůL´ˇśvşßC…Çşy›mâžă'>÷šŹ2EŽźU͈ÂqĺRŽUO=ôMjąs˙Ť^ˇě°C\?ztÜśűîąřÚkKŽŠ92&w\ÉXͰaÂëkÜQGEĂć›wl§ëţô׿Ţ鸜UŤ˛śBŠ˘ĐN8!;&…4r)HU,ofţčG%cé܏}üăą1•żŻëƍË~ÇJ´ˇÇěsÎéňuýR™´dzώúńăKžO ڵ̛Wrüœßü&î<č ¸žđ3Ü´ĺ–ńŕŰŢÖŠÝŇŘCéTE(ýô–LĐGŠMĘâ믏UO>Ů1–ÚŐ<đŚ7e@O­RŐ‰ŽŞÎ¤V+ĹĐĎ+`{â _ˆI…?ŕ§ĘĂ6ß<Śěc1ďĎîÉ,¸üň¸ëĐCcęI'Ĺˆíś‹Ś™3ł@@^dŐOÄüżţ5ĆqDÇ9ł*2EžúÚ×bĎ;ĆŘÂčSx"˙ą~4蝊H×{ĺ#tŒĽĆÖ§c ×ŠŚž>kë“ZńKŻ}zĎô§šşş˜^¸Ž}âcO|ţóąübňŢĂ&MŠ=Ď~ç;ąěîťłý)ô•Ţ/[źď}÷™ňśˇĹÓßúVI쑓OÎ*ʤŸ)…=R›ŻŮŽ))_§ß…GO9%śüřdzߝÔBíŠ/})ýóŸ]žc Ž_ÝŘąĎqűü ţsâ‰%ĎóĄ÷ź'v-j“6lʔXrĂ Ű Ž¸"xýëłöRáÚ*šgώ™gœQRQ'÷ÂĐ73ĐGĂ6Ű,ö¸üň¸ç%/) Í$)\Â3ŐÔÄśßúVlöŚ7• §?„§Š MłfuŒÍýòe§łĎŽ)˙ő_1ćŔcŤÂýŸřěg;ŽIX/ţăzšÍßńŽÔQۛ˝ůÍ1űÜs;śS¨ćž˘ýŮSŹ­Í8吧gŰ}÷ťqçÁwLRăá˘JšŇŘŚđ~)`ľđŞŤ˛ŔE.U/IKWR˟â*(#wŢ9füď˙Ɠ§žşö öö,X•–\j{”bĹa“ )ľŽsŔąäŚ›:ƞýŢ÷˛ĽŘČŵB]čëˇŮ[Ţó.ź0ű˝ÎÍűӟbÖ/~‘ýŽ&ă_üâ,(WüúÎý㳼+“^ýę÷˘Đ7Z2Ŕ:šË.ą÷-ˇÄf'œPąĽRšÔţh÷K/Í*tR¸˙V_ţrĹűbf|ć3ąĂgDíđáŃ­ÂůŚ}čCąĂYg• OxŮËbÚ?Ří]S`ěa‡}7z˙ýłkœU=IUˆvżä’,č1 ď]/ź0śxď{{<´nÔ¨Ř闿Œ)o}k§}3žđ…˜vĘ)]Ţ7ýŹ;˙ú׍$mHéů§ę,]I!°ť %âúĽßßňvJ~W‹jéyf˙Žô¤p7űŰc—ßý.€ž˜€u”‡öťďž,Ě2öC˛v7Š}Kݘ11r‡bʉ'fĐŢbÂK^Ňĺšśx÷ťcˇżü%Ć}tÖŽ)ľŐIçjoo/=î}ď‹ýy$śůÚ×běÁg¸O-aę'LˆQĎ{^”Ů÷îťłjéy”Űî{ߋÝ.ş(&|4ląEvßô8_ö˛ŘăŠ+búG>ŹťTŃg˙ÇË^ç Ç›…#RŔŠŽą1†o˝uLzĺ+c‡3ĎĚŢ]$=nzŹ}nż={_¤J0é=›]ó)S˛`ÔÖ_ţrě˙řăYűĽJRĹĄížóŘóŸ˙ŒÉŻ}mV ŠśĄ!†OŸž˝g÷žíśhÜmˇŘŘR€-ű=üß˙Ć=öČB@ŠL㎝fc{ßzkÔOžÜăyúúĽßí~ń‹’]ŞÎóŕ[ßÚŃn­väČěߕçÝpCL-üž§Ÿ'UţIżĎĂ ?Ăč}ö‰éţpö3íX8WMáz}×óWŕz>ŽŚÂíîÖ5]lçKmŃ:_ę֌Օ-i_j]ŰÔÔ|]Ŕ RţÇą´]ź´&ÔÓşĽĽ%VŹXmmí1cƖôݧžz:jkkbäČĆ¨ŻŻššš¨ŤŤËÖĹKąš^T˘€jÔĐ0ěŕÂŞ­°,^łn-[Ú׬ۊ–ö˘uů]lwˇ.ż]Žť}™ú€!D`€!E`€!E`€!E`€!E`€!E`€!Ľ6€ŞTSSŔ†gnŞŸŔ T™ňă>œŔ†an-™RT˜€*Uúíßd€ľvNe¨~3PE*}/koo ˙Ďšő4?TŘDőĺƒv~l[[[ý'Ÿs[—ů:`Ó%0ƒ@míę˙¤ˇ´´Đň9ˇ|ü—ôa=}keĺʕôŸ4ç–ćŢf`pń_v¨]őG.ţ°ž|ůňúO>ç–i­Ťy: şĚ@*˙žúĂzDsssGOe`ý¤šś4ç–ćŢĘ+ĚÉ@u˜€*UţźŽŽ>[ąbEë/ÍľĽ9ˇ4÷VLXŞŸŔ Tąź lZ×ŐŐec‹-`ýĺsmiî­x.¨~ţ‹UŚźOrž>¨§ĽĽĽ%V­ZŔşKsliŽ-Ÿwëj^¨N3° ëîwĽčőőŤŰ2͟ż €u—ć؊çÜr=e„h :Ě@Šôať¸ÂLúđžÖÍÍÍą|ůŠú.Í­Ľ9śâ9ˇŽ‚22Pf  8Ďoç˰aòőœ9s˘­­-€ŢKsjin­xŽ­xI´c€ę'0UŹüĂzZęęę:ĘÄΝ;7€ŢKsjy+Ś4×Vi¨~3°‰+˙^ü-–âąź-Sţ͗şşÚXąbe,Z´8€žĽš´4§–ćÖňę2•Ú1UšŁŤ´ lşf ŠUúvËÚÖL Ů7`.\˖-  ki-ÍĽĽ9ľ4ˇÖÝÜPýęŘäĽáíí흶‹Ç‹[2ĺҡ`RĎĺšsçeŰŁF  T ˤ9´ľŐ›ë˛Ę2Ĺ-™rŞËŔŕ Â TšJßpÉËÄŽţ6ĚęŇąé˙˘E‹X+͙•‡eĘ[1Š.ƒ 3PĽŠŤĚä҇řTQ&˙@Ÿä™ćććX¸pQŹZľ*&OžÜą†˘Ő•™çÊ+łš˛4V__ŸÝ.˔gÁ¨~3P%ĘŰ2UÚW”)–>č硙4đä“OŔ)›EcccŔPł|ůň˜={NI•ćź SůқŒ T¨"塙âíJŐeĘď›Ć›šš˘ľľ5ć̙›MLœ81FŒ0Ř­\š*ćϟŸ}ą,͕ĽLCCCG0ŚŤ°Lń|[y8FXŞ“Ŕ TšŢ„fŇvO†---ْ&f͚•M L˜0>FŽŠUƒJš[ąbE,X°0ű"Y’ćĂRUćź2sq@Ś/a z Ě@•ŠÔšŠ§ĐLŢŽ)ż—˜M™těę~Íó˛ýiߨQٞŞ3yĎfTƒ4÷•ćşŇ—ĹR5™e˖es`IŢ~)ÍwĽ9°|Ţ+Ďo÷%,cŢ Ş—Ŕ TĄŢ„fňŰéĂ~š$ȡóIƒüĂÚNߏI“évZ/Z´¨°D§Ç(>Gń6¤<¨Rž.ߟäa˜ôĺ°â`Lq8ŚxßżřÂ20řĚ@•ę)4Sü˝8@“W›Éƒ3ůvš,HŇX ĐŹnáÔůCä!›üݤ ?ôJ)Ÿ[=–ý˙l;Ż(“[”Š´]~^aœf ŠU °tšÉ?đç!™â6MĹcůDB./~ 6•ćż*…]Šƒ1ĺǡ`ęŽRMĽm z ĚŔ P^mŚĄ•ŽZ.•ďďë>`p˜€! Ťj3ÝíëjbĄwŐUWŽĎ˘śśëlvů{čßřjźůë_/*źţ?ţxÔÔDLŸže}ô‘ńŞW˝2ÌÓé<çŸ˙ÇřöˇżÓą˝ăŽ;Ć9çü"fΜ?ýé/⦛nŠ… Ĺäɓb×]w‰×żţuąĎ>{GwŇű÷˘‹.‰[o˝-ć̙K—.‹ĆƑąĹSłŸ÷ľŻ}Uö~Ş—Ŕ °ŢZZZăťß==~÷ťß—Œ?öŘcْ*Žœ~úwbË-ˇětß´řć7ż+VŹ(onnŽe˖g!’‹/ž$ Ţ|á Ÿ[Ż K Ç|îs_Ě&ĺćΝ—-)¸röŮżŠŻ~ő´,Ź3.žřŇěg_ľjU”>Ďůqýő7fË/yN|ĺ+_Î*š”KĄ¤ď˙‡^÷YłfǟţtA\sÍ5ńă˙(úKŞ,síľ×—ŒíˇßžąÍ6[—ŒÍŸż nşéć8đŔD_|ĺ+_‹.ş¸děÁ̖*úÖˇž‘…šz’/ď˙˙Ē%K;ĆfÎ|.[ţţ÷Ć 'ź9N>ůý=íííŮűř8/ť],…¸Ň’žKÚ˙Žwýwü÷ż=€ę¤%°Ţ.ťěňNĄbŠÚÇç?j§Â-ˇÜ§žzZ§°L%˙üçżă´Óžëjĺʕń|¸bXŚ\ ΜrĘGăŮgŸ’^Ż/ů+Â2ĺRČăţçƒńĐCwÚ÷ӟţźŰ×}öě9ńĽ/­­­ŃŇ5HprŠňÍóžˇWL™2%śÝvےc/żźom™.źđŻÂ2ĹŇëđÁž‹/îöńŃŘ}÷ݲÍĺ—_gžyVPHţöˇÄŰŢö`ěźóNńĄ}0ŢńŽĹŮţŰożŁäůäUUFŐ1öűߟ>úhÇö°aĂâ-oysV%U­šëŽťâŒ3ÎĘŞ¨$iýŤ_ý:>őŠGKá—ţđ̒ąç?żxík_“'OŽ'žx"{ě´NŇkńĹ/~9Î=÷ě¨I}Š žxâÉěu/–öyäYeœT %UćIŻy)oÇ´ÇťÇđáĂłŰ|PVM(÷Ż]…”FŒ˝‘*׌3şp}O,œwX°`aşëŽť;ŽI•k~đƒ3âӟţd—çIáŹä/x~źć5ŻÎÚ8ĽÔšçţ&{>šŸ˙üě8ć˜ŢŻÓ˛íô^ýőŻ[rŽtMN:éý1cƖ1gÎÜÂ59§¤őÔO~ňłě=__ďR@ľ1ťʎtřĹ/~Ú>H^řÂĂâýď?šä¸oźŠ$0óđĂĽUSŢţöˇĆA˜Ý;vlž¨­­‰űď Ť`˛ÝvŰĹf›MÎöoťí6Ů:U8)ĚěžűîŮXšÔŇč˝ď}wByüń'ăo|}źôĽ/é؟B8)d’BšŢTŁYçœsnÖr*wÔQ/ŠÓN;ľ# “‚(‡~Xźĺ-oËŞÄ$<ňH\{íuq衇dۗ\ri§Ę1)HňŠWźźcűÍo~cá| zčĄX_ .Œ›nşĽd젃֜\:ôЃă׿ţMÇv ]}őľqôŃGEo¤öHßýî˙ËÂRšĂ;$N>ůCqçwuŒ]uŐßâŁ=Ľ#¨SIşß7žńľŽ–KűîťOvŢřcǤ€L d˝ă˙•m?óĚł%šäŸřX̘1#ť=zôčŹ%Xţ\ˇÝv›ěý˜‡š€ę"0ʎăŽ;Ž$,“¤`Ěnťí–U–É͙3§ä˜ÔҧX Cźđ…‡Çřńă;ĆN<ń-Ńž˙üýłĽ;#F”†0.\ý-U‹ů÷żŻ){ßűŢÓ–ÉĽĘ(ŠâĚgü¸c,UaÉ3ĺçH!›â°L’Büŕ˙Ä>pJŹŻü㟝:tPÇíRJU†-ZŰ2éňË/ďu`ćˆ#/ Ë$Š PzmŠƒW)ˆsó͡tꕤŞ0yXfís=0 · Rœ<03lXç˙Yü—ż\ď}ç‘ËC3@u˜ÖŰśŰn]q|Ìé%™źÝQîC‰ .řsÇöÍ7ßÇ÷ĘŘe—] ËÎąóÎ;ĆŽťîŰoż]§ÄúHUAž}öŮxôŃDz>łfÍ)Ü~${üňăúŰÓO?ÓŠ’ÉYgý´âą×_CÉvŞ2“Ë[ĺş ěˇßžŃŘŘŘéľďŤ+ޏŞd;ľĎÚa‡í;śÓő9ě°Ă⢋.îťá†›bѢE1nܸĎßU˜)qRËŹ4Ę=÷Üs]žgâÄ Շʥö[Ł™™3Ÿí¸˝ĺ–[ĆÖ[oÝŃ+9÷Ü_g­ĹöŘcˇŘi§ł*DévúŮ€ę&0ʎúúú>çŢ˙ţ÷ÄÝwßSҚ)U1š÷Ţ{ł%—BŠzĘý×[łđÇşš9óš8ďź?ĆE]”ľ_ÚĘŤě$W^ůˇč… eë~)Ýlžůć,“&MZŻŔĚěŮłăŽ;î,[ąby\|ń%%cŤV•>§–––řŰßţŻyÍŤŁ'é9V’ž˙ĉă™gžé›;w^7ç™ÜĺžÍ6ŰŹd;˝ŇsĚß§_üâçâCúpÉ{#˝nŠUq;ŞÔěMoz}ü+:UރŔ °ŃŒ;6~öłÇď^\xáEńôÓOW<ŢöśłĺšçfĹ˝÷Ţ÷ß˙@Vaćž{îćććŽcSťœ_üâWqĘ)ˆžH­•žôĽÓJÂ23f̈7źáľą÷Ţ{ÇôéÓ˛Ę5˙ű?<0S^ĺdذaqőŐ˙ˆžHĎuĈ%UfR‹ŠJR•šsçĆú¸âŠŢUŔŠ$UJíŁzjcôĚ3•ĂRégœ7o~ÉؤIť:MÖŽ)]ďJ-źR;ŹbcǎéTiʔ)ńń$>úŃSâąÇ/źďűî{ ű9z衒c˙öˇÄąÇ^‡vhŐĽ66˛Ĺ‹g-śŘ<Ž:ęEqňÉď3ÎřAüńż­ˇŢşäŘŰoż#úęŃG+ ”¤°IŞlóú׿.vÜq‡Ž6O˗/‹śĺ–ÓŁĄĄĄc;‚xŕ?ŃWÓ§O/Ůžúęk+—Ş ”ˇoę‹Tő'…FÖUŞLsůĺWöxÜżţuuĹńkŻ˝ž$4•L›6­ŤÓŹiĄtsĹçQţÓŚMŻxŽÔ‚já…ąýöŰĹË_~\|âsÎůEœuÖ%×.šíśžż€O`Ř(zčá8ůäĹqÇÇó˛xç;ßK–,)9&UűŘsĎ=JĆG–l×ŐՕlWjš”9ĹF•ľƒ*–—\rYôĹŞUŤ:UjĎÓÔ´6đ‘Â9‡rPÉţ3ĎüqVĽÜWžňőxőŤ_˙ř'ăÇ?ţIVy'wŘa‡”űŔÄ˙ř§’ąôsŸ~úb}\qĹUĆR˜é†ŽŠ¸\wÝżcâÄ %Ç÷&0“*¸üőŻ•ŒĽĐʏ~tfÉXzýößżnĎőýď˙0–.]Z2öűß˙!kĽTěđĂ-yŽďz×{㨣މăM|éK_îԆjŻ˝öŒÉ“'—ŒŐ@őђ Ř(ŚM›š…$ňĐɂ 㤓>ď|çŰłĘ)drÍ5×Će—]^rż}÷ݧdť<œ‘BßűŢbë­gÄčŃcâĹ/>26ß|JÉ1sç΋ď|çűń–ˇź)&Mš?ţDüô§?‹Űnť=ş3rdi8bţü…űýZxß/}éąYŰĽT•¨źO:ÇąÇSňsĽ`šoź9>ýéĎfUˆRĺŁt­˙ô§ :ľžÚgŸ˝¨>3ŔF1jÔ¨8é¤÷fÁ•ÜC=ŸúÔgşźĎÔŠSă„ŢT2vŕ/ČBĹZ~űŰßeëwÜ1 ̤öEťíś[Üwß}ǤŠ#i)–‚/O=őT—żŰnťvK™$…<ŚNÝ" W¤đE X䎺ęďŮňšĎ}&Ž;ÇťÇ{ŢóŽ8óĚł:ŽIaâŔFšÔčůĎßżc{Ť­śŠ˙úݎĆĎ~ö‹ŽąźíPqëĄô¤Ş;Ď<óLôŐĂ?ŇŠ*K äם;G}TI`&šě˛+ş ̤Ş;ŠýŇ?ţńŻlŠdҤ‰Ů{Ś;“'O*źţ“âÁŒłĎţU—Ç˝ë]˙˝Ÿréľ}á +yíş{.ÉGűíˇoŐGK&`Łyăßüŕ˙İaĂz)ěŃÜźşŇžđŮNŐhŠM›6-N=ő ѝmˇÝŚŁ’Lš<ě’Z2˝÷˝ďîö˜äío[|ň“ëąZJ:_zţ÷?Ńiß;ßůŽxӛŢŘĺ}'LŸýLŠŃş¸âŠÎ­”Ž<ňˆžî{ďýź,ÜRěĘ+ŻŹŘvjíy_”UséJ ˇüđ‡§wjĽU.˝—žüĺ/v{­ßúÖ Ë[:ŸzęťźžĹŇ59çKT'f€ę„ŢGud\pÁ_âÖ[o‹§Ÿ~:–,Y#F  &f•[R%Ă;´ËsźűÝďŒvŘ>k™óŸ˙<K—.‹QŁcë­ˇŽ… Ćf›mV¸˝UüöˇçĆo~óťŹ=Ď̙3Łľľ5 ʤĘ"'žxBá~K{|žŸ˙ügc×]w‰Ë/ż*žx≬ĽT gŹ\š˘ă˜WžňřŹőŇyç<đŸěůŒ3:ŤSěŐŻ~UrČÁYő•ŤŻž&f͚•UŚil›ožEւéUŻ:> ęT’*˝œrʲç˙‡?œ÷ß˙@ÖÂ(e:č Ź˝Ő”)Sb]•ˇcJíĘ[buőź^ô˘Ĺůç˙ąclöě9YËŤý÷߯Ëű}ô٧dŐwŇýyäŃÂyjbúô-ă裏,źŻŒŃŁGGo¤k}öŮ?‹Ÿ˙ü—qÝu×eížRĺ™T!č ox}—-Ľ†_úҲc.şč’¸óÎťbΜٱ|ůŠěúM™˛yöó§vX;í´cŐŤŚŽŤŠpťťuMŰůR[´Î—ş5cueKڗžf\ŰÔÔ|]P^ň’—ŢE‹;ś?÷šOgU[ú*…kžýíďtl§śX\p~ŁĄaŘÁ…U*+żxÍşľli_łn+ZڋÖĺKtąÝÝşüvšîöeT˜`H˜`H˜`H˜`H˜`HŠé‡ăj*Üîn]ÓĹvžÔ­óĽnÍX]ْöM댌ćë€ÓĐ0ěŕÂŞ­°,^łn-[Ú׬ۊ–ö˘uů]lwˇ.ż]Žť}fRfRfRfRfRfRfRfRfRfRfRfRfRfRf€őÖŢŢ0Đjjj ?Ě=ˆ`SĐÓ<•@ Đ[3@'2TŁňy- +3@ŚŻ!Ą6ŚŢ„aŠç°„g€b30Äu|éM Fh€!…_úڞ)?^pHf`ˆŞ4ĄĐÝ$C[[[ŔŚ Ňž&†oˆaÆ&Ň$B‰ŞÂęŠÉiićććXľŞ)›űjjjĘć¸ŇÜWZR€ŚŤŕŒš0f`ęŞŞL^M&M¤u’&F PmV‡bŇR›}!Źąą1›K™e˖g_ ˗´?Ż:ŁÚ =30UŞ*“&Ň:eҒśÓ7i̝MŔ`”1#FŒČ–4/śdÉҎ/“Ľyą´¤pLĽŕŒĐ ^30ˆT ĘäK ČŹZľ*űöLÚ7n\a’`xŔP‘Â1'Nˆ•+WŢE‹:Ş1žzž,dň%Qm/$ŠĂ2ůퟪLúПÂ2ižI“ŞĘh˝ŔP•žHÖĐ09Ť6łrĺĘl-…fR‹ŚźÚLRœš€ÁE`ň°Lń’ĘËŚ°Lş=zô¨5jTŔP—B1ăƍúúşXştYŹXą" ͤ*4)@“d„f`p˜€*Ö] Śâ°Lú€ŸZ09"€ľŇĚjkë˛Mi.-IĄ™bZ4Ŕŕ#0Uާ°LKKK455 Ë@ňšłšIsj)S__úg´âŒj3Pýf  ő–immÍ>اő˜1Ł…e i­­­5–,YÚšŠŤŤ+9Fh¨2=…eRE™ÔŠ)U˜ihhČJĘ=KsiŤV5e™ÚÚÚ,“Öńf`p¨  Ş•‡eRU™˜IˇÇ@ďĽ9ľüKiiŽ-Ý.žƒ¨"ĺČӇőâ}iÉ[1Mœ8ĄÓˇ_€îĽ9ľ4ˇ–ˇ=/ĘĎÉ%B4Pü Ş\ńˇ[RŚ´Ô××Lj#čť4ˇ–ćŘňů6f`đ˜€*UŠşL*›ÖZ1ŔúIslĹsnÝU™ޏŔ Tąô!=JÄŚĽŽŽ.XwiŽ-ÍľĺónĹsq@ő˜€*TŠOr^věŘ1Źż4×V<÷VL•¨nőT­âŢÉéC{a$†› ߜٸjjj€uˇzŽmőÜ[Ş8“Ďřw€ę'0U&Ą÷MNßfIK]]}ÔÖnřr‚1›ŚŽŽ‹ €ŢIsmiÎ-ľdJóoiť84#<ŐKK&¨2ĺ!ˆ´>°'ąĄWˇĄş¸v˝—ĎšĽ9¸Jss@u˜€*•Ň7[VfR;چH‚ƒk Đ˝ŐsníUfĚĽŔŕ %T‘ââĺˇŰÚÚŁŽŽ.‚ €Ą!żÎĘŹ•ćÜŇÜ[wssćS úĚ@*°¤oś$Їň@>ÎŚv>Jő×Čŕ ŔZůœ[>—”€ę&0U(4”—íďŔÄĆş?댍×}]ß‚3Ľs#ů|\˜€ę&0U,4体űóœę~ źő U™ü†şŐ-ŃŰ:nŐO`…–ѲiĂęĐĘş†g„fĚ]Ŕ`"0dúVŮŘÁšĄŞˇŻcoƒ-}mš$4 3PE*&ú#ŒŇŰsô÷q Œň׿§K_‚3B3ŔP6PósŔ†'0UŞż>ˆ÷Wf]Ÿ …uÓ×vJ˝š_oĂ0B3ŔPg~ŞŸŔ a˝ ŤôGPF(Ś˙u÷šöŠéî˜ŢV›1)T3 K݅2ÖuŻ7-™zœˆ+˘ÖľrL>ŢÔÔ---ŃÖÖÖ1Ö_íč›Ţ[ňăŇşśś6† –-]Ł§ĐŒP P­f€Nş ˤeŊŃÚÚÚăń=íŁTzťŤ*“¤ë—–ććć9rdˇ÷Ё‚Ö%LJeć͛Ë.Œ‘ˇ^#ďš#†Í›ľÍMŃ/~pN ¨“ߪJž۰†hžźy,ß}ŸXš˙A1jÜř˜4iRśŻŻá  Ě@•)ťôw—JçKcŠÉŹYłbŐs3cĘůgǰ9ĎŐ)œ†Ď|*[šďş9fżîíYĽ™)SŚD]]]§ŒP Ŕj•ćć̛@uŞ  *­kPŚŻí“ňĘ2óçϏUK— Ë 2ĂfŻ@­\ş4ťĆůő.§íŔZćC ú Ě]Ę?ř/_žűl\yĺßâ™gžűîť?>öąOĹŮg˙4jk彀ő'0ŔFóüçď‡vhĹ}ďyĎťâĂţXÜxăÍYhćß˙ž:Ž8â…°ž|E(Ą ĺ6Ö{˘ĄĄ!>ýéOul§ŕ @Pa€MÖôéÓ˘ąą1–/_óćÍëň¸´ďĎž0Žťî†xěąÇbŊ•1aÂřŘjŤ­âČ#ˆW˝ęř,€Sîńǟˆ×˝îMŃ[[n9˝đ8çWÜwíľ×ĹĽ—^wß}O̙37† Ť)SŚÄóžˇWźá Ż‹vÚąŰsŻëϐpŔ!ŃÖÖďyĎ;ă]ďúď8˙ü?Ņ^O<ńdá<+ ˇ˙ÓŚM `56Y ,ČÂ2Éäɓ+sĹWĹWžňľXślyÉřěŮs˛ĺ–[n .řKüŕߍI“&E[şti|ęSŸ‰n¸ŠdźŠŠ){ěńlIᕏ~ô”xă_ý3|ň“ŸŽüă_tM`€MÖ~pFÇícŽyq§ý×]w}|öł_ČŞŤÔÖÖƹLJvhV™eţüqŮe—Çż˙}M<ôĐĂńĹ/~9N?ýť%÷Ÿ8qB|čC'Gw.şč’xä‘GłŰ/{Ůą%űŇă~čC;ďź+۞1cËxÍk^;ě°}ÔÔÔÄü'~ýëßƂ ă˙ţ뎝Ä^{íYrŽőýŠ]|ńĽńĚ3ĎfńĘWž"Ť*łrĺęJ5ŔZ3lRRE™˙üçÁ8çœ_gA‘$ľÚ{ďçu:öˇżý}4ŠŻŻÓO˙N<˙ůű—ěO!›SOýJVáĺúëoŒ'Ÿ|*śÚjFÇţącÇĆ[ßú–.ŸK ł<účcŮíŘ?kwTěöŰďˆűď ť}čĄÇ7żůľ’śIř‚8ňČśŢtbVqć÷ż?ŻS`f}†b),“ŞŘ|ěcÎ;@e3l4ţđÇťÝä‘GÄ;Ţń_Ye–JRľ•TyeîÜš‚&šWżú•YŘ$šďžűť ›”›9óšŹňK{{{Lž<)N;íKY˜bűíˇo\uŐĽqíľ×Ç ^đü’°L.=Ţ~ű퓅]ňpÍ@ý SŚlVxM?(,=˜`“uÝu7dë“O>ŠËČŽ;î-])ą,X° z#Uƒůä'?‹/ÉB2_ůĘŠ1qâĊÇ666ĆŃGŐíů† Öíă÷×ϰĎ>{g•j€î™M`Ł9é¤÷Ć{ě^2ÖŇŇłgωż˙ýY`ćď˙gÜ|ó-qć™?ŒwŢŠŰó-]ş4yäŃxúégbÖŹYŮ:ľU*>wo|űŰßÉ*š$ď{ßťłJ2˝‘Z+ĽÇ|üńÇăšçfeË<7Ýt˚Çoíńëó3Œ5*€ž ̰ѤŞ*đüŠű^őŞăăŠ+ŽĘÚ"-Y˛4[˙áżéÔnčąÇ/ŒŸ×^{]<űěĚNçék{˘K.š,ţô§?gˇ>řŔŹ%TwR€ĺâ‹/Ë.ť"îžűžXšreĹçZ;uĽż {3l˛Ž9ćĹqĎ=÷Ćo~óť,Trë­ˇĹţűď׹˙Ż˝8žň•ŻwT]IÁ’mśŮ:fĚŘ2śÜrËŘnťmcúôińţ÷ W÷đÏÄWżúěö”)›ĹЧ~ĄŰ°JŞsŇIě¨F“Œ3:vÜqǘ6mjöÔ˜™={vGĐdܸąqĘ)Œ#Ž8<ÌSr˙J[*YślY|â˙›UˆŠŤŤ‹Żý+1~üřnďóƒœŃ–9ę¨Ĺ;ßůŽŹjNůk–*ĺTŇß?Đ;3lŇ&L˜Đq;…Zr7ÜpSGU–Ď|ćSqä‘/Şx˙TŚ7žôĽÓâÉ'ŸĘnŸ|ňűcŻ˝öěń>W_}MśN!™°é*\´dɒŠăýý3˝#0Ŕ&íŽ;î츽Ĺ[tÜ^ž|yÇímśŮŚËű˙óŸ˙ŠžœsÎŻăď˙gvűđÍO9䠎}[m5Łăöß˙ţŠ÷żéŚ›ăěłĎ‰îÜ~űYkĽdęÔ-â‹_ü\ŻŰP͘ąú9ÜvŰíąhѢNűS{§Ď}lŮňŠ÷ﯟčf`ˆJ€ööö€uŐŰPIwnžůÖX¸°4h’Ţ—)|r˙ýÄ?˙ůďhjjĘĆO<ńÍ1qâĎă^đ‚bÚ´Šńěł3ăĚ3>úXźđ…‡ÇřńăbŢźůqÍ5×ĆUWý=śŮfël_%óć͋˙ýßĎFkkkś˝Ď>{ÇE]Ý9ţř—ÇčŃŁłŰŻyÍŤâŢ{ď‹ůóÄ 'ź-Ţđ†×eí™R›Ľ‡~$ţň—żĆ3Ď<ŰmˇmĹçĐ?Đw3@—„j†ŽţĂôĆo~óťIĎ%QN:é}%ăuuuńíoŁ0ţ,tsĹWeKąTÁĺ´Óž”…Y*šôŇËcîÜyۗ\rYśtç°Ăí̤đĚ=÷Ü\đ—˜5kvœ~ú:=÷|ŕ¤l_ĽŔKü @ß Ě°II!’qăĆĆäɓc˙ý÷‹—žô%ąëŽťT2Ţň–7Gsss—ľž°ˆůĚg>‡~hšIŐf-ZŁGŠ˝öÚ3N<ń„Řwß}â›ßüż.Ďąž?ôFűĘŚ¨iQťaÂp=™={vŒ3&FŽCogKkzšŻŚëš.śóĽśh/ukĆęʖ´olZ755_0ČĽś1éüiÉo§Ö/+V,/ü˝=fĚزâýş ww{ćĚç˛Ű›}ńC1 ~pN ¨“ßŞĘŸ˙œ/~/[OşEI…™ŢÜ.śĄŞÓŔQřw¸ůśGŁéšű˘őÉ9ŃždEԌuŰl /Ř9†=ÇÎA˜Öśhşá?Ń|ÝŃňđ̈–Ö옺-'Žß)^´gԌl€áĘ+˙–}餥aXźâ/ďrNkSňÔSOGmásŐȑQ__ŸÍ¤/ý¤u~†ŠÂĂ.ŹÚ Ëâ5ëÖ˛Ľ}Íş­hi/Z—/ŃĹvwëňŰĺzüĆŹ 30ôŚľRń1Z1‘ëM@ŚŤăő×6wq,˙áĹŃúäܒńöEˢĺδ<uWݍď::j7żú>łĹň3/Ö'攝Ź=;OZVĽűźç˜¨ßeӟ”Ÿ|0[755Ç_ţraźň•ÇWEh\f€ĺš%÷Ϗúć–+kÚcéĆ°á#b ´Ô´Ć؇İÓÚfŐđ†XňěS1Źv`žM´jĺň÷Źhh˜@Jó°aŮZŕ6młĆŇoü1Ú-ďö¸ÖGŸ‹Ľ§ý!O>.jęëbŮ÷/ŠöĽ+ş˝O Ü,ű΅1ę”ăŁ~W“ŇŔ†ľĂ;Äý÷?Ýniiš6ŠÚčAíšV+c ,Šm% Ä@YÍą|¨(‹ÇŽ%m­1P–^›Ĺ5Wőgĺ¨ŐŻM]˙y›„śöXţÓ+{ ËäÚ—ŻŠe˙ď/ąěŰô–éP˜”^ţ“ËŁ}٪ؐ^üâ#cűíˇëŘÎC3O>ůTl(ţ"CXo[줞ĚÉňńăb ĚŤm‹sgĆ@YVŰ‹§ŕóŸ4.´ ܝΝóę.łbüŘl÷Ţî‰J40°šo}8ŤÓ'… ćöŚžUKœŚżßRšxŮˎíššđÂż ÍŒŔ ĐŁáÇgëů;nĺţ†ćxřž[c <]ł(ßw›(÷ďş]<¸bI ”đ L;Ź$żś#F LK, ošo|06”Ś›6Ücä„f€M`čĐUՐ>M^Œ9"Ćnżm<šËÎŃßnŢ‹jŰcń‚šq×őţöPÍźXÍąxâč¸˙ˆÝ˘żÝpŔžą`̘XŘÔˇ/Yýíök݊% çĹÂÚś¸ĽđZőˇ'wŰ9Ćnˇ}46ŽĚŽun}Ţ3Ŕúi_6p-Ţ:?XaYŮ˙˙śô†Đ °ąĚ=JAˆ1cĆÄäɓăö‹–a⿏Źi+GŽýĂđŐý]4­ZýĽ9ZăΚ碽­&[Ž{ýÁŃ4˘!úËĘáĂ㲭í5ŃÖ^›77Vőc•œU+—ÇŐýžcűʑ+cUM˙Uąiihˆ˙°lśŮäě ˝ŔŚĄfôlVW5#űďßE€žš6âzHS§nvÜ>n9öĹýҚ)ľJúݨą¤vmŔdńÂůqÁYßî—ÖLí…˙ťşöŠXÖÖmí‘-‹ÇŽż~č¸~i͔^ƒsN8.ŽUxž5Ůů´´Äož}ş_Z3ľˇˇĹ_~ţ˝XşhAÇXŞÄóëŃËűĽ5SzţˇžřE1q‡íbóͧDmmďţ§ĄP źş­§Ä†RˇŐfőu°1 ÍšŔ P˘8 QŒ>|xěłĎóbîś[Ç=‡´^Ą™–š°qEÜ×ĐÜißĂ÷ŢW÷‹,0˛Îç/üßÍ53ă‰XmŠúKkÍęPK[m<źçvń÷ˇíľëóükâOŻ<2îÚe‡ěœmQ“=Nká1î[ş<ţ:kváůŻ{h&ýěWţáçńĐ]7wÚ÷Ŕ°–řkáľk_ÜJzţwŽáœś‹˝÷Ţ+FŒ(­fŃÝűxĂÝ56”†ƒw €MAšŮnťm;ĆňĐĚSO=ýI`†ţ>Lœ81=ôŕxěy{č/=zÚ3Ľ6LgZ×oęň˜›˙qqœć7׊=SjĂô÷Ú'⾚y‘27)ˇ˛zЉaIˇo~ńžń‡žrÚ3­1<~úö×Ŀ޿äœŮ’‚3…ĺ_óĆϞ~vžjĂô‡}˝đ\Ňĺ1׎hŠ_Ž^žNí™RŚ_zL<^¸†ü‚욎/Ąč_ĂöÚ6ęśŰ<ZíÔ Ńpřî°ŠHĄ™ăŽ{i§Đ̕W^ýЎuˇkzšŻŚëš.śť[j‹ÖĹKžÖŸűÜçß0ČW,Éo§ÖE--ÍYXcܸą1PŠcǎQŁFĹŁMMńčN;F]á9Œ›='zŠL¤Š(ˇ74ĹŮcVÄ3ő­Ń“yłž‰;Žš*ę‡ ‹i[ďĐc(#UeyŹvaüŁî‰˜Óž2{MÚÚVeRő—<<Ӛľgމš›OŒŰŰ+ęš[cÚł˘Ś‡Š0Š"Í­űîg˝ý5ńäô-˛LyP&œtîô8iߏ•MńĐ˙űTŸž˙=7ţ+Î;ăëńܓFOćÔľĹÍÛ˘žđĘoŮR׋׿&žŢi‡¸ńeÇÄňéS〞ŰlłMÇóꪪLůóŽôsĚ@?+üJŐďľM´ÜňP´ŻhЁP3zdŒ:ĺř¨?*6%iŢ롇Ž vŒ­Ž|źwl,‹/Îć?†ćyR[ët;_çˇ`¨řň—żüłˆěűī֬˗čfl“ŃŰżllČŔLĽpLÝšąş˛%íKŹmjjž.`kmmÍ& Ғßnii‰+–G[[{̘ąeçčŞMPĽ0NWˇóőěŮłă–[n‹ůóĈĽKcç;. Ď­ˆá+Z˛%Y5˛>V5ÖÇÂ-ă×O<‹j×í ?)vÚű€ŘaĎýc¤)1v¤l|ń‚yąpîŹxčî[ăÁ;oŠąßüĐÚKäA–ľëŐˇkJĆR¸eĚüĽąËíÇNw?ç.Žq gç_8~l̛4.îŰuű¸k÷bÁ˜ą‘E奘öŽ@NéXĐ)ÜŢ⇟ęÓó_˛p^Ź‹q…Ÿé„­śéöő˙ĎŢÇĊQŁcҤ‰ąß~űĔ)S˛cú˜é*#0ŁmÖÂXö˙ţmsGޝ0:?||ÔMŸ›’4çuńŗƣ>Ö1V__Ż|ĺń˝šű(Š%TmmMŒŮXx>őŮ\Hކ“fŇm*†\XĽ?—,^łn-[Ú׬ۊ–ö˘uO›čĹşüvš˙ %0UdCfʡ˃2šW­Z7ÜpS6i°ĹłWDwţôďťb MýńŠEA–ŇPL{ŰÚ`ËÚ0MMÇ1­%÷Ť)şßšu{M÷ç,KÇM?ăSąĄźćđ˝şÝ˙Ü´Łc‹-śČZj1"Ť†éku™îƁőמhy,űŢ_Łő‰ŮŃj§MŒQ>>j'Ž €MIšďşä’Ëâ‘GÖVŢMa™ăElľŐŒŘ˜f`­Á˜Q†˜ő 6TşoCCCě´ÓŽqČ!ĹŚ ľ´ŐÖľŃVXˇţçN[{žÔś×,YU˜˘ą, S“ÝŻ=ŇR“-Ť÷Ż9OÇvÍÚóćc5eÇĽűob!’C=$vß}ˇŹ„qšţ~_ý§f\cŒúäk˘~Ď­c}ŐmżEŒţäk…e€MÎŚ–' łŽĄ‡ü~yŒ­ľ­&Ť“––´n[łŹˡ[ÚkJDzŰ5YÜšĽčřśöľŐbÚÚ֎•œsÍăśo§uklRň Ěú^k`ĂŤ>,F}ŕĺŃpř†íť}ŒúŘŤŁfôŚńď5@NXŘę`imi‹öÚÚ5-’VˇPĘę÷­i™”ĹÚśJYťĽ(kżůąy+ŚźF`MÇvG]ŔâsŽŮŰRťŻ;-oŒm˙^Œ69jFFkáÎK›—Ć‚•łcöŇ'ăé…÷ÄSón‹•M‹ Guľ1ňmGFÍřQąę›út׆?/Fžé°”| €MI Ë\|ńĽń裏uŒ Ë‚Ŕ AŠRH{{{ŻŠt|oÎ1І×ŐÄëöťď7>Fn><+)łěŢ_ÇÍ[Äe{ź(VÖ[v) Ë䥘Ž@L ˔l§ă‹4‘gjÖg:‚4k‚2kîťSÓč8fٔأeLÔŚąôwé)“˘=…x K]aW7>ĆĆfcśś8"VľľĆăso{žúKĚ]ü@lH•*ƏőŚ˘ŒŞ3°~ĺFźňYKĽżúÇęŕz8~ř+Čî°Š–6& O6… L˛ĺčúřŔťśŠQŰ5F{ÖGŠ=ڛÚběˆöx~óĚŘĺž_ÇĎŚĎMŘŹŁ‚LqڤŞLŹ^Z‹C1QTi&U–ÉNJďżf˙äֆxóňąg븈şšŐ˙ kÍÁí­…Ľ0––śÚš¨kNý Rh§mő!ľuąőäýc‹Iűœón‹;ůy,_9;6$Ą¨> ‡í–ľVZ~ÖĺM-•*L27ţ÷Q1ě;ŔŚFXŘŘf€ë†éíýśŸ:>úC]áńŢőú‰Ń¸Ű¨ŐŠ–ć5ɗVIëÂjô¤ˆw>sq|Ťń„X>lDIu˜ŹŇL[YËĽâöMĹcąö˜Jcʜo]šuŒŹŻša5ŤŰÔDÇÉŰ[Ú;Â2ľ5Ťƒ7u…}őíŤo§ó´Ćë ëé÷‰‰cżOĎýu,Yzs „u ÇŐŔŚgŘ>ŰĹ菿:–}˙˘h_˛˘d_ÍđaŃxŇˢ~­`S#,l j  ›jHâe{ QťŽŠšŠ]P)<×üéŚçnŽßŻşóĘhkkς)ŠŐRۚ°LVi[‚iëhǔ*ÍŹŽ6łvŃqE÷;fůćńîUŰFcð¨^ˇzYXF¤Ľžđë´ÔEMCaťĄ6j†ŐFmaŠŠŻúÂsLKúęÖŹ˙?{÷çÖYĺ}ü¨ŒŚĎ¸ŒkÜí8śÓŤc'NOH! ¤aÝ„Ëť°KŰX °a—ś”°ŔŇI…қ“8Nďq;qÜűô˘ŽW瑮ćJŁ:ŁŃHšß—ĎĺV]]] xôĚ_çD÷ˆŰU'3Ś|T&N<_Ć 2¸L—ŚťXœS[Ű­ŇřĹ Ë([÷ß˙ŕ°ĚůçŸGX”f§ ­&“îřąhĎ4ĽVdÁ)%Œˆ#˘SŹŞŒ^G$l+Ł×2a—Lysłlmœ6XUFçfŠ…btŮÚŚĄšHę6­*c[×ýç×̒÷4ígB2a\&ŁÉ—X™Áę2ćőzôżBŃkvégtżVqFâóč;#ąů„ÖwI ě—ŢŽťd4¤ Ä’!T” Ë4}ń"éűÁí „¤ń3ç‰srł@šÚ°aCbŮ Ë̞=KJ‰ 3 ˘œqtct$ĹaÚ0Eü űĂŃ?GD4œ3…ăMĂ8ay˙ŢGcUet ŧ°#y=Ýśx€&y]äXi“óëg‹#zfŇŞ1ZA&QeƝťcašxEs\ʜLb2!‰U–ąćąŽNąĐMë„s¤śáH€\­ Ňřů ¤é_/$, ě-^źŘĚ=žÂ2`ĚPal,*˨šŇvpôÁţčsťÂąVLŚLźŸRP{)E‚b&ŤR̜ɽrÔÎu˛vňŇč6‡­šŒU1&e[ź}S$QafpߔH\Ţ0?Ö *>9\ąPŒÓ ÎDˇiu™°†_Âą0Ă6ÝçpĆdâݤL5‡Ř&łÍ!M“.•€˙ ÷Éh J P=ő€Jpúé§Ęa‡"ÍÍÍRWW'cŔ H2Va˜\´UŃŞĺÍąj2ał!–,‘x`&$ąÖLZyFŰ#‰M8şţŢŔ3ňdh‰„ěá˜HŹ-SrP&ŢŞÉÖ~ÉžíîYRçt&B-ń’0ƒá™xp& ĹÂ1Ń͑ÄÁżfGâړâ*ńŕLŇëvÔI턋d`ďĎeʌV¨ŚŤŤKžyć9Ů´i“ôöö™ĚSŚL‘e˖š)ßçÝłgüń×KžN:é„č ÜĄĎu×]÷H{{‡YŸ:uŠ\vŮĽĂ>ŽÂŃĚľkŸ”§Ÿ~6ńżÝóĎ?Wćϟg–˙ú×;ĺ­ˇŢÎë\uuľrŐUWëy˛yä‘Őňüó/&ÖuPô¤“NĚů8˝Çoźńfbý˜cŽ’•+Wd<Ż~KąąąQćΝ#Gq¸´´´ |čŔX"0Ŕ8VĚpĚhW*9n†Kę§{Da‘Ă4–ŒXf˘ŻÁĄĄ–PŹ-“#‘°Vš EbŐf˘ŰšëürŢćÇĺ晫A™pJ™Hx°˛Œ˝ŞŒ ŐD×÷7ÉAÎÖX剅iÖJ8Ö* ÇZB龘ÖP2x°Ä—%ţIĚ+Šď†ŽťëGíB‰řޒ‘(ć{4ŇsmÝşMnťív ‚‰m~XśmŰn& xœsÎYârš¤ôgčŮgŸ“5k֚`ČH+•ŽŽšűî{e׎Ý2šŠý<ëÖ˝.ŤVŸőýőů|˛aĂđćýţ@tęŒ^{§źňĘŤrŢyçƜ9łE`deՌUő™FWD<źÉ´b ť"ą–GÎřőÉ`ë% GąŞËcÁkůd÷r˙Ŕa˛ˇŚ%}(&Í6{˜ćĚH[ŹşM<“Ʉ FŐŠ2ářő…bá3éţpÄ6Ĺ+×Č`–ĆĘŐHĘśŘzDœ'Kh„™lě˜Ń?ie™[o˝M‚ÁŠ*ŁŐ?f͚%ň /ʎ;ĺíˇ7Ęý÷?(ďz×é9ϧ•CÎ=÷œŹÇh`băĆwÇŰůý~šýö;LˆGiE­ Óß?0ŹăJE+ŻÜwßýć>j5•Ůłg§­$sôŃG™Š=™h0ĺžű0˙ŰNW…%ßçɗţ|ů|~Yż~ƒ,Yr@Ćă^ý …Bât:ó 'iŔŞžžŢ,ëkéďď7?GzýzíwÝuˇüĂ?|´d!,@y#0JfRÓđzRŸ45"ޚčÁýŃ?šť4,1-Ž4Öa-KŸ8Âą 3šv‰há’Dp&VmŚĆ–÷o{X~8ç<[(&^U&2¸ Î8’Ži ×ČAΖÁЋ ÄD'WôÎčóéŐ辸ńO|żš ĆÖM¨'o=ĆäoÄ6żžX€&2XÉŚn™Lhž,ÎHŸTşÇ[c œ8÷Üw›ŕ‰e˙ýÉ-ˇÜ&[śl5UH´uĎ´iÓ˛žŻśśV.\qżBîšç^łŸO†ăÉ'Ÿ6ŐJT)!šh( ‡dŰ_,Úęĺ—_5ËZYF+̔ŠžĆŋ÷ˇ;öţk[&;ŤSCC˝Ě›7WFJĂI>řlٲU°Pa”ŚpDćLt˜K‘čßÔ!‡D4ÜĄQ_{1Ĺeb•eŹ*3áxu­úb‚/aqhe™pŹ%“–sqcűOóž,wő)Űj''ŞĘ˜S„m•fâëdńGŸÄDW´…SôůCŃÉqˆK5údŃkłgPb狘–J۰ŞČls ŕ#Š“ †g$š ĆĂ3•ÎŞœ˘ď‹†Y2…fěm˜†Ó¨ŤŤ+ź˜?žĚ˜1]ĘE[ŰdVJW9ĽžžNš››e´i˜Čj…´rĺąRjúž.^źŘ´dÚ´iłôôô˜×­ó͛ˇ˜c´ Ťňőяţ455%ÖőgHC2<˛Z:::ĺ–[n“‹/ž°Ź~c‡ 3 ě.>q…Âą 2‰)V=FUfB‰j3VńElibUgbŐeâŐgLu™čö`ě\5 |xó˝éŤĘ„IëÝŃ˙ DŤËčäÓ)z76sôšýAŰŽmˇŽ‹MśsÄ[3ůSŞÍ"CC4ą°Ěđ*­” „Xúűű3×××o{L˝jíÚ§Ć4’MKK‹rČAi÷wÜʂB"ĂŃŃŃa‚*jáÂ2mÚ4 t ™kphýú fY[RYA"kžôžŮ' ĺhŤ' Éh5ýyxüń5€˘Â ă\ŚJceZ S´RôÚ\aWôúœ‘XE33iÂaÍőň#ąę0fŽ˜Š2şS+ɘƒBa‰Ä+ÍHźÂŒśf:,´Q>˙ć÷egCMÖër¸˙Eü5sLB˝´ˆŁáŠ>ą3:wDçö&Gz9aó”ńöJ‰W‹‰UŒ ȄÓe+ŇXŐi\Ąv)#iĺ4yňäÄňŽ]ť3VSŮšs§™ˇ´4'ľgĘG{{ť ^(mý3eĘ)7't˘yí/żüŠôööÉĉä裏’X,ŁMĂDúży}Ç2L4sć ™4ibôýꐡŢz[Ž8âp3ˇöMœ8QŠAJóć͓ ޒmŰś'^;`|#0r*U¨&ú,rhĐ/źý’+b3&…ow¤­4!“ˈՖÉď§df$śŇpŒÄZ2…×:F ˆ,óőÉŽúÖXۧ źârĎֆLŃÉ!!Ń ŒĂ„f4,㌇eśČLÄü'–щ…eâí•$’Ôž)`kϔŽŇŒ5Ż ď–Ń6ÚA‚šsç$~žÖ­{ÝTIľwď^١Ż=~ü\)ÔO<™E{ě1RŽôڎ:ęH3•’ŢŰ7ß\o–5Ld0­"łzőc˛}űéěě4!*k{1YU{ôçB[šÝ| €ńŽ–L l,ęőIŁFL´•R lćoŹŐ’ŐzIŹ6KŢHŹ“WŤŃD’Ú3‰?eˆMVk'kťiŃ Kcôqó:źYŻÍçß}ZŤ˝R|Š„ăËańơ™öL‘X›&ÝćM´lŠ ›VLö) Ëř3„e´âL}dŁTşşş:ÓH˝ýöFyçMIűľmÎĂŻNŹxತý~żßT éęęJ{ţÝťw'Úű,]şD&Mš”ö¸]ťvÉƍď”UuĽR°ÂD YąbyÚcrÝăbŇ÷HŻEŻéąÇ֘šÇScÂ<ĹŇŰŰ+›6Ĺ~Κ››Ë F‹@Yđ„²ČiÁ¤í˜ŚhŒV–‰MoÇŤ€˘łH|S$ž‰X•eŤĚDʊ3ŃóÇZ3‰ ÉĪ̄%ëw$‹÷ôɖÖZ şŇç‰ţuâ\ăpIČWźÂŒS+ĚÄçćĘ"śŞ7Ť.ŁufbEn[3Ľś] Š6NZE‚ŇzSŞÁńÇŻ4a­ôń׿Ţ)‡vˆĚš5KäĹ_JTY˛ä™>}ZŇco¸á&S}ĆĺrÉĺ—_&&LHÚżfÍZ3×ĆňĺG§}~ ÔÜyç]fY+™œvÚ)2hHČjy´lŮŇ!÷ΒëS}}˝Š2¤Uo4¤Ł8ŕ€a…ZvěŘiÎg ƒŃ׹O^xáEńůüfŰÁ$(3 h´Ý+KK‡V’‡Óî[ÖŃ/ ˛h8Ć%Ś“fNGl›iÉOĆŘÚ1%ÎŚťL[$‡ ČDŹ^Haąz"™ĐŒh‰ÖLńy0"5ŃůŇm˝ňňœ–ôéż˙5 {Œ>Äa:EiHFC3ÚJĘďeľdŠÄ˙{đ2"I­™‚&kĎH ̈́‡śejż)5Ň/™8Ů[)…3Ü÷ą ŒóĎ?WnżýŻ †äŮgŸ7“ÝźysĺôÓOMÚ­š4lłw0‡&ʊ5´LZ[[Ó>żG,;wî”ń i&S˜(×= bąÚD)}ď†Ă Ae˘ÁœŁ>JPf@ф!qy2˙zQ穑ŻoČöfoPfőřLeŃ /˜Ńe– Ç*ĚXAGÄJŚ$B3‰r.ńj.&0c‚2bŇ*ŚňŒ Ěġ‡bf’ćA‘Ů;űdă”é­O˙‚KČ˝ĚT˜qšĐŒ#z™ń°LÄżŹÁ?‘řd…e졙`d08“ZeĆZśˇgšZ#ŮÔyˇV•Ń 7}}}YŤ&Űśm—M›6›ĺƒ>Pš››Ó—ë†ŮłgIkk‹tuuK[Űd™6mšƒţÔ××ÉÔŠSMë§ý÷_$XE8Αf9Űܑaݚœśš5šâŰ\)“îÓŻ;ýţ@öż"P´âƒ†?t˛–ľíČŔ@ż„Ăó‡çá0’ŰŹuűvkY+{¨ľ×~Fšj%“@ôZwďë0×jˇrc‡LŐd´Sě_~“D1ŰM`Ćjɔ”’ą.Ćë͉íłftťiÁŽÍM‹&퇎U—k=(˛§Ů-O:5ókhřˆ8e˘¸œŽŒÇôô{eĹU?0Ë3fL7s{ őhu•ükŸ#MĹ ‡#ß_!ŞĂ–-[M…ßúúÓJXÇGôË:ˇ–/<žš•ű+Lw|J™"ńyŘ6ElóÔI2Źg›§.§ĘśĎ Â (ˆ¤ بŢţŹ™šč`´śÉŇŮÓ#>Ż_ÂŃóĚhIÝ> ;âpEb­˜‚Žč„H<"ç`+&+•˘‹‘XžFb{cA"łŽA ą„cŐfôׯH|Ů ÎčŻi­şNžˇí ÉÔÝ^Ů=ľ.íkpyo“÷źče֙–LN[K&‰8’3ń–L‘ˆ•݉Ä~kÔ°ŒŘB3Öݖ˜ kČĆ+ó"é[Í8Ł÷˘ŽÖ#Z›˛†eŹ÷&0`ź!0ŠŚť@ŚG&d­Mçv9ĽmBëŕ†"/(eE#?łłń)-˝˘Š2\Úééó bœP$`Hz˛T2ÁŘčé@($ˆ!0ŠŞ˝ť/cË&”žśęčî "0Ňr8Ă:& ÉžŽŢX Œ9 ËCá!ۇűţT3 čźţ€ôy}‚ąŐ;ŕ•_@ŒŔ >ż ř5ŹAŠ™ą Ą%/a€´Ě€ź §=O(2í€ÂaB3Ľ‰Dâ÷=$…˘/ÜĆ= JhĐb´ŽGđĚcÜN§¸˘“ÓĐ‘Pô~†ƒáč%[śl•ÚščŻ ő⊊‘şÚ:ń‚fňűƒ‰e_ ”X^~ń?‹ŚB&L˜öůŞAş{ÝŃŃi^ߔ-w§˝/Öýęó’śĎu×ËôéÓdժ㤜śvČy‡{ĎҀjC` [śŞ3Ö˛Çă‘Ĺ‹÷—9sfËk›ďî ćunˇť6~gU6Ň˝6§SďHŘĄżŞĺżŽ?~ĽÔŐŐ%Â2ŮZ1‚ă0DŚ*3éśç ͨšwt[­„<-"~ŻäŁ~â9őԓĹ㩑I“&ĺ<žR ůTďiooż? Ď^÷dŢ÷ŤaŇ”Ń{+“î^eşk@5r @† hhh0ó@Ëěź3}áĄćšôą:Ď5UŠ|^K}}˝™Zćä}Ţi 5óĆĆF)Ą0Ţ˜#–Ž‚‰}›†^jk=♱DBő“sžŻyęlYtč1ŚZІG†s=ĺ4JöšétżôŰďWşç'@`d-X‘n_Žm'N”yóćÉŔôc$Ü8U2iš:GćsNôŘůŚS)*Łm8ŻA_űüůóĽÚŃ9ďׂĺąűĽ÷ŘţœéŽ#Ÿmůě¨dnIĂ ‘HDĆJşçĎśÍétĘA(˛ŁśNܝ›%´gŁťŰĹ퉍śY&O[$-3Ę̙3dٲĽE l”:řQŒ÷Eďׁ.“öövsż\[Ä˝_ŽžĄ÷kżýfšc­×YŒ° 2c\€ĘG`€ “JÍçĂ ĺd ÍXVŹ8VžţŮł§YdöCßÖ6Y?ü°œŻŤœ% šśl÷WĎcÝŻ˝{[Dć ˝_SŚ´%îWŚçνbĐ`(Ú_P=Ě€Ź˛…f2íËśÝăńČ1Ç-;wî’mŰśIooŻŮ×ÔÔ$űíˇŸLŸ>MƓ\ƒ*zż–/?&ëýN[%Z1€ńŒŔ *9Ô ËcӞ)[8FeÚ7cĆt3ť­Tš†=Fú:5c¤€áSa|€ĘG`€ ’ŤÝ‘îëšZ3ĺŞBc][śýŐŽTŻs¤­ŹěH–Ť=:ă)T&§€Šg}(‡Ă2Zň ZäŞjÂŕÁč)ĆýçýĘscě€ęB…Ş€Óé”P($Á`H\.—ŒĽ|ŞŃXĆK;&ËX˝^s†OÇܔŽÁ€ęA`€* Ö5áőzĽśÖ#Ł%WĆ~œĘuěx r”úőň|„jŇÓ17;!0@uá_v*˜ŐfÇú°Ţßß/Ł­ĐAŒŇ+ôžódfšY_Zc,€ę@…*PjĽ—؇u‘@ `z*öˇ]ň­4c?^ť%Q!Ď]j•ňZŕČLÇÚtĚÍĺrsc\€ĘF`€ •úÜĺrG?Ŕd``@e´ '“zÍ# •”ó D>×6–ŻŸ€ÜtŹMÇQtě͎ą**˜~ŤEC:wš\ćŰ.]]Ý% ĚX ­6“úŘńlŹ^?:ůŃą6ĽcoVKŚŃŽî JƒŃ¨0Š}’­uý ŽS0ŸĎ'ĽDďćĘŔű?cÓą6kÜ-Ó¸¨Lf¨Pé> ťÝn3ooŔ Ayâ}(œŽąŮÇÜ,ŒľPhÉ@I×ţČ^aF?źëˇ^´5S˙€44ÔËX° †ŰŞi4Ö`Ćxz­ŐNÇÖtŒM[1é˜[ş 3Ć`¨LT˜ Ů?œ[ËÖTSScć{öě‘p8,cÉ~]Ľ~žLS5>wŚë@átLMÇÖěcmŠc.ŒżPůĚPÁ҅2Źo˝čňŢ˝{Ľ\Œ4@R.”‘(ök¨Ä{PîtLÍjŤcmŒÁPhÉ@…ąÚ2Ysk›Ő–Iˇé7_ÂᐠxĽŤŤ[Z[[¤1¸0÷`ěčXšŽŠšÝŽDu™tí˜ě•f@e˘Â ,[Ľ’šůLgg§ôőő €Ět MÇŇtLMÇÖ*šŇ1ȍ 3T lUfô˝%Vi&,{÷î3덍 ™†et -öE´3ĆŚ•eě-™,T— :Pa€ —î.V™ŘءabĽcőWW—¤cfŠa™ÔVLT— úPa€ eŻ2cŃńZQĆú@ŻŹŔL ÎÎ.ńů|ŇÖ֖ŘŒGąĘĚ{e`ŔkĆĘtÍív›e{X&58ŁÎPůĚPěá™tAý o…ft`óć-2uęihh`źéďď—Ýť÷$UiśÚ0ĽN„d¨Nf¨ V0&Ýzşę2ŠŐí~ż_BĄěŮł× Lš4Ięęj¨v^ŻOÚŰŰÍËtŹLC2'ŒÉ–ąˇĽgŇP™ĚPáň ÍčşnWľľľ ͤťví2'NúúzZ5 Şč¸ŘŔŔ€tttš/’)ÓŞĚVef{@ڐ° ¨\f¨0ŠUfRˇĽ ÍX횬eŤÄŹfôŘXżć}fżîkll4UgŹžÍ  čؗŽué—Ĺ´šL__ŸSVű%ďŇ10kÜËÚn-–aÜ €ĘE`€ ”OhĆZÖű:H`­[ƒև]×oÖč ‚.럍Ť+:ɐ簟Ă>JÉ Ş¤ÎS÷++ Ł_łcěáűÜzźý„e¨>f¨PšB3öěöUmĆ ÎXë:X t›hb-œ"b=…˛ąÎ‘ ACŽPJęXl›ůołnU”ąŽM ʤ[O=/aށ*XşKŚĐŒőß ÉŘŰ4١Y kťý9Ä ¤˙JvącRľˇ`ĘVŠ&Ý:¨\f¨ŠŐfRƒ4Ö~ű €˝M“ýńąĘ2’6 cßfŒkœKeŤ “ŽÍRjx&ÓcíËP]ĚP% iѤŹ{Źę2öLşđŒ˝ÍPJ™Â-ŮÚ*ĽV ÉˇŞLŚm ˛˜ ŠdjŃdߖéj@&Ýšěű€ą–Ú‚Éږn?A`G`€*”ŠÚŒJ Îč\Ű+Ů׳ľcJ$Čž!X€áČTÉ´/ŸÖJö6NůžT'3TŠLbŇmOmϔnP!]ˆĆž(ľláűöBŞÇ0ŢŔř@`€*—ŽÚŒľ]Ľ†_Rˇ§Ť,“ď f0# ­djš”şżĐ} ş˜`ČTm&ŰžL ŠAš|ž(ś\Á˜LÇşT'3Œ#™ŞÍXűěr—kę2‰‘†XФՋŔ ăLśj3鎳d;žp Š-[ľät ž”`|#0Ŕ8•op&Ű1ePJÖxTş°‹îË'CP(3Œsé‚3ůa\@9Iײ_1–ě̀aĄş Ć0fç2ő‚Χ⠥Œ…Ôń+űötË*[;'0ţ˜`œJ7 )كápX 9Pléڋ[œNgŇşý{H†ŕ Pfgň Ęčzşmůž/Űv é-:ć”)č’ú…/=.5`CpXĚ0Žd ËX ş …Ěş.۷ۏʁUYĆ žčş.ëÜĺr%mO¸ÉÂՋŔ ă@Ž ŒN’ ƒ‰íöšýń™–ó}^ —\–t•bŹíÖžŹctîvťMxFC3Šű9Î0~˜ Ęej­¤Ń ŒNÖv8¨­őHMMMtđ@  "Ä*&ë’@ >ŸßŒ}ůý~3ĆĽc_:i€&Sp†ą0Ć3TŠLUeŹj2:` sĽƒMMâńx@Ľ‰…btrš/„544˜ń0 Ěôőő›/Y“ÎPm€ń‡Ŕ U(]UĐšetŇuý&Mss“Ş‘bęęę̤ăb==˝‰/“鸘NŽIœ!4@ő"0@I”ą& Čř|>óí]ommÔ 0^h8fҤ‰âőú¤ŤŤ+Qšś66NŚkRT› z˜ JŘĂ2Ö˛UUF?ôkXFçúM­*Cë%ŒWúE2§ÍT›ńz˝fMC3ڢɪ6ŁěÁB3T3TÔ°Œ}Ňň˛–Ń匌Fill`źÓPLkk‹¸Ý.éí퓁šŃ*4 ą2„f¨Nf¨`ŮZ0ŮĂ2ú_[0Ő×× €Aú3§ÓeZ4éXšŇЌ-š¨>f¨PšÂ2Á`Pü~?a kěLC3:ŚŚˇ;ůĎhö Őf¨|f¨@šÂ2ĄPČ|°×yssa C ‡CŇÓӛ͸\ޤcÍP=ĚPar…e´˘ŒśbŇ 3Ç””›ŽĽů|~˜q:&Łs;B3T§€Š––ŃŞ2˜Ńĺ Z@ţtLÍúRšŽľé˛} T3TÔäúaÝžO'ŤÓ¤I‡|ű@v:ŚŚckVŰóÔ Œ}LN˘ 2ńW4*œýŰ-چI'ˇŰ-uuu p:śŚclÖxf¨>f¨PéŞËh™XÓŠ cłšeŤ2**˜~Hˇz(k‰X\.—x<0|:ĆŚcmÖ¸›},T>3T t}’­Ň°--Í`ätŹÍ>öfG•**˜˝w˛~hn‘ÚÚZ0rąąśÁŔLjk&PšĚPaŹäöçúm\.ˇ8üóƒŽľé˜›5ţŚěăr„g¨\üE € “ú!\׾‡˛jhhĹcšé\şą9P™ĚPĄŹo˛č7[bmÇäĹs‹}iMÇâhË@up ¨öâŠËápD\.—T’á,8JAÇÜtě-ŰŘăUT3T Ô ‰Ő?Y{*—łb}ó&ő< H`´XcnÖœ…  •Ŕ Č Œ¤–-×čŁ]˘– F‹}ŹÉÓmf¨lf¨`VPÄę\nĆęšĐ ˜b-ŃÉePůĚPËd“íZÓ ?e¨&f@QUÚ7lFr˝„m**HşpGĽTrîyĘ9”Bë'€ńĽÜÇç@ţĚPĄĘíƒřpŽ'ŸÇd:ŚĂ)•ôŔČč8ă?T63 äŠö)÷ę.Öő1pP~̀Ë73šUqĘ5@Cp ü˜#2’śJ===’+l˘óĆĆĆźSn­œh×P>̀aIXŚĐcŠĽĎ5ŇŔ ္E`ŒšLá”;vš}uţLj].ŠuťsˇÓ9äř€7: 8ĚôŤY—™ÉÔŠSÍžąœłýSšś’¨ff¨0Š‹RVg)äy3í×íĹźćrœłbLş{Cˆ <¤›cě€ĘD`€ 5VA™|ž;[X&×1é„Ăa ÂâóErBd:oŠ.Źç/ćóeťW ȔŢXŽÍ€â 0Š*Ÿ°Lśăň9˙p[ĚAŒ|B*ĹŹ:“ďóŒösT 3  ق'éöe ʄB!šŽáď’Jzú˄ŘĹív›Ş3öpH!A‘‘†gRĂ0šž{4ŞÎ”ĂsT*3 (ň Ë( Ęčöp8(Îad:‚ÁX`FĎŁóLϕ-0ŇŰŰ+ĹÔÜܜó9UŠŞÎ؟‹ŕ ŔPf@ފQ™Ĺď÷›y0Ç%… …ŃÇךóŘ3éž+Óśîţ ˆC×%'{Üđ’đqÄ÷65 =Q!á™|3g†"0FʐVL^Ż×T‰‰n‘áĐĚJ ŠŻŻ7Űň ƒěÜšËĚW^łGޚčÉj˘çs˜ Œž×oŻä4ëşŰŚëfť#vœ#ž?đK(ŕ“;?>`Î;cĆô!ݎ­˘ŠvŃsšˆ!0ňRHu™La™p8,^ŻĎ^jj Ż.ŁÜn—C!ńůüŚ-“Ëĺ*Yľ–L˛…QŠŃ†ŠXAŞÍÄ8`2…cŇ­÷÷÷›°ŒŠŇ2ĚІĂT~ ›*5zžlוi ůœťŘ×0ÜóÖ=¨f@N™ůDěúúúÄď÷‹s„żh;$mí¤çÓŞ5…°ˆVşąŸżĐđL1‚4…>žĐ Ď̀˘ÉÂĐpK__żŠ.ătŽŹ%>ŢírJ˙€Š2SHđD+Ü›ĎçKť}¸Ő_F¤)äxB3`źr @Ũ.ŁU`şşş% Ƚ7HM°KF*äjő“/5ç­ŻŻgJٚÔ볂2~żOîű¸[ÜnWtršÇi›§Ř<śŽk96w$-[ű4(ŁSo_,´300`Ž%Ű˝PĂiG•î~g;u|ŽçŇă†Ű  RQa…=Бîčěě4a’É/%,Ł\Ą~iëÁœˇŁŁ#çńZ‰F['EÂ!)6§F‚Á Š˘3ÜvLÑďsĺs€ń„ 3`TiD['9B2šëY)ŚÉ˝/ČžÚĽŃó{¤Ľ% nwú_m´‚Š×ëżß/‘ˆf\RL‰˜ 6~˙ŕóŰC(é*¸ôôôHŢçĎłLKKKÚíT‘HF…Qží˜2U—Ńe­ţ˘m‹&w=)Îđ€“#i˝Ošók›Lź^Żi řFĽšŠž[[5)­d“j¤Ődň}|śýŨDP-¨0FVtŃĘ..‡Lę}IÄYü*'z_“˝őÉŔ€Çcęęꆣ­’´L8’ŃŞłâtĆ^Ż>W}}˝Ů–ŽŞËŽ;Í|Ăúuârš˘sšIM]Îw›NúÜ˝˝Ěšg̘žöůsUšĄ /¨0Ň*Fu­ú˘Ő_Śv<*Ó i4DdZ×ăćyşşş†TcŃę/>ŸßJBĄ Œ–Hôy´ýT0J܇‘T•)Ę5Ľy^*ɘŁd``ŔUjź;ĽĽ˙ MÍĽ~`ŤŠfŁ^RŻCC"Á€OÓ"2ZbÁ˜° čdkË4šň ČäjëPíhÉňVHu™îînSŐeÖž‡G5¨b™Ţńˆlʟ%˝˝}ŇŘؘ؎á•Xu™ŃŞp3Č!ÓúIŸłĄĄaLÚe ČҞi´[3ÝxăÍrÍ5˙qżÇă‘É“'É… äôÓO“3Ď<Ă´ŻŞŸřħ䊧ž‘šsçȟ˙|ƒ€ňC…0ÄHŤŒh•­.SŰűś4 l”Rhđm“†žőâőzMXG_ƒ†d`,0ôËh FŸC3V[ŚÔŠT*˝JŒž_;vě”Ç[#_ýęČG>r…ěŢ˝[FÓ˙÷䨣V˜)[¸ę˛Ë>dŽůűż˙˜€ĘE…0,ŮŞËôôôšŕČěöŐRJÓ:VËĆćEŇ××/ÍÍÍŇŰŰkZ$…B)U„DŸO†ššš’ö•28“Z%ŚÜŞĚX.ťěRŮ˙EIŰôggűöírß}ČśmŰĺľ×ÖÉg?űEůÍo~)N'yo0rf@^ň zôôô˜ŔC]çŤŇ8°EÄUş_7üť¤ŠóńŐaŞĚhľ˝–€ß'Ľ˘•l´BĘŔŔŔŔŒ˛B(ĄPŘĚĂáˆ8ąpŠÎuŠŽˆ+žÍá°ö‹ ‹ÄŽs&-ť\N ƒIçW# ͔ÂŃG)ŤVŸvߕWţƒ|ć3Ÿ•'Ÿ|ڄfVŻ~TN:éD)3 ÉH* Ä*ŤôÇŞËě+muËԎÇĺí ›ę2N§Ë„e‚Á€¸ÝĽůľG_ťŰ´eň˜j3Ša śh ćˇżšÉ]Źŕ‹Ăé§ Č8—ŽX(fČ6gňţxՕ|ôCR[[›ô|ů„f2ë0Çă‘űˇ/Ęůç_hÖ58C`P°Lí˜úűűMHÄÓý–4řv–´şŒĽŢż[jŁĎßĺ›eÂ#ÚŽŠ´"ůŁóFÚŃÖP Ęč=’ˆU=Śx“ ‡BڞĎçK Îä žŒu0&›ýö›) ćžíۡ/ëąŰˇď›oţ‹Ź]ű¤ěعߎ3fČG.—\r‘̝;gČcVŽ<Ńź/v˗VźůŻ˙úŽLžň‘+’Žyńŗ䨣V$Özčޤ÷:ííírĂ 7ÉŁ>.[ślţʆdʔ69ňČ#ä ß+¸,ç9ydľüíowËË/ż"RWW+łf͒O\%—^zIÚ*G€Ŕ ČCžUg4 ˘aŠ{—ąÔÖń„ěh>ŰTs‰„ýRj>ŸWš˘÷L[BY! mUĽ ÷[Ľő×ËŢz[ŽXĺIĚśšÓĚĹ9t[ňąąÇ†AřŐ>é|×{dťŰeB---iŻŻœ2Š:::b!ٍśśśŒÇiPćťßýž Ř­_żÁL7ÝôgšęŞ+äŁý°”ƒgŸ}N>÷š/JwwOŇömŰś›éöŰď÷˝ďbů—ůt˘‚ţl}ţó˙*kÖŹMÚŽŽÖ­{ÝLůË­ň“ŸüHćϟ' 0’vLú‡úP(ýK~—´öži‚cĽľo˝8<ÝŽi“úşzqGŻĹ安Î]Ńš[Ü5nqE—Ý.wŹ­‘8[#ĹŰIźőQlŸÄ–­öGńŞ.ĄpH"ሄŁópôŢE"a‰DfżVŰŃ{Ş•Q:Ú;¤áśżIÓÍ—8FĺţÔnŢ(“ňßŇsęٲë´3Lĺ+d2Ü*3cŽůń–X>ăŒÓŇóÇ?^'ß˙ţĚ˛VŁšč˘ dɒĚ{üĆo˜0S~úӟ›đÍ?ţă'ýíoe^ăý×÷ĺšçž7Ű~÷ť˙K´đš9s†Yţӟ~gÖ/ťěCf^__/żúŐĎçill”|iušO~ňŸL K+{î9Ś N}}lÜřŽÜxăͲsç.S}Fďýg?ű™!çřÎwž›ËhEš‹/žPfϞ}ÝŚb>v÷î=&TŁ×^SS#`PL혴‚ŠŽ×ď}FŽnťŔŒC"2=°^öD&Ʉ ­&8áršsˇ{pÝ ƒ˜š#ž1›âËąpŒŘ–×׉žTţWěAćźÁ`8ąăöěŮ#Ý]Ňüó_JýϙŞ2âtÉhq„ĂŇtÇ-âÚźY:?ň÷&´3uęTłĎ~)ç*3jyă7ĺ÷ż˙ŁŹ^ý˜Ůvĺ•/‡včc5`ň“Ÿ\k–5Üň‹_üLŚM›–ŘęŠ'Ëe—]*W]ő˛aĂ[ňťßýQN8a•rČÁf˙ţű/2óXœĚč˛ţlŘ-^źbţć›ëÍÜÚV 1}ýëß4a™śśÉňă˙P-Z˜ŘżjŐńŚÓ§>őy饗ĺúëo”wżűl˛č˙Ö´ “ZšňXůÁţ;Š ÍŃG% .o|ăjÓŚ*Ö>ęHƒ̀˘đůüŚĘĚÔŽ—ĽLxCś7–6$`ĺOŹQgg§8.iüÉĎĽVƒŁ”IUűÔZ EŇ}ĹŚBʤI“†“š‹*3ŸůĚç˛î?唓ä#ů;YştIÚý×]wƒ Ą¨o~óëIa˄ ä?˙ójšä’ËLË&­HcfJíá‡WËćÍ[ĚňWžňoIa‹VŤůÚמ"_ü~s˝úżţőOěßąc§ BŠĺˏI۲éüóϕ 曠 Őejěžú *B>mš4(cŞ­x;ĽĹżUĘAk`›8ü˝RząŠ4}}}Ś PímwHíCŤe,Ô>şZ3÷t˝-ĺ¤ÉťMĆB$6Ąś?Ý$˘í‚\ĽkĹ4D ľżűƒžöďŇÝÝmZ3Ů[,ĺۖi´ěż˙"dIç=ď9Oî˝÷~ůň—ż*==˝f~ăJ\ߞ={ÇNŸ>]r™:uJbYĂ6c˜ŮťwŸ™żöÚ:yď{/ÎűqZ%Č Ě¨/ů_Í{Ľ÷§ŁŁ3z_n6“š?žŹXqŹ\pÁ{dŢźš†˘%ąP(dćőcPɤɿSJ/$rmŮ* /˝"ĺŔýôłz{Łř|~䎹j夕T.˝ôłźqă;ňěłĎÉp9ƒżúŽŐëîóZĄ4K}}˝\}ő7äü­\~ůdéŇ%⊳ô>ýéO×Ë%—\fÚY€Ą¨02ʡęL8;Îę•rRé•~)-˝e:5<ś6śPÂj-EŻĂőČŁ9`ąiŸŐÜÜ,•äĚ3Ď0Ľ-Ž:ęHłÖ&Nœ˜XîëëK,O™2EZZb៧ăŻ/›§Ÿ~ĆĚ=ĚšľŸŒ… ć›ůŤŻž&ápXŠŠŽŽNŽ8âpůĚgţŸüěg˙“ŘţˇżÝ- P4î°OĘIMd,31î]ťĽœ8vě0sŤ}V%yá…ËÓ§OO,k‹ĽÓN;Ő,żôŇËfĘdóć-˛zőcfyժ㤥Ą!iżĂV (ßĘJĂqƧ›ůž}ír˙ýf=öž{î“çž{^ü~Ňv­Psë­ˇË÷ż˙ٌ=řŕƒ¤śśÖ,÷ôôHFK&P°Lag$(ĺôëEězĆFÍŔ@y´cŠsőĆ*ł„BĂŻj˘ďťŁÄŻiÓŚÍňŁýŘ,ťÝn9î¸Iűß˙ţ÷Éwü̈́Jžň•ŻÉ˙ţďOeÚ´iIÇtvvĘžđo&,¤!›|ŕýCž§ĄĄ>ąŹ”9sf§˝žĆĆF3ßšsgĆűQSScćé‚*§œr’üü翐mŰśËwžsLŸ>M9äŕ!Ç=ôĐĂňĽ/ýťYNmßtÇwF_çŻĚ˛VŹ9˙üs‡<ţÎ;ďJTZ´h‘ĘĎęՏĘ˙x˝iŻŤ-”ÓŃ/|tĐ2ůЇ>(Çť\P<fŔ¨VÔŻÚnÇĺ’ráHÓţÇř‹0ŒŇVJ]’z]]]]˛nÝëňđĂŤV>řÁ÷ˤI“’Ž?žüă?~\ž÷˝šĘĹ_&\đY˛äŽYż~˝üůϡHww,źňá_ž6 r衇$–żńŤMGŰk-[śĚ„Z;XžţŮ˝{|ë[ߑO\%}}ýrúé§FßîŘű˝ß~ąvOííňë_˙V8`ąš˝vm›ôo|M>öąOškşâŠËЧž,+V+'N0ç}ꊧŐg´JĚUW]™t­úúŽżţFóx˝†gŸ}NŽ?ţ8™0ĄŐTŽyôŃÇŻŻŻ—K/˝Dĺĺ'?ůYô3ăďr×ßßýœřŒůüüń_)ýč‡őď_Eyîsä1wdXˇ&§mnMŽř6WʤűZtî÷ÖUN+dh˜@'k9 ĘŔ@ż„Ă™={– GŚ0Œ}{śĺ;všĺ9^ýڝjâsűßć,bˆ$ŠŢ”`t Äçö)śmÓq?2AWôš­šŰ=¸n…DĚ<:™˙˜ßJbËfŽłÄňŕń~żO|^Ÿ™ű~ěřuŚ3/GôüÚĐšĂĺŒ.'ĎÍ䌞/1wŘćN3çĐmÉÇĆ%ě HČ›‡˝ş\ŽÎeőýćÚgΜ‘¸…öLŚeťb„jnźńfšćš˙Îűx}ÎK.šHţĺ_>mîg:7ßüůîwż—ąĺ”>ŽČ8°¨?ǟúÔ§eíÚ§’ś˙Ó?ýŁ\~ůëíííňÁ~Ř[ě~÷ť˙“e˖šĺ7ß\oŽ ŰBJ_řÂgĺâ‹/LŹżřâKňšĎ}фj2ŃĚŐWCŽ9ćč!ű´UÓg?ű…D(I“&Ęwžó-9âˆĂJĽŁŁCn¸á&yôŃÇM{\ĽU<ľzćűŢwqôłÎď´˛Ě?˙óçĽPúůřÚk,Gy„ ôślŮ_pH}}ƒŠ‚Ťď‡5śd-0^x<5+Ł3ďŽĎC)S$>ŰŚˆmž:I†őlóÔĺT9ż N…€q&Ÿj2cUqFéSkk‹´ľľÉQG)gő.YştIÖÇ\tѲrĺ œYťöIŮž}ťy 3fĚ0‰¸™;wNĆÇëkŐśGżůÍďäž{î3m™ô:R-Z%ć7żůĽüü翔5kž0űdçÎ]‰ŔĚâĹűËřß昡ßŢh‚3şßN+ÚÜrËMňˇżÝ-÷Ý÷€lݺ՜K[C-X°@Ž?~ĽyMMMMiŻWC0ˇŢzł =ţř˛iÓ&é–ćčëœ+ŤV'^řŢD ) T"^ż8<5&ě€ńGŰË~íkß0•8íŢxăM3]wÝ Ńý_‘“N:QĆ3mĂ4ú9÷źŽj3ťwď–ććfS`,Pa€ RnfŹ9f*ŤÂ̌ӓ_w\j@&]`fŹB4J ú˙éçŢ˙cŻIhó‰ô ˆŁŠ^\óڈgůRsôţCƒ0Ą°řמ!5ŻKpĂ‘`Čăš59zübńœ|°8ę=€ę§a™/|áKIŐ6ÓŃĎÉ×\ső¸͜pŠŚŐ’ĺ׿ţ…|đAi}ňɧ䓟ü§Äz[Űdšűî;¤Ňé—G^}ő5ývşœ{=ŚUJT˜`f@UˢTŸđŢné˙ɝÚź7i{¤ŤO‚/ęôޏîQţátqN‹•Đďî’ţkď’ĐŚ=)'‹˜óčäÓÇ\y†¸—”˙ŕ7†OŰ0ie™\aĽÇ|ýëߔĂ;tÜśg˛‡eTڰLş}Z]´źůć›fŽ_:şíśŰĺüóĎŤˆĐ ¨.fŔ˜ŰîtĘjK^¨qĘn‡CzœiŽţÁuj$"‡B˛Ę–™y şĄpöÖKĺŢŞ Ŕčďę”Ţ˙üłDşúłz{§ô~óFiřÇsÄávIߏîHoöÁz Üô}˙viüôyâ^Ęŕ7@šÓ0ˆ o™6ˇ>Ÿ?çń¸LfÍÚOn¸áڤ6LG>ń‰É™gžaÖďžű^ůéOn*łŞžž^ÓböĘ+˙AŞŃ㏯‘o}ë;˛{÷žźŽ?ꨒ/ Űd:~ęÔ)ňĺ/˙ŤiY\î-Z$ëÖ˝n–ƒÁĄ0&œ0FşůqC|ŞľVn¨wËn§t¸tˆ™ëúőőąý?nđ˜ăEŽH˙/ďË–ąDú}Ň÷˝Ű¤ďżnÉ–Iˆ~÷˙â‰ôůĺMĂ27ž“WXFMœŤłzőcIŰ5,óÁ^&mmmfŇ华ş"é˜GyTŞU!a™bŇçÔ玧vŠ,\¸ ąn…f6oŢ"ĽB`Œ‰M.§|ŽšV¨uKŽÚ1ş˙Z—9^7Zvw‡äű÷wÉ%?ß#'^łSNüîy˙˙î’?Řmö@ľ <ťÁTŽ)Ht ;âô äř|IPŢśmŰVĐńuuufžukňăÎ:ë]CŽ=眳’ÖˇlŮ*ż\.—œ}ö™CB3ˇßţWB3 d̀‚hKž‘ÚítČW›=f^čăžŇä‘]ŁPićž×äÝ˙łK~ůhźśĂ/ý!3­Ű_=Ö#\ť[XW}ÂU1ŢG•/đä›R*ţ§J÷\žbľŕM÷™3 Ľ<—T-m‹4mÚT)5}Î/}é‹R)̀ąć€Ňj1ßiôH×0GĆzœůnS­\Óí-ZňwőzŻüˍű˘zŽÄŕŕŮ7ˆ.Ýýj,$Óç Ë˙Ü.˙Së” ëd<ĐNG5`ĐŚÝR*áí „ÄQă”§™3gš–Lůňz˝ŇŘŘ(łfí'ožš>ąýŽťî‘Ë/˙@Ňąwß}oŇúěŮłĽZ­\šBîźóśÄúQG­HÚ˙Ě3OČHű|cÉ ÍüíowË[o˝mśYĄ™óÎ;Wć̩ޟ0ö¨0JęÁZˇltěWˇ\yČSœÜŻ/‘ż­SBśžPÓ[\ň•wˇĘ—ß=AŚś ţa7ůćâQ@uˆôů¤dô˙:˝~@ůZ´hĄĚŸ?Ojk=yßŢŢać'ž¸*iűĎ~öżňűß˙QöěŮcŚßýîríľżH:愎@QiŒ*̀’ş­ś8•nŻsÉŠ^ą›žé“Ý!ąwyúŇŮ­ŇXëGô?_ż?ź`l8NYźx3â}ďťXŽťîéíí3ë~ż_~řĂ›)ćć&óŔBĽ0¨0JfťÓ![]Ĺůőcsô<Ű]#otËóýIë§,Š—“ŁSb}i˝œ°8šÓŻ T×ÜŠR*Ž9SDÜ´c¨F&LŻ}í+&p“‹ŁÇśśś b>úŃ+ĺď˙ţcyoŻVTšĽF`”Ěú"˙Ąô-×ČΡˇ7$ŻnlâpˆüżS[†÷ɓ[Ě>ËşčcÚűÂR-"ZLăUÍńKĽT<+—Ş×I'(×\sľŠ“‰îűîwż-'žx‚`ĐK/˝,/žřRŢŰŤ™šY°`~b›šŮ˛eŤP2Î‘W„ąka…™WˇĞYš°NöŸZ3ä¸ĹÓj䨚ľ‰u}Čş~€JWsČ|q-˜&ŁÍ9c˘xN8PPÝ44sË-7ÉW|T–,9@Ě´téšňĘż—[o˝™° rŇĐĚ9çœ5$4sß}÷ @1š TŠ›—Ç ŁlŢLZׁő=mi˝<ťi0$ł­3$GĎúŤT,€CĹ"ú˙Ë Ÿú¸i‡SSă–9sćČ '/_|Ą477§}œśgúŘÇŽ0PÎ̀’™*ndr8÷ů~v˙^q¸Üfr:Łsw8ăË/n%ťlŚ'ăyLŮ÷ŔşŮś/,!@|~Ż~ D—ƒŸYţ•Á9ĄQ?ű^éűŢmŢŰ-ĹäœŘ$ Ÿ9O\űMTއzXžöľoH__bŰŔ€Č+ŻźjŚß˙ţrőŐߐ+Ž ŘBĄÜyç]ňöŰŰÜn—œ~úiPLf@Éě K1͆róűÇŰE\5âpÖD˙r[c–Eƒ3ŽŘşÓ1XöŚŠ6s œĆ”,Íó›}ňô[~ Ĺ2ÖÜZ&0 ’8§MŚťXú~řW mÚ-Ĺŕœ9I?sž8'5 *‡†ežđ…/I8œů3|OOŻ|úӟ•ď~÷Űr Ť( Ëüíow ˜wŢš2{ö,(&§”ČŒč`ŰŹPqB3s˘ç™.nŚWˇ2î{}gP š9Z¤ń ˆűŕš2RŽ…ÓĽé –¨0چI+Ëd ËX4ŘđÍo~[şşş(+,óÖ[o'śYa™9sf @ąQa”ÔůŢ ü¤Ń##Ľç)śďß×%ŤöŻ“ćşäLqŻ7,?~¸¸mJ 9jk¤ńS?<,ţŐŻĘpÔąPęŻ8C>nTšn¸)Š “Çă‘O|âcrć™g˜őťďžW~úӟ‹ßď7ëííręŠgJ!ÚÚ&ËŮgŸ%˙ř•RSS#€",Ćf@IâɂV™Y ËIţÜí˜ ľľ#(Ÿüă>éěźžŽž|ęş}˛­ƒ 3Ć —Sę?tŠÔžwŒĘsÚĄŇđ‰łËT¨ŐŤKZ×°Ě?x™´ľľ™I—Żşę ‰˝{÷Éď~÷šöÚ_ 4,sçw–%G`””ţňń…^ż´F†×NŠ9‘ĎőůG험g6ůäŹí’/ţšCţő/írî˙ě’śřƇHÝůËĽţçF˙Ű™×ń°Š˙ Ńe‡ 2mÝş-iýŹłŢ5ä˜sÎ9KŠáŽ;îŔ ËźýöĆÄ6Â2 TřÚ(šŠáˆüGŻOžŐP+ť]ů˙auj("_ę÷É´đđÂ6ůęń†ĺo/÷›żů:Ł˙ĺtňÇ_ă“gŐ2q4ŐI˙˙Ţ#âĎPi+:˜ÝđŃSĽfů€ęIóe 8ƒËĺŒo„eŔXŁÂ s‚ůnONósţB˘űO÷…俢ÇëăĽSsřiúÜ{ĹŃ\?dŸŁśF?őnÂ2UbÖŹý’Öďşëž!ÇÜ}÷˝R guŚ ćĐC‘Ă;4ďíՀ° (T˜cŚ%‘Oö佞 łî÷űĺ‡?üą™Ň™ăŒÓä ßk‚ČĎ{ß{žÜvŰ_ÍçŠbZźxsîJ5eĘKfPrň—żÜ:äۊ{öě5“3tVˁ§ZťöÉčôTŇśţţyçMfZ°`ž KäSBÜîŮgŸ3ÁŠç}ë­ˇÍtÜq+ä裏’r˘a#+,“ˆ oÉ˝÷Ţ7$¨˛k×n3ić=ď9ĎhRľˇˇ›`NggWŇöŽŽN3˝ňĘŤrć™ďĘP)%˝Ś\׳iÓćŒß˜Í‡†ŞźŢŘýÓçťä’‹¤ŠŠI€j ŸÇ>öą+̄‘Ń/'üŕ˙%Ÿţôg‹šŃ°Œž“ŕ>Ŕđ˜U­šŢ%ât‰Ăé4“¸u=şěŠ.;œât8t&.‡nŽ.;ô8Glťn‹ţWl{t.ş]Ě~]FŽž/=_(zž`t D÷é22ÓĘ2VXFďăŇĽKLŻr­öąqă;&˘űôŰwüŕeâršŐ}VXfňäI&Ŕ˘ƒ¸˝˝˝ň /š 1 yěąÇĺ„Vĺ}MŻżţF",ÓÔÔ(Gudôü“MPä駟‰žżOü ihh0UlʁĎ瓇~$ŻcwíÚ%wÝu„B!s?ľěőÜšsÍş†4ěŃÝÝ#ˇŢzť|ŕď—ÚÚÚ¤çŃíş_é ě,6žZáGƒFÂůŰßî–÷˝ď"™6mZÎë9ëŹ3͡S3Ń ?Ď<óœYÖ*6Ă ĂôdýÖŤU]ĂUŮŽG566˜ëśčńZąGďÝΝťĚýyŕ‡äüóĎHĽUQűŰ_É-ˇÜf>Ÿégąţţţ‚ÎĄŸIő‹gžy†Š,CX`d̀ŞvĎ皀€ËĺNĚÝîÁu l(3אŒÄ‚2ֲă3ƒËƒÇűý>ńy}fîřM° ŕ÷Ç*xüUÁ“O>•Ëh%mgcYślŠŹYó„<őÔ3Śr‰Yě Ż( ľh5Á`Ç4sž›oţ‹lŰśÝTKYšrEô˝Îý뮆F|Ynh¨—K/˝$Q%Dƒ<:ů§?]oZ?éq)‡AÉÇ[“hGĽUa´MU&kÖŹ5ŻSƒ!Zšgć̉}óçϓýö›)÷ÜsŸ }hđhůňcűő^Za™UŤŽ“#<"ąOsşţúÍĎ˝^“ž?}Îlž{îy3×˙­ÚŸ/Ú:kçΝ †L ćŘc—§=ÎëőšjĽmĽ4Ź•ţ,ĽkËĽ?łúúwďŢcÎ óúš0ţčgIý,ŤĆ_@ÉhhĂŞęĄUJěa‹V9ć˜ŘTWW—ŘŽhöîÝg–5¤aŻ‚˘Źj5JĂ]]]’ 9XmyŽ9ćč!-u­˜´ESž-ě4œĄĎłyó¨) ÇhŰ*ľjŐń2qâČÇęóiľĽa{XƢ÷múôXeëýąXĄ’ćć&9âˆĂ‡ŚłłÓ´Űşu›y?N>ů$sP!Ě dŹ0EMŰ„#îşëž¤ýBАÉ;ďź#çœsśĚŸ?OňĽÁ›Ýťca–+ŽÍűqfžŤ2ˆî×Ŕ‰u|>ŹśIŠŹÖTÚNŠ& ĄŽ>úČź7Z§­m˛ ˆźńĆr䑇iáôúëo$Ú )ŸĎ—XÖ*6{öě•ÎÎ.s\jő˝&­˘cIK˘'žXkćZ…']ű§|hpJ+Ć,\¸0úzß4-´úűűMő"ËŤŻŽ3s šh{/ý™ËEßűüŕŇîÓshČk8(ŔŘp P">ŸßĚCĄ°ÜsĎ}ŚEЅžW>őŠOČW|TŽ;n…¸\ąĘ wÝuwR;Ąl´ŠČ“O>m–5ĐQHK +˘­ ˛ąökë¨|iP#óžüƒ7–űďЄm&Lh•cŽ9:ďÇYÇAšńƛ套^–}űö™Š?<˛ÚźőőuiŤ•^4ŕ¤î˝÷~yüń5ćqZUć…^”뎝!ŠýŐp+Źh¸ĹŞúrä‘Gdlť•‹f”ŐňKCXŻ˝ś.ą_+ĐhpHi%{žáZż~ƒ<ôĐ##ŞŽ(-*Ě dŹ0…†´ŇĽ—^’˘h—Ł>ĘĚ5˜á÷L…–c]žőœ†xŕ‡Ě˛VC9ýôSĽĚĐđJ Čzœľ_Ť—äkęÔŠŚ:Kú}S¤ ˛ŞŔœrĘÉ&X”/m;¤  xĺÁNÚ?iŇDŞšűî{Íş=Ź˘­­Î:ëL`ŇŔÍÓO?k&‹†iŢýîs䦛ţlÖ š? šh… ŐĐP/‡v¨ŒÔœ9łÍϘś—Ňj>Gu¤ŮŽŐdŹŕ–ŞÉ‡śäúťżťř "ijlgĽ›Bi芣ŁÓ,kp'WľŸ|Y=ˇVĹQëÖ˝nćzÍóć͕BčëśOMMMŚuÔgœnö÷ôôšŞ;€ňG…”LKKKÚe;­BÓĐĐ`Şžx˝ŢŒçŇę3Ve Ëź÷˝çŤşI[[› ćh%’´ÝŢŐ՝8>_&L0UtVŻ~LśmŰfÂ<óçϗN8ž PČ#}Ú°Ă2jîÜ9&|Ł^ý 9üđÆŁŰíÇbҤIňž÷œ'#ąeË3×ŕ‡VÔÉćśŰţjć—\r‘ ͨ|H‚ÁL˜Đj*¸¤ňů|˛~ýzłźpá¤}Z1e÷î=&\rĘ)'Ľ­ŕŁ•~”VŹŃ×[}ŹVfQZu¨Đ AŮh{ŻůóçÉŰoo4“śČŇv`ސvLů°Â7öJ=€ňEK&”ĚôéÓeňäX âŮgŸ“žžž!ÇŹYó„ąĐÁ˘E ‡ěׇ=,sÁďÉ+,ŁAœ ŢJ„q,ږÇj)ôôÓĎ šŚŢŢ^ł]iőmOTi4˘mžxâIŮšsWŇ> áhĽ­NŁĄƒNnĽ`ôąŻžúZÚvC^ÚśmťY>䐃‡œ[+Ţdj­Ľá’§žzÚ,ˇśś˜Ş/ĹfľžÚłgŻyJƒZĂi•‰žF­ˆ¤´Š  üQa%u ŤäÖ[o7ƒëŽťAŽ:ęH™6mšiż¤ŐFŹ–BSŚ´Éţű/JzěsĎ=oÚ)§F=ôD‹TŠŐNn¸á&١ŻÝT0šüňËLť$ĺvťĺř㏓ťďž7éš4řĐŮŮ)Ď<ól" ąr劂Z)˕WţCÖýzíZGďÉ'>qՐýZUćw6™ËŸ˙ü9ě°CŁ÷wŠi5ĽA­ Ł9ä S…ĹN[$i¸IďÁc­‘˝{÷™*;ZŠEŤśhIľľM6ď‡ÝĂ?"/žř˛Y>óĚ3dɒ’ökŘŚŻŻß,ŻXqŹ8ĹĎóϟ?Ϣz{űL[&e…h ĄážÔvKZ™gǎIA˘bś”Œ3() [œrĘIŚJŒ†0ʌ†/Î;ďÝIíy´BŒýX­ˆrĎ=÷e|žc=&:-7ˁ@Ŕ„e”VLŃЇ˜Qäčîî–5kÖfźŚĺˏVТ̘1]N;íSIFŤ÷<ýôłCŽŃj>'žxíZ˝G[JÝrËm20ŕ•uë^7“ݤIM[ŹÔŔËŽ]ťË;wîL ĚčűŠa$ĽU‡8`ąŒ­šŁ•kžz*V%¨ŽŽ6mĺ˘\4ŘsóÍÉú<Çż2Ń PŢĚ ä´ ‡ ž{îٲe‹ŠţQ[ë1U]48ĄÁ{XFiu”áŇŞ0xŃ 53fĚ0m˜Ri–Ůłg›cvíÚe ŚâʑGaB'•ěŔ—™VzĎ7oŢl‚A55nóúô~/^źĆÇę1÷w—›J3ZĽEĂEŽŃБ>îđĂň~)˝§÷ÝwżÔŐŐ i×ôüó/˜ŽŇę28-úúŹŔŒ†vŇ]ëpčýkhhYłf™ęçŃŤ˘˙BťŁSM|nŸâۜĹůCľEoJ0:âsűۜ鸙?Žť˘ĎmÍÝîÁuëôfĚĚo%ąe3×Ybyđxżß'>ŻĎĚýżŠ˜đűM哦3/Gôü*ĐšĂĺŒ.'ĎÍ䌞/1wŘćN3çĐmÉÇĆ%ě HČ›‡˝ş\ŽÎeőýćÚ­ŕ‡= tl҅F3ŘPŽ´%´3:S_ß`Ú;ëřˆ5śd-0^x<5+ŁłptęŽĎC)S$>ŰŚˆmž:I†őlóÔĺT9ż…K…Œ+N(ŐEŞď)o¨0€q…Ŕ Ć3ŞűäÓĹátŠ3: zýâNŸNžčz ąˆ./(3 -‡Ă!‘HdÄÇ`ôôŹ:ՄetňűýâóůĚäőzÓ.Ű3úŢŒWfĄP­Ě`\q @ěŐF¨Q3ŚËĚŠSäÄO0űGRM†Ę3 š˜Ö˘ąÖ9ä`inn–7ŢxSöľÍ–}ňĄźĎ™o…›źuŒQHçGߑb*4°R=~Ţôirä‘G¤}|şóŠă$[%™tű2…fćϟ'3gΐ-[śĘŽ]ť¤ŻŻ_ü~żäóü™=LS€b†IŹ×aS׋u~ˇŰ-'N0•~ZZZ’žÇRhX† ¨6fŔˆe ÍÔÖÖʢE ÍdÉzË@LĽ(4ŘBŘ`(3`ˆBŤĚ¤ŰnŻž’z\şíö}vă1DShČĽ  Ą3`ň Íä:֒-C˜#˝bUšÉuš˙ ˜ieŤ2“mŚĐŒĘVľĆŽÖLÉň ­Š!,Ć+3T¨\–ąź†\í˜ŇíËt˛nč…{ 0|Œ­PůĚPaRC*Łůá<ŸPNścríłŁŞL~FZm&ßs0č0Tę˜ c(T.3 Ťb„f,Ă­*3žÂ4#d)F›%z@ľ#0@…J5čňč…Jň ͨ|C1…„`pdWĚ ÷ “ÁqĆP¨|f¨ é‚+Š!”Ńú°žOhĆ:Îş–|ŽłĐ’)?ĂyŔž\íŃ{ 2˜  XĘĂá°¸\.-ů†fŹcUĄÇç2VÁšb|äd)‚5ĹĄcnŠąŞ Ş€Óé”P($Á`hT3ŞĐŒuźĽa—j˜Í×@P ¸tĚMé¨üË@Đëzđz˝R Ă Xč㏠Ĺaż§„eŠOÇÜt …Ŕ Յ٨`VHÂú°Ţßß/Ľ2ŇŕKjЃ MvĹž_Üo€üXcn֗ÖS :В € ”Ú)öa]$˜žĘĽüś‹5@PŒvKöóaôpňŁcm:ććr9‡Œš1Ć@eŁÂ *őšËĺ6Űd,đíšňF€ÂéX›Ž§č؛c,T>3T0Ť ŹÎ].—ŮÖŐŐ-c‰`Fyá˝>kŹMÇŢěcq ňń/:&5a­ëu‚Á ř|>)„gJĎ~Ďšďçcl:Öfťe—•‰Ŕ *Ýtˇ;Ö–Š˝˝CĘMjƒ…‘á~Œ.cłšY‡ :¸T ý ‰D†lł*Ěč‡wýÖK ţţih¨—rÇŕʍŽ­é›śbŇ1ˇtf,ŒoP™¨0@˛8O­0RSScć{öě‘p8,ň§cj:śfkK­đK•**Xş–<Öˇ^tyďŢ˝ :ŚfľbŇą6ÚbPĚPaěßbąołÚ2Yß|qšœ20ŕ•ŽŽn›ŽĽé˜šŽ­YŐeŇľcJ7F* *Xşoˇ śfň˜oŔtvvJ__ŸČLÇĐt,MÇÔtl-Űب|nG?”G"‘ÄÜÚfľd˛čˇ`´çňŢ˝űĚzccŁHŚaCŹŢě2•eě-™,T— :Pa€ —î.V™ŘءabĽcőWW—¤cfŠa™ÔVLT— úPa€ eŻ2cŃńZQĆú@ŻŹŔL ÎÎ.ńů|ŇÖ֖ŘŒGąĘĚ{e`ŔkĆĘtÍív›e{X&58ŁÎPůĚPěá™tAý o…ft`óć-2uęihh`źéďď—Ýť÷$UiśÚ0ĽN„d¨Nf¨ V0&Ýzşę2ŠŐí~ż_BĄěŮł× Lš4Ięęj¨v^ŻOÚŰŰÍËtŹLC2'ŒÉ–ąˇĽgŇP™ĚPáň ÍčşnWľľľ ͤťví2'NúúzZ5 Şč¸ŘŔŔ€tttš/’)ÓŞĚVef{@ڐ° ¨\f¨0ŠUfRˇĽ ÍX횬eŤÄŹfôŘXżć}fżîkll4UgŹžÍ  čؗŽué—Ĺ´šL__ŸSVű%ďŇ10kÜËÚn-–aÜ €ĘE`€ ”OhĆZÖű:H`­[ƒև]×oÖč ‚.럍Ť+:ɐ簟Ă>JÉ Ş¤ÎS÷++ Ł_łcěáűÜzźý„e¨>f¨PšB3öěöUmĆ ÎXë:X t›hb-œ"b=…˛ąÎ‘ ACŽPJęXl›ůołnU”ąŽM ʤ[O=/aށ*XşKŚĐŒőß ÉŘŰ4١Y kťý9Ä ¤˙JvącRľˇ`ĘVŠ&Ý:¨\f¨ŠŐfRƒ4Ö~ű €˝M“ýńąĘ2’6 cßfŒkœKeŤ “ŽÍRjx&ÓcíËP]ň Ěč_Çř-€2VH‹&e Ř+ČčdU—ą‡d҅gěmž€RĘnÉÖV)ľMžUe2me+Ż?`Qa€*’ŠE“}[ŚüŠ™tç˛ďĆZj &k[şýe€ŞPŚj3*58ŁsmŻd_Ď֎)u [x†` †#[P%Óž|Z+ŮŰ8ĺ{>PĘ=0Ă_ŮŚLbŇmOmϔnP!]ˆĆž(ľláűöBŞÇ0Ţ@єuム3TštŐfŹí*5ü’ş=]e™| ¨0€áIh%SËĽÔý…îՅŔ ă@Śj3ŮöeXH Ňäóź@ąĺ Ćd:žĐ} :V`F˙‚Ćo”™LŐfŹ}všŽË5ˆ@uŒÄHC,ĹҀ˛0*tí 3g(3٪ͤ;ΒíxÂ1(ślՒÓ)4řBP€˛7Ş€˘%ăTžÁ™lÇ”@)YăQéÂ.ş/Ÿ A *!0Ă_âEé‚3ůa\@9Iײ_1–@I•}փ 3`X¨.€ąDŒĆšL˝ óŠ8Chc!uüĘž=ݲĘÖÎ Œ?c˜ŃßH ům¤Đă@é2`t!K!çŠ-]{q‹ÓéLZˇcÉœ`Ôú‡Ł1ůCSľT˜áŻtä)Ÿ ŒŽ§Ű–ďů˛mň‘.ТcN™‚.Š_řŇăR6g(ŠŞř#-™G˛…eŹ]…Bf]—íŰíÇĺŔŞ,c_t]—uîrš’ś§ Üd á€ęE`€q WPF' ɃÁÄvűÜţřLËů>/KŽKşJ1Övë _Ö1:wťÝ&<ŁĄ™Ô€ýg?*-0ɰß^Č Sk%8ЀŒet˛śëŔAm­Gjjj˘ƒ:ˆŕ` !V1Y§ńůüfěËď÷›1.űŇI4™‚3Œ…—HžŰĘVŠ3Ĺ ľDR&FŚŞ2V50ĐšŇA€ŚŚFńx<‰ ŇÄB1:9ÍÂĚx˜fúúúÍČŹI÷[Ug¨6Ŕ°ŒV~Ł$YZ2P…ŇU•сkPF']×oŇ477™Á i ŚŽŽÎL:.ÖÓӛř2™Ž‹é¤á˜tÁB3TŻąĚĐB €Q’.(cMńů|ćŰ3şŢÚÚ$¨`źĐp̤IĹëőIWWW˘smmlœL2Ö¤¨6@ɔźĂf¨ö°ŒľlU•Ńý–Ńš~“FŤĘĐz ă•~‘Ěăi3Őfź^ŻGÓЌśh˛ŞÍ({p†Đ ռ؁ŞÇ0RĂ2öIËËjXF—›šĽąąQ€ńNC1­­-âvť¤ˇˇOLhFŤĐh€Ć Čš lľ M9U˜î +yYĘEśLö°Œ~Ŕ×Lőőu`~ÁĚét™M:–Ś44cG‹&†NV#"e”ń(—ŔŒ˝2M$Í6"WX& Šßď',ä`ihFÇÔ4ăv'˙Í’ĄÚ y‹ČĐ LY„fJ˜I‚ÉŒ)Ťtĺ"WX& ™ö:onn",ä chápHzzzĄ—Ë•t Ąň–+ďÉsۨë 3ůV‘ Ǐ‹¤™DŐƑ\a­(Ł­˜´ÂŒÇă1%eäŚci>ŸßfœN§ Äč܎РIYtS¸ŔóŒ §Œ\d„ű }ŽLaB3€q)5,ŁUe40ŁË&´ €ü阚őĽ4kÓeűă\şŹFşśKĹzžáîĎŠŔLĄOĺýŠÇy€*—ú\?ŹŰ÷édľbš4iâożČNÇÔtlÍj{ž”ąÉ)B4€ńÄápXٌB3ŁľŘǗňŻhŁőۂ9o$îĆ!űˇ[´ “Nnˇ[ęęę@átlMÇŘŹń6*ĚGŹlƨf@JaŹžv>œɲ= Ev ăHşę2Z&Vçc݊É>€Ď„ÂpFŸŽąŮÇܲU™`ź…BšÍČÖ~ИyQ5™ážHžSęąúI$đmĆýnőPÖą:š\.ńxŔxĎf$˛’9ˑ+÷Q¨˘˙<f"iÖ#Yö§J˝é&ÂŰÓÓłA'ŇőIśJĂś´4K)Œvcź†č‡vý§ľśśVFÓX-Ş9ä1–Żŕ @fąąśÁŔ c)€ńîľ×^SbYŒÜ˜ţŁZŹŔLŽŢT#y‘™’EI)ĽŤŻžz0XČíÎőŰ,:š\nq:G/[.ƒŐ08Qn݁€ĄtŹMÇÜŹń7eÓaL0Ţ\s͡­lFş–L–‘´^˛oŸgÚ?"ĽŽ0“OëĽL=ŹÂ’ž–އyä‘ŢP(ü¤PĺR?„ëşöPV 2Ę9œR)­›*á:ů†ŔP֘›ŽÁĽ›`źĐLĆ<Đ+ąę2é˛é2™B5–|r$Ł˘ĐŔĚh^\>=Ş")ÇZ“ö íۡ>"ŒV¸AżŮ Ěh;&Űp?ô§Dň™ŠĄĎ1VĎ[Ş{Ę@Ŕ Ř˜[ěKk:ǗŽă•-“ĄtA˜|2Ł;ÉŰhU˜‰¸?×z.úf„Ż˝öZ3€Şf˙ žşGÄĺrI1úÁżAŃˇ 't2ZÁ”BŻu¤ç(ôq3ćŚcoŮĆć~öłŸ­–X™`ĘŽŃΈŒĘ?ś)œ#ĎíŽ4Ű)ŰS—ÓMNŰ\'W|ݕ25F'wOOďˇjkkOސý,Ö˛~łĽżżßĚ÷ŰoŚ8Ăůç}¨B>č—jP XŻ­\•ă}Źö{‹ŽŮlŰśÝg´=“ÎuĚÄétššľ @5óů|÷577}Iba™>‰ľe˛OV;&{ťŚlí™R; Ľ.KĘvIł]ňܞV1˙őÎ÷‚r•ă)¤dýř€Î׏yüV ĘYÁŠÔĘ!Ľˌfu•lĎWMßÚ‹×TČóń )0ŢŮÇÜěă*Œ›Ć“x#‘͐ôَLYtÇ‹äŸ Ég{Á†˜)֓çűbíűí“=‘¤“ž)áw˝ë]O‡Bá'€qŔúPnU›)ć9‹qÜhś5ŞôŕĚH^sąî'Ą€üXŸ­eĆÍ`hClŮ É^E&›Bł"ů*řÑŠŠ]!ŐcFíŕáţeđçžtËöyśeœ)ËΔe\ńI—5Ô¨Ë]]]_­ŻoxˇPEŹ`„5…BfšŻŻ7:ČěŮłd$ň ĂdۧsŸĎ'@@ňQSS#'gŸçá:Ć:2œoĺóŒäţfť'šîĄ0^mٲ5:žâĆĆ&3Îârš_\˛ćTفţ;Z[[ż.ąŕK_t ƗCń),C+Î؍ΤV ‘ËöyśĺT˙QĆ%ĂSŹŔŒ5O–q¤9ŻľÍ™áńJo‚;úǤ×N9ĺ” ˘Ë5@•H-űj…g4<Ą›Z[[d´ä–Ńj'˝˝˝Ň××'^Ż× ÔÖ֚ŔF}}˝YÖÁ=Üëţţ~ńűýć5h5”|ŠÚ鹊Y~7ŸsY÷W'˝żŞśś.:%ß_Ľű3Ýßá†f̀ńŞťťŰŒč—“tŒĹ ĘXă%fŐ(úĎÜŔWżúŐĎŻYłŚ7şŞ˜°Â2ö`ŒHćÖLš*ÌZő˜|ŒäŻŽ<ˇ;ŇlĎ–ąŻ;%sľ{•űź>:y^xᅳ–-;đ?€*Ąe” ŹIˇő÷÷¸ÂĚpŞËء H{{ť ďLœ8IZ[[͡nbcCť4ęCőń==ݲgĎ>qšœ2eĘŠŤŤË+˜Q-á|‚2zŒýţNš¤÷wBŢ÷wďŢö¤űkIwŠ2đ˙Űť›ß8ÎűŕĎ.ŠR˘,ËrĽ8‘r(Œ¤>ŐEĐCkbŔ‡ö/čŇćŇKzqa#€QŰŢ ˝¤Ç^zHŃÖŞěSŁyŃ“kYJÝŚ%‘ĹÝěłťCG3ł3ł3är÷óFóĚóĚĚî>k€ë嗿çiI…™ÍÍ ăę2Ih& ĘÄ>X6?ýéžóňË/˙(L–bÚ ‡•eŇűl…™tx&ÝÂěJ3!Ӟg)§™şˆťçčĎKĺ­k•>/ď Ż›߸{÷ś˙>s™–‰Onßţ2ô{ýpóƍpůňĽi˜#Żh\÷%łľľžyóFX_[_|q{|Żxďd+{NłÎYTu__2żkŁ/`žyóćh~ŸŠ5ż7o|ăČüŚ#ďq€ŐłÓ°LĚaÄ FşŞLśşL:ˑ ɄœóB˜/[Ҋă¨7ŤÄNQ_^‰žźTRČÇ-–Šĺ€WŻ^ůŰ'Ožü8…Ş,ˇTÔwîÜ —śśÂőŻ] ýń_Ó$•OĘ%ŐQâ5_{áúřwďţňŠPG•ę7§!čŃäľÄšˆs2™ßëç7ž7—ś.ŽßŤyB35°Üö÷Ÿü8f-Â$‘^Š)†Éć7ŠŰ-ËÔ4CŇşy3Mž\ŃD”U™ô B~u™¤ěĎăéś˙úëoü`0üGZľťťžúęĂććFxîę•0r„PRů$kZ eÚžúüsacăüřžńŢiuÂ&‹ę¨úœňÎIćwccc<7óÎďsWŸß+o~bśâťß}ăa’˝ˆ™‹˝p¸SYV#Q”ńČŤ.S%L3Kă_ uUaŚ„PŃ:VE“~#’öŁŃś÷ŃG˙zď{ßűłżš€zĘŞěďď‡_ýę˙ă§đüŐŤăžŢÁ?5ő/ű­çŸß3Ţ;>FŢăW Ĥƒ*Ç Šű¸Eç%ó;FsŇćü^}j~-ÍÄLEĚVČE˜ebć")Z’Íeä=ɆeŠ‚2Ąf_'ż´˜70Óe•™tťŹÂLz|?M1Ĺăqy >řŕ˙^ý?ˇ<U'‘>w{{;Œ~ކ+Ď>úýö2¸ń^Wž˝öööƏQ(Š„ÉYşÚę>Ÿ˘ţ{÷îçŕŮ˗[ŸßxĎřŢĽ—fŞC˜–K\†)f*bś"L–`ŠY‹ź FśŕIŐ 3Ůö‰V—‰şŞ0ŐŠ2S49E“šüAA_ň†íŒś˝[ˇţůţććĆ÷ďßßţa€S*V8‰đBŹL˛łł;Ţ_¸pá xđOMĂŁ—]źxaüş>Ü)­‚’ôŸŚGŮóMWď‰óŤËÄš8?ř§îƒfçws\eŚĘüphž›€śÝż˙‡ߏ™Š0Š,3ٰLQ.#/ˑČV› ™vYŽ$”œÓŠő0żřäę.PtMҟO^|<Ž“ů$}‰~ć8mgzŻłWŽ\ů›O?ýôgßúÖˇ˙rtźŕęúĆËîżťť;ßŘ87úi<ýŃ=Œëţ G­^źxŇ=ó#´2Ë´$BzŁ‹Ď;śˇ„Żžę…ÍÍÍ#Wőzĺ÷5~Üf˝WŮń‡†„­­‹ÎďŮ0 Çďe:ô”}^‹6—‹@P€%ąó‹_üüŻ^zéĽ “ß"<“Ę2ƒ‚-– áé˘'鞐:Ą8üŇđυçÓe…™¨,ů3ʰ/j§ßˆňß ýÔ>iďLˇÁč ˙Ń;ďźý'ťť;˙€™Ň_ěěěŒ÷çΞ‡7&?¨§Œáô¨ÂǔaR2exćNëüšóă} tä=—˛/%ĽęLÓççwH:ŽĂů=;>'=żžč€Őł13ł!“§GsÉ>/,“ő(ŰgŰyÇ­jóO†{ÇfľÓűYíţ´ÝO§ű’s×2ýą˛ÎůiďĂ?üÝď|ç÷˙tm­˙J€—ĎIBIűɓ'agçá¸ZȍßuÍZ(ďřË/żg0ś.\ç7΍ŤôzýĐë÷ŚíéńxŻČ~L˜>&Żep𚆃ĂăýÁ~č÷şÎö.śÁţ Ź­Żu2żťvĂööĂ0úüŽ]ťvpeś˘LQ…•g€Uňůç˙úŁďf666Ăúúúřť‘ľľľƒďjbNƒýýÁÇ?ůÉż˙ÝkŻ˝öI˜Rb &ţuí“đt‘’tĺ˜t`&„§ ”eކdĘÂ3ĄâXem,ÉTWvšĽ^…ńô˛LŮ%šň~[ťßźäÓÉ~νŒśř§ŐçF˙!|<Úƒ3Żźň{|öěŮ? @Ą$;ł~f}¤™,tôăÉäÇôp˜„:Ň×'UR2[*čŃ q⺚ßőľ3ăsGŒ°Ü=zô/Ÿ|ňń?¤‚2q{&Ë0%Á™lؤ?„âę2!ĚČdŰĄâx§Ú Ěä…_ŠĆŠB1yçĚ Í$oV?M.eŤĐäÝ'žů{ŁíÜh[O‚3o˝őÖ_żůć›xýú  ę ‹$]M$Šđ÷ý~üqW˙sD“ę2Ńäń&űĂ*'“§0L?ƒŸžĂ#?ů'Ť%Žô’A‡ŻqT1‰/żŤůŐj’÷ąĚ8ꤚ °ââ÷(ý#ŐÓ[€…ŤÉÜšsűŁ÷ß˙ßŢ{ď˝˙ ‡ůŠXMćQ8 Ŕd3éĘ2ƒĚq͖` %ýEçäi-XÓŏđŞK3e{5öeíô–,ŃÂŃ%™ň–mŠíXqćLŞ?źúęŤ[ożýöďźřâ‹ßžtéŇoŸ={îƨűúčƒŃ3a˛Ź“A›Á`˙ BHzIŚÝݝń’L_˙ú ľî×$0Űwďţrźfëb8svRФ7IwL*Ă$Ai;¤ęĹ “§ááđ°Ś•P˘˝'{áĚú™°ĘööFspŚ›ů}ź÷xź$Stýúľ#kY&€Łžřâö80sţüFΒL1PcI&NDüŇw8üzôő˙Ç}~ďŢ˝˙úěłĎ~ţîťďţěÖ­[ŰŠóbČ%yžÁdĂ1é`L6DS) ˔…hN$,-R`&}\74“×—äű9}Ůó⧚3ÓýZ˜ěɎÍA“ůö›(8}š<†%ýÂ㢠ĘţtŰ ůd†Ą8<“wNŮă6 ËT9Ž:V[WaŒyŤĚ¤Űó„g˛A˜ŽV˜™u^˛_Kmي5Ů×S´śÁě5 ÉŔň¨öTěOZ’ńýÔ6Č\WT-&]aŚěźÚ­(sba™¨Ë`Ćq‡f’}Yx&]e&„§C/y™ŢŒű÷3ĎwŢę2Â2°|ކ>ŞV™dÎ/Z")„IgDza™˛ű×ٗľóŽŤŽ5śşŸpŻâXú8yĄ˝TzŸ5kfU—)ę+ žDƒýmV’YŘŞ2i‹źhťÚLşÝdźWńşYĎ­¨ŻĘŘ<„i }];ęV^É ¤T ˇ4ŠS'4Sĺ¸ęXç%\Q7X2k)¤lťIuš:×ć]WtN¨1,Ż:ŐW†ĄZřl{Ş^ćYrŠJ°§ęŘąX´ŔF—ŐfÚhW ĚTéŤ2,ˇyŤËdűć Ç4iW9Ž:vŹÖÂ♧ÚLöxžvža(Nl żu4 —ädŞ,ËT6ÖFPڍŻĘŘą[äG[Őf˛Çu—sjz\ÔWgX^u–d*ęŤsÜ$@Óä¸ę؉YÄ 3i]U›Š3Vĺ Ž63y}]„hňŽ‹úŞŒ¨EĚDm†fş8ŽÓ6<§íĐL“㢞*c'î4f˘&Kd0ŚJXF č24“××uPŚĘř‰;-™ÄźŐfňúÚ:gVŐq`ő4 Ą4 É4=§¨ŻĘŘB9m™¨nhڍżiPŚI˙Ź1€¨I Ľj˙źĄ˜ĽËD§105­âŇĹ2KÇQQFŘN6Â#]VœŠÓWÖ_u|áœÖŔLÔfhŚÍţYcm^œ.MÂ%]ViÚ_u|!ćŔLԛ㜶ƒ0u/Â1@˘NčdŘňXÓ LŐsŇiĚDó„fşkr@˘jĽíÍŹą:ç,ŹeĚ$ş ÎTŻzN—׋kސIA–•Ę$–)0ľUőĽ‹pŒ0 0KÝ@J×!š&ç-źe ĚDm/•´¨K/ ŕŔÉ;îIŰᖕ ËD˘‰ę„Iş:ˇë€ŐÓ4œR纎Î=–505 МŚe–„pŕäd˜¤‹ĺ›Ú¸fá-s`&qÁ™śŻHĚZ”ÉX…ŔL4O€ĽŤđ‹P ĐU0ežű.uX&Z•ŔLÔV@EĐX4m…\–>,­R`&ŃEŕEˆ8.]„ZV"(“XĹŔLâ8C.5@UÇ^YŠ Lb•3 a`ŐŹdP&!0s”đ °ŹV:$“&0“OpX‚23ŐЧ…€Ě 3Í Ń'M8ځ™nÓmŠi™ŔĚňŇ€î Ż,VĘz€"0ŔJ˜`Ľ̰RfX)3ʁVŠŔ +ĺ7nŽ„ŘkIENDŽB`‚bazaar-org-bazaar-43ce9f7/screenshots/search.png000066400000000000000000011525521520414637400217570ustar00rootroot00000000000000‰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) variant = build_variant(json_path, linguas_path) data = variant.get_data_as_bytes() with open(output_path, "wb") as f: f.write(data.get_data()) print(f"GVariant saved to: {output_path} ({GLib.format_size(data.get_size())})") if __name__ == "__main__": main() bazaar-org-bazaar-43ce9f7/scripts/install-deps/000077500000000000000000000000001520414637400215175ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/scripts/install-deps/fedora-rawhide.sh000077500000000000000000000007631520414637400247450ustar00rootroot00000000000000#!/usr/bin/env bash DEPS=( meson ninja cmake blueprint-compiler desktop-file-utils python3-babel 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 gtksourceview5-devel webkitgtk6.0-devel libsecret-devel libproxy-devel malcontent-devel # lsp clangd ) dnf install ${DEPS[@]} bazaar-org-bazaar-43ce9f7/src/000077500000000000000000000000001520414637400162205ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/src/bazaar.gresource.xml000066400000000000000000000440031520414637400222000ustar00rootroot00000000000000 style.css internal-config.yaml progress-bar-designs/pride/pride-flags.yaml internal-config-schema.xml main-config-schema.xml blocklist-schema.xml curated-config-schema.xml pride-flag-config-schema.xml release-notes.xml countries.gvariant bz-addon-tile.ui bz-addons-dialog.ui bz-age-rating-dialog.ui bz-all-apps-page.ui bz-app-size-dialog.ui bz-app-tile.ui bz-apps-page.ui bz-appstream-description-render.ui bz-bundle-install-dialog.ui bz-category-tile.ui bz-context-tile.ui bz-curated-app-tile.ui bz-curated-view.ui bz-decorated-screenshot.ui bz-developer-badge.ui bz-donations-dialog.ui bz-entry-inspector.ui bz-entry-selection-row.ui bz-error-dialog.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-install-controls.ui bz-installed-tile.ui bz-library-page.ui bz-license-dialog.ui bz-login-page.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-filter-popover.ui bz-search-page.ui bz-section-view.ui bz-stats-dialog.ui bz-transaction-list-dialog.ui bz-transaction-tile.ui bz-updates-card.ui bz-user-data-page.ui bz-user-data-tile.ui bz-window.ui 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/bug-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/explore-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/flatpak-symbolic.svg icons/scalable/actions/flathub-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/meeting-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/open-book-symbolic.svg icons/scalable/actions/parent-symbolic.svg icons/scalable/actions/paintbrush-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/proprietary-code-symbolic.svg icons/scalable/actions/puzzle-piece-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/school-symbolic.svg icons/scalable/actions/server-pick-symbolic.svg icons/scalable/actions/share-alt-symbolic.svg icons/scalable/actions/share-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 bz-install-controls.wdgt bz-transact-icon.wdgt bazaar-org-bazaar-43ce9f7/src/blocklist-schema.xml000066400000000000000000000007141520414637400221700ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/bz-addon-tile.blp000066400000000000000000000062161520414637400213550ustar00rootroot00000000000000using Gtk 4.0; template $BzAddonTile: $BzListTile { accessibility { labelled-by: title_label; described-by: description_label; } child: Box { orientation: horizontal; spacing: 4; height-request: 64; $BzTransactIcon { margin-start: 10; margin-top: 10; margin-bottom: 10; width-request: 48; height-request: 48; valign: center; halign: center; info: $BzTransactIconInfo { group: bind template.group as <$BzEntryGroup>; paintable: bind template.parent-ui-entry as <$BzResult>.object as <$BzEntry>.icon-paintable; }; } Box { orientation: vertical; valign: center; spacing: 4; margin-start: 10; 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; visible: bind $logical_and($invert_boolean(eol_label.visible) as , $invert_boolean($is_empty(template.group as <$BzEntryGroup>.description) as ) as ) as ; xalign: 0.0; ellipsize: end; single-line-mode: true; styles ["dim-label", "caption"] } Label eol_label{ visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.eol) as ) as ; wrap: true; wrap-mode: word_char; ellipsize: end; vexpand: true; lines: 2; single-line-mode: true; halign: start; hexpand: true; label: _("Stopped Receiving Updates"); styles [ "warning", ] } } Box { orientation: horizontal; spacing: 8; margin-end: 8; margin-start: 4; 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; } Image { pixel-size: 14; icon-name: "go-next-symbolic"; margin-end: 4; styles ["dimmed"] } } }; }bazaar-org-bazaar-43ce9f7/src/bz-addon-tile.c000066400000000000000000000172161520414637400210240ustar00rootroot00000000000000/* bz-addon-tile.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 #include "bz-addon-tile.h" #include "bz-addons-dialog.h" #include "bz-entry-group.h" #include "bz-state-info.h" #include "bz-window.h" struct _BzAddonTile { BzListTile parent_instance; BzEntryGroup *group; BzResult *parent_ui_entry; GtkButton *install_remove_button; }; G_DEFINE_FINAL_TYPE (BzAddonTile, bz_addon_tile, BZ_TYPE_LIST_TILE) enum { PROP_0, PROP_GROUP, PROP_PARENT_UI_ENTRY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void install_remove_cb (BzAddonTile *self, GtkButton *button) { int removable = 0; if (self->group == NULL) return; removable = bz_entry_group_get_removable (self->group); if (removable > 0) gtk_widget_activate_action (GTK_WIDGET (self), "window.remove-group", "(sb)", bz_entry_group_get_id (self->group), FALSE); else gtk_widget_activate_action (GTK_WIDGET (self), "window.install-group", "(sb)", bz_entry_group_get_id (self->group), TRUE); } static void bz_addon_tile_dispose (GObject *object) { BzAddonTile *self = BZ_ADDON_TILE (object); g_clear_object (&self->group); g_clear_object (&self->parent_ui_entry); G_OBJECT_CLASS (bz_addon_tile_parent_class)->dispose (object); } static void bz_addon_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzAddonTile *self = BZ_ADDON_TILE (object); switch (prop_id) { case PROP_GROUP: g_value_set_object (value, bz_addon_tile_get_group (self)); break; case PROP_PARENT_UI_ENTRY: g_value_set_object (value, self->parent_ui_entry); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_addon_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzAddonTile *self = BZ_ADDON_TILE (object); switch (prop_id) { case PROP_GROUP: bz_addon_tile_set_group (self, g_value_get_object (value)); break; case PROP_PARENT_UI_ENTRY: g_clear_object (&self->parent_ui_entry); self->parent_ui_entry = g_value_dup_object (value); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PARENT_UI_ENTRY]); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean is_zero (gpointer object, int value) { return value == 0; } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static gboolean is_empty (gpointer object, const char *str) { return str == NULL || str[0] == '\0'; } static gboolean logical_and (gpointer object, gboolean value1, gboolean value2) { return value1 && value2; } static char * get_install_remove_tooltip (gpointer object, int removable) { if (removable > 0) return g_strdup (C_("Install Controls", "Uninstall")); else return g_strdup (C_("Install Controls", "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 void bz_addon_tile_realize (GtkWidget *widget) { BzAddonTile *self = BZ_ADDON_TILE (widget); GtkWidget *parent = widget; GtkWidget *addons_dialog = NULL; GTK_WIDGET_CLASS (bz_addon_tile_parent_class)->realize (widget); while ((parent = gtk_widget_get_parent (parent)) != NULL) { if (BZ_IS_ADDONS_DIALOG (parent)) { addons_dialog = parent; break; } } if (addons_dialog == NULL) return; g_object_bind_property ( addons_dialog, "parent-ui-entry", self, "parent-ui-entry", G_BINDING_SYNC_CREATE); } static void bz_addon_tile_class_init (BzAddonTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_addon_tile_dispose; object_class->get_property = bz_addon_tile_get_property; object_class->set_property = bz_addon_tile_set_property; widget_class->realize = bz_addon_tile_realize; 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_PARENT_UI_ENTRY] = g_param_spec_object ( "parent-ui-entry", 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); 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-addon-tile.ui"); gtk_widget_class_bind_template_child (widget_class, BzAddonTile, install_remove_button); 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_null); gtk_widget_class_bind_template_callback (widget_class, logical_and); gtk_widget_class_bind_template_callback (widget_class, is_empty); 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, switch_bool); gtk_widget_class_bind_template_callback (widget_class, install_remove_cb); gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_BUTTON); } static void bz_addon_tile_init (BzAddonTile *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_addon_tile_new (void) { return g_object_new (BZ_TYPE_ADDON_TILE, NULL); } void bz_addon_tile_set_group (BzAddonTile *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_ADDON_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_addon_tile_get_group (BzAddonTile *self) { g_return_val_if_fail (BZ_IS_ADDON_TILE (self), NULL); return self->group; } bazaar-org-bazaar-43ce9f7/src/bz-addon-tile.h000066400000000000000000000022711520414637400210240ustar00rootroot00000000000000/* bz-addon-tile.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 "bz-list-tile.h" #include G_BEGIN_DECLS #define BZ_TYPE_ADDON_TILE (bz_addon_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzAddonTile, bz_addon_tile, BZ, ADDON_TILE, BzListTile) GtkWidget * bz_addon_tile_new (void); void bz_addon_tile_set_group (BzAddonTile *self, BzEntryGroup *group); BzEntryGroup * bz_addon_tile_get_group (BzAddonTile *self); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-addons-dialog.blp000066400000000000000000000301151520414637400220350ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzAddonsDialog: Adw.Dialog { content-width: 500; content-height: 550; child: Adw.ToastOverlay { child:Adw.NavigationView navigation_view { notify::visible-page-tag => $on_visible_page_tag_changed(); Adw.NavigationPage { tag: "list"; title: _("Manage Add-Ons"); 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 list_clamp { maximum-size: 450; tightening-threshold: 500; margin-start: 6; margin-end: 6; margin-bottom: 12; child: ListView { styles [ "navigation-sidebar", "installed-list-view", ] model: NoSelection { model: SortListModel { sorter: CustomSorter sorter {}; model: bind template.addon-groups; }; }; factory: BuilderListItemFactory { template ListItem { activatable: false; selectable: false; focusable: false; child: $BzAddonTile { group: bind template.item as <$BzEntryGroup>; activated => $tile_activated_cb(); }; } }; }; }; }; }; } Adw.NavigationPage { tag: "empty"; title: _("Manage Add-Ons"); child: Adw.ToolbarView { [top] Adw.HeaderBar { show-title: false; } content: Adw.StatusPage { icon-name: "application-x-addon-symbolic"; title: _("No Add-Ons Visible"); description: _("Your current filter preferences are hiding all known add-ons. Try adjusting them."); }; }; } Adw.NavigationPage { tag: "full-view"; title: bind try { template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.title, _("Add-on Page") }; child: Adw.ToolbarView { [top] Adw.HeaderBar { show-title: false; } content: ScrolledWindow { vexpand: true; hscrollbar-policy: never; child: Adw.Clamp { maximum-size: 450; tightening-threshold: 500; margin-start: 12; margin-end: 12; child: Box full_view_clamp { orientation: vertical; spacing: 4; margin-top: 12; Box { halign: center; spacing: 8; orientation: vertical; margin-bottom: 12; Image { pixel-size: 96; paintable: bind template.parent-ui-entry as <$BzResult>.object as <$BzEntry>.icon-paintable; visible: bind $invert_boolean($is_null(template.parent-ui-entry as <$BzResult>.object as <$BzEntry>.icon-paintable) as ) as ; styles ["icon-dropshadow"] } Box { orientation: vertical; valign: center; halign: center; spacing: 2; margin-bottom: 8; Label { label: bind template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.title; justify: center; max-width-chars: 25; wrap: true; wrap-mode: word_char; styles ["title-3"] } Label { label: bind $format_parent_title(template.parent-ui-entry as <$BzResult>.object as <$BzEntry>.title) as ; justify: center; styles ["dim-label"] } } } Box { homogeneous: true; margin-bottom: 12; orientation: horizontal; halign: fill; styles ["app-context-bar"] $BzContextTile { label: bind $get_size_label($is_zero(template.selected-group as <$BzEntryGroup>.removable) as ) as ; clicked => $size_cb(template); has-tooltip: true; tooltip-text: bind $format_size_tooltip(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.size) as ; lozenge-style: "grey"; sensitive: bind $invert_boolean($is_zero($get_size_type(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>, $is_zero(template.selected-group as <$BzEntryGroup>.removable) as ) as ) as ) as ; lozenge-child: Label { justify: center; label: bind $format_size($get_size_type(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>, $is_zero(template.selected-group as <$BzEntryGroup>.removable) as ) as ) as ; lines: 3; ellipsize: end; halign: center; wrap: true; xalign: 0.5; use-markup: true; }; } $BzContextTile { label: bind $get_license_label(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>) as ; clicked => $license_cb(template); lozenge-style: bind $bool_to_string(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.is-floss, "grey", "warning") as ; has-tooltip: true; tooltip-text: bind $format_license_tooltip(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>) as ; lozenge-child: Box { spacing: 6; Image { icon-name: bind $get_license_icon(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.is-floss, 0) as ; } Image { icon-name: bind $get_license_icon(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.is-floss, 1) as ; } }; } $BzContextTile { can-target: bind $invert_boolean($is_null(template.selected-ui-entry) as ) as ; sensitive: bind $invert_boolean($is_null(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.recent-downloads) as ) as ; label: _("Downloads/Month"); clicked => $dl_stats_cb(template); has-tooltip: bind $invert_boolean($is_null(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.recent-downloads) as ) as ; tooltip-text: bind $format_recent_downloads_tooltip(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.recent-downloads) as ; lozenge-style: "grey"; lozenge-child: Label { justify: center; label: bind $format_recent_downloads(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.recent-downloads) as ; halign: center; use-markup: true; }; } } Box { visible: bind $invert_boolean($is_null(template.selected-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 add-on 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; } } Label { visible: bind $logical_and($invert_boolean($is_null(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.description) as ) as , $is_null(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.long-description) as ) as ; label: bind template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.description; wrap: true; wrap-mode: word_char; justify: center; halign: center; margin-bottom: 6; styles ["dimmed"] } $BzInstallControls { halign: center; margin-top: 6; margin-bottom: 8; wide: false; entry-group: bind template.selected-group; state: bind template.state; settings: bind template.state as <$BzStateInfo>.settings; } Label { visible: bind $logical_and($invert_boolean($is_null(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.description) as ) as , $invert_boolean($is_null(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.long-description) as ) as ) as ; label: bind template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.description; wrap: true; wrap-mode: word_char; xalign: 0; halign: fill; margin-top: 12; margin-bottom: 4; styles ["title-4"] } $BzFadingClamp fading_clamp { visible: bind $invert_boolean($is_null(template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.long-description) as ) as ; max-height: bind $get_description_max_height(description_toggle.active) as ; min-max-height: 170; child: $BzAppstreamDescriptionRender { appstream-description: bind template.selected-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; }; margin-bottom: 12; } $BzShareList { urls: bind template.selected-ui-entry as <$BzResult>.object as <$BzEntry>.share-urls; margin-bottom: 24; } }; }; }; }; } }; }; } bazaar-org-bazaar-43ce9f7/src/bz-addons-dialog.c000066400000000000000000000531241520414637400215070ustar00rootroot00000000000000/* bz-addons-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 "config.h" #include #include "bz-addon-tile.h" #include "bz-addons-dialog.h" #include "bz-app-size-dialog.h" #include "bz-application-map-factory.h" #include "bz-application.h" #include "bz-appstream-description-render.h" #include "bz-context-tile-callbacks.h" #include "bz-context-tile.h" #include "bz-entry-group.h" #include "bz-fading-clamp.h" #include "bz-flatpak-entry.h" #include "bz-install-controls.h" #include "bz-license-dialog.h" #include "bz-result.h" #include "bz-share-list.h" #include "bz-state-info.h" #include "bz-stats-dialog.h" #include "bz-template-callbacks.h" #include "bz-util.h" struct _BzAddonsDialog { AdwDialog parent_instance; GListModel *addon_groups; BzEntryGroup *selected_group; BzResult *selected_ui_entry; DexFuture *selected_ui_future; BzResult *parent_ui_entry; DexFuture *parent_ui_future; BzStateInfo *state; AdwAnimation *width_animation; AdwAnimation *height_animation; /* Template widgets */ AdwNavigationView *navigation_view; GtkToggleButton *description_toggle; AdwClamp *full_view_clamp; AdwClamp *list_clamp; GtkCustomSorter *sorter; }; G_DEFINE_FINAL_TYPE (BzAddonsDialog, bz_addons_dialog, ADW_TYPE_DIALOG) enum { PROP_0, PROP_ADDON_GROUPS, PROP_SELECTED_GROUP, PROP_SELECTED_UI_ENTRY, PROP_PARENT_UI_ENTRY, PROP_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static char *format_parent_title (gpointer object, const char *title); static int get_description_max_height (gpointer object, gboolean active); static char *get_description_toggle_text (gpointer object, gboolean active); static void size_cb (BzAddonsDialog *self, GtkButton *button); static void license_cb (BzAddonsDialog *self, GtkButton *button); static void dl_stats_cb (BzAddonsDialog *self, GtkButton *button); static void animate_to_size (BzAddonsDialog *self); static void on_visible_page_tag_changed (AdwNavigationView *nav_view, GParamSpec *pspec, BzAddonsDialog *self); static DexFuture *on_parent_ui_entry_resolved (DexFuture *future, GWeakRef *wr); static DexFuture *on_selected_ui_entry_resolved (DexFuture *future, GWeakRef *wr); static void set_selected_group (BzAddonsDialog *self, BzEntryGroup *group); static void tile_activated_cb (BzAddonTile *tile); static int sort_func (BzEntryGroup *a, BzEntryGroup *b, BzAddonsDialog *self); static void bz_addons_dialog_dispose (GObject *object) { BzAddonsDialog *self = BZ_ADDONS_DIALOG (object); dex_clear (&self->selected_ui_future); dex_clear (&self->parent_ui_future); g_clear_object (&self->addon_groups); g_clear_object (&self->selected_group); g_clear_object (&self->selected_ui_entry); g_clear_object (&self->parent_ui_entry); g_clear_object (&self->state); g_clear_object (&self->width_animation); g_clear_object (&self->height_animation); 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_ADDON_GROUPS: g_value_set_object (value, self->addon_groups); break; case PROP_SELECTED_GROUP: g_value_set_object (value, self->selected_group); break; case PROP_SELECTED_UI_ENTRY: g_value_set_object (value, self->selected_ui_entry); break; case PROP_PARENT_UI_ENTRY: g_value_set_object (value, self->parent_ui_entry); break; case PROP_STATE: g_value_set_object (value, bz_state_info_get_default ()); 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_ADDON_GROUPS: g_clear_object (&self->addon_groups); self->addon_groups = g_value_dup_object (value); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ADDON_GROUPS]); break; case PROP_SELECTED_GROUP: g_clear_object (&self->selected_group); self->selected_group = g_value_dup_object (value); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SELECTED_GROUP]); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } 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->get_property = bz_addons_dialog_get_property; object_class->set_property = bz_addons_dialog_set_property; props[PROP_ADDON_GROUPS] = g_param_spec_object ( "addon-groups", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_SELECTED_GROUP] = g_param_spec_object ( "selected-group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_SELECTED_UI_ENTRY] = g_param_spec_object ( "selected-ui-entry", NULL, NULL, BZ_TYPE_RESULT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_PARENT_UI_ENTRY] = g_param_spec_object ( "parent-ui-entry", NULL, NULL, BZ_TYPE_RESULT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); 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); g_type_ensure (BZ_TYPE_ADDON_TILE); g_type_ensure (BZ_TYPE_APPSTREAM_DESCRIPTION_RENDER); g_type_ensure (BZ_TYPE_CONTEXT_TILE); 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_FLATPAK_ENTRY); g_type_ensure (BZ_TYPE_INSTALL_CONTROLS); g_type_ensure (BZ_TYPE_RESULT); g_type_ensure (BZ_TYPE_SHARE_LIST); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-addons-dialog.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); bz_widget_class_bind_all_context_tile_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzAddonsDialog, navigation_view); gtk_widget_class_bind_template_child (widget_class, BzAddonsDialog, description_toggle); gtk_widget_class_bind_template_child (widget_class, BzAddonsDialog, full_view_clamp); gtk_widget_class_bind_template_child (widget_class, BzAddonsDialog, list_clamp); gtk_widget_class_bind_template_child (widget_class, BzAddonsDialog, sorter); gtk_widget_class_bind_template_callback (widget_class, tile_activated_cb); gtk_widget_class_bind_template_callback (widget_class, on_visible_page_tag_changed); gtk_widget_class_bind_template_callback (widget_class, format_parent_title); 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, license_cb); gtk_widget_class_bind_template_callback (widget_class, size_cb); gtk_widget_class_bind_template_callback (widget_class, dl_stats_cb); } static void bz_addons_dialog_init (BzAddonsDialog *self) { AdwAnimationTarget *width_target = NULL; AdwAnimationTarget *height_target = NULL; gtk_widget_init_template (GTK_WIDGET (self)); width_target = adw_property_animation_target_new (G_OBJECT (self), "content-width"); self->width_animation = adw_timed_animation_new (GTK_WIDGET (self), 0, 0, 300, width_target); height_target = adw_property_animation_target_new (G_OBJECT (self), "content-height"); self->height_animation = adw_timed_animation_new (GTK_WIDGET (self), 0, 0, 300, height_target); g_signal_connect_swapped (self, "map", G_CALLBACK (animate_to_size), self); gtk_custom_sorter_set_sort_func (self->sorter, (GCompareDataFunc) sort_func, self, NULL); } AdwDialog * bz_addons_dialog_new (BzEntryGroup *group) { GListModel *ids = NULL; GListModel *groups = NULL; BzApplicationMapFactory *factory = NULL; BzAddonsDialog *self = NULL; ids = bz_entry_group_get_addon_group_ids (group); if (ids != NULL) { factory = bz_state_info_get_application_factory (bz_state_info_get_default ()); if (factory != NULL) groups = bz_application_map_factory_generate (factory, ids); } self = g_object_new ( BZ_TYPE_ADDONS_DIALOG, "addon-groups", groups, NULL); self->parent_ui_entry = bz_entry_group_dup_ui_entry (group); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PARENT_UI_ENTRY]); if (groups == NULL || g_list_model_get_n_items (groups) == 0) adw_navigation_view_replace (self->navigation_view, (AdwNavigationPage *[]) { adw_navigation_view_find_page (self->navigation_view, "empty") }, 1); else if (g_list_model_get_n_items (groups) == 1) { g_autoptr (BzEntryGroup) single = g_list_model_get_item (groups, 0); AdwNavigationPage *full_view_page = NULL; set_selected_group (self, single); full_view_page = adw_navigation_view_find_page (self->navigation_view, "full-view"); adw_navigation_view_replace (self->navigation_view, &full_view_page, 1); } return ADW_DIALOG (self); } AdwDialog * bz_addons_dialog_new_single (BzEntryGroup *group) { BzAddonsDialog *self = NULL; AdwNavigationPage *full_view = NULL; self = g_object_new (BZ_TYPE_ADDONS_DIALOG, NULL); set_selected_group (self, group); full_view = adw_navigation_view_find_page (self->navigation_view, "full-view"); adw_navigation_view_replace (self->navigation_view, &full_view, 1); return ADW_DIALOG (self); } static char * format_parent_title (gpointer object, const char *title) { if (title == NULL || *title == '\0') return g_strdup (""); return g_strdup_printf (_ ("Add-on for %s"), title); } 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 size_cb (BzAddonsDialog *self, GtkButton *button) { AdwNavigationPage *page = NULL; if (self->selected_group == NULL) return; page = bz_app_size_page_new (self->selected_group); adw_navigation_view_push (self->navigation_view, page); } static void license_cb (BzAddonsDialog *self, GtkButton *button) { AdwNavigationPage *page = NULL; BzEntry *ui_entry = NULL; if (self->selected_ui_entry == NULL) return; ui_entry = bz_result_get_object (self->selected_ui_entry); if (ui_entry == NULL) return; page = bz_license_page_new (ui_entry); adw_navigation_view_push (self->navigation_view, page); } static void dl_stats_cb (BzAddonsDialog *self, GtkButton *button) { BzStatsDialog *bin = NULL; AdwNavigationPage *page = NULL; BzEntry *ui_entry = NULL; if (self->selected_ui_entry == NULL) return; ui_entry = bz_result_get_object (self->selected_ui_entry); if (ui_entry == NULL) return; bin = BZ_STATS_DIALOG (bz_stats_dialog_new (NULL, NULL, 0)); page = adw_navigation_page_new (GTK_WIDGET (bin), _ ("Download Stats")); adw_navigation_page_set_tag (page, "stats"); g_object_bind_property (ui_entry, "download-stats", bin, "model", G_BINDING_SYNC_CREATE); g_object_bind_property (ui_entry, "total-downloads", bin, "total-downloads", G_BINDING_SYNC_CREATE); adw_navigation_view_push (self->navigation_view, page); bz_stats_dialog_animate_open (bin); } static void animate_to_size (BzAddonsDialog *self) { const char *tag = NULL; int target_width = 0; int target_height = 0; int nat = 0; int cur_width = 0; int measure_for = 0; int cur_w = 0; int cur_h = 0; int delta_w = 0; int delta_h = 0; int delta = 0; guint duration = 0; tag = adw_navigation_view_get_visible_page_tag (self->navigation_view); if (g_strcmp0 (tag, "list") == 0) { cur_width = gtk_widget_get_width (GTK_WIDGET (self)); target_width = 500; measure_for = MAX (-1, MIN (target_width, cur_width) - 48); gtk_widget_measure (GTK_WIDGET (self->list_clamp), GTK_ORIENTATION_VERTICAL, measure_for, NULL, &nat, NULL, NULL); target_height = CLAMP (nat + 50, 150, 600); } else if (g_strcmp0 (tag, "full-view") == 0) { cur_width = gtk_widget_get_width (GTK_WIDGET (self)); target_width = 500; measure_for = MAX (-1, MIN (target_width, cur_width) - 48); gtk_widget_measure (GTK_WIDGET (self->full_view_clamp), GTK_ORIENTATION_VERTICAL, measure_for, NULL, &nat, NULL, NULL); target_height = CLAMP (nat + 50, 300, 700); } else if (g_strcmp0 (tag, "app-size") == 0) { target_width = 500; target_height = 300; } else if (g_strcmp0 (tag, "license") == 0) { cur_width = gtk_widget_get_width (GTK_WIDGET (self)); target_width = 400; measure_for = target_width - 48; gtk_widget_measure (GTK_WIDGET (self->navigation_view), GTK_ORIENTATION_VERTICAL, measure_for, NULL, &nat, NULL, NULL); target_height = CLAMP (nat, 300, 700); } else if (g_strcmp0 (tag, "stats") == 0) { target_width = 1250; target_height = 750; } else if (g_strcmp0 (tag, "empty") == 0) { target_width = 500; target_height = 500; } else return; cur_w = adw_dialog_get_content_width (ADW_DIALOG (self)); cur_h = adw_dialog_get_content_height (ADW_DIALOG (self)); delta_w = ABS (target_width - cur_w); delta_h = ABS (target_height - cur_h); delta = MAX (delta_w, delta_h); duration = (guint) CLAMP (delta * 0.6, 200, (target_width < cur_w || target_height < cur_h) ? 300 : 600); adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->width_animation), duration); adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->height_animation), duration); adw_timed_animation_set_value_from (ADW_TIMED_ANIMATION (self->width_animation), cur_w); adw_timed_animation_set_value_to (ADW_TIMED_ANIMATION (self->width_animation), target_width); adw_timed_animation_set_value_from (ADW_TIMED_ANIMATION (self->height_animation), cur_h); adw_timed_animation_set_value_to (ADW_TIMED_ANIMATION (self->height_animation), target_height); adw_animation_play (self->width_animation); adw_animation_play (self->height_animation); } static void on_visible_page_tag_changed (AdwNavigationView *nav_view, GParamSpec *pspec, BzAddonsDialog *self) { g_idle_add_once ((GSourceOnceFunc) animate_to_size, self); } static DexFuture * on_parent_ui_entry_resolved (DexFuture *future, GWeakRef *wr) { g_autoptr (BzAddonsDialog) self = NULL; bz_weak_get_or_return_reject (self, wr); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PARENT_UI_ENTRY]); return dex_future_new_for_boolean (TRUE); } static DexFuture * on_selected_ui_entry_resolved (DexFuture *future, GWeakRef *wr) { g_autoptr (BzAddonsDialog) self = NULL; const GValue *value = NULL; g_autoptr (BzEntry) ui_entry = NULL; const char *ref = NULL; g_auto (GStrv) parts = NULL; BzApplicationMapFactory *factory = NULL; GtkStringObject *item = NULL; BzEntryGroup *parent_group = NULL; bz_weak_get_or_return_reject (self, wr); value = dex_future_get_value (future, NULL); if (value == NULL || !G_VALUE_HOLDS_OBJECT (value)) return dex_future_new_for_boolean (TRUE); ui_entry = g_value_dup_object (value); if (ui_entry == NULL || !BZ_IS_FLATPAK_ENTRY (ui_entry)) return dex_future_new_for_boolean (TRUE); ref = bz_flatpak_entry_get_addon_extension_of_ref (BZ_FLATPAK_ENTRY (ui_entry)); if (ref == NULL) return dex_future_new_for_boolean (TRUE); parts = g_strsplit (ref, "/", -1); if (parts[0] == NULL || parts[1] == NULL) return dex_future_new_for_boolean (TRUE); factory = bz_state_info_get_application_factory (bz_state_info_get_default ()); item = gtk_string_object_new (parts[1]); parent_group = bz_application_map_factory_convert_one (factory, item); if (parent_group == NULL) return dex_future_new_for_boolean (TRUE); g_clear_object (&self->parent_ui_entry); self->parent_ui_entry = bz_entry_group_dup_ui_entry (parent_group); if (self->parent_ui_entry == NULL) return dex_future_new_for_boolean (TRUE); if (bz_result_get_resolved (self->parent_ui_entry)) { g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PARENT_UI_ENTRY]); } else { g_autoptr (DexFuture) parent_future = NULL; GWeakRef *parent_wr = NULL; parent_future = bz_result_dup_future (self->parent_ui_entry); parent_wr = bz_track_weak (self); parent_future = dex_future_then ( parent_future, (DexFutureCallback) on_parent_ui_entry_resolved, parent_wr, bz_weak_release); dex_clear (&self->parent_ui_future); self->parent_ui_future = g_steal_pointer (&parent_future); } return dex_future_new_for_boolean (TRUE); } static void set_selected_group (BzAddonsDialog *self, BzEntryGroup *group) { dex_clear (&self->selected_ui_future); dex_clear (&self->parent_ui_future); g_clear_object (&self->selected_group); g_clear_object (&self->selected_ui_entry); g_clear_object (&self->parent_ui_entry); gtk_toggle_button_set_active (self->description_toggle, FALSE); if (group == NULL) return; self->selected_group = g_object_ref (group); self->selected_ui_entry = bz_entry_group_dup_ui_entry (group); if (self->selected_ui_entry == NULL) goto notify; if (bz_result_get_resolved (self->selected_ui_entry)) { g_autoptr (BzEntry) entry = NULL; g_autoptr (DexFuture) object_future = NULL; GWeakRef *wr = NULL; entry = g_object_ref (bz_result_get_object (self->selected_ui_entry)); object_future = dex_future_new_for_object (entry); wr = bz_track_weak (self); dex_unref (on_selected_ui_entry_resolved (object_future, wr)); bz_weak_release (wr); } else { g_autoptr (DexFuture) ui_future = NULL; GWeakRef *wr = NULL; ui_future = bz_result_dup_future (self->selected_ui_entry); wr = bz_track_weak (self); ui_future = dex_future_then ( ui_future, (DexFutureCallback) on_selected_ui_entry_resolved, wr, bz_weak_release); self->selected_ui_future = g_steal_pointer (&ui_future); } notify: g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SELECTED_GROUP]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SELECTED_UI_ENTRY]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PARENT_UI_ENTRY]); } static void tile_activated_cb (BzAddonTile *tile) { BzAddonsDialog *self = NULL; BzEntryGroup *group = NULL; self = BZ_ADDONS_DIALOG (gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_ADDONS_DIALOG)); if (self == NULL) return; group = bz_addon_tile_get_group (tile); if (group == NULL) return; set_selected_group (self, group); adw_navigation_view_push_by_tag (self->navigation_view, "full-view"); } static int sort_func (BzEntryGroup *a, BzEntryGroup *b, BzAddonsDialog *self) { const char *desc_a = NULL; const char *desc_b = NULL; gboolean has_a = FALSE; gboolean has_b = FALSE; int result = 0; desc_a = bz_entry_group_get_description (a); desc_b = bz_entry_group_get_description (b); has_a = desc_a != NULL && *desc_a != '\0'; has_b = desc_b != NULL && *desc_b != '\0'; if (has_a != has_b) result = has_b - has_a; else result = g_utf8_collate (bz_entry_group_get_title (a), bz_entry_group_get_title (b)); return result; } bazaar-org-bazaar-43ce9f7/src/bz-addons-dialog.h000066400000000000000000000021411520414637400215050ustar00rootroot00000000000000/* 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-group.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 (BzEntryGroup *group); AdwDialog * bz_addons_dialog_new_single (BzEntryGroup *group); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-age-rating-attribute.txt000066400000000000000000000005271520414637400234150ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-age-rating-dialog.blp000066400000000000000000000015241520414637400226050ustar00rootroot00000000000000using 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", ] } } } }; } } bazaar-org-bazaar-43ce9f7/src/bz-age-rating-dialog.c000066400000000000000000001071071520414637400222560ustar00rootroot00000000000000/* 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 AsContentRatingValue get_rating_value (AsContentRating *content_rating, const gchar *id) { if (content_rating == NULL) return AS_CONTENT_RATING_VALUE_UNKNOWN; return as_content_rating_get_value (content_rating, id); } 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 = get_rating_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 = get_rating_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], get_rating_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 = get_rating_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 = get_rating_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]); } } } bazaar-org-bazaar-43ce9f7/src/bz-age-rating-dialog.h000066400000000000000000000023571520414637400222640ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-all-apps-page.blp000066400000000000000000000032031520414637400217510ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzAllAppsPage: Adw.NavigationPage { Adw.ToolbarView { [top] Adw.HeaderBar {} content: Adw.BreakpointBin { width-request: 360; height-request: 100; 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; } } }; } } bazaar-org-bazaar-43ce9f7/src/bz-all-apps-page.c000066400000000000000000000116151520414637400214240ustar00rootroot00000000000000/* 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 }; 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); 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) { BzEntryGroup *group = NULL; group = gtk_list_item_get_item (list_item); if (group == NULL) return; gtk_widget_activate_action (GTK_WIDGET (tile), "window.show-group", "s", bz_entry_group_get_id (group)); } bazaar-org-bazaar-43ce9f7/src/bz-all-apps-page.h000066400000000000000000000021051520414637400214230ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-app-permissions.c000066400000000000000000001235431520414637400221360ustar00rootroot00000000000000/* 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/pipewire-0:rw", BZ_APP_PERMISSIONS_FLAGS_SCREEN | BZ_APP_PERMISSIONS_FLAGS_AUDIO_DEVICES }, { "xdg-run/pipewire-0:ro", 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; } bazaar-org-bazaar-43ce9f7/src/bz-app-permissions.h000066400000000000000000000145531520414637400221430ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-app-size-dialog.blp000066400000000000000000000141621520414637400223210ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzAppSizeDialog: Adw.Bin { 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 ) as ; importance: neutral; visible: bind $is_zero(template.group as <$BzEntryGroup>.removable) as ; } $BzLozenge { title: _("Installed Size"); label: bind $format_size(template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.installed-size as ) as ; importance: neutral; visible: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.removable) as ) as ; } } 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 ) 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 ) 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_null(template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.runtime as <$BzResult>.object) as ) as ; [prefix] Label { label: bind $format_size($choose(template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.runtime as <$BzResult>.object as <$BzEntry>.installed, template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.runtime as <$BzResult>.object as <$BzEntry>.installed-size as , template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.runtime as <$BzResult>.object as <$BzEntry>.size as ) as ) as ; use-markup: true; valign: center; width-request: 90; margin-top: 8; margin-bottom: 8; styles [ "circular-lozenge", "title-4", "grey", ] } title: bind $get_runtime_size_title(template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.runtime as <$BzResult>.object as <$BzEntry>.installed) as ; subtitle: bind template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.runtime as <$BzResult>.object as <$BzEntry>.title; } } Adw.PreferencesGroup { margin-bottom: 15; visible: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.user-data-size) as ) as ; Adw.ActionRow { [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", ] } [suffix] Button { has-tooltip: true; tooltip-text: _("Open user data folder"); icon-name: "folder-open-symbolic"; clicked => $open_user_data_folder_cb(); valign: center; styles [ "flat", ] } title: _("Your User Data"); subtitle: _("Caches, settings, and other app data"); } Adw.ActionRow { [prefix] Label { label: bind $format_size(template.group as <$BzEntryGroup>.cache-size) as ; use-markup: true; valign: center; width-request: 90; margin-top: 8; margin-bottom: 8; styles [ "circular-lozenge", "title-4", "grey", ] } title: _("Cache"); subtitle: _("Temporary cached data"); } } Adw.PreferencesGroup { margin-bottom: 15; margin-top: 4; visible: bind $logical_and($invert_boolean($is_zero(template.group as <$BzEntryGroup>.user-data-size) as ) as , $invert_boolean($is_app_id(template.group as <$BzEntryGroup>.id) as ) as ) as ; Adw.ButtonRow { title: _("Clear Cache"); activated => $delete_cache_cb(); sensitive: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.cache-size) as ) as ; styles ["destructive-action"] } } }; }; }; }bazaar-org-bazaar-43ce9f7/src/bz-app-size-dialog.c000066400000000000000000000140151520414637400217630ustar00rootroot00000000000000/* 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-io.h" #include "bz-lozenge.h" #include "bz-template-callbacks.h" #include struct _BzAppSizeDialog { AdwBin parent_instance; BzEntryGroup *group; }; G_DEFINE_FINAL_TYPE (BzAppSizeDialog, bz_app_size_dialog, ADW_TYPE_BIN) 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 char * get_runtime_size_title (gpointer object, gboolean runtime_installed) { return g_strdup (runtime_installed ? _ ("Installed Runtime Size") : _ ("Runtime Download Size")); } 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_app_id (gpointer object, const char *id) { return g_strcmp0 (id, g_application_get_application_id (g_application_get_default ())) == 0; } static void open_user_data_folder_cb (GtkWidget *widget, BzAppSizeDialog *self) { const char *id = NULL; g_autofree char *path = NULL; g_autoptr (GFile) file = NULL; g_autoptr (GtkFileLauncher) launcher = NULL; GtkRoot *root = NULL; if (self->group == NULL) return; id = bz_entry_group_get_id (self->group); if (id == NULL) return; path = bz_dup_user_data_path (id); file = g_file_new_for_path (path); launcher = gtk_file_launcher_new (file); root = gtk_widget_get_root (widget); gtk_file_launcher_launch (launcher, GTK_WINDOW (root), NULL, NULL, NULL); } static void delete_cache_cb (GtkWidget *widget, BzAppSizeDialog *self) { if (self->group == NULL) return; bz_entry_group_reap_user_cache (self->group); } 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"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_callback (widget_class, is_app_id); gtk_widget_class_bind_template_callback (widget_class, format_size); gtk_widget_class_bind_template_callback (widget_class, get_runtime_size_title); gtk_widget_class_bind_template_callback (widget_class, open_user_data_folder_cb); gtk_widget_class_bind_template_callback (widget_class, delete_cache_cb); } 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 *widget = NULL; AdwDialog *dialog = NULL; widget = g_object_new (BZ_TYPE_APP_SIZE_DIALOG, "group", group, NULL); dialog = adw_dialog_new (); adw_dialog_set_content_height (dialog, 500); adw_dialog_set_content_width (dialog, 600); adw_dialog_set_child (dialog, GTK_WIDGET (widget)); return dialog; } AdwNavigationPage * bz_app_size_page_new (BzEntryGroup *group) { BzAppSizeDialog *widget = NULL; AdwNavigationPage *page = NULL; widget = g_object_new (BZ_TYPE_APP_SIZE_DIALOG, "group", group, NULL); page = adw_navigation_page_new (GTK_WIDGET (widget), _ ("App Size")); adw_navigation_page_set_tag (page, "app-size"); return page; } bazaar-org-bazaar-43ce9f7/src/bz-app-size-dialog.h000066400000000000000000000021761520414637400217750ustar00rootroot00000000000000/* 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, AdwBin) AdwDialog * bz_app_size_dialog_new (BzEntryGroup *group); AdwNavigationPage * bz_app_size_page_new (BzEntryGroup *group); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-app-tile.blp000066400000000000000000000043521520414637400210470ustar00rootroot00000000000000using Gtk 4.0; template $BzAppTile: Button { preferred-width: 270; 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>.ui-entry as <$BzResult>.object as <$BzEntry>.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; } 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; accessibility { label: _("Verified"); } } } 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 ; 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"); } } } } }; } bazaar-org-bazaar-43ce9f7/src/bz-app-tile.c000066400000000000000000000210341520414637400205100ustar00rootroot00000000000000/* bz-app-tile.c * * Copyright 2025 Adam Masciola * * Layout manager adapted from GNOME Softwares GsSummaryTileLayout * * Copyright (C) 2013 Matthias Clasen * Copyright (C) 2019 Richard Hughes * * 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-app-tile.h" #define BZ_TYPE_APP_TILE_LAYOUT (bz_app_tile_layout_get_type ()) G_DECLARE_FINAL_TYPE (BzAppTileLayout, bz_app_tile_layout, BZ, APP_TILE_LAYOUT, GtkLayoutManager) struct _BzAppTileLayout { GtkLayoutManager parent_instance; gint preferred_width; }; G_DEFINE_FINAL_TYPE (BzAppTileLayout, bz_app_tile_layout, GTK_TYPE_LAYOUT_MANAGER) static void bz_app_tile_layout_measure (GtkLayoutManager *layout_manager, GtkWidget *widget, GtkOrientation orientation, gint for_size, gint *minimum, gint *natural, gint *minimum_baseline, gint *natural_baseline) { BzAppTileLayout *self = BZ_APP_TILE_LAYOUT (layout_manager); GtkWidget *child = NULL; gint min = 0; gint nat = 0; for (child = gtk_widget_get_first_child (widget); child != NULL; child = gtk_widget_get_next_sibling (child)) { gint child_min_baseline = -1; gint child_nat_baseline = -1; gint child_min = 0; gint child_nat = 0; if (!gtk_widget_should_layout (child)) continue; gtk_widget_measure (child, orientation, for_size, &child_min, &child_nat, &child_min_baseline, &child_nat_baseline); min = MAX (min, child_min); nat = MAX (nat, child_nat); if (child_min_baseline > -1) *minimum_baseline = MAX (*minimum_baseline, child_min_baseline); if (child_nat_baseline > -1) *natural_baseline = MAX (*natural_baseline, child_nat_baseline); } *minimum = min; *natural = nat; if (self->preferred_width > 0 && orientation == GTK_ORIENTATION_HORIZONTAL) *natural = MAX (*minimum, self->preferred_width); } static void bz_app_tile_layout_allocate (GtkLayoutManager *layout_manager, GtkWidget *widget, gint width, gint height, gint baseline) { GtkWidget *child = NULL; for (child = gtk_widget_get_first_child (widget); child != NULL; child = gtk_widget_get_next_sibling (child)) { if (child && gtk_widget_should_layout (child)) gtk_widget_allocate (child, width, height, baseline, NULL); } } static void bz_app_tile_layout_class_init (BzAppTileLayoutClass *klass) { GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass); layout_manager_class->measure = bz_app_tile_layout_measure; layout_manager_class->allocate = bz_app_tile_layout_allocate; } static void bz_app_tile_layout_init (BzAppTileLayout *self) { } struct _BzAppTile { GtkButton parent_instance; BzEntryGroup *group; gint preferred_width; }; G_DEFINE_FINAL_TYPE (BzAppTile, bz_app_tile, GTK_TYPE_BUTTON); enum { PROP_0, PROP_GROUP, PROP_PREFERRED_WIDTH, 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; case PROP_PREFERRED_WIDTH: g_value_set_int (value, self->preferred_width); 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; case PROP_PREFERRED_WIDTH: bz_app_tile_set_preferred_width (self, g_value_get_int (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); props[PROP_PREFERRED_WIDTH] = g_param_spec_int ( "preferred-width", NULL, NULL, -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | 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-app-tile.ui"); gtk_widget_class_set_layout_manager_type (widget_class, BZ_TYPE_APP_TILE_LAYOUT); 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) { self->preferred_width = -1; 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]); } gint bz_app_tile_get_preferred_width (BzAppTile *self) { g_return_val_if_fail (BZ_IS_APP_TILE (self), -1); return self->preferred_width; } void bz_app_tile_set_preferred_width (BzAppTile *self, gint preferred_width) { GtkLayoutManager *layout_manager; g_return_if_fail (BZ_IS_APP_TILE (self)); if (self->preferred_width == preferred_width) return; self->preferred_width = preferred_width; layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self)); BZ_APP_TILE_LAYOUT (layout_manager)->preferred_width = preferred_width; gtk_layout_manager_layout_changed (layout_manager); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PREFERRED_WIDTH]); } /* End of bz-app-tile.c */ bazaar-org-bazaar-43ce9f7/src/bz-app-tile.h000066400000000000000000000025211520414637400205150ustar00rootroot00000000000000/* 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); gint bz_app_tile_get_preferred_width (BzAppTile *self); void bz_app_tile_set_preferred_width (BzAppTile *self, gint preferred_width); G_END_DECLS /* End of bz-app-tile.h */ bazaar-org-bazaar-43ce9f7/src/bz-application-map-factory.c000066400000000000000000000076621520414637400235330ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-application-map-factory.h000066400000000000000000000033101520414637400235220ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-application.c000066400000000000000000004063401520414637400213070ustar00rootroot00000000000000/* 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-appstream-parser.h" #include "bz-auth-state.h" #include "bz-backend-notification.h" #include "bz-bundle-install-dialog.h" #include "bz-content-provider.h" #include "bz-donations-dialog.h" #include "bz-download-worker.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-bundle-result.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-internal-config.h" #include "bz-io.h" #include "bz-login-page.h" #include "bz-malcontent-service.h" #include "bz-metainfo-preview.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; BzInternalConfig *internal_config; BzMainConfig *config; BzMalcontentService *malcontent; 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 *first_window_opened; 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 *sys_ref_to_addon_group_ids; GHashTable *usr_name_to_addons; GHashTable *usr_ref_to_addon_group_ids; GListStore *groups; GListStore *installed_apps; GListStore *search_biases_backing; 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; GtkFlattenListModel *search_biases; GtkMapListModel *blocklists_to_files; GtkMapListModel *curated_configs_to_files; GtkMapListModel *txt_blocklists_to_files; GtkStringList *blocklists; GtkStringList *curated_configs; GtkStringList *txt_blocklists; gboolean flathub_remote_initialized; gboolean running; guint periodic_timeout_source; int n_entries_incoming; int n_remotes_syncing; }; 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 ( cache_write_back, CacheWriteBack, { GWeakRef *self; GPtrArray *notify_groups; gboolean update_filters; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (notify_groups, g_ptr_array_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, bz_weak_release); BZ_RELEASE_DATA (id, g_free)) static DexFuture * init_fiber (GWeakRef *wr); static DexFuture * enumerate_disk_entries_fiber (GWeakRef *wr); static DexFuture * check_for_updates_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, CacheWriteBackData *data); static DexFuture * sync_finally (DexFuture *future, GWeakRef *wr); static DexFuture * watch_backend_notifs_then_loop_cb (DexFuture *future, GWeakRef *wr); static BzEntryGroup * ensure_group_and_add (BzApplication *self, const char *id, BzEntry *entry, BzEntry *eol_runtime, gboolean ignore_eol, gboolean installed); 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 * get_or_create_window (BzApplication *self); 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 DexFuture * preview_metainfo_then (DexFuture *future, GWeakRef *wr); 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 state_info_set_icon_themes (BzStateInfo *state); 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->first_window_opened); 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->malcontent); g_clear_object (&self->internal_config); g_clear_object (&self->network); g_clear_object (&self->search_biases); g_clear_object (&self->search_biases_backing); 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_clear_pointer (&self->sys_ref_to_addon_group_ids, g_hash_table_unref); g_clear_pointer (&self->usr_ref_to_addon_group_ids, 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; gboolean preview_metainfo = FALSE; 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)" }, { "preview-metainfo", 0, 0, G_OPTION_ARG_NONE, &preview_metainfo, "Preview a metainfo file by selecting it via file dialog" }, { 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 && !preview_metainfo) { if (locations == NULL || *locations == NULL) new_window (self); else get_or_create_window (self); } if (locations != NULL && *locations != NULL) command_line_open_location (self, cmdline, locations[0]); if (preview_metainfo) { g_autoptr (DexFuture) future = NULL; future = bz_metainfo_preview_pick_files (); future = dex_future_then ( g_steal_pointer (&future), (DexFutureCallback) preview_metainfo_then, bz_track_weak (self), bz_weak_release); dex_future_disown (g_steal_pointer (&future)); } 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 = get_or_create_window (self); dialog = bz_donations_dialog_new (); 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 = get_or_create_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 = get_or_create_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; const char *developers[] = { "Adam Masciola ", "Alexander Vanhee", 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 (); g_object_set ( dialog, "application-name", "Bazaar", "application-icon", "io.github.kolunmi.Bazaar", "developer-name", _ ("The Bazaar Contributors"), "developers", developers, // Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 "translator-credits", _ ("translator-credits"), "version", PACKAGE_VCS_VERSION, "copyright", "Š 2025-2026 The Bazaar Contributors", "license-type", GTK_LICENSE_GPL_3_0, "website", "https://usebazaar.org", "issue-url", "https://github.com/bazaar-org/bazaar/issues", 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 = get_or_create_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) { static BzStateInfo *fallback_state = NULL; if (g_once_init_enter_pointer (&fallback_state)) { g_autoptr (BzStateInfo) tmp = NULL; tmp = bz_state_info_new (); // state_info_set_icon_themes (tmp); g_once_init_leave_pointer ( &fallback_state, g_steal_pointer (&tmp)); } return fallback_state; } 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 cache_has_flathub = FALSE; gboolean result = FALSE; 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, TRUE); 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; AdwDialog *alert = NULL; dex_await (DEX_FUTURE (self->first_window_opened), NULL); window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (window == NULL) window = new_window (self); alert = adw_alert_dialog_new (NULL, NULL); #ifdef SANDBOXED_LIBFLATPAK adw_alert_dialog_format_heading ( ADW_ALERT_DIALOG (alert), _ ("Set Up System Flathub?")); adw_alert_dialog_format_body ( ADW_ALERT_DIALOG (alert), _ ("The system Flathub remote is not set up. Bazaar requires " "Flathub to be configured on the system Flatpak installation " "to browse and install applications.\n\n" "You can still use Bazaar to browse and remove already installed apps.")); #else 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.")); #endif 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) has_flathub = TRUE; else { g_warning ("Failed to install flathub: %s", local_error->message); g_clear_error (&local_error); } } } bz_state_info_set_has_flathub (self->state, has_flathub); 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 */ cache_has_flathub = dex_await_boolean ( dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) enumerate_disk_entries_fiber, bz_track_weak (self), bz_weak_release), NULL); 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); if (cache_has_flathub) { dex_promise_resolve_boolean (self->ready_to_open_files, TRUE); bz_state_info_set_busy (self->state, FALSE); } } 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 * enumerate_disk_entries_fiber (GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (GHashTable) cached_set = NULL; g_autoptr (GPtrArray) futures = NULL; GHashTableIter iter = { 0 }; g_autoptr (GPtrArray) entries = NULL; gboolean has_flathub_entry = FALSE; bz_weak_get_or_return_reject (self, wr); cached_set = dex_await_boxed ( bz_entry_cache_manager_enumerate_disk (self->cache), &local_error); if (cached_set == NULL) { g_warning ("Unable to enumerate cached entries: %s", local_error->message); return dex_future_new_for_error (g_steal_pointer (&local_error)); } 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_autoptr (BzEntry) entry = NULL; entry = g_value_dup_object (value); if (BZ_IS_FLATPAK_ENTRY (entry) && bz_flatpak_entry_get_bundle_path (BZ_FLATPAK_ENTRY (entry)) != NULL) /* refrain from restoring bundle entries */ continue; if (!has_flathub_entry && BZ_IS_FLATPAK_ENTRY (entry) && g_strcmp0 (bz_entry_get_remote_repo_name (entry), "flathub") == 0) has_flathub_entry = TRUE; g_ptr_array_add (entries, g_steal_pointer (&entry)); } 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); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) check_for_updates_fiber, bz_track_weak (self), bz_weak_release)); return dex_future_new_for_boolean (has_flathub_entry); } static DexFuture * check_for_updates_fiber (GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; bz_weak_get_or_return_reject (self, wr); fiber_check_for_updates (self); finish_with_background_task_label (self); 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 (GPtrArray) build_notify_groups = NULL; g_autoptr (DexFuture) read_future = NULL; g_autoptr (DexFuture) reread_timeout = NULL; gboolean update_labels = FALSE; gboolean update_filters = FALSE; bz_weak_get_or_return_reject (self, data->self); build_futures = g_ptr_array_new_with_free_func (dex_unref); build_notify_groups = g_ptr_array_new_with_free_func (g_object_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_PRESENT_ID: { const char *id = NULL; id = bz_backend_notification_get_generic_id (notif); if (id == NULL) break; open_generic_id (self, id); } break; 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), _ ("A backend error occurred"), error); } break; case BZ_BACKEND_NOTIFICATION_KIND_TELL_INCOMING: { int n_incoming = 0; n_incoming = bz_backend_notification_get_n_incoming (notif); self->n_entries_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)) { const char *id = NULL; BzEntryGroup *group = NULL; update_filters = TRUE; id = bz_entry_get_id (entry); group = g_hash_table_lookup (self->ids_to_groups, id); if (group != NULL) g_ptr_array_add (build_notify_groups, g_object_ref (group)); } self->n_entries_incoming--; update_labels = TRUE; } break; case BZ_BACKEND_NOTIFICATION_KIND_REMOTE_SYNC_START: { const char *remote_name = NULL; remote_name = bz_backend_notification_get_remote_name (notif); if (bz_state_info_get_has_flathub (self->state)) /* We only count instances of the "flathub" remote if we have flathub, since that's all we care about for the UI */ { if (g_strcmp0 (remote_name, "flathub") == 0) self->n_remotes_syncing++; } else self->n_remotes_syncing++; g_debug ("remote '%s' has begun synchronization; " "now currently syncing %u remote(s)", remote_name, self->n_remotes_syncing); } break; case BZ_BACKEND_NOTIFICATION_KIND_REMOTE_SYNC_FINISH: { const char *remote_name = NULL; remote_name = bz_backend_notification_get_remote_name (notif); if (bz_state_info_get_has_flathub (self->state)) { if (g_strcmp0 (remote_name, "flathub") == 0) { self->n_remotes_syncing--; if (self->n_remotes_syncing == 0) self->flathub_remote_initialized = TRUE; } } else { self->n_remotes_syncing--; if (self->n_remotes_syncing == 0) bz_state_info_set_busy (self->state, FALSE); } g_debug ("remote '%s' has finished synchronization; " "now currently syncing %u remote(s)", remote_name, self->n_remotes_syncing); } 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_EXTERNAL_CHANGE: case BZ_BACKEND_NOTIFICATION_KIND_INVALIDATE_REMOTES: case BZ_BACKEND_NOTIFICATION_KIND_PRESENT_ID: case BZ_BACKEND_NOTIFICATION_KIND_REMOTE_SYNC_FINISH: case BZ_BACKEND_NOTIFICATION_KIND_REMOTE_SYNC_START: case BZ_BACKEND_NOTIFICATION_KIND_REPLACE_ENTRY: case BZ_BACKEND_NOTIFICATION_KIND_TELL_INCOMING: default: g_assert_not_reached (); }; 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)) { const char *id = NULL; BzEntryGroup *group = NULL; id = bz_entry_get_id (entry); group = g_hash_table_lookup (self->ids_to_groups, id); if (group != NULL) g_ptr_array_add (build_notify_groups, g_object_ref (group)); } } break; case BZ_BACKEND_NOTIFICATION_KIND_INVALIDATE_REMOTES: case BZ_BACKEND_NOTIFICATION_KIND_EXTERNAL_CHANGE: { g_autoptr (GListModel) repos = NULL; 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, _ ("Refreshing…")); 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); } 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; g_autoptr (CacheWriteBackData) write_back_data = NULL; future = dex_future_allv ( (DexFuture *const *) build_futures->pdata, build_futures->len); write_back_data = cache_write_back_data_new (); write_back_data->self = bz_track_weak (self); write_back_data->notify_groups = g_ptr_array_ref (build_notify_groups); write_back_data->update_filters = update_filters; future = dex_future_finally ( future, (DexFutureCallback) cache_write_back_finally, cache_write_back_data_ref (write_back_data), cache_write_back_data_unref); dex_future_disown (g_steal_pointer (&future)); } if (update_labels) { if (self->n_entries_incoming > 0) bz_state_info_set_background_task_label_take_printf ( self->state, _ ("Loading %d apps…"), self->n_entries_incoming); else { fiber_check_for_updates (self); finish_with_background_task_label (self); } } if (self->n_entries_incoming == 0 && self->flathub_remote_initialized) { bz_state_info_set_busy (self->state, FALSE); 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; 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); value = dex_future_get_value (future, &local_error); if (value == NULL) { GtkWindow *window = get_or_create_window (self); bz_show_error_for_widget ( GTK_WIDGET (window), _ ("Failed to open file"), local_error->message); return dex_future_new_for_error (g_steal_pointer (&local_error)); } if (G_VALUE_HOLDS_OBJECT (value)) { GtkWindow *window = NULL; BzEntry *entry = NULL; BzFlatpakRepo *repo = NULL; BzBundleInstallDialog *install_ui = NULL; BzFlatpakBundleResult *bundle_result = NULL; AdwDialog *dialog = NULL; const char *id = NULL; window = get_or_create_window (self); if (adw_application_window_get_visible_dialog (ADW_APPLICATION_WINDOW (window)) != NULL) window = new_window (self); bundle_result = BZ_FLATPAK_BUNDLE_RESULT (g_value_get_object (value)); entry = BZ_ENTRY (bz_flatpak_bundle_result_get_entry (bundle_result)); repo = bz_flatpak_bundle_result_get_runtime_repo (bundle_result); id = bz_entry_get_id (entry); if (id != NULL) { BzEntryGroup *group = NULL; group = g_hash_table_lookup (self->ids_to_groups, id); if (group != NULL && bz_entry_group_get_removable (group) > 0) bz_entry_set_installed (entry, TRUE); } install_ui = g_object_new ( BZ_TYPE_BUNDLE_INSTALL_DIALOG, "state", self->state, "entry", entry, "runtime-repo", repo, NULL); dialog = adw_dialog_new (); adw_dialog_set_content_width (dialog, 500); adw_dialog_set_content_height (dialog, -1); adw_dialog_set_child (dialog, GTK_WIDGET (install_ui)); adw_dialog_present (dialog, GTK_WIDGET (window)); } 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); bz_malcontent_service_start (self->malcontent); } 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), _ ("An initialization error occurred"), 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); /* Do nothing */ 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); if (dex_future_is_resolved (future)) return dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) enumerate_disk_entries_fiber, bz_track_weak (self), bz_weak_release); else return dex_ref (future); } 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, CacheWriteBackData *data) { g_autoptr (BzApplication) self = NULL; GPtrArray *notify_groups = data->notify_groups; gboolean update_filters = data->update_filters; bz_weak_get_or_return_reject (self, data->self); for (guint i = 0; i < notify_groups->len; i++) { BzEntryGroup *group = NULL; group = g_ptr_array_index (notify_groups, i); g_object_notify (G_OBJECT (group), "ui-entry"); } if (update_filters) { 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_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_allow_manual_sync (self->state, TRUE); bz_state_info_set_busy (self->state, FALSE); bz_state_info_set_syncing (self->state, FALSE); finish_with_background_task_label (self); 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 BzEntryGroup * ensure_group_and_add (BzApplication *self, const char *id, BzEntry *entry, BzEntry *eol_runtime, gboolean ignore_eol, gboolean installed) { BzEntryGroup *group = NULL; group = g_hash_table_lookup (self->ids_to_groups, id); if (group != NULL) bz_entry_group_add (group, entry, eol_runtime, ignore_eol); 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)); group = new_group; } if (installed && !g_list_store_find (self->installed_apps, group, NULL)) g_list_store_insert_sorted ( self->installed_apps, group, (GCompareDataFunc) cmp_group, NULL); return group; } 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; GHashTable *name_to_addons = 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)); name_to_addons = user ? self->usr_name_to_addons : self->sys_name_to_addons; 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 (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 (name_to_addons, flatpak_id); addons = NULL; } } if (bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_APPLICATION)) { gboolean ignore_eol = FALSE; const char *runtime_name = NULL; g_autoptr (BzEntry) eol_runtime = NULL; BzEntryGroup *group = NULL; GHashTable *ref_to_addon_group_ids = NULL; GPtrArray *pending = NULL; 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) { char *runtime_checksum = NULL; runtime_checksum = g_hash_table_lookup (self->eol_runtimes, runtime_name); if (runtime_checksum != NULL) eol_runtime = dex_await_object ( bz_entry_cache_manager_get_by_checksum ( self->cache, runtime_checksum), NULL); } group = ensure_group_and_add (self, id, entry, eol_runtime, ignore_eol, installed); ref_to_addon_group_ids = user ? self->usr_ref_to_addon_group_ids : self->sys_ref_to_addon_group_ids; pending = g_hash_table_lookup (ref_to_addon_group_ids, id); if (pending != NULL) { for (guint i = 0; i < pending->len; i++) bz_entry_group_append_addon_group_id (group, g_ptr_array_index (pending, i)); g_hash_table_remove (ref_to_addon_group_ids, id); } } 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_strdup (unique_id_checksum)); 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 && g_str_has_prefix (extension_of_what, "app/")) { g_auto (GStrv) parts = NULL; BzEntryGroup *app_group = NULL; ensure_group_and_add (self, id, entry, NULL, FALSE, installed); parts = g_strsplit (extension_of_what, "/", -1); if (parts != NULL && parts[1] != NULL) { app_group = g_hash_table_lookup (self->ids_to_groups, parts[1]); if (app_group != NULL) bz_entry_group_append_addon_group_id (app_group, id); else { GHashTable *ref_to_addon_group_ids = user ? self->usr_ref_to_addon_group_ids : self->sys_ref_to_addon_group_ids; GPtrArray *pending = NULL; pending = g_hash_table_lookup (ref_to_addon_group_ids, parts[1]); if (pending == NULL) { pending = g_ptr_array_new_with_free_func (g_free); g_hash_table_replace (ref_to_addon_group_ids, g_strdup (parts[1]), pending); } g_ptr_array_add (pending, g_strdup (id)); } } } if (extension_of_what != NULL) { GPtrArray *addons = NULL; /* BzFlatpakInstance ensures addons come before applications */ addons = g_hash_table_lookup (name_to_addons, extension_of_what); if (addons == NULL) { addons = g_ptr_array_new_with_free_func (g_free); g_hash_table_replace ( 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_background_task_label (self->state, _ ("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), _ ("Failed to check for updates"), 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; GList *remaining_windows = NULL; gboolean reap_dl_workers = TRUE; width = gtk_widget_get_width (window); height = gtk_widget_get_height (window); g_settings_set (self->settings, "window-dimensions", "(ii)", width, height); remaining_windows = gtk_application_get_windows ( GTK_APPLICATION (self)); for (GList *l = remaining_windows; l != NULL; l = l->next) { if (l->data != window) { reap_dl_workers = FALSE; break; } } if (reap_dl_workers) /* If no windows are left, kill the dl-worker subprocesses to minimize idle memory usage */ bz_reap_default_download_workers (); /* 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) { g_autoptr (GError) local_error = NULL; g_autoptr (GBytes) internal_config_bytes = NULL; g_autoptr (BzYamlParser) internal_config_parser = NULL; g_autoptr (GHashTable) internal_config_parse_results = NULL; const char *app_id = NULL; #ifdef HARDCODED_MAIN_CONFIG 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_INTERNAL_CONFIG); internal_config_bytes = g_resources_lookup_data ( "/io/github/kolunmi/Bazaar/internal-config.yaml", G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); g_assert (internal_config_bytes != NULL); internal_config_parser = bz_yaml_parser_new_for_resource_schema ( "/io/github/kolunmi/Bazaar/internal-config-schema.xml"); g_assert (internal_config_parser != NULL); internal_config_parse_results = bz_parser_process_bytes ( BZ_PARSER (internal_config_parser), internal_config_bytes, &local_error); if (internal_config_parse_results == NULL) g_critical ("FATAL: unable to parse internal config resource: %s", local_error->message); g_assert (internal_config_parse_results != NULL); self->internal_config = g_value_dup_object (g_hash_table_lookup (internal_config_parse_results, "/")); 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); } } g_clear_error (&local_error); #endif self->init_timer = g_timer_new (); self->ready_to_open_files = dex_promise_new (); self->first_window_opened = 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)); self->search_biases = gtk_flatten_list_model_new (NULL); self->search_biases_backing = g_list_store_new (G_TYPE_LIST_MODEL); { GListModel *main_config_search_biases = NULL; GListModel *internal_config_search_biases = NULL; if (self->config != NULL) main_config_search_biases = bz_main_config_get_search_biases (self->config); internal_config_search_biases = bz_internal_config_get_search_biases (self->internal_config); /* Main config biases take precedence over the hardcoded ones */ if (main_config_search_biases != NULL) g_list_store_append (self->search_biases_backing, main_config_search_biases); if (internal_config_search_biases != NULL) g_list_store_append (self->search_biases_backing, internal_config_search_biases); } gtk_flatten_list_model_set_model ( self->search_biases, G_LIST_MODEL (self->search_biases_backing)); 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); bz_state_info_set_parental_age_rating (self->state, -1); state_info_set_icon_themes (self->state); { g_autoptr (GError) bus_error = NULL; g_autoptr (GDBusConnection) sys_bus = NULL; sys_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &bus_error); if (sys_bus != NULL) self->malcontent = bz_malcontent_service_new (sys_bus, self->state); else g_warning ("Failed to connect to system bus for malcontent: %s", bus_error->message); if (self->malcontent != NULL) g_signal_connect_swapped ( self->state, "notify::parental-age-rating", G_CALLBACK (show_hide_app_setting_changed), self); } 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); if (g_settings_get_boolean (self->settings, "force-adwaita-icons")) { GtkSettings *gtk_settings = NULL; gtk_settings = gtk_settings_get_default (); g_object_set ( gtk_settings, "gtk-icon-theme-name", "Adwaita", NULL); } 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_free); 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->sys_ref_to_addon_group_ids = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref); self->usr_ref_to_addon_group_ids = 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_search_engine_set_biases (self->search_engine, G_LIST_MODEL (self->search_biases)); 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_filtered_entry_groups (self->state, G_LIST_MODEL (self->group_filter_model)); 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); bz_state_info_set_cache_manager (self->state, self->cache); 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 * get_or_create_window (BzApplication *self) { GtkWindow *window = NULL; GList *windows = NULL; window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (BZ_IS_WINDOW (window)) { gtk_window_present (window); return window; } windows = gtk_application_get_windows (GTK_APPLICATION (self)); for (GList *l = windows; l != NULL; l = l->next) { if (BZ_IS_WINDOW (l->data)) { gtk_window_present (GTK_WINDOW (l->data)); return GTK_WINDOW (l->data); } } return new_window (self); } 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)); if (dex_future_is_pending (DEX_FUTURE (self->first_window_opened))) dex_promise_resolve_boolean (self->first_window_opened, TRUE); 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_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autofree char *path = NULL; g_autoptr (OpenFlatpakrefData) data = NULL; path = g_file_get_path (file); if (path != NULL) /* We must do this synchronously so we don't lose access to a portal file */ { g_autofree char *basename = NULL; g_autofree char *module_dir = NULL; g_autofree char *staging = NULL; g_autofree char *dest = NULL; g_autoptr (GFile) copied = NULL; basename = g_file_get_basename (file); module_dir = bz_dup_module_dir (); staging = g_build_filename (module_dir, "bundle-staging", NULL); g_mkdir_with_parents (staging, 0755); dest = g_build_filename (staging, basename, NULL); copied = g_file_new_for_path (dest); result = g_file_copy ( file, copied, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS, NULL, NULL, NULL, &local_error); if (result) { g_clear_object (&file); file = g_steal_pointer (&copied); } else { g_warning ("Failed to copy bundle to %s : %s", dest, local_error->message); g_clear_error (&local_error); g_clear_object (&copied); } } 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; g_autofree char *corrected_id = NULL; const char *original_id = generic_id; const char *matched_id = generic_id; gboolean case_fixed = FALSE; group = g_hash_table_lookup (self->ids_to_groups, generic_id); // This is needed because KDE likes to mangle IDs just for fun... if (group == NULL) { gsize len = 0; len = strlen (generic_id); // if it has more than 3 parts and end with ".desktop" then cut it off. if (len > 8 && g_str_has_suffix (generic_id, ".desktop")) { guint n_dots = 0; const char *suffix = NULL; for (const char *p = strchr (generic_id, '.'); p != NULL; p = strchr (p, '.')) { if (++n_dots >= 3) { suffix = strstr (generic_id, ".desktop"); g_assert (suffix != NULL); break; } } if (suffix != NULL) { corrected_id = g_strndup (generic_id, suffix - generic_id); generic_id = corrected_id; matched_id = corrected_id; group = g_hash_table_lookup (self->ids_to_groups, generic_id); } } if (group == NULL) { GHashTableIter iter = { 0 }; g_hash_table_iter_init (&iter, self->ids_to_groups); for (;;) /* screeching sounds */ { char *key = NULL; BzEntryGroup *value = NULL; if (!g_hash_table_iter_next ( &iter, (gpointer *) &key, (gpointer *) &value)) break; if (g_ascii_strcasecmp (key, generic_id) == 0) { group = value; matched_id = key; case_fixed = TRUE; break; } } } if (group == NULL) matched_id = original_id; } window = get_or_create_window (self); if (group != NULL) { gtk_widget_activate_action (GTK_WIDGET (window), "window.show-group", "s", matched_id); if (case_fixed) bz_show_error_for_widget ( GTK_WIDGET (window), _ ("Malformed Link"), _ ("The link used to open this app has incorrect capitalization and may stop working in the future.\n\n" "This is most likely caused by KRunner sending incorrect app IDs")); } else { g_autofree char *message = NULL; message = g_strdup_printf ("ID '%s' was not found", original_id); bz_show_error_for_widget (GTK_WIDGET (window), _ ("Could not find app"), message); } } static DexFuture * preview_metainfo_then (DexFuture *future, GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; g_autoptr (GError) local_error = NULL; const GValue *value = NULL; BzMetainfoPickResult *result = NULL; g_autoptr (BzEntry) entry = NULL; GtkWindow *window = NULL; bz_weak_get_or_return_reject (self, wr); value = dex_future_get_value (future, &local_error); if (value == NULL) return dex_future_new_true (); result = g_value_get_boxed (value); window = get_or_create_window (self); entry = bz_appstream_parser_entry_from_metainfo ( result->metainfo_file, result->icon_file, &local_error); if (entry == NULL) { bz_show_error_for_widget (GTK_WIDGET (window), _ ("Failed to load metainfo"), local_error->message); return dex_future_new_true (); } bz_window_show_entry (BZ_WINDOW (window), entry); return dex_future_new_true (); } 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 (self->malcontent != NULL) { int parental_age = -1; int app_age = 0; parental_age = bz_state_info_get_parental_age_rating (self->state); app_age = bz_entry_group_get_content_age_rating (group); if (app_age > parental_age && parental_age != -1) 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 (GError) local_error = NULL; g_autoptr (GSubprocess) refresh_worker = NULL; 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); finish_with_background_task_label (self); refresh_worker = g_subprocess_new ( G_SUBPROCESS_FLAGS_NONE, &local_error, REFRESH_WORKER_BIN_NAME, NULL); if (refresh_worker == NULL) g_critical ("FATAL!!! The refresh worker could not be spawned: %s", local_error->message); g_assert (refresh_worker != NULL); backend_future = dex_subprocess_wait_check (refresh_worker); 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_finally ( ret_future, (DexFutureCallback) sync_finally, 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_entries_incoming > 0) bz_state_info_set_background_task_label_take_printf ( self->state, _ ("Loading %d apps…"), self->n_entries_incoming); else if (bz_state_info_get_syncing (self->state)) bz_state_info_set_background_task_label (self->state, _ ("Refreshing…")); else if (bz_state_info_get_busy (self->state)) bz_state_info_set_background_task_label (self->state, _ ("Writing to cache…")); else bz_state_info_set_background_task_label (self->state, NULL); } static void state_info_set_icon_themes (BzStateInfo *state) { g_autoptr (GtkIconTheme) user_theme = NULL; g_autoptr (GtkIconTheme) system_theme = NULL; g_autofree char *user_export_dir = NULL; user_theme = gtk_icon_theme_new (); user_export_dir = g_build_filename (g_get_home_dir (), ".local/share/flatpak/exports/share/icons", NULL); gtk_icon_theme_add_search_path (user_theme, user_export_dir); bz_state_info_set_user_icon_theme (state, user_theme); system_theme = gtk_icon_theme_new (); gtk_icon_theme_add_search_path (system_theme, "/var/lib/flatpak/exports/share/icons"); bz_state_info_set_system_icon_theme (state, system_theme); } bazaar-org-bazaar-43ce9f7/src/bz-application.h000066400000000000000000000020221520414637400213010ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-apps-page.blp000066400000000000000000000065251520414637400212150ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzAppsPage: Adw.NavigationPage { Adw.ToolbarView { [top] Adw.HeaderBar { [title] Revealer { reveal-child: bind $is_scrolled_down(main_scroll.vadjustment as .value, carousel.visible) as ; transition-type: slide_up; transition-duration: 500; overflow: visible; child: Label { label: bind template.page-title; styles ["title"] }; } } content: Adw.BreakpointBin { width-request: 360; height-request: 100; child: Gtk.ScrolledWindow main_scroll { 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 carousel { margin-start: 3; margin-end: 3; margin-bottom: 12; hexpand: true; visible: bind $is_not_null(template.carousel-applications) as ; model: SliceListModel { offset: 0; size: 7; model: bind template.carousel-applications; }; } 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: 9; list_view.row-spacing: 9; title.halign: center; title.justify: center; subtitle.halign: center; } } }; } } bazaar-org-bazaar-43ce9f7/src/bz-apps-page.c000066400000000000000000000364701520414637400206640ustar00rootroot00000000000000/* 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 }; 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 gboolean is_scrolled_down (gpointer object, double value, gboolean carousel_visible) { return value > (carousel_visible ? 400.0 : 50.0); } static void featured_carousel_group_clicked_cb (BzAppsPage *self, BzEntryGroup *group, GtkWidget *carousel) { gtk_widget_activate_action (GTK_WIDGET (self), "window.show-group", "s", bz_entry_group_get_id (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; 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); 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, is_scrolled_down); 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) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (group), FALSE); g_return_val_if_fail (category_name != NULL, FALSE); return bz_entry_group_has_category (group, category_name); } 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_filtered_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) { gtk_widget_activate_action (GTK_WIDGET (button), "window.show-group", "s", bz_entry_group_get_id (group)); } bazaar-org-bazaar-43ce9f7/src/bz-apps-page.h000066400000000000000000000027251520414637400206650ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-appstream-description-render.blp000066400000000000000000000004111520414637400251160ustar00rootroot00000000000000using 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; } }; }bazaar-org-bazaar-43ce9f7/src/bz-appstream-description-render.c000066400000000000000000000471741520414637400246040ustar00rootroot00000000000000/* 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 (BzAppstreamDescriptionRender *self, 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 on_map (GtkWidget *widget, BzAppstreamDescriptionRender *self); static const char * get_link_at_coords (GtkTextView *text_view, double x, double y); static void on_click_released (GtkGestureClick *gesture, int n_press, double x, double y, GtkTextView *text_view); static void on_motion (GtkEventControllerMotion *controller, double x, double y, GtkTextView *text_view); 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; GtkGesture *click = NULL; GtkEventController *motion = NULL; AdwStyleManager *style_manager = 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"); g_signal_connect (self, "map", G_CALLBACK (on_map), self); click = gtk_gesture_click_new (); gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (click), GDK_BUTTON_PRIMARY); g_signal_connect (click, "released", G_CALLBACK (on_click_released), self->text_view); gtk_widget_add_controller (GTK_WIDGET (self->text_view), GTK_EVENT_CONTROLLER (click)); motion = gtk_event_controller_motion_new (); g_signal_connect (motion, "motion", G_CALLBACK (on_motion), self->text_view); gtk_widget_add_controller (GTK_WIDGET (self->text_view), motion); style_manager = adw_style_manager_get_default (); g_signal_connect_object (style_manager, "notify::accent-color", G_CALLBACK (regenerate), self, G_CONNECT_SWAPPED); } static const char * get_link_at_coords (GtkTextView *text_view, double x, double y) { GtkTextIter iter = { 0 }; int bx = 0; int by = 0; g_autoptr (GSList) tags = NULL; GSList *l = NULL; const char *href = NULL; gtk_text_view_window_to_buffer_coords (text_view, GTK_TEXT_WINDOW_WIDGET, (int) x, (int) y, &bx, &by); gtk_text_view_get_iter_at_location (text_view, &iter, bx, by); tags = gtk_text_iter_get_tags (&iter); for (l = tags; l != NULL; l = l->next) { href = g_object_get_data (G_OBJECT (l->data), "href"); if (href != NULL) return href; } return NULL; } static void on_click_released (GtkGestureClick *gesture, int n_press, double x, double y, GtkTextView *text_view) { const char *href = NULL; g_autoptr (GtkUriLauncher) launcher = NULL; GtkWindow *root = NULL; href = get_link_at_coords (text_view, x, y); if (href == NULL) return; launcher = gtk_uri_launcher_new (href); root = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (text_view))); gtk_uri_launcher_launch (launcher, root, NULL, NULL, NULL); } static void on_motion (GtkEventControllerMotion *controller, double x, double y, GtkTextView *text_view) { if (get_link_at_coords (text_view, x, y) != NULL) gtk_widget_set_cursor_from_name (GTK_WIDGET (text_view), "pointer"); else gtk_widget_set_cursor (GTK_WIDGET (text_view), NULL); } 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_url (BzAppstreamDescriptionRender *self, GtkTextBuffer *buffer, GtkTextIter *iter, const char *url) { g_autoptr (GdkRGBA) rgba = NULL; GtkTextTag *tag = NULL; GtkTextMark *mark = NULL; GtkTextIter start = { 0 }; rgba = adw_style_manager_get_accent_color_rgba (adw_style_manager_get_default ()); tag = gtk_text_buffer_create_tag (buffer, NULL, "foreground-rgba", rgba, "underline", PANGO_UNDERLINE_SINGLE, NULL); g_object_set_data_full (G_OBJECT (tag), "href", g_strdup (url), g_free); mark = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE); gtk_text_buffer_insert (buffer, iter, url, -1); gtk_text_buffer_get_iter_at_mark (buffer, &start, mark); gtk_text_buffer_apply_tag (buffer, tag, &start, iter); gtk_text_buffer_delete_mark (buffer, mark); } static void insert (BzAppstreamDescriptionRender *self, GtkTextBuffer *buffer, GtkTextIter *iter, const char *text) { g_auto (GStrv) parts = NULL; const char *p = NULL; const char *http = NULL; const char *https = NULL; const char *url_start = NULL; const char *url_end = NULL; const char *chunk = NULL; GtkTextMark *m = NULL; GtkTextIter si = { 0 }; g_autofree char *url = NULL; int j = 0; parts = g_strsplit (text, "**", -1); for (j = 0; parts[j] != NULL; j++) { chunk = parts[j]; if (j % 2 != 0) { m = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE); gtk_text_buffer_insert (buffer, iter, chunk, -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); continue; } p = chunk; while (*p != '\0') { http = strstr (p, "http://"); https = strstr (p, "https://"); url_start = (http != NULL && (https == NULL || http < https)) ? http : https; if (url_start == NULL) { gtk_text_buffer_insert (buffer, iter, p, -1); break; } if (url_start > p) gtk_text_buffer_insert (buffer, iter, p, (int) (url_start - p)); url_end = url_start; while (*url_end != '\0' && !g_unichar_isspace (g_utf8_get_char (url_end))) url_end = g_utf8_next_char (url_end); url = g_strndup (url_start, url_end - url_start); for (char *end = url + strlen (url) - 1; end >= url && strchr (").,!?", *end) != NULL; end--) { *end = '\0'; url_end--; } insert_url (self, buffer, iter, url); p = url_end; } } } 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 (self, 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 (self, 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 void on_map (GtkWidget *widget, BzAppstreamDescriptionRender *self) { gtk_widget_queue_resize (GTK_WIDGET (self)); } static char * normalize_whitespace (const char *text) { g_autoptr (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) in_space = TRUE; } else { if (!at_start && in_space) g_string_append_c (result, ' '); g_string_append_unichar (result, ch); in_space = FALSE; at_start = FALSE; } } return g_string_free (g_steal_pointer (&result), FALSE); } /* End of bz-appstream-description-render.c */ bazaar-org-bazaar-43ce9f7/src/bz-appstream-description-render.h000066400000000000000000000027411520414637400246000ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-appstream-parser.c000066400000000000000000000647441520414637400223020ustar00rootroot00000000000000/* 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-category-flags.h" #include "bz-io.h" #include "bz-release.h" #include "bz-url.h" #include "bz-verification-status.h" #include "bz-flatpak-entry.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 recommended_controls, guint supported_controls) { return (required_controls & BZ_CONTROL_TOUCH) != 0 || (recommended_controls & BZ_CONTROL_TOUCH) != 0 || (supported_controls & BZ_CONTROL_TOUCH) != 0; } static char * proxy_screenshot_url (const char *url, gboolean high_quality) { g_autofree char *src = NULL; g_autofree char *encoded_url = NULL; const char *suffix = NULL; if (g_str_has_prefix (url, "https://dl.flathub.org/repo/screenshots/")) { suffix = url + strlen ("https://dl.flathub.org/repo/screenshots/"); src = g_strdup_printf ("https://dl.flathub.org/media/%s", suffix); } else if (g_str_has_prefix (url, "https://dl.flathub.org/")) { src = g_strdup (url); } else { return g_strdup (url); } encoded_url = g_base64_encode ((const guchar *) src, strlen (src)); g_strdelimit (encoded_url, "=", '\0'); for (char *p = encoded_url; *p; p++) { if (*p == '+') *p = '-'; if (*p == '/') *p = '_'; } return g_strdup_printf ( "https://imgproxy.flathub.org/insecure/%s/%s", high_quality ? "q:90/f:avif" : "dpr:1/f:avif/rs:fill-down", encoded_url); } 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 (best_url == NULL || pixels > best_res) { best_url = url; best_res = pixels; } } else { gint diff = ABS ((gint) pixels - (gint) target_pixels); if (best_url == NULL || 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; g_autofree char *proxied_url = NULL; BzAsyncTexture *texture = NULL; proxied_url = proxy_screenshot_url (best_url, match_highest); screenshot_file = g_file_new_for_uri (proxied_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 *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; BzCategoryFlags categories = BZ_CATEGORY_FLAGS_NONE; 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", NULL); if (thumbnail_paintable == NULL) thumbnail_paintable = find_screenshot (images, caption, FALSE, 400, 300, FALSE, module_dir, unique_id_checksum, "thumbnail", NULL); } cache_name = g_strdup_printf ("screenshot_%u", 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_id (url, "flathub"); bz_url_set_url (url, flathub_url); 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) { g_autoptr (BzUrl) share_url = NULL; switch (e) { case AS_URL_KIND_DONATION: g_clear_pointer (&donation_url, g_free); donation_url = g_strdup (url); break; default: break; } share_url = g_object_new ( BZ_TYPE_URL, "id", as_url_kind_to_string (e), "url", url, 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, recommended_controls, supported_controls); 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) { for (guint i = 0; i < as_categories->len; i++) { const char *name = NULL; name = g_ptr_array_index (as_categories, i); categories = bz_category_flags_add (categories, name); } } 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, "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; } BzEntry * bz_appstream_parser_entry_from_metainfo (GFile *metainfo_file, GFile *icon_file, GError **error) { g_autoptr (AsMetadata) mdata = as_metadata_new (); AsComponent *component = NULL; g_autofree char *xml_contents = NULL; g_autofree char *xml_path = NULL; g_autofree char *xml_dir = NULL; g_autofree char *module_dir = NULL; g_autofree char *checksum = NULL; gsize xml_length = 0; g_autoptr (BzEntry) entry = NULL; g_return_val_if_fail (G_IS_FILE (metainfo_file), NULL); xml_path = g_file_get_path (metainfo_file); if (!g_file_get_contents (xml_path, &xml_contents, &xml_length, error)) return NULL; as_metadata_parse_data (mdata, xml_contents, xml_length, AS_FORMAT_KIND_XML, error); if (*error != NULL) return NULL; component = as_metadata_get_component (mdata); if (component == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No component found in metainfo file"); return NULL; } xml_dir = g_path_get_dirname (xml_path); module_dir = bz_dup_module_dir (); checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, xml_path, -1); entry = BZ_ENTRY (g_object_new (BZ_TYPE_FLATPAK_ENTRY, NULL)); bz_appstream_parser_populate_entry ( entry, component, xml_dir, "local-preview", module_dir, checksum, as_component_get_id (component), BZ_ENTRY_KIND_APPLICATION, NULL); g_object_set (entry, "remote-repo-name", "local-preview", NULL); if (icon_file != NULL) { g_autoptr (GFile) cache_into = NULL; cache_into = g_file_new_build_filename ( module_dir, checksum, "icon-paintable.png", NULL); g_object_set ( entry, "icon-paintable", GDK_PAINTABLE (bz_async_texture_new_lazy (icon_file, cache_into)), NULL); } return g_steal_pointer (&entry); } bazaar-org-bazaar-43ce9f7/src/bz-appstream-parser.h000066400000000000000000000032321520414637400222700ustar00rootroot00000000000000/* 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); BzEntry * bz_appstream_parser_entry_from_metainfo (GFile *metainfo_file, GFile *icon_file, GError **error); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-async-texture.c000066400000000000000000001023461520414637400216160ustar00rootroot00000000000000/* 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 #define TEXTURE_LINGER_SECONDS 2 #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 ( cache_entry, CacheEntry, { GdkTexture *texture; DexFuture *linger_timeout; }, BZ_RELEASE_DATA (texture, g_object_unref); BZ_RELEASE_DATA (linger_timeout, dex_unref)); static GMutex texture_cache_mutex = { 0 }; static GHashTable *texture_cache = NULL; static void texture_cache_ensure (void); static DexFuture * linger_timeout_finally (DexFuture *future, char *uri); static GdkTexture * texture_cache_acquire (const char *uri); static void texture_cache_store (const char *uri, GdkTexture *texture); static void texture_cache_release (const char *uri); 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 mutex; gboolean cache_acquired; }; 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 GMutex debug_n_textures_mutex = { 0 }; static gsize debug_n_textures = 0; 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); if (self->cache_acquired && self->source_uri != NULL) { texture_cache_release (self->source_uri); self->cache_acquired = FALSE; } 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->mutex); if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN)) { g_mutex_lock (&debug_n_textures_mutex); debug_n_textures--; g_debug ("%zu %s object(s) in memory", debug_n_textures, g_type_name (BZ_TYPE_ASYNC_TEXTURE)); g_mutex_unlock (&debug_n_textures_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; self->cache_acquired = FALSE; g_mutex_init (&self->mutex); if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN)) { g_mutex_lock (&debug_n_textures_mutex); debug_n_textures++; g_mutex_unlock (&debug_n_textures_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->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->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->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->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->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->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->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->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->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->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->cache_acquired) { g_autoptr (GdkTexture) cached = NULL; cached = texture_cache_acquire (self->source_uri); if (cached != NULL) { g_clear_object (&self->paintable); self->paintable = (GdkPaintable *) g_object_ref (cached); self->cache_acquired = TRUE; g_idle_add_full ( G_PRIORITY_DEFAULT_IDLE, (GSourceFunc) idle_notify, g_object_ref (self), g_object_unref); 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/bazaar-org/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 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 != NULL ? local_error->message : "variant parse failed"); 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->mutex); dex_clear (&self->task); if (dex_future_is_resolved (future)) { GdkTexture *texture = NULL; texture = g_value_get_object (dex_future_get_value (future, NULL)); g_clear_object (&self->paintable); self->paintable = g_object_ref (GDK_PAINTABLE (texture)); if (!self->cache_acquired) { texture_cache_store (self->source_uri, texture); self->cache_acquired = TRUE; } 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 != NULL ? local_error->message : "unknown error", RETRY_INTERVAL_SECONDS); else g_warning ("Loading %s failed: %s. Retrying in %d seconds. Retries left: %d", self->source_uri, local_error != NULL ? local_error->message : "unknown error", 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->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; } static void texture_cache_ensure (void) { if (texture_cache == NULL) texture_cache = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, cache_entry_data_unref); } static DexFuture * linger_timeout_finally (DexFuture *future, char *uri) { g_mutex_lock (&texture_cache_mutex); texture_cache_ensure (); g_hash_table_remove (texture_cache, uri); g_debug ("Texture cache: evicted '%s' after linger (table size: %u)", uri, g_hash_table_size (texture_cache)); g_mutex_unlock (&texture_cache_mutex); return dex_future_new_true (); } static GdkTexture * texture_cache_acquire (const char *uri) { g_autoptr (GMutexLocker) locker = NULL; CacheEntryData *data = NULL; locker = g_mutex_locker_new (&texture_cache_mutex); texture_cache_ensure (); data = g_hash_table_lookup (texture_cache, uri); if (data != NULL) { dex_clear (&data->linger_timeout); return g_object_ref (data->texture); } else return NULL; } static void texture_cache_store (const char *uri, GdkTexture *texture) { g_autoptr (CacheEntryData) data = NULL; g_mutex_lock (&texture_cache_mutex); texture_cache_ensure (); data = cache_entry_data_new (); data->texture = g_object_ref (texture); g_hash_table_replace ( texture_cache, g_strdup (uri), cache_entry_data_ref (data)); g_mutex_unlock (&texture_cache_mutex); } static void texture_cache_release (const char *uri) { g_autoptr (GMutexLocker) locker = NULL; CacheEntryData *data = NULL; g_autoptr (DexFuture) future = NULL; locker = g_mutex_locker_new (&texture_cache_mutex); texture_cache_ensure (); data = g_hash_table_lookup (texture_cache, uri); if (data == NULL) return; dex_clear (&data->linger_timeout); future = dex_timeout_new_seconds (TEXTURE_LINGER_SECONDS); future = dex_future_finally ( future, (DexFutureCallback) linger_timeout_finally, g_strdup (uri), g_free); data->linger_timeout = dex_ref (future); } bazaar-org-bazaar-43ce9f7/src/bz-async-texture.h000066400000000000000000000034441520414637400216220ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-auth-state.c000066400000000000000000000342141520414637400210600ustar00rootroot00000000000000/* 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); } bazaar-org-bazaar-43ce9f7/src/bz-auth-state.h000066400000000000000000000032061520414637400210620ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-backend-notification.txt000066400000000000000000000012521520414637400234450ustar00rootroot00000000000000prefix=bz name=backend_notification parent-prefix=g parent-name=object author=AUTOGEN enum=bz backend_notification_kind error tell_incoming replace_entry invalidate_remotes remote_sync_start remote_sync_finish install_done update_done remove_done external_change present_id 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=remote_name char G_TYPE_STRING string property=generic_id char G_TYPE_STRING string property=unique_id char G_TYPE_STRING string bazaar-org-bazaar-43ce9f7/src/bz-backend-transaction-op-payload.txt000066400000000000000000000004641520414637400253530ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-backend-transaction-op-progress-payload.txt000066400000000000000000000010351520414637400272100ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-backend.c000066400000000000000000000226211520414637400203670ustar00rootroot00000000000000/* 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 gboolean bz_backend_real_cancel_task_for_entry (BzBackend *self, BzEntry *entry) { return FALSE; } 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; iface->cancel_task_for_entry = bz_backend_real_cancel_task_for_entry; } 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); } gboolean bz_backend_cancel_task_for_entry (BzBackend *self, BzEntry *entry) { g_return_val_if_fail (BZ_IS_BACKEND (self), FALSE); g_return_val_if_fail (BZ_IS_ENTRY (entry), FALSE); return BZ_BACKEND_GET_IFACE (self)->cancel_task_for_entry (self, entry); } bazaar-org-bazaar-43ce9f7/src/bz-backend.h000066400000000000000000000103761520414637400204000ustar00rootroot00000000000000/* 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); gboolean (*cancel_task_for_entry) (BzBackend *self, BzEntry *entry); }; 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); gboolean bz_backend_cancel_task_for_entry (BzBackend *self, BzEntry *entry); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-blocklist-condition-match-envvar.txt000066400000000000000000000002631520414637400257360ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-blocklist-condition-match-locale.txt000066400000000000000000000002141520414637400256700ustar00rootroot00000000000000prefix=bz name=blocklist_condition_match_locale parent-prefix=g parent-name=object author=AUTOGEN property=regex char G_TYPE_STRING string bazaar-org-bazaar-43ce9f7/src/bz-blocklist-condition.txt000066400000000000000000000010601520414637400233410ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-blocklist.txt000066400000000000000000000007401520414637400213610ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-bulk-install-dialog-result.txt000066400000000000000000000003331520414637400245430ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-bundle-install-dialog.blp000066400000000000000000000360101520414637400235020ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzBundleInstallDialog: Adw.BreakpointBin { child: Adw.NavigationView nav_view { Adw.NavigationPage { tag: "main"; title: _("Bundle Installation"); child: Adw.ToolbarView { [top] Adw.HeaderBar { title-widget: Label { label: _("Bundle Installation"); }; show-title: false; } content: Stack main_stack { StackPage { name: "carousel"; child: Adw.Carousel carousel { interactive: false; spacing: 64; Box page_info { orientation: vertical; spacing: 16; valign: center; halign: fill; hexpand: true; margin-top: 24; margin-bottom: 24; margin-start: 24; margin-end: 24; Box { orientation: bind $get_header_orientation(template.runtime-repo) as ; spacing: 16; halign: fill; valign: start; Image icon { paintable: bind template.entry as <$BzEntry>.icon-paintable; visible: bind $invert_boolean( $is_null(template.entry as <$BzEntry>.icon-paintable) as ) as ; use-fallback: true; pixel-size: 96; halign: bind $get_header_halign(template.runtime-repo) as ; valign: center; styles [ "icon-dropshadow", ] } Image { icon-name: "application-x-executable"; pixel-size: 96; visible: bind $invert_boolean(icon.visible) as ; halign: bind $get_header_halign(template.runtime-repo) as ; valign: center; styles [ "icon-dropshadow", ] } Box { orientation: vertical; spacing: 2; valign: center; hexpand: true; Label { label: bind template.entry as <$BzEntry>.title; wrap: true; wrap-mode: word_char; halign: bind $get_header_halign(template.runtime-repo) as ; xalign: 0; styles [ "title-3", ] } Label { label: bind template.entry as <$BzEntry>.developer; wrap: true; wrap-mode: word_char; halign: bind $get_header_halign(template.runtime-repo) as ; xalign: 0; visible: bind $not($is_empty_string(template.entry as <$BzEntry>.developer) as ) as ; styles [ "dim-label", ] } Label { label: bind $get_version(template.entry as <$BzEntry>.version-history); visible: bind $not( $is_empty_string($get_version(template.entry as <$BzEntry>.version-history) as ) as ) as ; halign: bind $get_header_halign(template.runtime-repo) as ; xalign: 0; styles [ "dim-label", "caption", ] } } Button { styles [ "suggested-action", "pill", ] valign: center; halign: bind $get_header_halign(template.runtime-repo) as ; label: C_("Install Controls", "Install"); clicked => $install_cb(template); } } Adw.PreferencesGroup { margin-top: 12; Adw.ActionRow { [prefix] Image { icon-name: "drive-harddisk-symbolic"; valign: center; styles [ "circular-lozenge", "grey", ] } title: bind $get_disk_title(template.entry as <$BzEntry>.installed-size); subtitle: _("Additional dependencies may take extra space"); } Adw.ActionRow { [prefix] Image safety_icon { icon-name: bind $get_safety_icon_name(template.entry as <$BzEntry>); valign: center; styles [ "circular-lozenge", ] } [suffix] Image { icon-name: "go-next-symbolic"; } title: bind $get_safety_rating_label(template.entry); subtitle: bind $get_safety_subtitle(template.entry); subtitle-lines: 1; activatable: true; activated => $permission_cb(); } } Box { orientation: vertical; spacing: 4; visible: bind $not($is_null(template.runtime-repo) as ) as ; Label { label: _( "Installing this app may require adding a new software source. Other apps from this source will show up in Bazaar.\n\nOnly add this source if you're sure you trust it." ); wrap: true; wrap-mode: word_char; halign: start; margin-bottom: 6; styles [ "body", ] } Adw.PreferencesGroup { Adw.ActionRow { activatable: bind $not( $is_null(template.runtime-repo as <$BzFlatpakRepo>.homepage) as ) as ; activated => $repo_cb(); child: Box { margin-top: 8; margin-bottom: 8; margin-start: 8; margin-end: 16; spacing: 8; Image bundle_image { pixel-size: 48; } Box { orientation: vertical; spacing: 4; hexpand: true; Label { label: bind template.runtime-repo as <$BzFlatpakRepo>.title; halign: start; ellipsize: end; styles [ "heading", ] } Label { label: bind template.runtime-repo as <$BzFlatpakRepo>.description; wrap: true; halign: start; wrap-mode: word_char; lines: 2; ellipsize: end; } Label { halign: start; label: bind $format_url(template.runtime-repo as <$BzFlatpakRepo>.url); ellipsize: end; styles [ "accent", "caption", ] } } Image { icon-name: "external-link-symbolic"; margin-start: 8; visible: bind $not( $is_null(template.runtime-repo as <$BzFlatpakRepo>.homepage) as ) as ; } }; } } } } Box page_progress { orientation: vertical; spacing: 12; valign: center; halign: fill; margin-top: 24; margin-bottom: 24; margin-start: 48; margin-end: 48; Image loading_icon { paintable: bind template.entry as <$BzEntry>.icon-paintable; visible: bind $invert_boolean( $is_null(template.entry as <$BzEntry>.icon-paintable) as ) as ; pixel-size: 128; margin-bottom: 12; styles [ "icon-dropshadow", ] } Image { icon-name: "application-x-executable"; pixel-size: 128; visible: bind $invert_boolean(loading_icon.visible) as ; margin-bottom: 12; styles [ "icon-dropshadow", ] } Label { label: bind template.entry as <$BzEntry>.title; wrap: true; wrap-mode: word_char; halign: center; styles [ "title-3", ] } ProgressBar progress_bar { margin-top: 16; pulse-step: 0.05; width-request: 250; } } Box page_finish { orientation: vertical; spacing: 8; valign: center; halign: fill; margin-top: 24; margin-bottom: 24; margin-start: 24; margin-end: 24; Image end_icon { paintable: bind template.entry as <$BzEntry>.icon-paintable; visible: bind $invert_boolean( $is_null(template.entry as <$BzEntry>.icon-paintable) as ) as ; pixel-size: 128; margin-bottom: 12; styles [ "icon-dropshadow", ] } Image { icon-name: "application-x-executable"; pixel-size: 128; visible: bind $invert_boolean(end_icon.visible) as ; margin-bottom: 12; styles [ "icon-dropshadow", ] } Label { label: bind template.entry as <$BzEntry>.title; wrap: true; wrap-mode: word_char; halign: center; styles [ "title-3", ] } Label { label: _("Successfully Installed!"); halign: center; margin-bottom: 16; margin-top: 8; styles [ "dim-label", ] } Box { width-request: 40; orientation: vertical; spacing: 8; margin-top: 8; halign: center; Button open_btn { styles [ "suggested-action", "pill", ] halign: fill; label: _("Open"); clicked => $run_cb(template); } Button show_in_store_btn { styles [ "pill", ] halign: fill; label: _("Show App Details"); clicked => $show_cb(template); } } } }; } StackPage { name: "installed"; child: Box { orientation: vertical; spacing: 8; valign: center; halign: fill; margin-top: 24; margin-bottom: 24; margin-start: 24; margin-end: 24; Image installed_icon { paintable: bind template.entry as <$BzEntry>.icon-paintable; visible: bind $invert_boolean( $is_null(template.entry as <$BzEntry>.icon-paintable) as ) as ; pixel-size: 128; margin-bottom: 12; } Image { icon-name: "application-x-executable"; pixel-size: 128; visible: bind $invert_boolean(installed_icon.visible) as ; margin-bottom: 12; } Label { label: bind template.entry as <$BzEntry>.title; wrap: true; wrap-mode: word_char; halign: center; styles [ "title-3", ] } Label { label: _("Already Installed"); styles [ "dim-label", "caption", ] halign: center; } Box { orientation: vertical; spacing: 8; margin-top: 24; halign: center; Button { styles [ "suggested-action", "pill", ] halign: fill; label: _("Open"); clicked => $run_cb(template); } Button { styles [ "pill", ] halign: fill; label: _("Show App Details"); clicked => $show_cb(template); } } }; } StackPage { name: "error"; child: Adw.StatusPage error_status { icon-name: "sad-computer-symbolic"; title: _("Installation Failed"); }; } }; }; } }; } bazaar-org-bazaar-43ce9f7/src/bz-bundle-install-dialog.c000066400000000000000000000421761520414637400231610ustar00rootroot00000000000000/* bz-bundle-install-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 #include "bz-app-permissions.h" #include "bz-app-size-dialog.h" #include "bz-application-map-factory.h" #include "bz-application.h" #include "bz-async-texture.h" #include "bz-bundle-install-dialog.h" #include "bz-context-tile-callbacks.h" #include "bz-env.h" #include "bz-flatpak-repo.h" #include "bz-release.h" #include "bz-safety-calculator.h" #include "bz-safety-dialog.h" #include "bz-state-info.h" #include "bz-template-callbacks.h" #include "bz-util.h" struct _BzBundleInstallDialog { AdwBreakpointBin parent_instance; BzStateInfo *state; BzEntry *entry; BzFlatpakRepo *runtime_repo; AdwNavigationView *nav_view; GtkStack *main_stack; AdwCarousel *carousel; GtkWidget *page_info; GtkWidget *page_progress; GtkWidget *page_finish; GtkProgressBar *progress_bar; AdwStatusPage *error_status; GtkImage *safety_icon; GtkImage *bundle_image; guint pulse_source_id; }; G_DEFINE_FINAL_TYPE (BzBundleInstallDialog, bz_bundle_install_dialog, ADW_TYPE_BREAKPOINT_BIN); enum { PROP_0, PROP_STATE, PROP_ENTRY, PROP_RUNTIME_REPO, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static DexFuture * install_fiber (GWeakRef *wr); static void bz_bundle_install_dialog_dispose (GObject *object) { BzBundleInstallDialog *self = BZ_BUNDLE_INSTALL_DIALOG (object); g_clear_handle_id (&self->pulse_source_id, g_source_remove); g_clear_pointer (&self->state, g_object_unref); g_clear_pointer (&self->entry, g_object_unref); g_clear_pointer (&self->runtime_repo, g_object_unref); G_OBJECT_CLASS (bz_bundle_install_dialog_parent_class)->dispose (object); } static void bz_bundle_install_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzBundleInstallDialog *self = BZ_BUNDLE_INSTALL_DIALOG (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, bz_bundle_install_dialog_get_state (self)); break; case PROP_ENTRY: g_value_set_object (value, bz_bundle_install_dialog_get_entry (self)); break; case PROP_RUNTIME_REPO: g_value_set_object (value, bz_bundle_install_dialog_get_runtime_repo (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_bundle_install_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzBundleInstallDialog *self = BZ_BUNDLE_INSTALL_DIALOG (object); switch (prop_id) { case PROP_STATE: bz_bundle_install_dialog_set_state (self, g_value_get_object (value)); break; case PROP_ENTRY: bz_bundle_install_dialog_set_entry (self, g_value_get_object (value)); break; case PROP_RUNTIME_REPO: bz_bundle_install_dialog_set_runtime_repo (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean pulse_progress_bar (gpointer user_data) { BzBundleInstallDialog *self = BZ_BUNDLE_INSTALL_DIALOG (user_data); gtk_progress_bar_pulse (self->progress_bar); return G_SOURCE_CONTINUE; } static char * get_version (gpointer object, GListModel *version_history) { g_autoptr (BzRelease) release = NULL; if (version_history == NULL || g_list_model_get_n_items (version_history) == 0) return NULL; release = g_list_model_get_item (version_history, 0); return g_strdup (bz_release_get_version (release)); } static char * get_disk_title (gpointer object, guint64 installed_size) { g_autofree char *size_str = NULL; if (installed_size == 0) return g_strdup (_ ("Unknown install size")); size_str = g_format_size (installed_size); return g_strdup_printf (_ ("About %s to install"), size_str); } static char * get_safety_subtitle (gpointer object, BzEntry *entry) { g_autoptr (GListModel) model = NULL; g_autoptr (GString) result = NULL; guint n_items = 0; guint n_picked = 0; guint n_total = 0; if (entry == NULL) return g_strdup (_ ("N/A")); model = bz_safety_calculator_analyze_entry (entry); n_items = g_list_model_get_n_items (model); result = g_string_new (NULL); for (guint i = 0; i < n_items; i++) { g_autoptr (BzSafetyRow) row = g_list_model_get_item (model, i); BzImportance importance = BZ_IMPORTANCE_UNIMPORTANT; g_autofree char *title = NULL; g_object_get (row, "importance", &importance, "title", &title, NULL); if (importance <= BZ_IMPORTANCE_UNIMPORTANT || title == NULL) continue; n_total++; if (n_picked < 2) { if (n_picked > 0) g_string_append (result, ", "); g_string_append (result, title); n_picked++; } } if (n_picked == 0) return g_strdup (_ ("No special permissions")); if (n_total > 2) g_string_append (result, ", …"); return g_string_free (g_steal_pointer (&result), FALSE); } static char * get_safety_icon_name (gpointer object, BzEntry *entry) { BzImportance importance; if (entry == NULL) return g_strdup ("app-safety-unknown-symbolic"); importance = bz_safety_calculator_calculate_rating (entry); switch (importance) { case BZ_IMPORTANCE_UNIMPORTANT: case BZ_IMPORTANCE_NEUTRAL: case BZ_IMPORTANCE_INFORMATION: return g_strdup ("app-safety-ok-symbolic"); case BZ_IMPORTANCE_WARNING: return g_strdup ("permissions-warning-symbolic"); case BZ_IMPORTANCE_IMPORTANT: return g_strdup ("app-safety-unsafe-symbolic"); default: return g_strdup ("app-safety-unknown-symbolic"); } } static char * format_url (gpointer object, const char *url) { g_autoptr (GUri) uri = NULL; const char *host = NULL; if (url == NULL || (uri = g_uri_parse (url, G_URI_FLAGS_NONE, NULL)) == NULL || (host = g_uri_get_host (uri)) == NULL) return g_strdup (url); return g_strdup (host); } static GtkAlign get_header_halign (gpointer object, BzFlatpakRepo *runtime_repo) { return runtime_repo != NULL ? GTK_ALIGN_FILL : GTK_ALIGN_CENTER; } static GtkOrientation get_header_orientation (gpointer object, BzFlatpakRepo *runtime_repo) { return runtime_repo != NULL ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; } static void install_cb (BzBundleInstallDialog *self, GtkButton *button) { if (self->entry == NULL || self->state == NULL) return; adw_carousel_scroll_to (self->carousel, self->page_progress, TRUE); self->pulse_source_id = g_timeout_add (80, pulse_progress_bar, self); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) install_fiber, bz_track_weak (self), bz_weak_release)); } static void run_cb (BzBundleInstallDialog *self, GtkButton *button) { const char *id = NULL; if (self->entry == NULL) return; id = bz_entry_get_id (self->entry); gtk_widget_activate_action (GTK_WIDGET (self), "window.launch-group", "s", id); } static void show_cb (BzBundleInstallDialog *self, GtkButton *button) { const char *id = NULL; if (self->entry == NULL) return; id = bz_entry_get_id (self->entry); adw_dialog_close (ADW_DIALOG (gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_DIALOG))); gtk_widget_activate_action (GTK_WIDGET (self), "window.show-group", "s", id); } static void permission_cb (AdwActionRow *row, BzBundleInstallDialog *self) { AdwNavigationPage *page = NULL; if (self->entry == NULL) return; page = bz_safety_dialog_page_new (self->entry); adw_navigation_view_push (self->nav_view, page); } static void repo_cb (AdwActionRow *row, BzBundleInstallDialog *self) { if (self->runtime_repo != NULL) gtk_uri_launcher_launch ( gtk_uri_launcher_new (bz_flatpak_repo_get_homepage (self->runtime_repo)), NULL, NULL, NULL, NULL); } static void bz_bundle_install_dialog_class_init (BzBundleInstallDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_bundle_install_dialog_set_property; object_class->get_property = bz_bundle_install_dialog_get_property; object_class->dispose = bz_bundle_install_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); 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_RUNTIME_REPO] = g_param_spec_object ( "runtime-repo", NULL, NULL, BZ_TYPE_FLATPAK_REPO, 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-bundle-install-dialog.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); bz_widget_class_bind_all_context_tile_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzBundleInstallDialog, nav_view); gtk_widget_class_bind_template_child (widget_class, BzBundleInstallDialog, main_stack); gtk_widget_class_bind_template_child (widget_class, BzBundleInstallDialog, carousel); gtk_widget_class_bind_template_child (widget_class, BzBundleInstallDialog, page_info); gtk_widget_class_bind_template_child (widget_class, BzBundleInstallDialog, page_progress); gtk_widget_class_bind_template_child (widget_class, BzBundleInstallDialog, page_finish); gtk_widget_class_bind_template_child (widget_class, BzBundleInstallDialog, progress_bar); gtk_widget_class_bind_template_child (widget_class, BzBundleInstallDialog, error_status); gtk_widget_class_bind_template_child (widget_class, BzBundleInstallDialog, safety_icon); gtk_widget_class_bind_template_child (widget_class, BzBundleInstallDialog, bundle_image); gtk_widget_class_bind_template_callback (widget_class, install_cb); gtk_widget_class_bind_template_callback (widget_class, run_cb); gtk_widget_class_bind_template_callback (widget_class, show_cb); gtk_widget_class_bind_template_callback (widget_class, repo_cb); gtk_widget_class_bind_template_callback (widget_class, permission_cb); gtk_widget_class_bind_template_callback (widget_class, get_version); gtk_widget_class_bind_template_callback (widget_class, get_disk_title); gtk_widget_class_bind_template_callback (widget_class, get_safety_subtitle); gtk_widget_class_bind_template_callback (widget_class, get_safety_icon_name); gtk_widget_class_bind_template_callback (widget_class, format_url); gtk_widget_class_bind_template_callback (widget_class, get_header_halign); gtk_widget_class_bind_template_callback (widget_class, get_header_orientation); } static void bz_bundle_install_dialog_init (BzBundleInstallDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } static void bz_bundle_install_dialog_update_visible_page (BzBundleInstallDialog *self) { if (self->entry == NULL) return; if (bz_entry_is_installed (self->entry)) gtk_stack_set_visible_child_name (self->main_stack, "installed"); else gtk_stack_set_visible_child_name (self->main_stack, "carousel"); } BzBundleInstallDialog * bz_bundle_install_dialog_new (void) { return g_object_new (BZ_TYPE_BUNDLE_INSTALL_DIALOG, NULL); } BzStateInfo * bz_bundle_install_dialog_get_state (BzBundleInstallDialog *self) { g_return_val_if_fail (BZ_IS_BUNDLE_INSTALL_DIALOG (self), NULL); return self->state; } BzEntry * bz_bundle_install_dialog_get_entry (BzBundleInstallDialog *self) { g_return_val_if_fail (BZ_IS_BUNDLE_INSTALL_DIALOG (self), NULL); return self->entry; } BzFlatpakRepo * bz_bundle_install_dialog_get_runtime_repo (BzBundleInstallDialog *self) { g_return_val_if_fail (BZ_IS_BUNDLE_INSTALL_DIALOG (self), NULL); return self->runtime_repo; } void bz_bundle_install_dialog_set_state (BzBundleInstallDialog *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_BUNDLE_INSTALL_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]); } void bz_bundle_install_dialog_set_entry (BzBundleInstallDialog *self, BzEntry *entry) { BzImportance importance = 0; const char *style = NULL; g_return_if_fail (BZ_IS_BUNDLE_INSTALL_DIALOG (self)); g_return_if_fail (entry == NULL || BZ_IS_ENTRY (entry)); if (entry == self->entry) return; g_clear_pointer (&self->entry, g_object_unref); if (entry != NULL) self->entry = g_object_ref (entry); bz_bundle_install_dialog_update_visible_page (self); if (self->entry != NULL) { importance = bz_safety_calculator_calculate_rating (self->entry); style = bz_safety_style_for_importance (importance); gtk_widget_add_css_class (GTK_WIDGET (self->safety_icon), style); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ENTRY]); } void bz_bundle_install_dialog_set_runtime_repo (BzBundleInstallDialog *self, BzFlatpakRepo *runtime_repo) { g_return_if_fail (BZ_IS_BUNDLE_INSTALL_DIALOG (self)); g_return_if_fail (runtime_repo == NULL || BZ_IS_FLATPAK_REPO (runtime_repo)); if (runtime_repo == self->runtime_repo) return; g_set_object (&self->runtime_repo, runtime_repo); if (self->bundle_image != NULL) { const char *icon_url = NULL; icon_url = runtime_repo != NULL ? bz_flatpak_repo_get_icon (runtime_repo) : NULL; if (icon_url != NULL) { g_autoptr (BzAsyncTexture) async_tex = NULL; async_tex = bz_async_texture_new (g_file_new_for_uri (icon_url), NULL); gtk_image_set_from_paintable (self->bundle_image, GDK_PAINTABLE (async_tex)); } else gtk_image_set_from_icon_name (self->bundle_image, "application-x-executable"); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_RUNTIME_REPO]); } static DexFuture * install_fiber (GWeakRef *wr) { g_autoptr (BzBundleInstallDialog) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (BzTransaction) transaction = NULL; g_autoptr (BzTransactionManager) ts_manager = NULL; gboolean success = FALSE; g_autofree char *error_message = NULL; bz_weak_get_or_return_reject (self, wr); if (self->entry == NULL || self->state == NULL) return dex_future_new_false (); transaction = bz_transaction_new_full ( &self->entry, 1, NULL, 0, NULL, 0); ts_manager = g_object_ref (bz_state_info_get_transaction_manager (self->state)); dex_await ( bz_transaction_manager_add ( ts_manager, transaction), &local_error); g_object_get (transaction, "success", &success, "error", &error_message, NULL); g_clear_handle_id (&self->pulse_source_id, g_source_remove); if (local_error != NULL || !success) { const char *description = local_error != NULL ? local_error->message : error_message; adw_status_page_set_description (self->error_status, description); gtk_stack_set_visible_child_name (self->main_stack, "error"); } else adw_carousel_scroll_to (self->carousel, self->page_finish, TRUE); return dex_future_new_true (); } /* End of bz-bundle-install-dialog.c */ bazaar-org-bazaar-43ce9f7/src/bz-bundle-install-dialog.h000066400000000000000000000035561520414637400231650ustar00rootroot00000000000000/* bz-bundle-install-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-entry.h" #include "bz-flatpak-repo.h" #include "bz-state-info.h" #include G_BEGIN_DECLS #define BZ_TYPE_BUNDLE_INSTALL_DIALOG (bz_bundle_install_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzBundleInstallDialog, bz_bundle_install_dialog, BZ, BUNDLE_INSTALL_DIALOG, AdwBreakpointBin) BzBundleInstallDialog * bz_bundle_install_dialog_new (void); BzStateInfo * bz_bundle_install_dialog_get_state (BzBundleInstallDialog *self); BzEntry * bz_bundle_install_dialog_get_entry (BzBundleInstallDialog *self); BzFlatpakRepo * bz_bundle_install_dialog_get_runtime_repo (BzBundleInstallDialog *self); void bz_bundle_install_dialog_set_state (BzBundleInstallDialog *self, BzStateInfo *state); void bz_bundle_install_dialog_set_entry (BzBundleInstallDialog *self, BzEntry *entry); void bz_bundle_install_dialog_set_runtime_repo (BzBundleInstallDialog *self, BzFlatpakRepo *runtime_repo); G_END_DECLS /* End of bz-bundle-install-dialog.h */ bazaar-org-bazaar-43ce9f7/src/bz-category-flags.c000066400000000000000000000123561520414637400217130ustar00rootroot00000000000000/* bz-category-flags.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 "bz-category-flags.h" static const struct { const char *name; BzCategoryFlags flag; } name_flag_map[] = { { "audiovideo", BZ_CATEGORY_FLAGS_AUDIOVIDEO }, { "development", BZ_CATEGORY_FLAGS_DEVELOPMENT }, { "education", BZ_CATEGORY_FLAGS_EDUCATION }, { "game", BZ_CATEGORY_FLAGS_GAME }, { "graphics", BZ_CATEGORY_FLAGS_GRAPHICS }, { "network", BZ_CATEGORY_FLAGS_NETWORK }, { "office", BZ_CATEGORY_FLAGS_OFFICE }, { "science", BZ_CATEGORY_FLAGS_SCIENCE }, { "system", BZ_CATEGORY_FLAGS_SYSTEM }, { "utility", BZ_CATEGORY_FLAGS_UTILITY }, { "trending", BZ_CATEGORY_FLAGS_TRENDING }, { "popular", BZ_CATEGORY_FLAGS_POPULAR }, { "recently-added", BZ_CATEGORY_FLAGS_RECENTLY_ADDED }, { "recently-updated", BZ_CATEGORY_FLAGS_RECENTLY_UPDATED }, { "mobile", BZ_CATEGORY_FLAGS_MOBILE }, { "adwaita", BZ_CATEGORY_FLAGS_ADWAITA }, { "kde", BZ_CATEGORY_FLAGS_KDE }, }; GType bz_category_flags_get_type (void) { static gsize g_define_type_id = 0; if (g_once_init_enter (&g_define_type_id)) { static const GFlagsValue values[] = { { BZ_CATEGORY_FLAGS_NONE, "BZ_CATEGORY_FLAGS_NONE", "none" }, { BZ_CATEGORY_FLAGS_AUDIOVIDEO, "BZ_CATEGORY_FLAGS_AUDIOVIDEO", "audiovideo" }, { BZ_CATEGORY_FLAGS_DEVELOPMENT, "BZ_CATEGORY_FLAGS_DEVELOPMENT", "development" }, { BZ_CATEGORY_FLAGS_EDUCATION, "BZ_CATEGORY_FLAGS_EDUCATION", "education" }, { BZ_CATEGORY_FLAGS_GAME, "BZ_CATEGORY_FLAGS_GAME", "game" }, { BZ_CATEGORY_FLAGS_GRAPHICS, "BZ_CATEGORY_FLAGS_GRAPHICS", "graphics" }, { BZ_CATEGORY_FLAGS_NETWORK, "BZ_CATEGORY_FLAGS_NETWORK", "network" }, { BZ_CATEGORY_FLAGS_OFFICE, "BZ_CATEGORY_FLAGS_OFFICE", "office" }, { BZ_CATEGORY_FLAGS_SCIENCE, "BZ_CATEGORY_FLAGS_SCIENCE", "science" }, { BZ_CATEGORY_FLAGS_SYSTEM, "BZ_CATEGORY_FLAGS_SYSTEM", "system" }, { BZ_CATEGORY_FLAGS_UTILITY, "BZ_CATEGORY_FLAGS_UTILITY", "utility" }, { BZ_CATEGORY_FLAGS_TRENDING, "BZ_CATEGORY_FLAGS_TRENDING", "trending" }, { BZ_CATEGORY_FLAGS_POPULAR, "BZ_CATEGORY_FLAGS_POPULAR", "popular" }, { BZ_CATEGORY_FLAGS_RECENTLY_ADDED, "BZ_CATEGORY_FLAGS_RECENTLY_ADDED", "recently-added" }, { BZ_CATEGORY_FLAGS_RECENTLY_UPDATED, "BZ_CATEGORY_FLAGS_RECENTLY_UPDATED", "recently-updated" }, { BZ_CATEGORY_FLAGS_MOBILE, "BZ_CATEGORY_FLAGS_MOBILE", "mobile" }, { BZ_CATEGORY_FLAGS_ADWAITA, "BZ_CATEGORY_FLAGS_ADWAITA", "adwaita" }, { BZ_CATEGORY_FLAGS_KDE, "BZ_CATEGORY_FLAGS_KDE", "kde" }, { 0, NULL, NULL } }; GType type = g_flags_register_static ("BzCategoryFlags", values); g_once_init_leave (&g_define_type_id, type); } return g_define_type_id; } BzCategoryFlags bz_category_flags_add (BzCategoryFlags flags, const char *name) { g_autofree char *lower = NULL; if (name == NULL) return flags; lower = g_ascii_strdown (name, -1); for (gsize i = 0; i < G_N_ELEMENTS (name_flag_map); i++) { if (g_strcmp0 (name_flag_map[i].name, lower) == 0) return flags | name_flag_map[i].flag; } return flags; } gboolean bz_category_flags_has_name (BzCategoryFlags flags, const char *name) { for (gsize i = 0; i < G_N_ELEMENTS (name_flag_map); i++) { if (g_strcmp0 (name_flag_map[i].name, name) == 0) return (flags & name_flag_map[i].flag) != 0; } return FALSE; } BzCategoryFlags bz_category_flags_from_name (const char *name) { g_autofree char *lower = g_ascii_strdown (name, -1); for (gsize i = 0; i < G_N_ELEMENTS (name_flag_map); i++) if (g_strcmp0 (name_flag_map[i].name, lower) == 0) return name_flag_map[i].flag; return BZ_CATEGORY_FLAGS_NONE; } bazaar-org-bazaar-43ce9f7/src/bz-category-flags.h000066400000000000000000000040721520414637400217140ustar00rootroot00000000000000/* bz-category-flags.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 #define BZ_TYPE_CATEGORY_FLAGS (bz_category_flags_get_type ()) typedef enum { BZ_CATEGORY_FLAGS_NONE = 0, BZ_CATEGORY_FLAGS_AUDIOVIDEO = 1 << 0, BZ_CATEGORY_FLAGS_DEVELOPMENT = 1 << 1, BZ_CATEGORY_FLAGS_EDUCATION = 1 << 2, BZ_CATEGORY_FLAGS_GAME = 1 << 3, BZ_CATEGORY_FLAGS_GRAPHICS = 1 << 4, BZ_CATEGORY_FLAGS_NETWORK = 1 << 5, BZ_CATEGORY_FLAGS_OFFICE = 1 << 6, BZ_CATEGORY_FLAGS_SCIENCE = 1 << 7, BZ_CATEGORY_FLAGS_SYSTEM = 1 << 8, BZ_CATEGORY_FLAGS_UTILITY = 1 << 9, BZ_CATEGORY_FLAGS_TRENDING = 1 << 10, BZ_CATEGORY_FLAGS_POPULAR = 1 << 11, BZ_CATEGORY_FLAGS_RECENTLY_ADDED = 1 << 12, BZ_CATEGORY_FLAGS_RECENTLY_UPDATED = 1 << 13, BZ_CATEGORY_FLAGS_MOBILE = 1 << 14, BZ_CATEGORY_FLAGS_ADWAITA = 1 << 15, BZ_CATEGORY_FLAGS_KDE = 1 << 16, } BzCategoryFlags; GType bz_category_flags_get_type (void); BzCategoryFlags bz_category_flags_add (BzCategoryFlags flags, const char *name); gboolean bz_category_flags_has_name (BzCategoryFlags flags, const char *name); BzCategoryFlags bz_category_flags_from_name (const char *name); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-category-tile.blp000066400000000000000000000014331520414637400221010ustar00rootroot00000000000000using 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; wrap: true; wrap-mode: word_char; } }; } bazaar-org-bazaar-43ce9f7/src/bz-category-tile.c000066400000000000000000000107531520414637400215530ustar00rootroot00000000000000/* 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]); }bazaar-org-bazaar-43ce9f7/src/bz-category-tile.h000066400000000000000000000023561520414637400215600ustar00rootroot00000000000000/* 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_DECLSbazaar-org-bazaar-43ce9f7/src/bz-comet.txt000066400000000000000000000007001520414637400204760ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-content-provider.c000066400000000000000000000444771520414637400223170ustar00rootroot00000000000000/* 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; } bazaar-org-bazaar-43ce9f7/src/bz-content-provider.h000066400000000000000000000030101520414637400222760ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-context-row.c000066400000000000000000000054221520414637400212710ustar00rootroot00000000000000/* 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; } bazaar-org-bazaar-43ce9f7/src/bz-context-row.h000066400000000000000000000025271520414637400213010ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-context-tile-callbacks.c000066400000000000000000000275161520414637400233440ustar00rootroot00000000000000/* bz-context-tile-callbacks.c * * Copyright 2026 Eva M, 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-context-tile-callbacks.h" #include "bz-entry.h" #include "bz-safety-calculator.h" #include "bz-spdx.h" static char * format_with_small_suffix (char *number, const char *suffix) { char *dot = g_strrstr (number, "."); if (dot != NULL) { char *end = dot; while (*(end + 1) != '\0') end++; while (end > dot && *end == '0') *end-- = '\0'; if (end == dot) *dot = '\0'; } return g_strdup_printf ("%s\xC2\xA0%s", number, suffix); } 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 month"), 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, gboolean runtime_installed, guint64 runtime_size) { if (is_installable && !runtime_installed && runtime_size > 0) { g_autofree char *size_str = g_format_size (runtime_size); return g_strdup_printf (_ ("+%s runtime"), size_str); } 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 (license == NULL || *license == '\0') return g_strdup (_ ("Unknown")); if (bz_spdx_is_proprietary (license)) return g_strdup (_ ("Proprietary")); 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 * 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; } const char * bz_safety_style_for_importance (BzImportance importance) { switch (importance) { case BZ_IMPORTANCE_UNIMPORTANT: case BZ_IMPORTANCE_NEUTRAL: return "grey"; case BZ_IMPORTANCE_INFORMATION: return "warning"; case BZ_IMPORTANCE_WARNING: return "orange"; case BZ_IMPORTANCE_IMPORTANT: return "error"; default: return "grey"; } } static char * get_safety_rating_style (gpointer object, BzEntry *entry) { if (entry == NULL) return g_strdup ("grey"); return g_strdup (bz_safety_style_for_importance ( bz_safety_calculator_calculate_rating (entry))); } 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")); } } void bz_widget_class_bind_all_context_tile_callbacks (GtkWidgetClass *widget_class) { g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class)); 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, get_size_type); gtk_widget_class_bind_template_callback (widget_class, format_size_tooltip); 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_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); } bazaar-org-bazaar-43ce9f7/src/bz-context-tile-callbacks.h000066400000000000000000000017561520414637400233470ustar00rootroot00000000000000/* bz-context-tile-callbacks.h * * Copyright 2026 Eva M, 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-safety-calculator.h" void bz_widget_class_bind_all_context_tile_callbacks (GtkWidgetClass *widget_class); const char * bz_safety_style_for_importance (BzImportance importance); bazaar-org-bazaar-43ce9f7/src/bz-context-tile.blp000066400000000000000000000013001520414637400217410ustar00rootroot00000000000000using Gtk 4.0; template $BzContextTile: Button { styles [ "context-tile", "flat", ] focusable: false; halign: center; 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; }; accessibility { described-by: label; } } Label label { styles [ "context-tile-text", ] justify: center; wrap: true; wrap-mode: word_char; xalign: 0.5; } } } bazaar-org-bazaar-43ce9f7/src/bz-context-tile.c000066400000000000000000000167521520414637400214270ustar00rootroot00000000000000/* 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]); } bazaar-org-bazaar-43ce9f7/src/bz-context-tile.h000066400000000000000000000031121520414637400214160ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-country-data-point.txt000066400000000000000000000002571520414637400231370ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-country.txt000066400000000000000000000004341520414637400210760ustar00rootroot00000000000000prefix=bz name=country parent-prefix=g parent-name=object author=AUTOGEN property=name char G_TYPE_STRING string property=iso_code char G_TYPE_STRING string property=coordinates GVariant G_TYPE_VARIANT variant g_variant_unref g_variant_ref property=value double G_TYPE_DOUBLE double bazaar-org-bazaar-43ce9f7/src/bz-curated-app-tile.blp000066400000000000000000000002461520414637400224720ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzCuratedAppTile: Adw.Bin { child: $BzAppTile { group: bind template.group; clicked => $clicked_cb(template); }; } bazaar-org-bazaar-43ce9f7/src/bz-curated-app-tile.c000066400000000000000000000110421520414637400221330ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-curated-app-tile.h000066400000000000000000000024141520414637400221430ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-curated-category-info.txt000066400000000000000000000014011520414637400235610ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-curated-image-info.txt000066400000000000000000000006311520414637400230320ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-curated-markdown-info.txt000066400000000000000000000002021520414637400235640ustar00rootroot00000000000000prefix=bz name=curated_markdown_info parent-prefix=g parent-name=object author=AUTOGEN property=string char G_TYPE_STRING string bazaar-org-bazaar-43ce9f7/src/bz-curated-row.txt000066400000000000000000000002441520414637400216260ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-curated-section.txt000066400000000000000000000013611520414637400224640ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-curated-view.blp000066400000000000000000000035261520414637400217350ustar00rootroot00000000000000using 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; }; } }; }; }; }; } }; } bazaar-org-bazaar-43ce9f7/src/bz-curated-view.c000066400000000000000000000210311520414637400213710ustar00rootroot00000000000000/* 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-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_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_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); 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); } bazaar-org-bazaar-43ce9f7/src/bz-curated-view.h000066400000000000000000000023201520414637400213760ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-data-graph.c000066400000000000000000001175631520414637400210220ustar00rootroot00000000000000/* 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 *other; GskRenderNode *graph; GskRenderNode *overlay; 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; int allocated_width; int allocated_height; }; 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 refresh_graph (BzDataGraph *self); static void refresh_overlay (BzDataGraph *self); 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->other, gsk_render_node_unref); g_clear_pointer (&self->graph, gsk_render_node_unref); g_clear_pointer (&self->overlay, 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); GtkRequisition natural_size = { 0 }; graphene_point_t card_position = { 0 }; if (width != self->allocated_width || height != self->allocated_height) { refresh_path ( self, (double) width - LABEL_MARGIN - LABEL_MARGIN_RIGHT, (double) height - LABEL_MARGIN); refresh_graph (self); refresh_overlay (self); self->allocated_width = width; self->allocated_height = height; } gtk_widget_get_preferred_size (self->tooltip_box, NULL, &natural_size); if (self->motion_x > width / 2.0) card_position.x = self->motion_x - natural_size.width - 10.0; else card_position.x = self->motion_x + 10.0; card_position.y = self->motion_y + 10.0; gtk_widget_allocate ( self->tooltip_box, natural_size.width, natural_size.height, baseline, gsk_transform_translate (NULL, &card_position)); gtk_widget_queue_draw (widget); } static void on_style_changed (BzDataGraph *self, GParamSpec *pspec, AdwStyleManager *style_manager) { refresh_graph (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void bz_data_graph_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzDataGraph *self = BZ_DATA_GRAPH (widget); if (self->path == NULL) return; if (self->graph != NULL) gtk_snapshot_append_node (snapshot, self->graph); if (self->other != NULL) { GdkRGBA widget_color = { 0 }; gtk_widget_get_color (widget, &widget_color); if (self->other != NULL) { graphene_rect_t bounds = { 0 }; gsk_render_node_get_bounds (self->other, &bounds); gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_ALPHA); gtk_snapshot_append_node (snapshot, self->other); gtk_snapshot_pop (snapshot); gtk_snapshot_append_color (snapshot, &widget_color, &bounds); gtk_snapshot_pop (snapshot); } } if (self->overlay != NULL) { gtk_snapshot_append_node (snapshot, self->overlay); /* tooltip card */ gtk_widget_snapshot_child (GTK_WIDGET (self), self->tooltip_box, 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); refresh_overlay (self); gtk_widget_queue_allocate (GTK_WIDGET (self)); } 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); } 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); } static void motion_leave (BzDataGraph *self, GtkEventControllerMotion *controller) { self->motion_x = -1.0; self->motion_y = -1.0; update_cursor (self, -1.0, -1.0); } 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); self->allocated_width = -1; self->allocated_height = -1; 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; refresh_graph (self); 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->other, 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 (); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (LABEL_MARGIN, 0.0)); 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 }); gtk_snapshot_restore (snapshot); self->path = gsk_path_builder_to_path (curve_builder); self->path_measure = gsk_path_measure_new (self->path); self->other = gtk_snapshot_to_node (snapshot); } static void refresh_graph (BzDataGraph *self) { 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; g_autoptr (GtkSnapshot) snapshot = NULL; if (self->path == NULL) { g_clear_pointer (&self->graph, gsk_render_node_unref); return; } widget_width = gtk_widget_get_width (GTK_WIDGET (self)); (void) widget_width; widget_height = gtk_widget_get_height (GTK_WIDGET (self)); style_manager = adw_style_manager_get_default (); accent_color = adw_style_manager_get_accent_color_rgba (style_manager); gtk_widget_get_color (GTK_WIDGET (self), &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); snapshot = gtk_snapshot_new (); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (LABEL_MARGIN, 0.0)); if (self->transition_progress > 0.0) { g_autoptr (GskPathBuilder) builder = NULL; GskPathPoint point0 = { 0 }; GskPathPoint point1 = { 0 }; graphene_point_t start_position = { 0 }; graphene_point_t end_position = { 0 }; g_autoptr (GskPath) path = NULL; const GskColorStop gradient_stops[] = { { 0.0, { .red = accent_color->red, .green = accent_color->green, .blue = accent_color->blue, .alpha = 0.75, }, }, { 1.0, { .red = accent_color->red, .green = accent_color->green, .blue = accent_color->blue, .alpha = 0.0, }, }, }; const GskColorStop hfadeout_mask_stops[] = { { 0.0, { .red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0, }, }, { 0.75, { .red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0, }, }, { 1.0, { .red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 0.0, }, }, }; gtk_snapshot_append_stroke ( snapshot, transitioning != NULL ? transitioning : self->path, stroke, accent_color); /* Gradient under the graph line */ builder = gsk_path_builder_new (); gsk_path_get_start_point ( transitioning != NULL ? transitioning : self->path, &point0); gsk_path_point_get_position ( &point0, transitioning != NULL ? transitioning : self->path, &start_position); gsk_path_get_end_point ( transitioning != NULL ? transitioning : self->path, &point1); gsk_path_point_get_position ( &point1, transitioning != NULL ? transitioning : self->path, &end_position); gsk_path_builder_move_to (builder, start_position.x, start_position.y); gsk_path_builder_add_segment ( builder, transitioning != NULL ? transitioning : self->path, &point0, &point1); gsk_path_builder_move_to (builder, end_position.x, end_position.y); /* close the loop for `gtk_snapshot_push_fill` */ gsk_path_builder_line_to (builder, end_position.x, widget_height - LABEL_MARGIN); gsk_path_builder_line_to (builder, start_position.x, widget_height - LABEL_MARGIN); gsk_path_builder_line_to (builder, start_position.x, start_position.y); path = gsk_path_builder_to_path (builder); gtk_snapshot_push_fill ( snapshot, path, GSK_FILL_RULE_WINDING); gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_ALPHA); gtk_snapshot_append_linear_gradient ( snapshot, &GRAPHENE_RECT_INIT ( 0.0, 0.0, end_position.x, widget_height - LABEL_MARGIN), &GRAPHENE_POINT_INIT (0.0, 0.0), &GRAPHENE_POINT_INIT (end_position.x, 0.0), hfadeout_mask_stops, G_N_ELEMENTS (hfadeout_mask_stops)); gtk_snapshot_pop (snapshot); /* Push Mask (mask) */ gtk_snapshot_append_linear_gradient ( snapshot, &GRAPHENE_RECT_INIT ( 0.0, 0.0, end_position.x, widget_height - LABEL_MARGIN), &GRAPHENE_POINT_INIT (0.0, 0.0), &GRAPHENE_POINT_INIT (0.0, widget_height - LABEL_MARGIN), gradient_stops, G_N_ELEMENTS (gradient_stops)); gtk_snapshot_pop (snapshot); /* Push Mask (image) */ gtk_snapshot_pop (snapshot); /* Push Fill */ } gtk_snapshot_restore (snapshot); g_clear_pointer (&self->graph, gsk_render_node_unref); self->graph = gtk_snapshot_to_node (snapshot); } static void refresh_overlay (BzDataGraph *self) { double widget_width = 0.0; double widget_height = 0.0; GdkRGBA widget_color = { 0 }; AdwStyleManager *style_manager = NULL; g_autoptr (GdkRGBA) accent_color = NULL; 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 rounded_axis_max = 0.0; const char *prefix = NULL; g_autofree char *line2_text = NULL; g_autoptr (GtkSnapshot) snapshot = NULL; if (self->path == NULL) { g_clear_pointer (&self->overlay, gsk_render_node_unref); return; } widget_width = gtk_widget_get_width (GTK_WIDGET (self)); widget_height = gtk_widget_get_height (GTK_WIDGET (self)); 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) { g_clear_pointer (&self->overlay, gsk_render_node_unref); return; } gtk_widget_get_color (GTK_WIDGET (self), &widget_color); style_manager = adw_style_manager_get_default (); accent_color = adw_style_manager_get_accent_color_rgba (style_manager); 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); } snapshot = gtk_snapshot_new (); 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); g_clear_pointer (&self->overlay, gsk_render_node_unref); self->overlay = gtk_snapshot_to_node (snapshot); gtk_label_set_label (GTK_LABEL (self->tooltip_label1), bz_data_point_get_label (point)); prefix = self->tooltip_prefix != NULL ? self->tooltip_prefix : ""; gtk_label_set_label (GTK_LABEL (self->tooltip_prefix_label), prefix); line2_text = g_strdup_printf ("%'.0f", bz_data_point_get_dependent (point)); gtk_label_set_label (GTK_LABEL (self->tooltip_label2), line2_text); } bazaar-org-bazaar-43ce9f7/src/bz-data-graph.h000066400000000000000000000046131520414637400210160ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-data-point.txt000066400000000000000000000003261520414637400214330ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-decorated-screenshot.blp000066400000000000000000000004171520414637400234370ustar00rootroot00000000000000using 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; }; }bazaar-org-bazaar-43ce9f7/src/bz-decorated-screenshot.c000066400000000000000000000116661520414637400231140ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-decorated-screenshot.h000066400000000000000000000025611520414637400231130ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-developer-badge.blp000066400000000000000000000030671520414637400223630ustar00rootroot00000000000000using 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_link(template.entry, template.entry as <$BzEntry>.verification-status) as ; use-markup: true; xalign: 0.0; wrap: true; lines: 3; ellipsize: end; 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", ] has-tooltip: true; tooltip-text: bind $get_verified_tooltip(template.entry as <$BzEntry>.verification-status) as ; 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; activate-link => $on_popover_label_activate_link(); } }; } bazaar-org-bazaar-43ce9f7/src/bz-developer-badge.c000066400000000000000000000320101520414637400220160ustar00rootroot00000000000000/* 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 * get_verified_tooltip (gpointer object, GObject *status) { gboolean verified = FALSE; if (status == NULL) return g_strdup (_ ("Not Verified")); g_object_get (status, "verified", &verified, NULL); return g_strdup (verified ? _ ("Verified") : _ ("Not Verified")); } 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, 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 * format_provider_url (const char *login_provider, const char *login_name) { if (g_strcmp0 (login_provider, "github") == 0) return g_strdup_printf ("https://github.com/%s", login_name); else if (g_strcmp0 (login_provider, "gitlab") == 0) return g_strdup_printf ("https://gitlab.com/%s", login_name); else if (g_strcmp0 (login_provider, "gnome") == 0) return g_strdup_printf ("https://gitlab.gnome.org/%s", login_name); else if (g_strcmp0 (login_provider, "kde") == 0) return g_strdup_printf ("https://invent.kde.org/%s", login_name); else return NULL; } static char * get_developer_link (gpointer object, BzEntry *entry, BzVerificationStatus *status) { const char *dev = NULL; const char *method = NULL; const char *login_name = NULL; const char *login_provider = NULL; const char *website = NULL; gboolean verified = FALSE; g_autofree char *escaped_dev = NULL; if (entry == NULL || !BZ_IS_ENTRY (entry)) return NULL; dev = bz_entry_get_developer (entry); if (dev == NULL) return NULL; escaped_dev = g_markup_escape_text (dev, -1); if (status == NULL) return g_steal_pointer (&escaped_dev); g_object_get (status, "verified", &verified, "method", &method, "login-name", &login_name, "login-provider", &login_provider, "website", &website, NULL); if (!verified) return g_steal_pointer (&escaped_dev); if (g_strcmp0 (method, "login_provider") == 0 && login_name != NULL && login_provider != NULL) { g_autofree char *url = NULL; url = format_provider_url (login_provider, login_name); if (url != NULL) return g_strdup_printf ("%s", url, url, escaped_dev); } if (g_strcmp0 (method, "website") == 0 && website != NULL && *website != '\0') return g_strdup_printf ("%s", website, website, escaped_dev); return g_steal_pointer (&escaped_dev); } 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) { g_autofree char *url = NULL; g_autofree char *linked_name = NULL; provider_name = format_provider_name (login_provider); url = format_provider_url (login_provider, login_name); if (url != NULL) linked_name = g_strdup_printf ("%s", url, url, login_name); else linked_name = g_strdup (login_name); return g_strdup_printf (_ ("The ownership of the %1$s app ID has been verified by %2$s on %3$s."), formatted_app_id, linked_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 gboolean on_popover_label_activate_link (GtkLabel *label, const char *uri, BzDeveloperBadge *self) { gtk_popover_popdown (self->popover); return FALSE; } 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, on_popover_label_activate_link); 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_developer_link); gtk_widget_class_bind_template_callback (widget_class, get_icon_name); gtk_widget_class_bind_template_callback (widget_class, get_verified_tooltip); 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]); } } bazaar-org-bazaar-43ce9f7/src/bz-developer-badge.h000066400000000000000000000023351520414637400220320ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-donations-dialog.blp000066400000000000000000000062431520414637400225700ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzDonationsDialog: Adw.Dialog { width-request: 450; follows-content-size: true; child: Adw.ToolbarView { [top] Adw.HeaderBar { show-title: false; } content: ScrolledWindow { hscrollbar-policy: never; vscrollbar-policy: automatic; propagate-natural-height: true; min-content-height: 500; child: Box { orientation: vertical; Box { orientation: vertical; margin-start: 40; margin-end: 40; margin-top: 20; margin-bottom: 20; Label title { styles [ "title-1", ] wrap: true; justify: center; margin-bottom: 5; } Label subtitle { styles [ "dimmed", ] wrap: true; justify: center; margin-bottom: 15; } $BzAppstreamDescriptionRender { vexpand: true; appstream-description: bind template.release-notes; } Button release_button { styles [ "pill", ] margin-top: 15; margin-start: 25; margin-end: 20; margin-bottom: 15; halign: center; has-tooltip: true; clicked => $release_page_clicked(template); child: Box { orientation: horizontal; spacing: 10; Label { label: _("Full Release Notes"); wrap: true; wrap-mode: word_char; justify: right; } Image { icon-name: "external-link-symbolic"; } }; } } Adw.Bin { styles [ "bz-donations-dialog", ] child: Box { orientation: vertical; margin-start: 25; margin-end: 25; margin-top: 20; margin-bottom: 20; Label { styles [ "title-1", ] margin-top: 10; margin-bottom: 20; halign: center; wrap: true; justify: center; label: _("This 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. Help support further development by donating on Ko-Fi."); } Button donate_button { styles [ "pill", ] margin-start: 20; margin-end: 20; margin-bottom: 20; halign: center; has-tooltip: true; child: Adw.ButtonContent { label: _("Donate to Bazaar"); icon-name: "heart-filled-symbolic"; }; clicked => $donate_clicked(template); } }; } }; }; }; } bazaar-org-bazaar-43ce9f7/src/bz-donations-dialog.c000066400000000000000000000216011520414637400222300ustar00rootroot00000000000000/* 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 #include "bz-appstream-description-render.h" #include "bz-donations-dialog.h" #include "bz-template-callbacks.h" struct _BzDonationsDialog { AdwDialog parent_instance; char *release_notes; char *release_url; AdwBreakpoint *breakpoint; /* Template widgets */ GtkLabel *title; GtkLabel *subtitle; GtkButton *release_button; GtkButton *donate_button; }; G_DEFINE_FINAL_TYPE (BzDonationsDialog, bz_donations_dialog, ADW_TYPE_DIALOG); enum { PROP_0, PROP_RELEASE_NOTES, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static const char *bz_donations_dialog_get_release_notes (BzDonationsDialog *self); static void bz_donations_dialog_dispose (GObject *object) { BzDonationsDialog *self = BZ_DONATIONS_DIALOG (object); g_clear_pointer (&self->release_notes, g_free); g_clear_pointer (&self->release_url, g_free); g_clear_object (&self->breakpoint); 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_RELEASE_NOTES: g_value_set_string (value, bz_donations_dialog_get_release_notes (self)); 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) { if (self->release_url != NULL) g_app_info_launch_default_for_uri (self->release_url, NULL, NULL); } static void on_map (BzDonationsDialog *self, gpointer user_data) { GtkRoot *root = NULL; root = gtk_widget_get_root (GTK_WIDGET (self)); if (root == NULL || self->breakpoint == NULL) return; adw_application_window_add_breakpoint (ADW_APPLICATION_WINDOW (root), g_object_ref (self->breakpoint)); } 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->get_property = bz_donations_dialog_get_property; object_class->dispose = bz_donations_dialog_dispose; props[PROP_RELEASE_NOTES] = g_param_spec_string ( "release-notes", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); 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_child (widget_class, BzDonationsDialog, subtitle); gtk_widget_class_bind_template_child (widget_class, BzDonationsDialog, release_button); gtk_widget_class_bind_template_child (widget_class, BzDonationsDialog, donate_button); 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_autoptr (GBytes) release_notes_bytes = NULL; g_autoptr (GError) error = NULL; g_autoptr (XbBuilderSource) source = NULL; g_autoptr (XbBuilder) builder = NULL; g_autoptr (XbSilo) silo = NULL; g_autoptr (XbNode) release_node = NULL; g_autoptr (XbNode) url_node = NULL; g_autoptr (XbNode) description_node = NULL; const char *version = NULL; const char *date = NULL; const char *url = NULL; AdwBreakpointCondition *condition = NULL; gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_set_tooltip_text (GTK_WIDGET (self->release_button), RELEASE_PAGE); gtk_widget_set_tooltip_text (GTK_WIDGET (self->donate_button), DONATE_LINK); condition = adw_breakpoint_condition_new_length ( ADW_BREAKPOINT_CONDITION_MAX_WIDTH, 500, ADW_LENGTH_UNIT_PX); self->breakpoint = adw_breakpoint_new (condition); adw_breakpoint_add_setter (self->breakpoint, G_OBJECT (self), "width-request", &(GValue) { G_TYPE_INT, { { .v_int = 350 } } }); g_signal_connect (self, "map", G_CALLBACK (on_map), NULL); release_notes_bytes = g_resources_lookup_data ( "/io/github/kolunmi/Bazaar/release-notes.xml", G_RESOURCE_LOOKUP_FLAGS_NONE, &error); if (release_notes_bytes == NULL) { g_warning ("Failed to load release notes: %s", error->message); return; } source = xb_builder_source_new (); if (!xb_builder_source_load_bytes (source, release_notes_bytes, XB_BUILDER_SOURCE_FLAG_LITERAL_TEXT, &error)) { g_warning ("Failed to load release notes into xmlb: %s", error->message); return; } builder = xb_builder_new (); xb_builder_import_source (builder, source); silo = xb_builder_compile (builder, XB_BUILDER_COMPILE_FLAG_NONE, NULL, &error); if (silo == NULL) { g_warning ("Failed to compile release notes silo: %s", error->message); return; } release_node = xb_silo_query_first (silo, "release", &error); if (release_node == NULL) { g_warning ("Failed to find release node: %s", error != NULL ? error->message : "no error"); g_clear_error (&error); return; } version = xb_node_get_attr (release_node, "version"); date = xb_node_get_attr (release_node, "date"); if (version != NULL) { g_autofree char *title_str = NULL; /* 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 %s?"), version); gtk_label_set_label (self->title, title_str); } if (date != NULL) { g_autofree char *date_full = NULL; g_autoptr (GDateTime) dt = NULL; g_autofree char *subtitle_str = NULL; date_full = g_strdup_printf ("%sT00:00:00Z", date); dt = g_date_time_new_from_iso8601 (date_full, NULL); if (dt != NULL) { /* Translators: this is a release date label, like "Released February 9, 2026" */ subtitle_str = g_date_time_format (dt, _ ("Released %B %-e, %Y")); if (subtitle_str != NULL) gtk_label_set_label (self->subtitle, subtitle_str); } } url_node = xb_silo_query_first (silo, "release/url[@type='details']", &error); if (url_node != NULL) { url = xb_node_get_text (url_node); if (url != NULL) self->release_url = g_strdup (url); } else g_clear_error (&error); description_node = xb_silo_query_first (silo, "release/description", &error); if (description_node != NULL) { self->release_notes = xb_node_export (description_node, XB_NODE_EXPORT_FLAG_INCLUDE_SIBLINGS, &error); if (self->release_notes == NULL) { g_warning ("Failed to export description node: %s", error->message); g_clear_error (&error); } } else { g_warning ("Failed to find description node: %s", error != NULL ? error->message : "no error"); g_clear_error (&error); } if (self->release_notes != NULL) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_RELEASE_NOTES]); } AdwDialog * bz_donations_dialog_new (void) { return g_object_new (BZ_TYPE_DONATIONS_DIALOG, NULL); } static const char * bz_donations_dialog_get_release_notes (BzDonationsDialog *self) { g_return_val_if_fail (BZ_IS_DONATIONS_DIALOG (self), NULL); return self->release_notes; } /* End of bz-donations-dialog.c */ bazaar-org-bazaar-43ce9f7/src/bz-donations-dialog.h000066400000000000000000000021021520414637400222300ustar00rootroot00000000000000/* 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); G_END_DECLS /* End of bz-donations-dialog.h */ bazaar-org-bazaar-43ce9f7/src/bz-download-worker.c000066400000000000000000000407311520414637400221200ustar00rootroot00000000000000/* 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 GMutex default_worker_mutex = { 0 }; static GPtrArray *default_workers = NULL; static guint next_default_worker = 0; 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) { g_autoptr (GMutexLocker) locker = NULL; BzDownloadWorker *ret = NULL; locker = g_mutex_locker_new (&default_worker_mutex); if (default_workers == NULL) { default_workers = g_ptr_array_new_with_free_func (g_object_unref); for (guint i = 0; i < bz_get_n_download_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 (default_workers, g_steal_pointer (&worker)); } } /* Check if any of the subprocesses need to be recreated */ for (guint i = 0; i < default_workers->len; i++) { BzDownloadWorker **loc = NULL; loc = (BzDownloadWorker **) &g_ptr_array_index (default_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 (default_workers, next_default_worker); next_default_worker = (next_default_worker + 1) % default_workers->len; return ret; } void bz_reap_default_download_workers (void) { g_autoptr (GMutexLocker) locker = NULL; locker = g_mutex_locker_new (&default_worker_mutex); if (default_workers == NULL) return; for (guint i = 0; i < default_workers->len; i++) { BzDownloadWorker *worker = NULL; worker = g_ptr_array_index (default_workers, i); g_subprocess_force_exit (worker->subprocess); } g_clear_pointer (&default_workers, g_ptr_array_unref); next_default_worker = 0; } 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 */ bazaar-org-bazaar-43ce9f7/src/bz-download-worker.h000066400000000000000000000030461520414637400221230ustar00rootroot00000000000000/* 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); void bz_reap_default_download_workers (void); G_END_DECLS /* End of bz-download-worker.h */ bazaar-org-bazaar-43ce9f7/src/bz-dynamic-list-view.c000066400000000000000000000664311520414637400223540ustar00rootroot00000000000000/* 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, 11, 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, 11, 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 = 11; self->column_spacing = 11; 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 */ bazaar-org-bazaar-43ce9f7/src/bz-dynamic-list-view.h000066400000000000000000000066741520414637400223640ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-entry-cache-manager.c000066400000000000000000000732251520414637400226200ustar00rootroot00000000000000/* 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, { GWeakRef *self; 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 (self, bz_weak_release); 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; GMutex mutex; guint living_entries; 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_LIVING_ENTRIES, 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); static DexFuture * notify_props_fiber (GWeakRef *wr); 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); g_mutex_clear (&self->mutex); 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_LIVING_ENTRIES: g_value_set_uint (value, bz_entry_cache_manager_get_living_entries (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); (void) self; switch (prop_id) { case PROP_LIVING_ENTRIES: 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_LIVING_ENTRIES] = g_param_spec_uint ( "living-entries", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READABLE | 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 ()); g_mutex_init (&self->mutex); self->scheduler = dex_ref (global_scheduler); self->memory_usage = 0; task_data = ongoing_task_data_new (); task_data->self = bz_track_weak (self); 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); } guint bz_entry_cache_manager_get_living_entries (BzEntryCacheManager *self) { g_autoptr (GMutexLocker) locker = NULL; g_return_val_if_fail (BZ_IS_ENTRY_CACHE_MANAGER (self), 0); locker = g_mutex_locker_new (&self->mutex); return self->living_entries; } 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 (BzEntryCacheManager) self = NULL; 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); bz_weak_get_or_return_reject (self, task_data->self); g_mutex_lock (&self->mutex); self->living_entries = active + alive; g_mutex_unlock (&self->mutex); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) notify_props_fiber, bz_track_weak (self), bz_weak_release)); return dex_timeout_new_msec (WATCH_CLEANUP_INTERVAL_MSEC); } static DexFuture * notify_props_fiber (GWeakRef *wr) { g_autoptr (BzEntryCacheManager) self = NULL; bz_weak_get_or_return_reject (self, wr); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LIVING_ENTRIES]); return dex_future_new_true (); } /* End of bz-entry-cache-manager.c */ bazaar-org-bazaar-43ce9f7/src/bz-entry-cache-manager.h000066400000000000000000000036501520414637400226200ustar00rootroot00000000000000/* 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); guint bz_entry_cache_manager_get_living_entries (BzEntryCacheManager *self); 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 */ bazaar-org-bazaar-43ce9f7/src/bz-entry-group-util.c000066400000000000000000000100371520414637400222440ustar00rootroot00000000000000/* 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; } bazaar-org-bazaar-43ce9f7/src/bz-entry-group-util.h000066400000000000000000000021231520414637400222460ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-entry-group.c000066400000000000000000001360471520414637400213030ustar00rootroot00000000000000/* 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-env.h" #include "bz-io.h" #include "bz-size-result.h" #include "bz-util.h" typedef enum { ENTRY_INSTALLABLE = 1 << 0, ENTRY_INSTALLABLE_AVAILABLE = 1 << 1, ENTRY_UPDATABLE = 1 << 2, ENTRY_UPDATABLE_AVAILABLE = 1 << 3, ENTRY_REMOVABLE = 1 << 4, ENTRY_REMOVABLE_AVAILABLE = 1 << 5, } EntryStateFlags; struct _BzEntryGroup { GObject parent_instance; BzApplicationMapFactory *factory; GtkStringList *unique_ids; GtkStringList *installed_versions; GArray *state_flags; char *id; char *title; char *developer; char *description; GIcon *mini_icon; gboolean is_floss; char *light_accent_color; char *dark_accent_color; gboolean is_flathub; gboolean is_verified; char *search_tokens; char *eol; guint64 installed_size; GtkStringList *addon_group_ids; int n_addons; char *donation_url; BzCategoryFlags categories; int content_age_rating; int max_usefulness; int installable; int updatable; int removable; int installable_available; int updatable_available; int removable_available; gboolean read_only; gboolean searchable; gboolean is_addon; guint64 user_data_size; guint64 cache_size; DexFuture *user_data_size_future; DexFuture *reap_user_data_future; DexFuture *reap_cache_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_ADDONS_MODEL, PROP_INSTALLED_VERSIONS, PROP_ID, PROP_TITLE, PROP_DEVELOPER, PROP_DESCRIPTION, 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_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, PROP_CACHE_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); dex_clear (&self->reap_cache_future); g_clear_object (&self->factory); g_clear_object (&self->unique_ids); g_clear_object (&self->installed_versions); g_clear_pointer (&self->state_flags, g_array_unref); 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->mini_icon); g_clear_pointer (&self->search_tokens, g_free); g_clear_pointer (&self->eol, g_free); g_clear_pointer (&self->donation_url, g_free); 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_ADDONS_MODEL: g_value_set_object (value, bz_entry_group_get_addon_group_ids (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_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_uint (value, self->categories); break; case PROP_UI_ENTRY: g_value_take_object (value, bz_entry_group_dup_ui_entry (self)); 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; case PROP_CACHE_SIZE: g_value_set_uint64 (value, bz_entry_group_get_cache_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_ADDONS_MODEL: case PROP_ID: case PROP_TITLE: case PROP_DEVELOPER: case PROP_DESCRIPTION: 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_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: case PROP_CACHE_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_ADDONS_MODEL] = g_param_spec_object ( "addons-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_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_uint ( "categories", NULL, NULL, 0, G_MAXUINT, BZ_CATEGORY_FLAGS_NONE, G_PARAM_READABLE); props[PROP_UI_ENTRY] = g_param_spec_object ( "ui-entry", NULL, NULL, BZ_TYPE_RESULT, 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); props[PROP_CACHE_SIZE] = g_param_spec_uint64 ( "cache-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->state_flags = g_array_new (FALSE, TRUE, sizeof (gint32)); 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; 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; BzCategoryFlags entry_categories = BZ_CATEGORY_FLAGS_NONE; 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); 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_category_flags (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 (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); group->categories = 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; } 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; } GListModel * bz_entry_group_get_addon_group_ids (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); if (self->addon_group_ids == NULL) return NULL; return G_LIST_MODEL (self->addon_group_ids); } void bz_entry_group_append_addon_group_id (BzEntryGroup *self, const char *id) { g_return_if_fail (BZ_IS_ENTRY_GROUP (self)); g_return_if_fail (id != NULL); if (self->addon_group_ids == NULL) self->addon_group_ids = gtk_string_list_new (NULL); if (gtk_string_list_find (self->addon_group_ids, id) != G_MAXUINT) return; gtk_string_list_append (self->addon_group_ids, id); } 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; } gboolean bz_entry_group_has_category (BzEntryGroup *self, const char *name) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), FALSE); return bz_category_flags_has_name (self->categories, name); } BzCategoryFlags bz_entry_group_get_categories (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), BZ_CATEGORY_FLAGS_NONE); return self->categories; } int bz_entry_group_get_content_age_rating (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); return self->content_age_rating; } 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; } guint64 bz_entry_group_get_cache_size (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); check_user_data_size (self); return self->cache_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; } gboolean bz_entry_group_is_addon (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), FALSE); return self->is_addon; } 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; 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; BzCategoryFlags entry_categories = BZ_CATEGORY_FLAGS_NONE; guint existing = 0; gboolean is_searchable = FALSE; AsContentRating *content_rating = NULL; gboolean is_addon = FALSE; gint32 state_flags = 0; 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); is_addon = bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_ADDON); if (is_addon) self->is_addon = TRUE; 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); description = bz_entry_get_description (entry); installed_size = bz_entry_get_installed_size (entry); is_flathub = bz_entry_get_is_flathub (entry); is_floss = bz_entry_get_is_foss (entry); if (is_addon) // You would not see any addon when the filter is on without this. is_verified = TRUE; if (!is_addon) { developer = bz_entry_get_developer (entry); mini_icon = bz_entry_get_mini_icon (entry); search_tokens = bz_entry_get_search_tokens (entry); light_accent_color = bz_entry_get_light_accent_color (entry); dark_accent_color = bz_entry_get_dark_accent_color (entry); is_verified = bz_entry_is_verified (entry); donation_url = bz_entry_get_donation_url (entry); entry_categories = bz_entry_get_category_flags (entry); content_rating = bz_entry_get_content_rating (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 (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]); } if (installed_size != self->installed_size) { self->installed_size = installed_size; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLED_SIZE]); } 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_floss != !!self->is_floss) { self->is_floss = is_floss; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IS_FLOSS]); } if (!!is_verified != !!self->is_verified) { self->is_verified = is_verified; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IS_VERIFIED]); } if (!is_addon) { 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 (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 (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 (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 != BZ_CATEGORY_FLAGS_NONE) { self->categories = entry_categories; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CATEGORIES]); } if (content_rating != NULL) self->content_age_rating = as_content_rating_get_minimum_age (content_rating); } 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 (description != NULL && self->description == NULL) { self->description = g_strdup (description); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DESCRIPTION]); } 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 (!is_addon) { if (developer != NULL && self->developer == NULL) { self->developer = g_strdup (developer); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEVELOPER]); } 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 (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) { gint32 previous_state_flags = 0; /* revert the old state if we are replacing */ previous_state_flags = g_array_index (self->state_flags, gint32, existing); if (previous_state_flags & ENTRY_INSTALLABLE) self->installable--; if (previous_state_flags & ENTRY_INSTALLABLE_AVAILABLE) self->installable_available--; if (previous_state_flags & ENTRY_UPDATABLE) self->updatable--; if (previous_state_flags & ENTRY_UPDATABLE_AVAILABLE) self->updatable_available--; if (previous_state_flags & ENTRY_REMOVABLE) self->removable--; if (previous_state_flags & ENTRY_REMOVABLE_AVAILABLE) self->removable_available--; } if (bz_entry_is_installed (entry)) { self->removable++; state_flags |= ENTRY_REMOVABLE; if (!bz_entry_is_holding (entry)) { self->removable_available++; state_flags |= ENTRY_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 { if (bz_entry_is_reinstallable (entry)) { self->installable++; state_flags |= ENTRY_INSTALLABLE; if (!bz_entry_is_holding (entry)) { self->installable_available++; state_flags |= ENTRY_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 (existing != G_MAXUINT) g_array_index (self->state_flags, gint32, existing) = state_flags; else g_array_append_val (self->state_flags, state_flags); if (!is_addon && is_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 reinstallable = FALSE; const char *unique_id = NULL; const char *version = NULL; guint index = 0; gint32 state_flags = 0; locker = g_mutex_locker_new (&self->mutex); reinstallable = bz_entry_is_reinstallable (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) return; state_flags = g_array_index (self->state_flags, gint32, index); 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)) { if (state_flags & ENTRY_INSTALLABLE) { self->installable--; state_flags &= ~ENTRY_INSTALLABLE; } if (!(state_flags & ENTRY_REMOVABLE)) { self->removable++; state_flags |= ENTRY_REMOVABLE; } if (!bz_entry_is_holding (entry)) { if (state_flags & ENTRY_INSTALLABLE_AVAILABLE) { self->installable_available--; state_flags &= ~ENTRY_INSTALLABLE_AVAILABLE; } if (!(state_flags & ENTRY_REMOVABLE_AVAILABLE)) { self->removable_available++; state_flags |= ENTRY_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 { if (state_flags & ENTRY_REMOVABLE) { self->removable--; state_flags &= ~ENTRY_REMOVABLE; } if (reinstallable) { if (!(state_flags & ENTRY_INSTALLABLE)) { self->installable++; state_flags |= ENTRY_INSTALLABLE; } } if (!bz_entry_is_holding (entry)) { if (state_flags & ENTRY_REMOVABLE_AVAILABLE) { self->removable_available--; state_flags &= ~ENTRY_REMOVABLE_AVAILABLE; } if (reinstallable) { if (!(state_flags & ENTRY_INSTALLABLE_AVAILABLE)) { self->installable_available++; state_flags |= ENTRY_INSTALLABLE_AVAILABLE; } } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REMOVABLE_AND_AVAILABLE]); if (reinstallable) 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 (reinstallable) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLABLE]); } g_array_index (self->state_flags, gint32, index) = state_flags; dex_clear (&self->user_data_size_future); dex_clear (&self->reap_cache_future); self->user_data_size = 0; self->cache_size = 0; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USER_DATA_SIZE]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CACHE_SIZE]); } static void holding_changed (BzEntryGroup *self, GParamSpec *pspec, BzEntry *entry) { g_autoptr (GMutexLocker) locker = NULL; gboolean reinstallable = FALSE; const char *unique_id = NULL; guint index = 0; gint32 state_flags = 0; locker = g_mutex_locker_new (&self->mutex); reinstallable = bz_entry_is_reinstallable (entry); unique_id = bz_entry_get_unique_id (entry); index = gtk_string_list_find (self->unique_ids, unique_id); if (index == G_MAXUINT) return; state_flags = g_array_index (self->state_flags, gint32, index); if (bz_entry_is_holding (entry)) { if (bz_entry_is_installed (entry)) { if (state_flags & ENTRY_REMOVABLE_AVAILABLE) { self->removable_available--; state_flags &= ~ENTRY_REMOVABLE_AVAILABLE; } } else { if (state_flags & ENTRY_INSTALLABLE_AVAILABLE) { self->installable_available--; state_flags &= ~ENTRY_INSTALLABLE_AVAILABLE; } } } else { if (bz_entry_is_installed (entry)) { if (!(state_flags & ENTRY_REMOVABLE_AVAILABLE)) { self->removable_available++; state_flags |= ENTRY_REMOVABLE_AVAILABLE; } } else if (reinstallable) { if (!(state_flags & ENTRY_INSTALLABLE_AVAILABLE)) { self->installable_available++; state_flags |= ENTRY_INSTALLABLE_AVAILABLE; } } } g_array_index (self->state_flags, gint32, index) = state_flags; 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; bz_weak_get_or_return_reject (self, wr); dex_clear (&self->reap_user_data_future); self->user_data_size = 0; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USER_DATA_SIZE]); return dex_future_new_true (); } DexFuture * bz_entry_group_reap_user_data (BzEntryGroup *self) { dex_return_error_if_fail (BZ_IS_ENTRY_GROUP (self)); dex_return_error_if_fail (self->id != NULL); if (self->reap_user_data_future != NULL) return dex_ref (self->reap_user_data_future); 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); return dex_ref (self->reap_user_data_future); } static DexFuture * reap_user_cache_then (DexFuture *future, GWeakRef *wr) { g_autoptr (BzEntryGroup) self = NULL; bz_weak_get_or_return_reject (self, wr); dex_clear (&self->reap_cache_future); self->cache_size = 0; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CACHE_SIZE]); return dex_future_new_true (); } DexFuture * bz_entry_group_reap_user_cache (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); g_return_val_if_fail (self->id != NULL, NULL); if (self->reap_cache_future != NULL) return dex_ref (self->reap_cache_future); self->reap_cache_future = dex_future_then ( bz_reap_user_cache_dex (self->id), (DexFutureCallback) reap_user_cache_then, bz_track_weak (self), bz_weak_release); return dex_ref (self->reap_cache_future); } static DexFuture * user_data_size_then (DexFuture *future, GWeakRef *wr) { g_autoptr (BzEntryGroup) self = NULL; g_autoptr (GError) error = NULL; g_autoptr (BzSizeResult) sizes = NULL; bz_weak_get_or_return_reject (self, wr); dex_clear (&self->user_data_size_future); sizes = g_value_dup_object (dex_future_get_value (future, &error)); if (error != NULL || sizes == NULL) { g_clear_error (&error); return dex_future_new_true (); } self->user_data_size = bz_size_result_get_user_data_size (sizes); self->cache_size = bz_size_result_get_cache_size (sizes); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USER_DATA_SIZE]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CACHE_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 || self->reap_cache_future != NULL) return; future = bz_get_user_sizes_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); } bazaar-org-bazaar-43ce9f7/src/bz-entry-group.h000066400000000000000000000077531520414637400213110ustar00rootroot00000000000000/* 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); 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); GListModel * bz_entry_group_get_addon_group_ids (BzEntryGroup *self); void bz_entry_group_append_addon_group_id (BzEntryGroup *self, const char *id); int bz_entry_group_get_n_addons (BzEntryGroup *self); const char * bz_entry_group_get_donation_url (BzEntryGroup *self); gboolean bz_entry_group_has_category (BzEntryGroup *self, const char *name); BzCategoryFlags bz_entry_group_get_categories (BzEntryGroup *self); int bz_entry_group_get_content_age_rating (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); gboolean bz_entry_group_is_addon (BzEntryGroup *self); guint64 bz_entry_group_get_user_data_size (BzEntryGroup *self); guint64 bz_entry_group_get_cache_size (BzEntryGroup *self); DexFuture * bz_entry_group_reap_user_data (BzEntryGroup *self); DexFuture * bz_entry_group_reap_user_cache (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 bazaar-org-bazaar-43ce9f7/src/bz-entry-inspector.blp000066400000000000000000000045331520414637400225020ustar00rootroot00000000000000using 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: $GtkSourceView { styles [ "monospace", ] // wrap-mode: word_char; buffer: $GtkSourceBuffer text_buffer {}; }; } }; [top] Adw.HeaderBar top_header_bar {} } } bazaar-org-bazaar-43ce9f7/src/bz-entry-inspector.c000066400000000000000000000144621520414637400221510ustar00rootroot00000000000000/* 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 #include "bz-entry-inspector.h" #include "bz-entry.h" #include "bz-serializable.h" struct _BzEntryInspector { AdwWindow parent_instance; BzResult *result; /* Template widgets */ GtkSourceBuffer *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; GtkSourceLanguageManager *lang_mgr = NULL; GtkSourceLanguage *language = 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); lang_mgr = gtk_source_language_manager_get_default (); language = gtk_source_language_manager_get_language (lang_mgr, "json"); gtk_source_buffer_set_language (self->text_buffer, language); } else { string = g_variant_print (variant, FALSE); gtk_source_buffer_set_language (self->text_buffer, NULL); } gtk_text_buffer_set_text (GTK_TEXT_BUFFER (self->text_buffer), string, -1); } else { gtk_source_buffer_set_language (self->text_buffer, NULL); gtk_text_buffer_set_text ( GTK_TEXT_BUFFER (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) { GtkSourceStyleSchemeManager *scheme_mgr = NULL; GtkSourceStyleScheme *scheme = NULL; gtk_widget_init_template (GTK_WIDGET (self)); scheme_mgr = gtk_source_style_scheme_manager_get_default (); scheme = gtk_source_style_scheme_manager_get_scheme (scheme_mgr, "Adwaita-dark"); gtk_source_buffer_set_style_scheme (self->text_buffer, scheme); } 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 */ bazaar-org-bazaar-43ce9f7/src/bz-entry-inspector.h000066400000000000000000000024001520414637400221430ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-entry-selection-row.blp000066400000000000000000000010631520414637400232610ustar00rootroot00000000000000using 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 ; } bazaar-org-bazaar-43ce9f7/src/bz-entry-selection-row.c000066400000000000000000000114621520414637400227320ustar00rootroot00000000000000/* 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; } bazaar-org-bazaar-43ce9f7/src/bz-entry-selection-row.h000066400000000000000000000024021520414637400227310ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-entry.c000066400000000000000000002600261520414637400201440ustar00rootroot00000000000000/* 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-category-flags.h" #include "bz-country-data-point.h" #include "bz-data-point.h" #include "bz-entry.h" #include "bz-env.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 reinstallable; 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 *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; BzCategoryFlags 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; } BzEntryPrivate; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (BzEntry, bz_entry, G_TYPE_OBJECT); enum { PROP_0, PROP_HOLDING, PROP_INSTALLED, PROP_INSTALLED_VERSION, PROP_REINSTALLABLE, 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_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 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_REINSTALLABLE: g_value_set_boolean (value, priv->reinstallable); 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); 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_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_uint (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_RECENT_DOWNLOADS); 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_REINSTALLABLE: priv->reinstallable = g_value_get_boolean (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_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: priv->categories = g_value_get_uint (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); } 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_REINSTALLABLE] = g_param_spec_boolean ( "reinstallable", NULL, NULL, TRUE, 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_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_uint ( "categories", NULL, NULL, 0, G_MAXUINT, BZ_CATEGORY_FLAGS_NONE, 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->reinstallable = TRUE; 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}", "reinstallable", g_variant_new_boolean (priv->reinstallable)); 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(ss)")); for (guint i = 0; i < n_items; i++) { g_autoptr (BzUrl) url = NULL; const char *id = NULL; const char *url_str = NULL; url = g_list_model_get_item (priv->share_urls, i); id = bz_url_get_id (url); url_str = bz_url_get_url (url); g_variant_builder_add (sub_builder, "(ss)", id ? id : "", url_str ? url_str : ""); } 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->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 != BZ_CATEGORY_FLAGS_NONE) g_variant_builder_add (builder, "{sv}", "categories", g_variant_new_uint32 (priv->categories)); 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, "reinstallable") == 0) priv->reinstallable = g_variant_get_boolean (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 *id = NULL; g_autofree char *url_str = NULL; g_autoptr (BzUrl) url = NULL; if (!g_variant_iter_next (url_iter, "(ss)", &id, &url_str)) break; url = bz_url_new (); bz_url_set_id (url, id); bz_url_set_url (url, url_str); 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, "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) priv->categories = g_variant_get_uint32 (value); 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_reinstallable (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), TRUE); priv = bz_entry_get_instance_private (self); return priv->reinstallable; } 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; } 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; } BzCategoryFlags bz_entry_get_category_flags (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), BZ_CATEGORY_FLAGS_NONE); 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; } 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); } GIcon * bz_load_mini_icon_sync (const char *unique_id_checksum, const char *path) { guint icon_size = 0; g_autofree char *main_cache = NULL; g_autofree char *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; icon_size = bz_get_desktop_search_provider_icon_size (); main_cache = bz_dup_module_dir (); mini_icon_basename = g_strdup_printf ("%s-%ux%u", unique_id_checksum, icon_size, icon_size); mini_icon_path = g_build_filename (main_cache, mini_icon_basename, 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); surface_out = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, icon_size, icon_size); cairo = cairo_create (surface_out); cairo_scale (cairo, (double) icon_size / (double) width, (double) icon_size / (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 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_RECENT_DOWNLOADS || 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_RECENT_DOWNLOADS: 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 *root = NULL; JsonObject *per_day = NULL; g_autoptr (GListStore) store = NULL; if (!JSON_NODE_HOLDS_OBJECT (node)) return dex_future_new_for_error ( g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Unexpected JSON response format")); root = json_node_get_object (node); per_day = json_object_get_object_member (root, "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; if (!JSON_NODE_HOLDS_OBJECT (node)) return dex_future_new_for_error ( g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Unexpected JSON response format")); 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_RECENT_DOWNLOADS: { int recent_downloads = 0; if (!JSON_NODE_HOLDS_OBJECT (node)) return dex_future_new_for_int (0); if (json_object_has_member (json_node_get_object (node), "installs_last_month")) recent_downloads = json_object_get_int_member (json_node_get_object (node), "installs_last_month"); return dex_future_new_for_int (recent_downloads); } break; case PROP_TOTAL_DOWNLOADS: { int total_downloads = 0; if (!JSON_NODE_HOLDS_OBJECT (node)) return dex_future_new_for_int (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)) { 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 void clear_entry (BzEntry *self) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); 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->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->permissions); } bazaar-org-bazaar-43ce9f7/src/bz-entry.h000066400000000000000000000124021520414637400201420ustar00rootroot00000000000000/* 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-category-flags.h" #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_reinstallable (BzEntry *self); 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); 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); BzCategoryFlags bz_entry_get_category_flags (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 bazaar-org-bazaar-43ce9f7/src/bz-env.c000066400000000000000000000106111520414637400175640ustar00rootroot00000000000000/* 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; } guint64 bz_get_n_download_workers (void) { static guint64 n_dl_workers = 0; if (g_once_init_enter (&n_dl_workers)) { const char *envvar = NULL; guint64 value = 0; value = 8; envvar = g_getenv ("BAZAAR_N_DOWNLOAD_WORKERS"); 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 == 0) g_warning ("BAZAAR_N_DOWNLOAD_WORKERS must be greater than 0"); else value = parse_result; } else g_warning ("BAZAAR_N_DOWNLOAD_WORKERS is invalid: %s", local_error->message); } g_once_init_leave (&n_dl_workers, value); } return n_dl_workers; } guint bz_get_desktop_search_provider_icon_size (void) { static guint64 icon_size = 0; if (g_once_init_enter (&icon_size)) { const char *envvar = NULL; guint64 value = 0; /* default 24x24 for the gnome-shell search provider */ value = 24; envvar = g_getenv ("BAZAAR_DESKTOP_SEARCH_PROVIDER_ICON_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 == 0 || parse_result > 256) g_warning ("BAZAAR_DESKTOP_SEARCH_PROVIDER_ICON_SIZE must be " "greater than 0 but no greater than 256"); else value = parse_result; } else g_warning ("BAZAAR_DESKTOP_SEARCH_PROVIDER_ICON_SIZE is invalid: %s", local_error->message); } g_once_init_leave (&icon_size, value); } return (guint) icon_size; } bazaar-org-bazaar-43ce9f7/src/bz-env.h000066400000000000000000000016621520414637400175770ustar00rootroot00000000000000/* 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); guint64 bz_get_n_download_workers (void); guint bz_get_desktop_search_provider_icon_size (void); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-error-dialog.blp000066400000000000000000000027761520414637400217320ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzErrorDialog: Adw.Dialog { content-width: 500; content-height: 400; child: Adw.ToastOverlay toast_overlay { child: Adw.ToolbarView { [top] Adw.HeaderBar {} content: Box { orientation: vertical; spacing: 0; margin-start: 24; margin-end: 24; margin-top: 12; margin-bottom: 24; Label error_title { halign: center; styles [ "title-1", ] } Box { orientation: horizontal; spacing: 6; margin-top: 12; margin-bottom: 6; Label { label: _("Details"); halign: start; hexpand: true; styles [ "heading", ] } Button copy_button { icon-name: "edit-copy-symbolic"; tooltip-text: _("Copy"); clicked => $on_copy_button_clicked(); styles [ "flat", ] } } ScrolledWindow { vexpand: true; hscrollbar-policy: automatic; vscrollbar-policy: automatic; TextView text_view { editable: false; wrap-mode: word_char; monospace: true; left-margin: 6; right-margin: 6; top-margin: 6; bottom-margin: 6; styles [ "card", ] } } }; }; }; } bazaar-org-bazaar-43ce9f7/src/bz-error-dialog.c000066400000000000000000000060161520414637400213660ustar00rootroot00000000000000/* bz-error-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 #include "bz-error-dialog.h" struct _BzErrorDialog { AdwDialog parent_instance; AdwToastOverlay *toast_overlay; GtkLabel *error_title; GtkTextView *text_view; }; G_DEFINE_FINAL_TYPE (BzErrorDialog, bz_error_dialog, ADW_TYPE_DIALOG) static void on_copy_button_clicked (GtkButton *button, BzErrorDialog *self) { GtkTextBuffer *buffer = NULL; GtkTextIter start = { 0 }; GtkTextIter end = { 0 }; g_autofree char *text = NULL; GdkClipboard *clipboard = NULL; g_autoptr (AdwToast) toast = NULL; buffer = gtk_text_view_get_buffer (self->text_view); gtk_text_buffer_get_bounds (buffer, &start, &end); text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); clipboard = gdk_display_get_clipboard (gdk_display_get_default ()); gdk_clipboard_set_text (clipboard, text); toast = adw_toast_new (_ ("Copied!")); adw_toast_set_timeout (toast, 2); adw_toast_overlay_add_toast (self->toast_overlay, g_steal_pointer (&toast)); } static void bz_error_dialog_class_init (BzErrorDialogClass *klass) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-error-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, BzErrorDialog, toast_overlay); gtk_widget_class_bind_template_child (widget_class, BzErrorDialog, error_title); gtk_widget_class_bind_template_child (widget_class, BzErrorDialog, text_view); gtk_widget_class_bind_template_callback (widget_class, on_copy_button_clicked); } static void bz_error_dialog_init (BzErrorDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } BzErrorDialog * bz_error_dialog_new (const char *title, const char *text) { BzErrorDialog *self; GtkTextBuffer *buffer; GtkTextIter iter; g_return_val_if_fail (title != NULL, NULL); g_return_val_if_fail (text != NULL, NULL); self = g_object_new (BZ_TYPE_ERROR_DIALOG, NULL); gtk_label_set_text (self->error_title, title); buffer = gtk_text_view_get_buffer (self->text_view); gtk_text_buffer_get_start_iter (buffer, &iter); gtk_text_buffer_insert (buffer, &iter, text, -1); return self; } bazaar-org-bazaar-43ce9f7/src/bz-error-dialog.h000066400000000000000000000020701520414637400213670ustar00rootroot00000000000000/* bz-error-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 G_BEGIN_DECLS #define BZ_TYPE_ERROR_DIALOG (bz_error_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzErrorDialog, bz_error_dialog, BZ, ERROR_DIALOG, AdwDialog) BzErrorDialog *bz_error_dialog_new (const char *title, const char *text); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-error.c000066400000000000000000000074631520414637400201400ustar00rootroot00000000000000/* 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-dialog.h" #include "bz-error.h" #include "bz-window.h" static void show_alert (GtkWidget *widget, const char *title, const char *text); static void await_alert_response (AdwAlertDialog *alert, gchar *response, DexPromise *promise); static void unref_dex_closure (gpointer data, GClosure *closure); void bz_show_error_for_widget (GtkWidget *widget, const char *title, const char *text) { g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (text != NULL); show_alert (widget, title, text); } static void on_toast_button_clicked (AdwToast *toast, GtkWidget *widget) { BzErrorDialog *dialog; const char *title = NULL; const char *text = NULL; if (!GTK_IS_WIDGET (widget)) return; title = g_object_get_data (G_OBJECT (toast), "title"); text = g_object_get_data (G_OBJECT (toast), "text"); dialog = bz_error_dialog_new (title ? title : _ ("Details"), text ? text : ""); adw_dialog_present (ADW_DIALOG (dialog), widget); } static void show_alert (GtkWidget *widget, const char *title, const char *text) { BzWindow *window = NULL; AdwToast *toast = NULL; g_autofree char *toast_title = NULL; window = BZ_WINDOW (gtk_widget_get_ancestor (widget, BZ_TYPE_WINDOW)); if (window == NULL) return; toast_title = g_strdup_printf ("%s", title); toast = adw_toast_new (toast_title); adw_toast_set_button_label (toast, _ ("Details")); adw_toast_set_priority (toast, ADW_TOAST_PRIORITY_HIGH); adw_toast_set_timeout (toast, 5); g_object_set_data_full (G_OBJECT (toast), "title", g_strdup (title), g_free); g_object_set_data_full (G_OBJECT (toast), "text", g_strdup (text), g_free); g_signal_connect (toast, "button-clicked", G_CALLBACK (on_toast_button_clicked), widget); bz_window_add_toast (window, toast); } 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 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); } bazaar-org-bazaar-43ce9f7/src/bz-error.h000066400000000000000000000020241520414637400201310ustar00rootroot00000000000000/* 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_error_for_widget (GtkWidget *widget, const char *title, const char *text); DexFuture * bz_make_alert_dialog_future (AdwAlertDialog *dialog); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-exponential-function.txt000066400000000000000000000002641520414637400235450ustar00rootroot00000000000000prefix=bz name=exponential_function parent-prefix=g parent-name=object author=AUTOGEN property=factor double G_TYPE_DOUBLE double property=y_intercept double G_TYPE_DOUBLE double bazaar-org-bazaar-43ce9f7/src/bz-fading-clamp.c000066400000000000000000000263261520414637400213300ustar00rootroot00000000000000/* 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 #include "bz-fading-clamp.h" #include "bz-util.h" #define FADE_HEIGHT 75 #define CLAMP_LEEWAY 100 struct _BzFadingClamp { GtkWidget parent_instance; BgeAnimation *animation; GtkWidget *child; int max_height; int min_max_height; int current_height; int allocated_width; 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 animate (BzFadingClamp *self, const char *key, double value, gpointer user_data) { self->current_height = round (value); gtk_widget_queue_resize (GTK_WIDGET (self)); } 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_object (&self->animation); g_clear_pointer (&self->child, gtk_widget_unparent); 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 = 0; 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 (!bge_animation_has_key (self->animation, "height")) self->current_height = target_height; *minimum = self->current_height; *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 = 0; int natural_height = 0; gtk_widget_measure (self->child, GTK_ORIENTATION_VERTICAL, width, NULL, &natural_height, NULL, NULL); if (natural_height > height) child_height = natural_height; else child_height = 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) { self->animation = bge_animation_new (GTK_WIDGET (self)); self->max_height = 300; self->min_max_height = 150; self->current_height = CLAMP_LEEWAY; self->allocated_width = 0; self->will_change = FALSE; } 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 = 0; int target_height = 0; int width = 0; 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; bge_animation_add_spring ( self->animation, "height", self->current_height, target_height, 1.25, 1.0, 800.0, (BgeAnimationCallback) animate, NULL, NULL, NULL); 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; } bazaar-org-bazaar-43ce9f7/src/bz-fading-clamp.h000066400000000000000000000025221520414637400213250ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-favorite-button.blp000066400000000000000000000020601520414637400224560ustar00rootroot00000000000000using 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; }; } }; }bazaar-org-bazaar-43ce9f7/src/bz-favorite-button.c000066400000000000000000000314521520414637400221320ustar00rootroot00000000000000/* 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, _ ("Failed to update favorite"), 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)); } bazaar-org-bazaar-43ce9f7/src/bz-favorite-button.h000066400000000000000000000026501520414637400221350ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-favorites-page.blp000066400000000000000000000054071520414637400222520ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzFavoritesPage: Adw.NavigationPage { title: _("Favorites"); Adw.ToolbarView { [top] Adw.HeaderBar { [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: 100; 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; } } }; } } bazaar-org-bazaar-43ce9f7/src/bz-favorites-page.c000066400000000000000000000310621520414637400217130ustar00rootroot00000000000000/* 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-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 }; 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 void tile_activated_cb (BzFavoritesTile *tile) { BzEntryGroup *group = NULL; g_assert (BZ_IS_FAVORITES_TILE (tile)); group = bz_favorites_tile_get_group (tile); if (group == NULL) return; gtk_widget_activate_action (GTK_WIDGET (tile), "window.show-group", "s", bz_entry_group_get_id (group)); } 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) { GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("as")); guint n_items = 0; g_return_if_fail (BZ_IS_FAVORITES_PAGE (self)); if (self->model == NULL || self->favorites == NULL) return; 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_variant_builder_add (&builder, "s", bz_entry_group_get_id (group)); } gtk_widget_activate_action (GTK_WIDGET (self), "window.bulk-install", "as", &builder); } 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); 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 (); } bazaar-org-bazaar-43ce9f7/src/bz-favorites-page.h000066400000000000000000000021001520414637400217070ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-favorites-tile.blp000066400000000000000000000072001520414637400222640ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzFavoritesTile: $BzListTile { accessibility { labelled-by: title_label; described-by: description_label; } child: Box { orientation: horizontal; spacing: 10; $BzTransactIcon { margin-start: 10; margin-top: 10; margin-bottom: 10; width-request: 48; height-request: 48; info: $BzTransactIconInfo { group: bind template.group as <$BzEntryGroup>; paintable: bind template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.icon-paintable; }; } 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"] } } }; } bazaar-org-bazaar-43ce9f7/src/bz-favorites-tile.c000066400000000000000000000244551520414637400217440ustar00rootroot00000000000000/* 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; 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 void install_remove_cb (BzFavoritesTile *self, GtkButton *button); 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 (C_("Install Controls", "Uninstall")); else return g_strdup (C_("Install Controls", "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, 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 void install_remove_cb (BzFavoritesTile *self, GtkButton *button) { int removable = 0; if (self->group == NULL) return; removable = bz_entry_group_get_removable (self->group); if (removable > 0) gtk_widget_activate_action (GTK_WIDGET (self), "window.remove-group", "(sb)", bz_entry_group_get_id (self->group), FALSE); else gtk_widget_activate_action (GTK_WIDGET (self), "window.install-group", "(sb)", bz_entry_group_get_id (self->group), TRUE); } static void support_cb (BzFavoritesTile *self, GtkButton *button) { const char *url = NULL; if (self->group == NULL) return; url = bz_entry_group_get_donation_url (self->group); if (url == NULL) return; g_app_info_launch_default_for_uri (url, NULL, NULL); } 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, _("Failed to remove favorite"), 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)); } bazaar-org-bazaar-43ce9f7/src/bz-favorites-tile.h000066400000000000000000000023731520414637400217440ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-featured-carousel.blp000066400000000000000000000031311520414637400227400ustar00rootroot00000000000000using Gtk 4.0; 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"; visible: bind $is_gt(selection.n-items, 1); 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"; visible: bind $is_gt(selection.n-items, 1); clicked => $next_button_clicked_cb(); styles [ "circular", "flat", "image-button", ] accessibility { label: _("Next"); } } child: $BgeCarousel carousel { styles ["card"] allow-mouse-drag: true; allow-overshoot: false; allow-scroll-wheel: true; allow-raise: false; create-widget => $on_create_widget(template); remove-widget => $on_remove_widget(template); model: SingleSelection selection { autoselect: true; model: bind template.model; notify::selected => $on_notify_selected(template); // notify::n-items => $on_notify_n_items(template); }; }; } EventControllerKey { key-pressed => $key_pressed_cb(); } } bazaar-org-bazaar-43ce9f7/src/bz-featured-carousel.c000066400000000000000000000257051520414637400224200ustar00rootroot00000000000000/* 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 #include "bz-entry-group.h" #include "bz-featured-carousel.h" #include "bz-featured-tile.h" #include "bz-template-callbacks.h" #define FEATURED_ROTATE_TIME 5 #define MANUAL_ROTATE_RECOVER_TIME 7.5 struct _BzFeaturedCarousel { GtkBox parent_instance; GListModel *model; guint rotation_timer_source; GTimer *time_since_manual_rotate; BgeCarousel *carousel; GtkSingleSelection *selection; GtkButton *next_button; GtkButton *previous_button; }; G_DEFINE_FINAL_TYPE (BzFeaturedCarousel, bz_featured_carousel, GTK_TYPE_BOX) enum { PROP_0, PROP_MODEL, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { NULL, }; static void update_buttons_for_tile (BzFeaturedCarousel *self) { GtkWidget *child = NULL; const char *class_name = NULL; guint index = 0; index = gtk_single_selection_get_selected (self->selection); child = bge_carousel_get_nth_page (self->carousel, index); if (child == NULL) return; class_name = gtk_widget_has_css_class (child, "flathub-lotion") ? "flathub-lotion" : "flathub-gunmetal"; gtk_widget_remove_css_class (GTK_WIDGET (self->next_button), "flathub-lotion"); gtk_widget_remove_css_class (GTK_WIDGET (self->next_button), "flathub-gunmetal"); gtk_widget_remove_css_class (GTK_WIDGET (self->previous_button), "flathub-lotion"); gtk_widget_remove_css_class (GTK_WIDGET (self->previous_button), "flathub-gunmetal"); gtk_widget_add_css_class (GTK_WIDGET (self->next_button), class_name); gtk_widget_add_css_class (GTK_WIDGET (self->previous_button), class_name); } static void on_style_changed (AdwStyleManager *style_manager, GParamSpec *pspec, BzFeaturedCarousel *self) { g_idle_add_once ((GSourceOnceFunc) update_buttons_for_tile, self); } static void on_notify_selected (BzFeaturedCarousel *self, GParamSpec *pspec, GtkSingleSelection *selection) { g_timer_start (self->time_since_manual_rotate); update_buttons_for_tile (self); } static void show_relative_page (BzFeaturedCarousel *self, gint delta, gboolean use_custom_spring) { guint n_pages; guint current_page; guint new_page; n_pages = g_list_model_get_n_items (G_LIST_MODEL (self->selection)); if (n_pages == 0) return; current_page = gtk_single_selection_get_selected (self->selection); new_page = (n_pages + current_page + delta) % n_pages; g_signal_handlers_block_by_func (self->selection, on_notify_selected, self); gtk_single_selection_set_selected (self->selection, new_page); g_signal_handlers_unblock_by_func (self->selection, on_notify_selected, self); update_buttons_for_tile (self); } static gboolean rotate_cb (gpointer user_data) { BzFeaturedCarousel *self = BZ_FEATURED_CAROUSEL (user_data); double elapsed = 0.0; elapsed = g_timer_elapsed (self->time_since_manual_rotate, NULL); if (elapsed > MANUAL_ROTATE_RECOVER_TIME) show_relative_page (self, +1, TRUE); return G_SOURCE_CONTINUE; } 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) { BzEntryGroup *group = NULL; group = bz_featured_tile_get_group (tile); gtk_widget_activate_action (GTK_WIDGET (user_data), "window.show-group", "s", bz_entry_group_get_id (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 bz_featured_carousel_dispose (GObject *object) { BzFeaturedCarousel *self = BZ_FEATURED_CAROUSEL (object); g_signal_handlers_disconnect_by_func (adw_style_manager_get_default (), on_style_changed, self); g_clear_handle_id (&self->rotation_timer_source, g_source_remove); g_clear_pointer (&self->time_since_manual_rotate, g_timer_destroy); 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; 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; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GtkWidget * on_create_widget (BzFeaturedCarousel *self, BzEntryGroup *group, BgeCarousel *carousel) { BzFeaturedTile *tile = NULL; tile = bz_featured_tile_new (group); 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); return GTK_WIDGET (tile); } static void on_remove_widget (BzFeaturedCarousel *self, BzFeaturedTile *tile, BzEntryGroup *group, BgeCarousel *carousel) { } 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; 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); g_object_class_install_properties (object_class, LAST_PROP, props); 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); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzFeaturedCarousel, carousel); gtk_widget_class_bind_template_child (widget_class, BzFeaturedCarousel, selection); 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_callback (widget_class, on_create_widget); gtk_widget_class_bind_template_callback (widget_class, on_remove_widget); gtk_widget_class_bind_template_callback (widget_class, on_notify_selected); 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) { gtk_widget_init_template (GTK_WIDGET (self)); self->rotation_timer_source = g_timeout_add_seconds ( FEATURED_ROTATE_TIME, rotate_cb, self); self->time_since_manual_rotate = g_timer_new (); g_signal_connect (adw_style_manager_get_default (), "notify::dark", G_CALLBACK (on_style_changed), 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; 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]); } bazaar-org-bazaar-43ce9f7/src/bz-featured-carousel.h000066400000000000000000000023431520414637400224160ustar00rootroot00000000000000/* 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); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-featured-tile.blp000066400000000000000000000035541520414637400220710ustar00rootroot00000000000000using 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>.ui-entry as <$BzResult>.object as <$BzEntry>.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; wrap: true; wrap-mode: word_char; 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; } } } } bazaar-org-bazaar-43ce9f7/src/bz-featured-tile.c000066400000000000000000000352171520414637400215370ustar00rootroot00000000000000/* 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; 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, 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; 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_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); 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]); } bazaar-org-bazaar-43ce9f7/src/bz-featured-tile.h000066400000000000000000000023331520414637400215350ustar00rootroot00000000000000/* 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); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-finished-search-query.txt000066400000000000000000000004701520414637400235720ustar00rootroot00000000000000prefix=bz name=finished_search_query parent-prefix=g parent-name=object author=AUTOGEN property=interpreted_query char G_TYPE_STRING string property=results GPtrArray G_TYPE_PTR_ARRAY boxed g_ptr_array_unref g_ptr_array_ref property=n_results guint G_TYPE_UINT uint property=elapsed double G_TYPE_DOUBLE double bazaar-org-bazaar-43ce9f7/src/bz-flathub-auth-provider.txt000066400000000000000000000002511520414637400236040ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-flathub-category-section.blp000066400000000000000000000021341520414637400242320ustar00rootroot00000000000000using 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(); } }bazaar-org-bazaar-43ce9f7/src/bz-flathub-category-section.c000066400000000000000000000243351520414637400237060ustar00rootroot00000000000000/* 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 }; static void tile_clicked (BzEntryGroup *group, GtkButton *button) { gtk_widget_activate_action (GTK_WIDGET (button), "window.show-group", "s", bz_entry_group_get_id (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; 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 ? 9 : 11; } 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); 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; } bazaar-org-bazaar-43ce9f7/src/bz-flathub-category-section.h000066400000000000000000000035241520414637400237100ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-flathub-category.c000066400000000000000000000634061520414637400222460ustar00rootroot00000000000000/* 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_IS_XDG, PROP_SYMBOLIC_ICON_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; gboolean is_xdg; const char *icon_name; const char *symbolic_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"), TRUE, "io.github.kolumni.Bazaar.Audiovideo", "applications-multimedia-symbolic", audiovideo_subcategories }, { "development", N_ ("Developer Tools"), N_ ("Develop"), N_ ("More Developer Tools"), TRUE, "io.github.kolumni.Bazaar.Develop", "code-symbolic", NULL }, { "education", N_ ("Education"), N_ ("Learn"), N_ ("More Education"), TRUE, "io.github.kolumni.Bazaar.Learn", "open-book-symbolic", NULL }, { "game", N_ ("Gaming"), N_ ("Play"), N_ ("More Gaming"), TRUE, "io.github.kolumni.Bazaar.Play", "applications-games-symbolic", game_subcategories }, { "graphics", N_ ("Graphics & Photography"), N_ ("Create"), N_ ("More Graphics & Photography"), TRUE, "io.github.kolumni.Bazaar.Create", "paintbrush-symbolic", NULL }, { "network", N_ ("Networking"), N_ ("Internet"), N_ ("More Networking"), TRUE, "io.github.kolumni.Bazaar.Network", "globe-symbolic", NULL }, { "office", N_ ("Productivity"), N_ ("Work"), N_ ("More Productivity"), TRUE, "io.github.kolumni.Bazaar.Work", "meeting-symbolic", NULL }, { "science", N_ ("Science"), N_ ("Science"), N_ ("More Science"), TRUE, "io.github.kolumni.Bazaar.Science", "applications-science-symbolic", NULL }, { "system", N_ ("System"), N_ ("System"), N_ ("More System"), TRUE, "io.github.kolumni.Bazaar.System", "applications-system-symbolic", NULL }, { "utility", N_ ("Utilities"), N_ ("Tools"), N_ ("More Utilities"), TRUE, "io.github.kolumni.Bazaar.Utilities", "applications-utilities-symbolic", NULL }, { "trending", N_ ("Trending"), N_ ("Trending"), N_ ("More Trending"), FALSE, "io.github.kolumni.Bazaar.Trending", "", NULL }, { "popular", N_ ("Popular"), N_ ("Popular"), N_ ("More Popular"), FALSE, "io.github.kolumni.Bazaar.Popular", "", NULL }, { "recently-added", N_ ("Recently Added"), N_ ("New"), N_ ("More New"), FALSE, "io.github.kolumni.Bazaar.New", "", NULL }, { "recently-updated", N_ ("Recently Updated"), N_ ("Updated"), N_ ("More Updated"), FALSE, "io.github.kolumni.Bazaar.Updated", "", NULL }, { "mobile", N_ ("Mobile"), N_ ("Mobile"), N_ ("More Mobile"), FALSE, "io.github.kolumni.Bazaar.Mobile", "", NULL }, { "adwaita", N_ ("Adwaita"), N_ ("Adwaita"), N_ ("More Adwaita"), FALSE, "io.github.kolumni.Bazaar.Adwaita", "", NULL }, { "kde", N_ ("KDE Apps"), N_ ("KDE Apps"), N_ ("More KDE Apps"), FALSE, "io.github.kolumni.Bazaar.Kde", "", NULL }, { NULL, NULL, NULL, NULL, FALSE, 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_IS_XDG: g_value_set_boolean (value, bz_flathub_category_get_is_xdg (self)); break; case PROP_SYMBOLIC_ICON_NAME: g_value_set_string (value, bz_flathub_category_get_symbolic_icon_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_IS_XDG] = g_param_spec_boolean ( "is-xdg", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_SYMBOLIC_ICON_NAME] = g_param_spec_string ( "symbolic-icon-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; } gboolean bz_flathub_category_get_is_xdg (BzFlathubCategory *self) { const CategoryInfo *info; g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), FALSE); info = get_category_info (self->name); return info ? info->is_xdg : FALSE; } const char * bz_flathub_category_get_symbolic_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->symbolic_icon_name : NULL; } 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 */ bazaar-org-bazaar-43ce9f7/src/bz-flathub-category.h000066400000000000000000000057571520414637400222600ustar00rootroot00000000000000/* 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); gboolean bz_flathub_category_get_is_xdg (BzFlathubCategory *self); const char * bz_flathub_category_get_symbolic_icon_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 */ bazaar-org-bazaar-43ce9f7/src/bz-flathub-page.blp000066400000000000000000000501351520414637400216730ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzFlathubPage: Adw.Bin { child: Adw.BreakpointBin { width-request: 360; height-request: 100; child: Adw.BreakpointBin { width-request: 360; height-request: 100; 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 { styles [ "flathub-page-section", ] margin-top: 16; margin-bottom: 3; hexpand: true; model: bind template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.apps_of_the_week; } 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; 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>; 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>; 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>; 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>; min-items: 12; }; } } $BzFlathubCategorySection section_productivity { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "office") as <$BzFlathubCategory>; } Box { orientation: vertical; spacing: 10; margin-top: 16; margin-bottom: 20; Label { styles [ "title-1", ] xalign: 0.0; hexpand: true; margin-start: 3; margin-end: 3; margin-bottom: 5; ellipsize: end; label: _("App of the Day"); } $BzFeaturedCarousel { styles [ "flathub-page-section", ] hexpand: true; model: SliceListModel { offset: 0; size: 1; model: bind template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.apps_of_the_day_week; }; } } $BzFlathubCategorySection section_graphics { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "graphics") as <$BzFlathubCategory>; } $BzFlathubCategorySection section_audiovideo { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "audiovideo") as <$BzFlathubCategory>; } 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-top: 8; margin-bottom: 20; 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>; } $BzFlathubCategorySection section_network { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "network") as <$BzFlathubCategory>; } 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-top: 8; margin-bottom: 20; 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>; } $BzFlathubCategorySection section_science { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "science") as <$BzFlathubCategory>; } $BzFlathubCategorySection section_system { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "system") as <$BzFlathubCategory>; } $BzFlathubCategorySection section_utility { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "utility") as <$BzFlathubCategory>; } }; }; }; } }; } }; Adw.Breakpoint { condition ("max-width: 1250sp") 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: 970sp") 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; } } }; } bazaar-org-bazaar-43ce9f7/src/bz-flathub-page.c000066400000000000000000000237771520414637400213540ustar00rootroot00000000000000/* 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-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_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 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 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 show_group_action (GtkWidget *widget, BzEntryGroup *group) { gtk_widget_activate_action (widget, "window.show-group", "s", bz_entry_group_get_id (group)); } 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_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_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, 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, 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::has-flathub", G_CALLBACK (invalidating_state_changed), self); g_signal_connect_swapped ( state, "notify::online", G_CALLBACK (invalidating_state_changed), self); } invalidating_state_changed (self, NULL, state); 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 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); adw_navigation_view_push (ADW_NAVIGATION_VIEW (nav_view), apps_page); } static void tile_clicked (BzEntryGroup *group, GtkButton *button) { show_group_action (GTK_WIDGET (button), group); } static void invalidating_state_changed (BzFlathubPage *self, GParamSpec *pspec, BzStateInfo *info) { BzFlathubState *flathub = NULL; gboolean has_repo = FALSE; const char *page = NULL; if (self->state != NULL) { flathub = bz_state_info_get_flathub (self->state); has_repo = bz_state_info_get_has_flathub (self->state); } if (flathub != NULL && has_repo) page = "content"; else if (!has_repo) page = "empty"; else page = "offline"; adw_view_stack_set_visible_child_name (self->stack, page); } bazaar-org-bazaar-43ce9f7/src/bz-flathub-page.h000066400000000000000000000022571520414637400213470ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-flathub-state.c000066400000000000000000000773341520414637400215560ustar00rootroot00000000000000/* 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 = { 0 }; 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); { static const char *categories[] = { "audiovideo", "development", "education", "game", "graphics", "network", "office", "science", "system", "utility" }; g_autoptr (GPtrArray) category_futures = NULL; category_futures = g_ptr_array_new_with_free_func (dex_unref); for (guint i = 0; i < G_N_ELEMENTS (categories); i++) { g_autofree char *request = NULL; g_autoptr (DexFuture) future = NULL; request = g_strdup_printf ( "/collection/category/%s?page=0&per_page=%d", categories[i], 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 < G_N_ELEMENTS (categories); i++) { DexFuture *future = NULL; JsonNode *node = NULL; future = g_ptr_array_index (category_futures, i); node = GET_BOXED (future); add_category (self, categories[i], 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 */ bazaar-org-bazaar-43ce9f7/src/bz-flathub-state.h000066400000000000000000000041011520414637400215410ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-flathub-sub-category.txt000066400000000000000000000002441520414637400234210ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-flatpak-bundle-result.txt000066400000000000000000000004141520414637400235760ustar00rootroot00000000000000prefix=bz name=flatpak_bundle_result parent-prefix=g parent-name=object author=AUTOGEN include="bz-flatpak-entry.h" include="bz-flatpak-repo.h" property=entry BzFlatpakEntry BZ_TYPE_FLATPAK_ENTRY object property=runtime_repo BzFlatpakRepo BZ_TYPE_FLATPAK_REPO object bazaar-org-bazaar-43ce9f7/src/bz-flatpak-entry.c000066400000000000000000000665741520414637400216000ustar00rootroot00000000000000/* 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-application-map-factory.h" #include "bz-application.h" #include "bz-appstream-parser.h" #include "bz-flatpak-private.h" #include "bz-io.h" #include "bz-result.h" #include "bz-serializable.h" #include "bz-state-info.h" #define VERSION_SUFFIX_REGEX "\\s+[0-9][0-9.]*\\s*$" 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; char *bundle_path; BzResult *runtime_result; 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_BUNDLE_PATH, PROP_FLATPAK_ID, PROP_FLATPAK_VERSION, PROP_APPLICATION_NAME, PROP_APPLICATION_RUNTIME, PROP_APPLICATION_COMMAND, PROP_RUNTIME_NAME, PROP_RUNTIME_RESULT, PROP_ADDON_OF_REF, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void clear_entry (BzFlatpakEntry *self); static void apply_icon_theme (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_NAME: g_value_set_string (value, self->flatpak_name); 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_BUNDLE_PATH: g_value_set_string (value, self->bundle_path); 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_RUNTIME_RESULT: g_value_take_object (value, bz_flatpak_entry_dup_runtime_result (self)); 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: case PROP_BUNDLE_PATH: 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_BUNDLE_PATH] = g_param_spec_string ( "bundle-path", NULL, NULL, NULL, 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_RUNTIME_RESULT] = g_param_spec_object ( "runtime", NULL, NULL, BZ_TYPE_RESULT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); 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-bundle", g_variant_new_boolean (self->is_bundle)); g_variant_builder_add (builder, "{sv}", "is-installed-ref", g_variant_new_boolean (self->is_installed_ref)); if (self->bundle_path != NULL) g_variant_builder_add (builder, "{sv}", "bundle-path", g_variant_new_string (self->bundle_path)); 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-bundle") == 0) self->is_bundle = 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, "bundle-path") == 0) self->bundle_path = g_variant_dup_string (value, NULL); 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); } if (self->is_installed_ref) apply_icon_theme (self); 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; } BzResult * bz_flatpak_entry_dup_runtime_result (BzFlatpakEntry *self) { BzStateInfo *state = NULL; BzApplicationMapFactory *factory = NULL; g_autofree char *runtime_unique_id = NULL; g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), NULL); state = bz_state_info_get_default (); if (self->runtime_result != NULL) return g_object_ref (self->runtime_result); if (self->application_runtime == NULL) return NULL; factory = bz_state_info_get_entry_factory (state); if (factory == NULL) return NULL; runtime_unique_id = g_strdup_printf ("FLATPAK-SYSTEM::flathub::runtime/%s", self->application_runtime); self->runtime_result = bz_application_map_factory_convert_one ( factory, gtk_string_object_new (runtime_unique_id)); return self->runtime_result != NULL ? g_object_ref (self->runtime_result) : NULL; } 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; gboolean reinstallable = 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); if (FLATPAK_IS_BUNDLE_REF (ref)) { GFile *file = NULL; file = flatpak_bundle_ref_get_file (FLATPAK_BUNDLE_REF (ref)); if (file != NULL) self->bundle_path = g_file_get_path (file); } 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)) apply_icon_theme (self); } 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 ((kinds & BZ_ENTRY_KIND_RUNTIME) && !(kinds & BZ_ENTRY_KIND_ADDON) && self->flatpak_version != NULL) { static GRegex *version_regex = NULL; g_autofree char *stripped_title = NULL; if (g_once_init_enter_pointer (&version_regex)) { g_autoptr (GRegex) re = NULL; /* GNOME runtimes have the flatpak version at the end whilst others don't. */ re = g_regex_new (VERSION_SUFFIX_REGEX, 0, 0, NULL); g_once_init_leave_pointer (&version_regex, g_steal_pointer (&re)); } stripped_title = g_regex_replace (version_regex, title, -1, 0, "", 0, NULL); title = g_strdup_printf ("%s %s", stripped_title, self->flatpak_version); } 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); reinstallable = !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, "reinstallable", reinstallable, 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 != NULL ? origin : "bundle", 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_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; } const char * bz_flatpak_entry_get_bundle_path (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), NULL); return self->bundle_path; } 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); g_clear_pointer (&self->bundle_path, g_free); g_clear_object (&self->runtime_result); } static void apply_icon_theme (BzFlatpakEntry *self) { FlatpakRef *ref = NULL; BzStateInfo *state = NULL; const char *icon_name = NULL; GtkIconTheme *theme = NULL; ref = bz_flatpak_entry_get_ref (self); state = bz_state_info_get_default (); icon_name = flatpak_ref_get_name (ref); theme = self->user ? bz_state_info_get_user_icon_theme (state) : bz_state_info_get_system_icon_theme (state); if (theme != NULL) { g_autoptr (GtkIconPaintable) paintable = NULL; paintable = gtk_icon_theme_lookup_icon ( theme, icon_name, NULL, 128, 1, GTK_TEXT_DIR_NONE, 0); if (paintable != NULL) g_object_set ( self, "icon-paintable", paintable, NULL); } } bazaar-org-bazaar-43ce9f7/src/bz-flatpak-entry.h000066400000000000000000000041551520414637400215700ustar00rootroot00000000000000/* 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" #include "bz-result.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); BzResult * bz_flatpak_entry_dup_runtime_result (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_bundle_path (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 bazaar-org-bazaar-43ce9f7/src/bz-flatpak-instance.c000066400000000000000000003426571520414637400222420ustar00rootroot00000000000000/* 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-bundle-result.h" #include "bz-flatpak-private.h" #include "bz-flatpak-repo.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; FlatpakInstallation *system_interactive; GFileMonitor *system_events; int system_mute; FlatpakInstallation *user; FlatpakInstallation *user_interactive; GFileMonitor *user_events; int user_mute; GMutex mute_mutex; GMutex notif_mutex; GPtrArray *notif_channels; DexFuture *notif_send; GMutex transactions_mutex; /* BzEntry* -> GPtrArray* -> GCancellable* */ GHashTable *ongoing_cancellables; }; 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); DexFuture * bz_flatpak_repo_new_from_url (const char *url, GCancellable *cancellable); 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); static DexFuture * ensure_runtime_remote_fiber (BzFlatpakInstance *self, FlatpakInstallation *installation, const char *bundle_path, GCancellable *cancellable); 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 DexFuture * retrieve_refs_for_enumerable_remote (BzFlatpakInstance *self, GCancellable *cancellable, const char *remote_name, FlatpakInstallation *installation, FlatpakRemote *remote); static DexFuture * retrieve_refs_for_noenumerable_remote (BzFlatpakInstance *self, GCancellable *cancellable, const char *remote_name, FlatpakInstallation *installation, FlatpakRemote *remote); 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); BZ_DEFINE_DATA ( transaction_operation_done, TransactionOperationDone, { TransactionData *parent; FlatpakTransaction *transaction; FlatpakTransactionOperation *operation; }, BZ_RELEASE_DATA (parent, transaction_data_unref); BZ_RELEASE_DATA (transaction, g_object_unref); BZ_RELEASE_DATA (operation, g_object_unref)); static DexFuture * transaction_operation_done_fiber (TransactionOperationDoneData *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_interactive); g_clear_object (&self->system_events); g_clear_object (&self->user); g_clear_object (&self->user_interactive); 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_clear_pointer (&self->ongoing_cancellables, g_hash_table_unref); g_mutex_clear (&self->transactions_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); self->ongoing_cancellables = g_hash_table_new_full ( g_direct_hash, g_direct_equal, g_object_unref, (GDestroyNotify) g_ptr_array_unref); g_mutex_init (&self->transactions_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 gboolean bz_flatpak_instance_cancel_task_for_entry (BzBackend *backend, BzEntry *entry) { BzFlatpakInstance *self = BZ_FLATPAK_INSTANCE (backend); g_autoptr (GMutexLocker) locker = NULL; GPtrArray *cancellables = NULL; locker = g_mutex_locker_new (&self->transactions_mutex); cancellables = g_hash_table_lookup (self->ongoing_cancellables, entry); if (cancellables == NULL) return FALSE; for (guint i = 0; i < cancellables->len; i++) { GCancellable *cancellable = NULL; cancellable = g_ptr_array_index (cancellables, i); g_cancellable_cancel (cancellable); } return TRUE; } 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; iface->cancel_task_for_entry = bz_flatpak_instance_cancel_task_for_entry; } 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) { g_autoptr (GFile) path = NULL; flatpak_installation_set_no_interaction (self->system, TRUE); path = flatpak_installation_get_path (self->system); self->system_interactive = flatpak_installation_new_for_path ( path, FALSE, NULL, NULL); g_assert (self->system_interactive != NULL); flatpak_installation_set_no_interaction (self->system_interactive, FALSE); 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) { g_autoptr (GFile) path = NULL; flatpak_installation_set_no_interaction (self->user, TRUE); path = flatpak_installation_get_path (self->user); self->user_interactive = flatpak_installation_new_for_path ( path, TRUE, NULL, NULL); g_assert (self->user_interactive != NULL); flatpak_installation_set_no_interaction (self->user_interactive, FALSE); 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); } #ifdef SANDBOXED_LIBFLATPAK if (g_getenv ("FLATPAK_BINARY") == NULL) { g_autofree char *flatpak_path = NULL; gint exit_status = 0; g_spawn_command_line_sync ("flatpak-spawn --host sh -c 'command -v flatpak'", &flatpak_path, NULL, &exit_status, NULL); if (exit_status == 0 && flatpak_path != NULL) g_setenv ("FLATPAK_BINARY", g_strstrip (flatpak_path), FALSE); else g_warning ("Failed to resolve host flatpak binary! User refs wont be updated"); } #endif 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; } // Downloading from user remotes in the Flatpak is unsupported. #ifndef SANDBOXED_LIBFLATPAK 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; } #endif 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) remote = NULL; FlatpakInstallation *installation = NULL; gboolean result = FALSE; bz_weak_get_or_return_reject (self, data->self); #define REPO_URL "https://dl.flathub.org/repo/flathub.flatpakrepo" #ifdef SANDBOXED_LIBFLATPAK if (self->system != NULL) { remote = flatpak_installation_get_remote_by_name ( self->system, "flathub", cancellable, NULL); installation = self->system; } if (remote == NULL) return dex_future_new_true (); #else if (self->user != NULL) { remote = flatpak_installation_get_remote_by_name ( self->user, "flathub", cancellable, NULL); installation = self->user; } if (remote == NULL && self->system != NULL) { remote = flatpak_installation_get_remote_by_name ( self->system, "flathub", cancellable, NULL); if (remote != NULL) installation = self->system; } #endif if (remote != NULL) { flatpak_remote_set_disabled (remote, FALSE); flatpak_remote_set_noenumerate (remote, FALSE); flatpak_remote_set_gpg_verify (remote, TRUE); result = flatpak_installation_modify_remote ( installation, remote, cancellable, &local_error); if (!result) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_REMOTE_SYNCHRONIZATION_FAILURE, "Failed to modify existing system flathub remote: %s", local_error->message); } else { g_autoptr (SoupMessage) message = NULL; g_autoptr (GOutputStream) output = NULL; g_autoptr (GBytes) bytes = NULL; g_autoptr (FlatpakRemote) imported = 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)); imported = flatpak_remote_new_from_file ("flathub", bytes, &local_error); if (imported == 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 (imported, TRUE); result = flatpak_installation_add_remote ( installation, imported, 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 (); } DexFuture * bz_flatpak_repo_new_from_url (const char *url, GCancellable *cancellable) { g_autoptr (SoupMessage) message = NULL; g_autoptr (GOutputStream) output = NULL; g_autoptr (GBytes) bytes = NULL; g_autoptr (GKeyFile) key_file = NULL; BzFlatpakRepo *repo = NULL; g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autofree char *name = NULL; g_autofree char *title = NULL; g_autofree char *repo_url = NULL; g_autofree char *homepage = NULL; g_autofree char *comment = NULL; g_autofree char *description = NULL; g_autofree char *icon = NULL; g_autofree char *gpg_key = NULL; g_autofree char *default_branch = NULL; g_autofree char *filter = NULL; g_autoptr (GError) bool_error = NULL; gboolean gpg_verify = FALSE; name = g_path_get_basename (url); { char *dot = strrchr (name, '.'); if (dot != NULL) *dot = '\0'; } message = soup_message_new (SOUP_METHOD_GET, 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", url, local_error->message); bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output)); key_file = g_key_file_new (); result = g_key_file_load_from_bytes (key_file, bytes, G_KEY_FILE_NONE, &local_error); if (!result) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to parse flatpakrepo file from %s: %s", url, local_error->message); title = g_key_file_get_string (key_file, "Flatpak Repo", "Title", NULL); repo_url = g_key_file_get_string (key_file, "Flatpak Repo", "Url", NULL); homepage = g_key_file_get_string (key_file, "Flatpak Repo", "Homepage", NULL); comment = g_key_file_get_string (key_file, "Flatpak Repo", "Comment", NULL); description = g_key_file_get_string (key_file, "Flatpak Repo", "Description", NULL); icon = g_key_file_get_string (key_file, "Flatpak Repo", "Icon", NULL); gpg_key = g_key_file_get_string (key_file, "Flatpak Repo", "GPGKey", NULL); default_branch = g_key_file_get_string (key_file, "Flatpak Repo", "DefaultBranch", NULL); filter = g_key_file_get_string (key_file, "Flatpak Repo", "Filter", NULL); gpg_verify = g_key_file_get_boolean (key_file, "Flatpak Repo", "GPGVerify", &bool_error); if (bool_error != NULL) { gpg_verify = gpg_key != NULL; g_clear_error (&bool_error); } repo = g_object_new (BZ_TYPE_FLATPAK_REPO, "name", name, "title", title, "url", repo_url, "homepage", homepage, "comment", comment, "description", description, "icon", icon, "gpg-key", gpg_key, "default-branch", default_branch, "filter", filter, "gpg-verify", gpg_verify, NULL); return dex_future_new_for_object (repo); } static DexFuture * load_local_ref_fiber (LoadLocalRefData *data) { g_autoptr (BzFlatpakInstance) self = NULL; GFile *file = data->file; GCancellable *cancellable = data->cancellable; gboolean result = FALSE; g_autoptr (GError) local_error = NULL; g_autofree char *uri = NULL; g_autofree char *path = NULL; g_autofree char *runtime_repo_url = NULL; bz_weak_get_or_return_reject (self, data->self); 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); { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_PRESENT_ID); bz_backend_notification_set_generic_id (notif, name); send_notif_all (self, notif, TRUE); } return dex_future_new_take_string (g_steal_pointer (&name)); } else /* This is a bundle ref */ { g_autoptr (FlatpakBundleRef) bref = NULL; const char *name = NULL; const char *origin = NULL; FlatpakInstallation *add_to_installation = NULL; g_autoptr (FlatpakRemote) remote = NULL; g_autoptr (BzFlatpakEntry) entry = NULL; g_autoptr (BzFlatpakRepo) runtime_repo = NULL; g_autoptr (GBytes) appstream_gz = NULL; g_autoptr (GBytes) appstream = NULL; g_autoptr (AsComponent) component = NULL; g_autoptr (BzFlatpakBundleResult) bundle_result = NULL; if (path == NULL) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Cannot load '%s' as a flatpak bundle: URI is not a local file", uri); 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); name = flatpak_ref_get_name (FLATPAK_REF (bref)); origin = flatpak_bundle_ref_get_origin (bref); runtime_repo_url = flatpak_bundle_ref_get_runtime_repo_url (bref); if (runtime_repo_url != NULL) { g_autoptr (GError) repo_error = NULL; runtime_repo = dex_await_object ( bz_flatpak_repo_new_from_url (runtime_repo_url, cancellable), &repo_error); if (runtime_repo == NULL) g_warning ("Failed to parse runtime repo from %s: %s", runtime_repo_url, repo_error->message); } if (self->system != NULL) add_to_installation = self->system; else if (self->user != NULL) add_to_installation = self->user; /* First check if we already should have the origin remote installed */ if (self->system != NULL) { g_autoptr (GPtrArray) remotes = NULL; remotes = flatpak_installation_list_remotes ( self->system, NULL, NULL); if (remotes != NULL) { for (guint i = 0; i < remotes->len; i++) { FlatpakRemote *existing = NULL; const char *url = NULL; existing = g_ptr_array_index (remotes, i); url = flatpak_remote_get_url (existing); if (url != NULL && g_strcmp0 (url, origin) == 0) { remote = g_object_ref (existing); add_to_installation = NULL; break; } } } } if (self->user != NULL) { g_autoptr (GPtrArray) remotes = NULL; remotes = flatpak_installation_list_remotes ( self->user, NULL, NULL); if (remotes != NULL) { for (guint i = 0; i < remotes->len; i++) { FlatpakRemote *existing = NULL; const char *url = NULL; existing = g_ptr_array_index (remotes, i); url = flatpak_remote_get_url (existing); if (url != NULL && g_strcmp0 (url, origin) == 0) { remote = g_object_ref (existing); add_to_installation = NULL; break; } } } } if (add_to_installation != NULL) { g_autoptr (FlatpakRemote) config_remote = NULL; g_autofree char *remote_name = NULL; /* Configure and sync the new remote */ remote_name = g_strdup_printf ("%s-bazaar-origin", name); config_remote = flatpak_remote_new (remote_name); flatpak_remote_set_url (config_remote, origin); flatpak_remote_set_disabled (config_remote, FALSE); flatpak_remote_set_noenumerate (config_remote, FALSE); flatpak_remote_set_gpg_verify (config_remote, TRUE); result = flatpak_installation_add_remote ( add_to_installation, config_remote, FALSE, cancellable, NULL); if (result) { { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_INVALIDATE_REMOTES); send_notif_all (self, notif, TRUE); } remote = flatpak_installation_get_remote_by_name ( add_to_installation, remote_name, cancellable, NULL); if (remote != NULL) { { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_REMOTE_SYNC_START); bz_backend_notification_set_remote_name (notif, remote_name); send_notif_all (self, notif, TRUE); } result = dex_await ( retrieve_refs_for_enumerable_remote ( self, cancellable, remote_name, add_to_installation, remote), NULL); { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_REMOTE_SYNC_FINISH); bz_backend_notification_set_remote_name (notif, remote_name); send_notif_all (self, notif, TRUE); } } } } appstream_gz = flatpak_bundle_ref_get_appstream (bref); if (appstream_gz != 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 { g_autoptr (XbBuilderSource) source = NULL; 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 { g_autoptr (XbSilo) silo = NULL; 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), remote, 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); bundle_result = g_object_new (BZ_TYPE_FLATPAK_BUNDLE_RESULT, "entry", entry, "runtime-repo", runtime_repo, NULL); return dex_future_new_for_object (g_steal_pointer (&bundle_result)); } } 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); { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_REMOTE_SYNC_START); bz_backend_notification_set_remote_name (notif, name); send_notif_all (self, notif, TRUE); } 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 DexFuture * retrieve_refs_for_enumerable_remote (BzFlatpakInstance *self, GCancellable *cancellable, const char *remote_name, FlatpakInstallation *installation, FlatpakRemote *remote) { 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; 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, NULL, NULL, 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 (BzFlatpakInstance *self, GCancellable *cancellable, const char *remote_name, FlatpakInstallation *installation, FlatpakRemote *remote) { g_autoptr (GError) local_error = NULL; g_autoptr (GPtrArray) installed_apps = NULL; guint matched = 0; 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; g_autoptr (BzFlatpakInstance) self = NULL; const char *remote_name = NULL; gboolean is_noenumerate = FALSE; g_autoptr (DexFuture) ret = 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); /* the fedora flatpak repos cause too many issues */ if (strstr (remote_name, "fedora") != NULL) is_noenumerate = TRUE; #ifdef SANDBOXED_LIBFLATPAK if (is_noenumerate || installation == self->user) #else if (is_noenumerate) #endif ret = retrieve_refs_for_noenumerable_remote ( self, data->parent->cancellable, remote_name, installation, remote); else ret = retrieve_refs_for_enumerable_remote ( self, data->parent->cancellable, remote_name, installation, remote); { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_REMOTE_SYNC_FINISH); bz_backend_notification_set_remote_name (notif, remote_name); send_notif_all (self, notif, TRUE); } return g_steal_pointer (&ret); } 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; } #ifndef SANDBOXED_LIBFLATPAK if (self->user != NULL) #else if (self->user != NULL && g_getenv ("FLATPAK_BINARY") != NULL) #endif { 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 * ensure_runtime_remote_fiber (BzFlatpakInstance *self, FlatpakInstallation *installation, const char *bundle_path, GCancellable *cancellable) { g_autoptr (GError) local_error = NULL; g_autoptr (GFile) bundle_file = NULL; g_autoptr (FlatpakBundleRef) bundle_ref = NULL; g_autofree char *runtime_repo_url = NULL; g_autoptr (SoupMessage) message = NULL; g_autoptr (GOutputStream) output = NULL; g_autoptr (GBytes) bytes = NULL; g_autoptr (FlatpakRemote) remote = NULL; g_autofree char *remote_name = NULL; g_autoptr (GKeyFile) key_file = NULL; g_autofree char *gpg_key_base64 = NULL; g_autoptr (GBytes) gpg_key_bytes = NULL; bundle_file = g_file_new_for_path (bundle_path); bundle_ref = flatpak_bundle_ref_new (bundle_file, NULL); if (bundle_ref == NULL) return dex_future_new_true (); runtime_repo_url = flatpak_bundle_ref_get_runtime_repo_url (bundle_ref); if (runtime_repo_url == NULL) return dex_future_new_true (); remote_name = g_path_get_basename (runtime_repo_url); { char *dot = strrchr (remote_name, '.'); if (dot != NULL) *dot = '\0'; } { g_autoptr (FlatpakRemote) existing = NULL; existing = flatpak_installation_get_remote_by_name ( installation, remote_name, cancellable, NULL); if (existing != NULL) return dex_future_new_true (); } message = soup_message_new (SOUP_METHOD_GET, runtime_repo_url); output = g_memory_output_stream_new_resizable (); dex_await ( bz_send_with_global_http_session_then_splice_into (message, output), &local_error); if (local_error != NULL) { g_warning ("failed to fetch %s: %s", runtime_repo_url, local_error->message); return dex_future_new_true (); } bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output)); key_file = g_key_file_new (); if (!g_key_file_load_from_bytes (key_file, bytes, G_KEY_FILE_NONE, NULL)) return dex_future_new_true (); gpg_key_base64 = g_key_file_get_string (key_file, "Flatpak Repo", "GPGKey", NULL); if (gpg_key_base64 == NULL) return dex_future_new_true (); { gsize gpg_key_len = 0; guchar *gpg_key_data = g_base64_decode (gpg_key_base64, &gpg_key_len); gpg_key_bytes = g_bytes_new_take (gpg_key_data, gpg_key_len); } remote = flatpak_remote_new_from_file (remote_name, bytes, &local_error); if (remote == NULL) { g_warning ("failed to parse flatpakrepo from %s: %s", runtime_repo_url, local_error->message); return dex_future_new_true (); } flatpak_remote_set_gpg_verify (remote, TRUE); flatpak_remote_set_gpg_key (remote, gpg_key_bytes); if (!flatpak_installation_add_remote ( installation, remote, TRUE, cancellable, &local_error)) { g_warning ("failed to add remote '%s': %s", remote_name, local_error->message); g_clear_error (&local_error); } return dex_future_new_true (); } 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; const char *bundle_path = NULL; FlatpakInstallation *installation = NULL; entry = g_ptr_array_index (installations, i); bundle_path = bz_flatpak_entry_get_bundle_path (entry); if (bundle_path == NULL) continue; installation = bz_flatpak_entry_is_user (entry) ? self->user_interactive : self->system_interactive; if (bundle_path != NULL && installation != NULL) dex_await ( ensure_runtime_remote_fiber (self, installation, bundle_path, cancellable), NULL); } for (guint i = 0; i < installations->len; i++) { BzFlatpakEntry *entry = NULL; const char *bundle_path = 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); bundle_path = bz_flatpak_entry_get_bundle_path (entry); 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_interactive : self->system_interactive, 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); } if (bundle_path != NULL) /* Prioritize bundle installation */ { g_autoptr (GFile) file = NULL; file = g_file_new_for_path (bundle_path); result = flatpak_transaction_add_install_bundle ( transaction, file, NULL, &local_error); } else 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_interactive, cancellable, &local_error); else if (!is_user && sys_transaction == NULL) sys_transaction = flatpak_transaction_new_for_installation ( self->system_interactive, 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_interactive : self->system_interactive, 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)); } } g_mutex_lock (&self->transactions_mutex); #define REGISTER_CANCELLABLES(entry) \ G_STMT_START \ { \ GPtrArray *cancellables = NULL; \ \ cancellables = g_hash_table_lookup (self->ongoing_cancellables, entry); \ if (cancellables != NULL) \ g_ptr_array_add (cancellables, g_object_ref (cancellable)); \ else \ { \ cancellables = g_ptr_array_new_with_free_func (g_object_unref); \ g_ptr_array_add (cancellables, g_object_ref (cancellable)); \ g_hash_table_replace (self->ongoing_cancellables, g_object_ref (entry), cancellables); \ } \ } \ G_STMT_END if (installations != NULL) { for (guint i = 0; i < installations->len; i++) { BzEntry *entry = NULL; entry = g_ptr_array_index (installations, i); REGISTER_CANCELLABLES (entry); } } if (removals != NULL) { for (guint i = 0; i < removals->len; i++) { BzEntry *entry = NULL; entry = g_ptr_array_index (removals, i); REGISTER_CANCELLABLES (entry); } } if (updates != NULL) { for (guint i = 0; i < updates->len; i++) { BzEntry *entry = NULL; entry = g_ptr_array_index (updates, i); REGISTER_CANCELLABLES (entry); } } #undef REGISTER_CANCELLABLES g_mutex_unlock (&self->transactions_mutex); 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); g_mutex_lock (&self->transactions_mutex); #define UNREGISTER_CANCELLABLES(entry) \ G_STMT_START \ { \ GPtrArray *cancellables = NULL; \ \ cancellables = g_hash_table_lookup (self->ongoing_cancellables, entry); \ if (cancellables != NULL) \ { \ g_ptr_array_remove (cancellables, cancellable); \ if (cancellables->len == 0) \ g_hash_table_remove (self->ongoing_cancellables, entry); \ } \ } \ G_STMT_END if (installations != NULL) { for (guint i = 0; i < installations->len; i++) { BzEntry *entry = NULL; entry = g_ptr_array_index (installations, i); UNREGISTER_CANCELLABLES (entry); } } if (removals != NULL) { for (guint i = 0; i < removals->len; i++) { BzEntry *entry = NULL; entry = g_ptr_array_index (removals, i); UNREGISTER_CANCELLABLES (entry); } } if (updates != NULL) { for (guint i = 0; i < updates->len; i++) { BzEntry *entry = NULL; entry = g_ptr_array_index (updates, i); UNREGISTER_CANCELLABLES (entry); } } #undef UNREGISTER_CANCELLABLES g_mutex_unlock (&self->transactions_mutex); 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_interactive == 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 (GMutexLocker) locker = NULL; g_autoptr (BzFlatpakInstance) self = NULL; g_autoptr (BzBackendTransactionOpPayload) payload = NULL; g_autoptr (TransactionOperationDoneData) future_data = NULL; g_autoptr (DexFuture) future = NULL; bz_weak_get_or_return (self, data->self); locker = g_mutex_locker_new (&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))); if (result == FLATPAK_TRANSACTION_RESULT_NO_CHANGE) return; future_data = transaction_operation_done_data_new (); future_data->parent = transaction_data_ref (data); future_data->transaction = g_object_ref (transaction); future_data->operation = g_object_ref (operation); future = dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) transaction_operation_done_fiber, transaction_operation_done_data_ref (future_data), transaction_operation_done_data_unref); g_ptr_array_add (data->send_futures, g_steal_pointer (&future)); } 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 DexFuture * transaction_operation_done_fiber (TransactionOperationDoneData *data) { g_autoptr (BzFlatpakInstance) self = NULL; FlatpakTransaction *transaction = data->transaction; FlatpakTransactionOperation *operation = data->operation; g_autoptr (GError) local_error = 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; const char *version = NULL; FlatpakInstallation *installation = NULL; g_autoptr (FlatpakInstalledRef) iref = NULL; g_autoptr (FlatpakRef) parsed_ref = NULL; bz_weak_get_or_return_reject (self, data->parent->self); 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 (); } installation = flatpak_transaction_get_installation (transaction); origin = flatpak_transaction_operation_get_remote (operation); ref = flatpak_transaction_operation_get_ref (operation); is_user = installation == self->user_interactive; unique_id = bz_flatpak_ref_parts_format_unique (origin, ref, is_user); if (op_type == FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE) { g_autoptr (FlatpakRemote) remote = NULL; { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_INVALIDATE_REMOTES); send_notif_all (self, notif, TRUE); } remote = flatpak_installation_get_remote_by_name ( installation, origin, NULL, NULL); if (remote != NULL) { { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_REMOTE_SYNC_START); bz_backend_notification_set_remote_name (notif, origin); send_notif_all (self, notif, TRUE); } dex_await ( retrieve_refs_for_noenumerable_remote ( self, NULL, origin, installation, remote), NULL); { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_REMOTE_SYNC_FINISH); bz_backend_notification_set_remote_name (notif, origin); send_notif_all (self, notif, TRUE); } } } if (notif_kind == BZ_BACKEND_NOTIFICATION_KIND_INSTALL_DONE || notif_kind == BZ_BACKEND_NOTIFICATION_KIND_UPDATE_DONE) { 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); } } { g_autoptr (BzBackendNotification) notif = NULL; 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); } return dex_future_new_true (); } 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); } bazaar-org-bazaar-43ce9f7/src/bz-flatpak-instance.h000066400000000000000000000033101520414637400222230ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-flatpak-private.h000066400000000000000000000034411520414637400220760ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-flatpak-repo.txt000066400000000000000000000013101520414637400217520ustar00rootroot00000000000000prefix=bz name=flatpak_repo parent-prefix=g parent-name=object author=AUTOGEN property=name char G_TYPE_STRING string property=title char G_TYPE_STRING string property=url char G_TYPE_STRING string property=homepage char G_TYPE_STRING string property=comment char G_TYPE_STRING string property=description char G_TYPE_STRING string property=icon char G_TYPE_STRING string property=gpg_key char G_TYPE_STRING string property=default_branch char G_TYPE_STRING string property=filter char G_TYPE_STRING string property=is_user gboolean G_TYPE_BOOLEAN boolean property=disabled gboolean G_TYPE_BOOLEAN boolean property=noenumerate gboolean G_TYPE_BOOLEAN boolean property=gpg_verify gboolean G_TYPE_BOOLEAN boolean bazaar-org-bazaar-43ce9f7/src/bz-full-view.blp000066400000000000000000000750271520414637400212550ustar00rootroot00000000000000using 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"] }; } } 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: 100; 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; screenshots.compact: true; header_bar.show-title: false; } } child: Adw.BreakpointBin breakpoint_bin { width-request: 360; height-request: 100; Adw.Breakpoint breakpoint { condition ("max-width: 525px") 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"); // visible: bind template.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.is-bundle as ; // revealed: true; // } Adw.Banner { title: _("This is a local preview, some details may differ from the published listing"); visible: bind $metainfo_banner_visible(template.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.remote-repo-name) as ; revealed: true; button-label: _("Preview Store Appearance"); button-clicked => $preview_other_metainfo_cb(template); } Adw.Clamp { maximum-size: 910; tightening-threshold: 576; 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>.ui-entry as <$BzResult>.object as <$BzEntry>.icon-paintable; visible: bind $invert_boolean($is_null(template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.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>.ui-entry as <$BzResult>.object as <$BzEntry>.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; lines: 2; ellipsize: end; wrap-mode: word_char; natural-wrap-mode: word; label: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.title; } Box { styles [ "bz-debug", ] halign: start; orientation: horizontal; spacing: 6; visible: bind template.state as <$BzStateInfo>.debug-mode; Button { icon-name: "edit-copy-symbolic"; clicked => $copy_id_cb(template); } Label { styles [ "bz-monospace", ] selectable: true; label: bind template.entry-group as <$BzEntryGroup>.id; } Button { label: "Inspect UI Entry"; clicked => $debug_id_inspect_cb(template); } } $BzDeveloperBadge { entry: bind template.ui-entry as <$BzResult>.object as <$BzEntry>; } Box { layout-manager: Adw.WrapLayout { child-spacing: 4; line-spacing: 0; }; 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 { use-underline: true; label: _("_Support"); icon-name: "heart-filled-symbolic"; }; } $BzFavoriteButton { state: bind template.state as <$BzStateInfo>; entry: bind template.ui-entry as <$BzResult>.object as <$BzEntry>; } } } $BzInstallControls wide_install_controls { wide: true; entry-group: bind template.entry-group as <$BzEntryGroup>; state: bind template.state as <$BzStateInfo>; settings: bind template.state as <$BzStateInfo>.settings; update => $update_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 try {$get_size_label( $is_zero(template.entry-group as <$BzEntryGroup>.removable) as , template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.runtime as <$BzResult>.object as <$BzEntry>.installed, template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.runtime as <$BzResult>.object as <$BzEntry>.size, ) as , $get_size_label($is_zero(template.entry-group as <$BzEntryGroup>.removable) as ,0,0) 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 { 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 { 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; }; } } } $BzInstallControls narrow_install_controls { wide: false; visible: false; entry-group: bind template.entry-group as <$BzEntryGroup>; state: bind template.state as <$BzStateInfo>; settings: bind template.state as <$BzStateInfo>.settings; update => $update_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: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.screenshot-paintables; } } Adw.Clamp { maximum-size: 910; tightening-threshold: 576; 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 $invert_boolean($is_zero(other_apps_model.n-items) as ) 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: bind $get_dev_apps_max_children_per_line(other_apps_model.model) as ; bind-widget => $bind_app_tile_cb(template); unbind-widget => $unbind_app_tile_cb(template); model: SliceListModel other_apps_model { 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; 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; }; } } }; } }; }; }; }; }; } }; }; } bazaar-org-bazaar-43ce9f7/src/bz-full-view.c000066400000000000000000000626551520414637400207250ustar00rootroot00000000000000/* 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-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-callbacks.h" #include "bz-context-tile.h" #include "bz-developer-badge.h" #include "bz-dynamic-list-view.h" #include "bz-entry-inspector.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-install-controls.h" #include "bz-license-dialog.h" #include "bz-metainfo-preview.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" #include "bz-util.h" #include "bz-window.h" struct _BzFullView { AdwBin parent_instance; BzStateInfo *state; BzTransactionManager *transactions; BzEntryGroup *group; DexFuture *ui_future; BzResult *ui_entry; BzResult *runtime; BzResult *group_model; gboolean show_sidebar; /* Template widgets */ GtkScrolledWindow *main_scroll; AdwViewStack *stack; GtkWidget *shadow_overlay; GtkToggleButton *description_toggle; }; G_DEFINE_FINAL_TYPE (BzFullView, bz_full_view, ADW_TYPE_BIN) enum { PROP_0, PROP_STATE, PROP_ENTRY_GROUP, PROP_UI_ENTRY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_UPDATE, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void bz_full_view_dispose (GObject *object) { BzFullView *self = BZ_FULL_VIEW (object); dex_clear (&self->ui_future); 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->runtime); g_clear_object (&self->group_model); 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; 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: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean is_scrolled_down (gpointer object, double value) { return value > 100.0; } 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 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 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 int get_dev_apps_max_children_per_line (gpointer object, GListModel *model) { if (!model) return 3; return g_list_model_get_n_items (model) > 2 ? 3 : 2; } 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); 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 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; AdwBreakpointBin *bin = NULL; BzEntry *ui_entry = NULL; if (self->group == NULL) return; ui_entry = bz_result_get_object (self->ui_entry); bin = bz_stats_dialog_new (NULL, NULL, 0); dialog = adw_dialog_new (); adw_dialog_set_content_width (dialog, 1250); adw_dialog_set_content_height (dialog, 750); adw_dialog_set_child (dialog, GTK_WIDGET (bin)); g_object_bind_property (ui_entry, "download-stats", bin, "model", G_BINDING_SYNC_CREATE); g_object_bind_property (ui_entry, "download-stats-per-country", bin, "country-model", G_BINDING_SYNC_CREATE); g_object_bind_property (ui_entry, "total-downloads", bin, "total-downloads", G_BINDING_SYNC_CREATE); adw_dialog_present (dialog, GTK_WIDGET (self)); bz_stats_dialog_animate_open (BZ_STATS_DIALOG (bin)); } 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; 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_safety_dialog_new (ui_entry); adw_dialog_present (dialog, GTK_WIDGET (self)); } static void update_cb (BzFullView *self, GListModel *entries, BzInstallControls *controls) { g_signal_emit (self, signals[SIGNAL_UPDATE], 0, entries); } static DexFuture * reap_user_data_done (DexFuture *future, GWeakRef *wr) { g_autoptr (BzFullView) self = NULL; g_autoptr (GError) local_error = NULL; dex_future_get_value (future, &local_error); self = g_weak_ref_get (wr); if (self != NULL && local_error != NULL) bz_show_error_for_widget ( GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (self))), _ ("Failed to Remove User Data"), local_error->message); return dex_future_new_true (); } static void delete_user_data_cb (BzFullView *self, GtkButton *button) { g_autoptr (DexFuture) future = NULL; g_return_if_fail (BZ_IS_FULL_VIEW (self)); if (self->group == NULL) return; future = bz_entry_group_reap_user_data (self->group); if (future != NULL) dex_future_disown (dex_future_finally ( dex_ref (future), (DexFutureCallback) reap_user_data_done, bz_track_weak (self), bz_weak_release)); } 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) { if (self->group == NULL) return; gtk_widget_activate_action (GTK_WIDGET (self), "window.addons-group", "s", bz_entry_group_get_id (self->group)); } 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 gboolean metainfo_banner_visible (gpointer object, const char *remote_name) { return g_strcmp0 (remote_name, "local-preview") == 0; } static void preview_other_metainfo_cb (BzFullView *self, AdwBanner *banner) { GtkWidget *window = NULL; window = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (self))); bz_window_push_page (BZ_WINDOW (window), create_entry_group_preview_page (self->group)); } static void copy_id_cb (BzFullView *self, GtkButton *button) { const char *id = NULL; GdkClipboard *clipboard = NULL; if (self->group == NULL) return; id = bz_entry_group_get_id (self->group); clipboard = gdk_display_get_clipboard (gdk_display_get_default ()); gdk_clipboard_set_text (clipboard, id); } static void debug_id_inspect_cb (BzFullView *self, GtkButton *button) { g_autofree char *unique_id = NULL; g_autoptr (GtkStringObject) string = NULL; g_autoptr (BzResult) result = NULL; if (self->group == NULL) return; unique_id = bz_entry_group_dup_ui_entry_id (self->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_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); 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_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_INSTALL_CONTROLS); 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); bz_widget_class_bind_all_context_tile_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_callback (widget_class, is_scrolled_down); gtk_widget_class_bind_template_callback (widget_class, age_rating_cb); gtk_widget_class_bind_template_callback (widget_class, format_as_link); 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, get_dev_apps_max_children_per_line); gtk_widget_class_bind_template_callback (widget_class, more_apps_button_clicked_cb); 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, formfactor_cb); gtk_widget_class_bind_template_callback (widget_class, safety_cb); gtk_widget_class_bind_template_callback (widget_class, update_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, 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, metainfo_banner_visible); gtk_widget_class_bind_template_callback (widget_class, preview_other_metainfo_cb); gtk_widget_class_bind_template_callback (widget_class, copy_id_cb); gtk_widget_class_bind_template_callback (widget_class, debug_id_inspect_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); } static DexFuture * on_ui_entry_resolved (DexFuture *future, GWeakRef *wr) { g_autoptr (BzFullView) self = NULL; BzEntry *ui_entry = NULL; g_autoptr (BzResult) runtime_result = NULL; const GValue *value = NULL; bz_weak_get_or_return_reject (self, wr); value = dex_future_get_value (future, NULL); if (value != NULL && G_VALUE_HOLDS_OBJECT (value)) { ui_entry = g_value_get_object (value); if (BZ_IS_FLATPAK_ENTRY (ui_entry)) self->runtime = bz_flatpak_entry_dup_runtime_result (BZ_FLATPAK_ENTRY (ui_entry)); } return dex_future_new_for_boolean (TRUE); } 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; dex_clear (&self->ui_future); g_clear_object (&self->group); g_clear_object (&self->ui_entry); g_clear_object (&self->runtime); 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)) { BzEntry *entry = NULL; g_autoptr (GListStore) store = NULL; g_autoptr (DexFuture) future = NULL; g_autoptr (DexFuture) object_future = NULL; GWeakRef *wr = 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); object_future = dex_future_new_for_object (entry); wr = bz_track_weak (self); dex_unref (on_ui_entry_resolved (object_future, wr)); bz_weak_release (wr); } else { g_autoptr (DexFuture) future = NULL; future = bz_entry_group_dup_all_into_store (group); self->group_model = bz_result_new (future); if (self->ui_entry != NULL) { g_autoptr (DexFuture) ui_future = NULL; ui_future = bz_result_dup_future (self->ui_entry); ui_future = dex_future_then ( ui_future, (DexFutureCallback) on_ui_entry_resolved, bz_track_weak (self), bz_weak_release); self->ui_future = g_steal_pointer (&ui_future); } } adw_view_stack_set_visible_child_name (self->stack, "content"); } else adw_view_stack_set_visible_child_name (self->stack, "empty"); 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; } bazaar-org-bazaar-43ce9f7/src/bz-full-view.h000066400000000000000000000030761520414637400207220ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-global-net.c000066400000000000000000000235011520414637400210220ustar00rootroot00000000000000/* 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 "config.h" #include #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); GProxyResolver * bz_get_default_proxy_resolver (void) { static GProxyResolver *resolver = NULL; if (g_once_init_enter_pointer (&resolver)) { pxProxyFactory *factory = NULL; g_auto (GStrv) proxies = NULL; g_autoptr (GProxyResolver) resolver_instance = NULL; factory = px_proxy_factory_new (); /* blocking */ proxies = px_proxy_factory_get_proxies (factory, DONATE_LINK); g_clear_pointer (&factory, px_proxy_factory_free); resolver_instance = g_simple_proxy_resolver_new ( proxies != NULL && *proxies != NULL ? proxies[0] : NULL, NULL); g_once_init_leave_pointer (&resolver, g_steal_pointer (&resolver_instance)); } return resolver; } 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_autoptr (SoupSession) session_instance = NULL; session_instance = soup_session_new (); soup_session_set_proxy_resolver (session_instance, bz_get_default_proxy_resolver ()); g_once_init_leave_pointer (&session, g_steal_pointer (&session_instance)); } 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); } bazaar-org-bazaar-43ce9f7/src/bz-global-net.h000066400000000000000000000033041520414637400210260ustar00rootroot00000000000000/* 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 GProxyResolver * bz_get_default_proxy_resolver (void); 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 bazaar-org-bazaar-43ce9f7/src/bz-gnome-shell-search-provider.c000066400000000000000000000354751520414637400243200ustar00rootroot00000000000000/* 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-finished-search-query.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; BzFinishedSearchQuery *finished = NULL; GPtrArray *results = NULL; g_autoptr (GVariantBuilder) builder = NULL; value = dex_future_get_value (future, &local_error); if (value != NULL) { finished = g_value_get_object (value); results = bz_finished_search_query_get_results (finished); 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 */ bazaar-org-bazaar-43ce9f7/src/bz-gnome-shell-search-provider.h000066400000000000000000000034111520414637400243060ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-group-tile-css-watcher.c000066400000000000000000000235321520414637400233120ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-group-tile-css-watcher.h000066400000000000000000000031021520414637400233060ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-hardware-support-dialog.blp000066400000000000000000000016501520414637400240760ustar00rootroot00000000000000using 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", ] } } } }; } } bazaar-org-bazaar-43ce9f7/src/bz-hardware-support-dialog.c000066400000000000000000000235151520414637400235470ustar00rootroot00000000000000/* 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); } bazaar-org-bazaar-43ce9f7/src/bz-hardware-support-dialog.h000066400000000000000000000021771520414637400235550ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-hash-table-object.txt000066400000000000000000000002571520414637400226520ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-hook-dialog-option.txt000066400000000000000000000003431520414637400230750ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-hook-dialog.txt000066400000000000000000000007041520414637400215700ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-hook.txt000066400000000000000000000011201520414637400203240ustar00rootroot00000000000000prefix=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 view_app before_transaction after_transaction enum=bz hook_return_status continue stop confirm deny enum=bz hook_transaction_type install update removal 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 property=check_appid_regex char G_TYPE_STRING string bazaar-org-bazaar-43ce9f7/src/bz-hooks.c000066400000000000000000000521551520414637400201300ustar00rootroot00000000000000/* bz-hooks.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::HOOKS" #include #include "bz-env.h" #include "bz-error.h" #include "bz-hooks.h" #include "bz-util.h" BZ_DEFINE_DATA ( execute_hook, ExecuteHook, { BzHook *hook; BzHookTransactionType ts_type; char *ts_appid; BzEntryGroup *group; }, BZ_RELEASE_DATA (hook, g_object_unref); BZ_RELEASE_DATA (ts_appid, g_free); BZ_RELEASE_DATA (group, g_object_unref)) BZ_DEFINE_DATA ( run_emission, RunEmission, { GListModel *hooks; BzHookSignal signal; BzHookTransactionType ts_type; char *ts_appid; BzEntryGroup *group; }, BZ_RELEASE_DATA (hooks, g_object_unref); BZ_RELEASE_DATA (ts_appid, g_free); BZ_RELEASE_DATA (group, g_object_unref)) BZ_DEFINE_DATA ( dialog, Dialog, { char *id; AdwDialog *dialog; }, BZ_RELEASE_DATA (id, g_free); BZ_RELEASE_DATA (dialog, g_object_unref)); static DexFuture * execute_hook_fiber (ExecuteHookData *data); static DexFuture * run_emission_fiber (RunEmissionData *data); DexFuture * bz_execute_hook (BzHook *hook, BzHookTransactionType ts_type, const char *ts_appid, BzEntryGroup *group) { g_autoptr (ExecuteHookData) data = NULL; dex_return_error_if_fail (BZ_IS_HOOK (hook)); data = execute_hook_data_new (); data->hook = g_object_ref (hook); data->ts_type = ts_type; data->ts_appid = bz_maybe_strdup (ts_appid); data->group = bz_object_maybe_ref (group); return dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) execute_hook_fiber, execute_hook_data_ref (data), execute_hook_data_unref); } DexFuture * bz_run_hook_emission (GListModel *hooks, BzHookSignal signal, BzHookTransactionType ts_type, const char *ts_appid, BzEntryGroup *group) { g_autoptr (RunEmissionData) data = NULL; dex_return_error_if_fail (G_IS_LIST_MODEL (hooks)); data = run_emission_data_new (); data->hooks = g_object_ref (hooks); data->signal = signal; data->ts_type = ts_type; data->ts_appid = bz_maybe_strdup (ts_appid); data->group = bz_object_maybe_ref (group); return dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) run_emission_fiber, execute_hook_data_ref (data), execute_hook_data_unref); } static DexFuture * execute_hook_fiber (ExecuteHookData *data) { BzHook *hook = data->hook; BzHookTransactionType ts_type = data->ts_type; char *ts_appid = data->ts_appid; BzEntryGroup *group = data->group; BzHookSignal signal = 0; g_autoptr (GEnumClass) signal_enum_class = NULL; g_autoptr (GEnumClass) ts_type_enum_class = NULL; GEnumValue *signal_enum = NULL; GEnumValue *ts_type_enum = NULL; 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; signal = bz_hook_get_when (hook); switch (signal) { case BZ_HOOK_SIGNAL_BEFORE_TRANSACTION: case BZ_HOOK_SIGNAL_AFTER_TRANSACTION: dex_return_error_if_fail (ts_appid != NULL); break; case BZ_HOOK_SIGNAL_VIEW_APP: default: dex_return_error_if_fail (BZ_IS_ENTRY_GROUP (group)); break; } signal_enum_class = g_type_class_ref (BZ_TYPE_HOOK_SIGNAL); ts_type_enum_class = g_type_class_ref (BZ_TYPE_HOOK_TRANSACTION_TYPE); signal_enum = g_enum_get_value (signal_enum_class, signal); ts_type_enum = g_enum_get_value (ts_type_enum_class, ts_type); 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 dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_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) dialog_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 dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_CONTINUE); } if (dialog_default_response == NULL) { g_warning ("Main Config: dialog definition must have a default response, skipping this hook"); return dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_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 dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_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 dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_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 dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_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); dialog_data = dialog_data_new (); dialog_data->id = dialog_id != NULL ? g_strdup (dialog_id) : NULL; dialog_data->dialog = g_steal_pointer (&dialog); g_ptr_array_add (dialogs, g_steal_pointer (&dialog_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", signal_enum->value_nick, TRUE); g_subprocess_launcher_setenv (launcher, "BAZAAR_HOOK_WAS_ABORTED", hook_aborted ? "true" : "false", TRUE); switch (signal) { case BZ_HOOK_SIGNAL_BEFORE_TRANSACTION: case BZ_HOOK_SIGNAL_AFTER_TRANSACTION: g_subprocess_launcher_setenv (launcher, "BAZAAR_TS_APPID", ts_appid, TRUE); g_subprocess_launcher_setenv (launcher, "BAZAAR_TS_TYPE", ts_type_enum->value_nick, TRUE); break; case BZ_HOOK_SIGNAL_VIEW_APP: default: g_subprocess_launcher_setenv (launcher, "BAZAAR_APPID", bz_entry_group_get_id (group), TRUE); break; } 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 dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_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 dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_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 dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_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 dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_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 dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_CONTINUE); else if (g_strcmp0 (stdout_str, "stop") == 0) return dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_STOP); else if (g_strcmp0 (stdout_str, "confirm") == 0) return dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_CONFIRM); else if (g_strcmp0 (stdout_str, "deny") == 0) return dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_DENY); } else g_assert_not_reached (); g_warning ("Received invalid response from hook for stage \"%s\", abandoning it now", hook_stage); return dex_future_new_for_int (BZ_HOOK_RETURN_STATUS_CONTINUE); } } static DexFuture * run_emission_fiber (RunEmissionData *data) { GListModel *hooks = data->hooks; BzHookSignal signal = data->signal; BzHookTransactionType ts_type = data->ts_type; char *ts_appid = data->ts_appid; BzEntryGroup *group = data->group; guint n_hooks = 0; n_hooks = g_list_model_get_n_items (hooks); for (guint i = 0; i < n_hooks; i++) { g_autoptr (BzHook) hook = NULL; BzHookSignal when = 0; hook = g_list_model_get_item (hooks, i); when = bz_hook_get_when (hook); if (when == signal) { const char *check_appid_regex = NULL; BzHookReturnStatus hook_result = BZ_HOOK_RETURN_STATUS_CONTINUE; check_appid_regex = bz_hook_get_check_appid_regex (hook); if (check_appid_regex != NULL) { GRegex *regex = NULL; regex = g_object_get_data (G_OBJECT (hook), "check-appid-regex"); if (regex == NULL) { g_autoptr (GError) local_error = NULL; regex = g_regex_new ( check_appid_regex, G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &local_error); if (regex != NULL) g_object_set_data_full ( G_OBJECT (hook), "check-appid-regex", regex, (GDestroyNotify) g_regex_unref); else g_warning ("Hook check-appid-regex property '%s' " "is an invalid regex string: %s", check_appid_regex, local_error->message); } if (regex != NULL && !g_regex_match (regex, ts_appid, G_REGEX_MATCH_DEFAULT, NULL)) continue; } hook_result = dex_await_int ( bz_execute_hook (hook, ts_type, ts_appid, group), NULL); if (hook_result == BZ_HOOK_RETURN_STATUS_CONFIRM || hook_result == BZ_HOOK_RETURN_STATUS_STOP) break; else if (hook_result == BZ_HOOK_RETURN_STATUS_DENY) return dex_future_new_reject ( G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Prevented by a configured hook"); } } return dex_future_new_true (); } bazaar-org-bazaar-43ce9f7/src/bz-hooks.h000066400000000000000000000024401520414637400201250ustar00rootroot00000000000000/* bz-hooks.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 "bz-entry-group.h" #include "bz-hook.h" G_BEGIN_DECLS DexFuture * bz_execute_hook (BzHook *hook, BzHookTransactionType ts_type, const char *ts_appid, BzEntryGroup *group); DexFuture * bz_run_hook_emission (GListModel *hooks, BzHookSignal signal, BzHookTransactionType ts_type, const char *ts_appid, BzEntryGroup *group); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-inspector.blp000066400000000000000000000550021520414637400213400ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzInspector: Adw.Window { title: "Bazaar Inspector"; default-width: 1200; default-height: 800; width-request: 600; height-request: 600; Adw.ToolbarView { top-bar-style: raised_border; bottom-bar-style: raised_border; reveal-bottom-bars: false; content: Paned { orientation: horizontal; start-child: ScrolledWindow { child: Box { orientation: vertical; width-request: 100; spacing: 10; Box { orientation: vertical; Box { 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: horizontal; spacing: 10; Label { styles [ "heading" ] label: "Active Entry Objects in Memory:"; xalign: 0.0; } Label { label: bind $format_uint(template.state as <$BzStateInfo>.cache-manager as <$BzEntryCacheManager>.living-entries) 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; }; } } Box { orientation: vertical; spacing: 3; Box { orientation: horizontal; spacing: 10; Label { styles [ "heading" ] label: "Max Age Rating:"; xalign: 0.0; } Label { label: bind $format_int(template.state as <$BzStateInfo>.parental-age-rating) as ; xalign: 0.0; } } Label { styles [ "heading" ] label: "Restricted App IDs"; xalign: 0.0; } ScrolledWindow { propagate-natural-height: true; child: ListView { model: NoSelection { model: bind template.state as <$BzStateInfo>.parental-blocked-ids; }; factory: plain_string_list_factory; }; } } }; }; end-child: Box { orientation: vertical; spacing: 8; Label { styles [ "heading" ] margin-top: 10; label: "All Entry Groups"; xalign: 0.0; } Separator { orientation: horizontal; } Expander { label: "Serialize All Entries Into File"; child: Box { margin-start: 3; margin-end: 3; margin-top: 3; margin-bottom: 3; orientation: vertical; spacing: 5; Box { orientation: horizontal; spacing: 5; Entry serialize_all_entries_path_entry { hexpand: true; placeholder-text: "Enter the path to an output file..."; } Button serialize_all_entries_btn { styles [ "suggested-action", ] label: "Go"; clicked => $serialize_all_entries_cb(template); } } ProgressBar serialize_all_entries_progress { visible: false; } }; } Separator { orientation: horizontal; } 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 { incremental: true; model: bind template.state as <$BzStateInfo>.all-entry-groups; }; notify::selected-item => $selected_group_changed(template); }; factory: BuilderListItemFactory { template ListItem { activatable: false; child: Expander { styles [ "bz-monospace", ] resize-toplevel: true; label-widget: Label { label: bind template.item as <$BzEntryGroup>.id as ; }; child: Box { styles [ "card", ] margin-start: 3; margin-end: 3; margin-top: 3; margin-bottom: 3; halign: start; orientation: horizontal; Box { margin-start: 5; margin-end: 5; margin-top: 5; margin-bottom: 5; orientation: vertical; spacing: 2; Box { margin-start: 2; orientation: horizontal; spacing: 2; Label { styles [ "accent", ] label: bind template.item as <$BzEntryGroup>.title; } Image { gicon: bind template.item as <$BzEntryGroup>.mini-icon; } Box { styles [ "linked", ] hexpand: true; halign: end; orientation: horizontal; MenuButton { styles [ "bz-small-button", ] child: Label { styles [ "bz-monospace", ] margin-start: 2; margin-end: 2; label: "Entries"; }; popover: Popover { child: ScrolledWindow { propagate-natural-width: true; propagate-natural-height: true; child: ListView { model: NoSelection { model: bind template.item as <$BzEntryGroup>.model; }; factory: BuilderListItemFactory { template ListItem { activatable: false; child: Box { margin-top: 1; margin-bottom: 1; orientation: horizontal; spacing: 5; Box { styles [ "linked", ] orientation: horizontal; Button { styles [ "bz-small-button", ] has-tooltip: true; tooltip-text: "Decache and Inspect"; child: Image { icon-name: "external-link-symbolic"; pixel-size: 12; }; clicked => $decache_and_inspect_cb(template); } Button { styles [ "bz-small-button", ] has-tooltip: true; tooltip-text: "Copy Unique ID"; child: Image { icon-name: "edit-copy-symbolic"; pixel-size: 12; }; clicked => $copy_unique_id_cb(template); } } Label { hexpand: true; ellipsize: end; xalign: 0.0; label: bind template.item as <$GtkStringObject>.string as ; selectable: true; } }; } }; }; }; }; } MenuButton { styles [ "bz-small-button", ] visible: bind $not($is_null(template.item as <$BzEntryGroup>.addons-model as <$GListModel>) as ) as ; child: Label { styles [ "bz-monospace", ] margin-start: 2; margin-end: 2; label: "Addons"; }; popover: Popover { child: ScrolledWindow { propagate-natural-width: true; propagate-natural-height: true; child: ListView { model: NoSelection { model: bind template.item as <$BzEntryGroup>.addons-model; }; factory: BuilderListItemFactory { template ListItem { activatable: false; child: Label { hexpand: true; ellipsize: end; xalign: 0.0; label: bind template.item as <$GtkStringObject>.string as ; selectable: true; }; } }; }; }; }; } } } Separator { orientation: horizontal; } Grid { column-spacing: 2; row-spacing: 1; Label { layout { column: 0; row: 0; } label: "Developer:"; xalign: 1.0; } Label { layout { column: 1; row: 0; } styles [ "accent", ] label: bind template.item as <$BzEntryGroup>.developer; ellipsize: end; xalign: 0.5; } Label { layout { column: 0; row: 1; } label: "Description:"; xalign: 1.0; } Label { layout { column: 1; row: 1; } styles [ "accent", ] label: bind template.item as <$BzEntryGroup>.description; ellipsize: end; xalign: 0.5; } Label { layout { column: 0; row: 2; } label: "EOL:"; xalign: 1.0; } Label { layout { column: 1; row: 2; } styles [ "accent", ] label: bind template.item as <$BzEntryGroup>.eol; ellipsize: end; xalign: 0.5; } Label { layout { column: 2; row: 0; } label: "Installable:"; xalign: 1.0; } Label { layout { column: 3; row: 0; } styles [ "accent", ] label: bind $format_int(template.item as <$BzEntryGroup>.installable) as ; xalign: 0.0; } Label { layout { column: 2; row: 1; } label: "Installable-And-Available:"; xalign: 1.0; } Label { layout { column: 3; row: 1; } styles [ "accent", ] label: bind $format_int(template.item as <$BzEntryGroup>.installable-and-available) as ; xalign: 0.0; } Label { layout { column: 2; row: 2; } label: "Updatable:"; xalign: 1.0; } Label { layout { column: 3; row: 2; } styles [ "accent", ] label: bind $format_int(template.item as <$BzEntryGroup>.updatable) as ; xalign: 0.0; } Label { layout { column: 2; row: 3; } label: "Updatable-And-Available:"; xalign: 1.0; } Label { layout { column: 3; row: 3; } styles [ "accent", ] label: bind $format_int(template.item as <$BzEntryGroup>.updatable-and-available) as ; xalign: 0.0; } Label { layout { column: 2; row: 4; } label: "Removable:"; xalign: 1.0; } Label { layout { column: 3; row: 4; } styles [ "accent", ] label: bind $format_int(template.item as <$BzEntryGroup>.removable) as ; xalign: 0.0; } Label { layout { column: 2; row: 5; } label: "Removable-And-Available:"; xalign: 1.0; } Label { layout { column: 3; row: 5; } styles [ "accent", ] label: bind $format_int(template.item as <$BzEntryGroup>.removable-and-available) as ; xalign: 0.0; } } } }; }; } }; }; } }; }; [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); } }; } } BuilderListItemFactory plain_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 ; } }; } } bazaar-org-bazaar-43ce9f7/src/bz-inspector.c000066400000000000000000000366741520414637400210230ustar00rootroot00000000000000/* 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 */ #define G_LOG_DOMAIN "BAZAAR::INSPECTOR" #include #include "bz-entry-inspector.h" #include "bz-env.h" #include "bz-inspector.h" #include "bz-serializable.h" #include "bz-template-callbacks.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 *serialize_all_entries_path_entry; GtkButton *serialize_all_entries_btn; GtkProgressBar *serialize_all_entries_progress; 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 DexFuture * serialize_all_entries_fiber (BzInspector *self); 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 serialize_all_entries_cb (BzInspector *self, GtkButton *button) { dex_future_disown ( dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) serialize_all_entries_fiber, g_object_ref (self), g_object_unref)); } 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 copy_unique_id_cb (GtkListItem *list_item, GtkButton *button) { GtkStringObject *item = NULL; const char *text = NULL; GdkClipboard *clipboard = NULL; item = gtk_list_item_get_item (list_item); text = gtk_string_object_get_string (item); clipboard = gdk_display_get_clipboard (gdk_display_get_default ()); gdk_clipboard_set_text (clipboard, text); } 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 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"); bz_widget_class_bind_all_util_callbacks (widget_class); 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, serialize_all_entries_path_entry); gtk_widget_class_bind_template_child (widget_class, BzInspector, serialize_all_entries_btn); gtk_widget_class_bind_template_child (widget_class, BzInspector, serialize_all_entries_progress); 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, serialize_all_entries_cb); 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, copy_unique_id_cb); gtk_widget_class_bind_template_callback (widget_class, open_file_externally_cb); gtk_widget_class_bind_template_callback (widget_class, entry_changed); } static void on_map (BzInspector *self, GtkWidget *widget) { gtk_widget_grab_focus (GTK_WIDGET (self->search_entry)); } static void bz_inspector_init (BzInspector *self) { GtkCustomFilter *filter = NULL; g_autofree char *serialize_all_entries_output = 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)); g_signal_connect_swapped (self, "map", G_CALLBACK (on_map), self); serialize_all_entries_output = g_build_filename ( g_get_home_dir (), "BAZAAR_SERIALIZED_ENTRIES.TXT", NULL); gtk_editable_set_text ( self->serialize_all_entries_path_entry, serialize_all_entries_output); } 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 DexFuture * serialize_all_entries_fiber (BzInspector *self) { g_autoptr (GError) local_error = NULL; g_autoptr (BzEntryCacheManager) cache = NULL; const char *path = NULL; g_autofree char *path_clone = NULL; g_autoptr (GFile) file = NULL; g_autoptr (GHashTable) cached_set = NULL; guint cached_set_size = 0; g_autoptr (GFileOutputStream) output = NULL; GHashTableIter iter = { 0 }; if (self->state == NULL) return dex_future_new_false (); cache = bz_state_info_get_cache_manager (self->state); if (cache == NULL) return dex_future_new_false (); g_object_ref (cache); path = gtk_editable_get_text (self->serialize_all_entries_path_entry); if (path == NULL || *path == '\0') return dex_future_new_false (); path_clone = g_strdup (path); file = g_file_new_for_path (path_clone); gtk_widget_set_sensitive (GTK_WIDGET (self->serialize_all_entries_btn), FALSE); gtk_widget_set_visible (GTK_WIDGET (self->serialize_all_entries_progress), TRUE); gtk_progress_bar_set_fraction (self->serialize_all_entries_progress, 0.0); cached_set = dex_await_boxed ( bz_entry_cache_manager_enumerate_disk ( bz_state_info_get_cache_manager (self->state)), &local_error); if (cached_set == NULL) goto err; cached_set_size = g_hash_table_size (cached_set); output = dex_await_object ( dex_file_replace ( file, NULL, TRUE, G_FILE_CREATE_REPLACE_DESTINATION, G_PRIORITY_DEFAULT), &local_error); if (output == NULL) goto err; #define WRITE_STRING(_string) \ G_STMT_START \ { \ dex_await ( \ dex_output_stream_write ( \ G_OUTPUT_STREAM (output), \ (_string), \ strlen ((_string)), \ G_PRIORITY_DEFAULT), \ &local_error); \ if (local_error != NULL) \ goto err; \ } \ G_STMT_END WRITE_STRING ("[\n"); g_hash_table_iter_init (&iter, cached_set); for (guint i = 1;; i++) { char *checksum = NULL; g_autoptr (BzEntry) entry = NULL; g_autoptr (GVariantBuilder) builder = NULL; g_autoptr (GVariant) variant = NULL; g_autoptr (JsonNode) node = NULL; g_autoptr (JsonGenerator) generator = NULL; gsize length = 0; g_autofree char *string = NULL; if (!g_hash_table_iter_next ( &iter, (gpointer *) &checksum, NULL)) break; if (i > 1) WRITE_STRING (",\n\n"); entry = dex_await_object ( bz_entry_cache_manager_get_by_checksum ( cache, checksum), &local_error); if (entry == NULL) goto err; builder = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); bz_serializable_serialize (BZ_SERIALIZABLE (entry), builder); variant = g_variant_builder_end (builder); 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, &length); dex_await ( dex_output_stream_write ( G_OUTPUT_STREAM (output), string, length, G_PRIORITY_DEFAULT), &local_error); if (local_error != NULL) goto err; gtk_progress_bar_set_fraction ( self->serialize_all_entries_progress, (double) i / (double) cached_set_size); } WRITE_STRING ("\n]\n"); dex_await ( dex_output_stream_close ( G_OUTPUT_STREAM (output), G_PRIORITY_DEFAULT), NULL); gtk_widget_set_sensitive (GTK_WIDGET (self->serialize_all_entries_btn), TRUE); gtk_widget_set_visible (GTK_WIDGET (self->serialize_all_entries_progress), FALSE); return dex_future_new_true (); err: if (local_error != NULL) g_warning ("Failed to serialize: %s", local_error->message); gtk_widget_set_sensitive (GTK_WIDGET (self->serialize_all_entries_btn), TRUE); gtk_widget_set_visible (GTK_WIDGET (self->serialize_all_entries_progress), FALSE); return dex_future_new_for_error (g_steal_pointer (&local_error)); } 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 */ bazaar-org-bazaar-43ce9f7/src/bz-inspector.h000066400000000000000000000022561520414637400210150ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-install-controls.blp000066400000000000000000000124221520414637400226400ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzInstallControls: Box { hexpand: bind $invert_boolean(template.wide) as ; Stack { transition-type: crossfade; visible-child-name: bind try { $get_visible_page(template.entry-group as <$BzEntryGroup>.installable, template.entry-group as <$BzEntryGroup>.removable, template.state as <$BzStateInfo>.available-updates, template.tracker as <$BzTransactionEntryTracker>.active as ) as , $get_visible_page(template.entry-group as <$BzEntryGroup>.installable, template.entry-group as <$BzEntryGroup>.removable, template.state as <$BzStateInfo>.available-updates, false ) as }; hexpand: bind $invert_boolean(template.wide) as ; valign: center; StackPage install { name: "install"; child: $BgeWdgtRenderer animated_button { margin-top: 3; margin-bottom: 3; margin-start: 3; margin-end: 3; resource: "/io/github/kolunmi/Bazaar/bz-install-controls.wdgt"; reference: bind template.tracker as <$BzTransactionEntryTracker>; state: bind try { $get_install_btn_state( template.tracker as <$BzTransactionEntryTracker>.status as <$BzTransactionEntryStatus>, template.tracker as <$BzTransactionEntryTracker>.active as , template.tracker as <$BzTransactionEntryTracker>.pending as , template.tracker as <$BzTransactionEntryTracker>.progress as ) as , $install_btn_state_fallback() as }; has-tooltip: true; hexpand: bind $invert_boolean(template.wide) as ; halign: bind $choose(template.wide, 2, 0) as ; }; } StackPage open { name: "open"; child: Box { spacing: bind $choose(template.wide, 10, 8) as ; homogeneous: bind $invert_boolean(template.wide) as ; halign: bind $choose(template.wide, 2, 0) as ; valign: center; margin-top: 3; margin-bottom: 3; margin-start: 3; margin-end: 3; Button open_button { styles [ "pill", ] visible: bind $invert_boolean($is_blocked(template.state as <$BzStateInfo>.parental-blocked-ids, template.entry-group as <$BzEntryGroup>) as ) as ; has-tooltip: true; hexpand: bind $invert_boolean(template.wide) as ; label: _("_Open"); use-underline: true; sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable-and-available) as ) as ; clicked => $run_cb(template); } Button { styles [ "destructive-action", "circular", ] width-request: bind $choose(template.wide, 45, -1) as ; hexpand: bind $invert_boolean(template.wide) as ; has-tooltip: bind template.wide as ; tooltip-text: _("Uninstall Application"); sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable-and-available) as ) as ; clicked => $remove_cb(template); child: Box { halign: center; hexpand: true; Label { visible: bind $invert_boolean(template.wide) as ; label: _("_Remove"); use-underline: true; } Image { visible: bind template.wide as ; icon-name: "user-trash-symbolic"; } }; } }; } StackPage update { name: "update"; child: Box { spacing: bind $choose(template.wide, 10, 8) as ; homogeneous: bind $invert_boolean(template.wide) as ; halign: bind $choose(template.wide, 2, 0) as ; valign: center; margin-top: 3; margin-bottom: 3; margin-start: 3; margin-end: 3; Button update_button { styles [ "pill", "suggested-action" ] hexpand: bind $invert_boolean(template.wide) as ; label: _("Update"); clicked => $update_cb(template); } Button { styles [ "destructive-action", "circular", ] width-request: bind $choose(template.wide, 45, -1) as ; hexpand: bind $invert_boolean(template.wide) as ; has-tooltip: bind template.wide as ; tooltip-text: _("Uninstall Application"); sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable-and-available) as ) as ; clicked => $remove_cb(template); child: Box { halign: center; hexpand: true; Label { visible: bind $invert_boolean(template.wide) as ; label: _("Remove"); } Image { visible: bind template.wide as ; icon-name: "user-trash-symbolic"; } }; } }; } StackPage empty { name: "empty"; child: Adw.Bin {}; } } } bazaar-org-bazaar-43ce9f7/src/bz-install-controls.c000066400000000000000000000465741520414637400223240ustar00rootroot00000000000000/* bz-install-controls.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 #include "bz-install-controls.h" #include "bz-state-info.h" #include "bz-template-callbacks.h" #include "bz-util.h" #include "progress-bar-designs/common.h" struct _BzInstallControls { GtkBox parent_instance; BzEntryGroup *group; BzStateInfo *state; GSettings *settings; gboolean wide; BzTransactionEntryTracker *tracker; GListModel *all_trackers; GtkWidget *install_button; char *install_btn_class; char *pride_class; /* Template widgets */ GtkWidget *open_button; GtkWidget *animated_button; }; G_DEFINE_FINAL_TYPE (BzInstallControls, bz_install_controls, GTK_TYPE_BOX) enum { PROP_0, PROP_WIDE, PROP_ENTRY_GROUP, PROP_STATE, PROP_SETTINGS, PROP_TRACKER, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_UPDATE, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void pride_flag_changed (BzInstallControls *self, const char *key, GSettings *settings); static void ensure_draw_css (BzInstallControls *self); static void update_tracker (BzInstallControls *self) { BzTransactionManager *manager = NULL; g_autoptr (GListModel) all = NULL; const char *group_id = NULL; g_autoptr (BzTransactionEntryTracker) found = NULL; if (self->state != NULL) manager = bz_state_info_get_transaction_manager (self->state); if (manager != NULL) g_object_get (manager, "all-trackers", &all, NULL); if (self->group != NULL) group_id = bz_entry_group_get_id (self->group); if (all != NULL && group_id != NULL) { for (guint i = 0; i < g_list_model_get_n_items (all); i++) { g_autoptr (BzTransactionEntryTracker) tracker = NULL; BzEntry *entry = NULL; tracker = g_list_model_get_item (all, i); entry = bz_transaction_entry_tracker_get_entry (tracker); if (g_strcmp0 (entry != NULL ? bz_entry_get_id (entry) : NULL, group_id) == 0) { found = g_steal_pointer (&tracker); break; } } } if (g_set_object (&self->tracker, found)) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRACKER]); } static void on_all_trackers_changed (GListModel *model, guint position, guint removed, guint added, BzInstallControls *self) { update_tracker (self); } static void install_cancel_cb (BzInstallControls *self, GtkButton *button) { const char *state = NULL; if (self->group == NULL) return; state = bge_wdgt_renderer_get_state (BGE_WDGT_RENDERER (self->animated_button)); if (state == NULL) return; if (g_strcmp0 (state, "inactive") == 0) gtk_widget_activate_action (GTK_WIDGET (self), "window.install-group", "(sb)", bz_entry_group_get_id (self->group), TRUE); else gtk_widget_activate_action (GTK_WIDGET (self), "window.cancel-group", "s", bz_entry_group_get_id (self->group)); } static void remove_cb (BzInstallControls *self, GtkButton *button) { if (self->group == NULL) return; gtk_widget_activate_action (GTK_WIDGET (self), "window.remove-group", "(sb)", bz_entry_group_get_id (self->group), TRUE); } static void run_cb (BzInstallControls *self, GtkButton *button) { if (self->group == NULL) return; gtk_widget_activate_action (GTK_WIDGET (self), "window.launch-group", "s", bz_entry_group_get_id (self->group)); } static GListStore * find_matching_updates (BzInstallControls *self, GListModel *available_updates) { const char *group_id = NULL; guint n_items = 0; GListStore *store = NULL; if (self->group == NULL || available_updates == NULL) return NULL; group_id = bz_entry_group_get_id (self->group); n_items = g_list_model_get_n_items (available_updates); store = g_list_store_new (BZ_TYPE_ENTRY); for (guint i = 0; i < n_items; i++) { g_autoptr (BzEntry) entry = NULL; const char *id = NULL; entry = g_list_model_get_item (available_updates, i); id = bz_entry_get_id (entry); if (g_strcmp0 (id, group_id) == 0) g_list_store_append (store, entry); } if (g_list_model_get_n_items (G_LIST_MODEL (store)) == 0) g_clear_object (&store); return store; } static void update_cb (BzInstallControls *self, GtkButton *button) { GListModel *available_updates = NULL; g_autoptr (GListStore) store = NULL; if (self->state == NULL) return; available_updates = bz_state_info_get_available_updates (self->state); store = find_matching_updates (self, available_updates); if (store != NULL) g_signal_emit (self, signals[SIGNAL_UPDATE], 0, G_LIST_MODEL (store)); } static char * get_visible_page (gpointer object, int installable, int removable, GListModel *available_updates, gboolean active) { BzInstallControls *self = BZ_INSTALL_CONTROLS (object); g_autoptr (GListStore) store = NULL; if (active) return g_strdup ("install"); if (removable > 0) { if (g_signal_has_handler_pending (self, signals[SIGNAL_UPDATE], 0, FALSE)) store = find_matching_updates (self, available_updates); return g_strdup (store != NULL ? "update" : "open"); } else if (installable > 0) return g_strdup ("install"); else return g_strdup ("empty"); } static void set_install_btn_class (BzInstallControls *self, const char *class) { if (self->install_button == NULL) return; if (self->install_btn_class != NULL && g_strcmp0 (class, self->install_btn_class) == 0) return; if (self->install_btn_class != NULL) gtk_widget_remove_css_class (self->install_button, self->install_btn_class); g_clear_pointer (&self->install_btn_class, g_free); if (class != NULL) { gtk_widget_add_css_class (self->install_button, class); self->install_btn_class = g_strdup (class); } } static char * get_install_btn_state (BzInstallControls *self, BzTransactionEntryStatus status, gboolean active, gboolean pending, double progress) { g_autofree char *state = NULL; const char *class = NULL; if ((active || pending) && status == BZ_TRANSACTION_ENTRY_STATUS_CANCELLED) { state = g_strdup ("cancelling"); class = NULL; } else if (pending || status == BZ_TRANSACTION_ENTRY_STATUS_QUEUED) { state = g_strdup ("pending"); class = NULL; } else if (!active || status == BZ_TRANSACTION_ENTRY_STATUS_DONE) { state = g_strdup ("inactive"); class = "suggested-action"; } else { state = g_strdup ("fraction"); class = NULL; } set_install_btn_class (self, class); return g_steal_pointer (&state); } static char * install_btn_state_fallback (BzInstallControls *self) { set_install_btn_class (self, "suggested-action"); return g_strdup ("inactive"); } static gboolean is_blocked (gpointer object, GListModel *parental_blocked, BzEntryGroup *group) { const char *id = NULL; if (parental_blocked == NULL || group == NULL) return FALSE; id = bz_entry_group_get_id (group); if (id == NULL) return FALSE; for (guint i = 0; i < g_list_model_get_n_items (parental_blocked); i++) { g_autoptr (GtkStringObject) obj = g_list_model_get_item (parental_blocked, i); if (strstr (gtk_string_object_get_string (obj), id) != NULL) return TRUE; } return FALSE; } static gboolean idle_grab_focus (GWeakRef *wr) { g_autoptr (BzInstallControls) self = NULL; self = g_weak_ref_get (wr); if (self == NULL) goto done; if (gtk_widget_is_visible (GTK_WIDGET (self))) gtk_widget_grab_focus (self->group != NULL && bz_entry_group_get_removable (self->group) > 0 ? self->open_button : self->install_button); done: return G_SOURCE_REMOVE; } static void bz_install_controls_dispose (GObject *object) { BzInstallControls *self = BZ_INSTALL_CONTROLS (object); if (self->settings != NULL) g_signal_handlers_disconnect_by_func ( self->settings, pride_flag_changed, self); if (self->all_trackers != NULL) g_signal_handlers_disconnect_by_func ( self->all_trackers, on_all_trackers_changed, self); g_clear_object (&self->group); g_clear_object (&self->state); g_clear_object (&self->settings); g_clear_object (&self->tracker); g_clear_object (&self->install_button); g_clear_pointer (&self->install_btn_class, g_free); g_clear_pointer (&self->pride_class, g_free); g_clear_object (&self->all_trackers); G_OBJECT_CLASS (bz_install_controls_parent_class)->dispose (object); } static void bz_install_controls_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzInstallControls *self = BZ_INSTALL_CONTROLS (object); switch (prop_id) { case PROP_WIDE: g_value_set_boolean (value, self->wide); break; case PROP_ENTRY_GROUP: g_value_set_object (value, self->group); break; case PROP_STATE: g_value_set_object (value, self->state); break; case PROP_TRACKER: g_value_set_object (value, self->tracker); break; case PROP_SETTINGS: g_value_set_object (value, self->settings); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_install_controls_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzInstallControls *self = BZ_INSTALL_CONTROLS (object); switch (prop_id) { case PROP_WIDE: bz_install_controls_set_wide (self, g_value_get_boolean (value)); break; case PROP_ENTRY_GROUP: bz_install_controls_set_entry_group (self, g_value_get_object (value)); break; case PROP_STATE: bz_install_controls_set_state (self, g_value_get_object (value)); break; case PROP_SETTINGS: { if (self->settings != NULL) g_signal_handlers_disconnect_by_func ( self->settings, pride_flag_changed, self); g_clear_object (&self->settings); self->settings = g_value_dup_object (value); if (self->settings != NULL) { g_signal_connect_swapped ( self->settings, "changed::global-progress-bar-theme", G_CALLBACK (pride_flag_changed), self); g_signal_connect_swapped ( self->settings, "changed::rotate-flag", G_CALLBACK (pride_flag_changed), self); } ensure_draw_css (self); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_install_controls_class_init (BzInstallControlsClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_install_controls_dispose; object_class->get_property = bz_install_controls_get_property; object_class->set_property = bz_install_controls_set_property; props[PROP_WIDE] = g_param_spec_boolean ( "wide", NULL, NULL, TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); 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_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_SETTINGS] = g_param_spec_object ( "settings", NULL, NULL, G_TYPE_SETTINGS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_TRACKER] = g_param_spec_object ( "tracker", NULL, NULL, BZ_TYPE_TRANSACTION_ENTRY_TRACKER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); 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_ENTRY_GROUP); g_type_ensure (BZ_TYPE_STATE_INFO); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-install-controls.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzInstallControls, open_button); gtk_widget_class_bind_template_child (widget_class, BzInstallControls, animated_button); gtk_widget_class_bind_template_callback (widget_class, install_cancel_cb); gtk_widget_class_bind_template_callback (widget_class, remove_cb); gtk_widget_class_bind_template_callback (widget_class, run_cb); gtk_widget_class_bind_template_callback (widget_class, update_cb); gtk_widget_class_bind_template_callback (widget_class, get_visible_page); gtk_widget_class_bind_template_callback (widget_class, get_install_btn_state); gtk_widget_class_bind_template_callback (widget_class, install_btn_state_fallback); gtk_widget_class_bind_template_callback (widget_class, is_blocked); } static void bz_install_controls_init (BzInstallControls *self) { self->wide = TRUE; gtk_widget_init_template (GTK_WIDGET (self)); self->install_button = bge_wdgt_renderer_lookup_object ( BGE_WDGT_RENDERER (self->animated_button), "btn"); gtk_widget_add_css_class (self->install_button, "pill"); g_signal_connect_swapped ( self->install_button, "clicked", G_CALLBACK (install_cancel_cb), self); gtk_widget_add_css_class (self->install_button, "suggested-action"); self->install_btn_class = g_strdup ("suggested-action"); } GtkWidget * bz_install_controls_new (void) { return g_object_new (BZ_TYPE_INSTALL_CONTROLS, NULL); } gboolean bz_install_controls_get_wide (BzInstallControls *self) { g_return_val_if_fail (BZ_IS_INSTALL_CONTROLS (self), FALSE); return self->wide; } void bz_install_controls_set_wide (BzInstallControls *self, gboolean wide) { g_return_if_fail (BZ_IS_INSTALL_CONTROLS (self)); wide = !!wide; if (self->wide == wide) return; self->wide = wide; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_WIDE]); } BzEntryGroup * bz_install_controls_get_entry_group (BzInstallControls *self) { g_return_val_if_fail (BZ_IS_INSTALL_CONTROLS (self), NULL); return self->group; } void bz_install_controls_set_entry_group (BzInstallControls *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_INSTALL_CONTROLS (self)); if (self->group == group) return; g_clear_object (&self->group); if (group != NULL) self->group = g_object_ref (group); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ENTRY_GROUP]); if (group != NULL) g_idle_add_full ( G_PRIORITY_DEFAULT_IDLE, (GSourceFunc) idle_grab_focus, bz_track_weak (self), bz_weak_release); update_tracker (self); } BzStateInfo * bz_install_controls_get_state (BzInstallControls *self) { g_return_val_if_fail (BZ_IS_INSTALL_CONTROLS (self), NULL); return self->state; } void bz_install_controls_set_state (BzInstallControls *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_INSTALL_CONTROLS (self)); if (self->all_trackers != NULL) { g_signal_handlers_disconnect_by_func (self->all_trackers, on_all_trackers_changed, self); g_clear_object (&self->all_trackers); } g_set_object (&self->state, state); if (state != NULL) { BzTransactionManager *mgr = NULL; mgr = bz_state_info_get_transaction_manager (state); if (mgr != NULL) g_object_get (mgr, "all-trackers", &self->all_trackers, NULL); if (self->all_trackers != NULL) g_signal_connect (self->all_trackers, "items-changed", G_CALLBACK (on_all_trackers_changed), self); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]); update_tracker (self); } static void pride_flag_changed (BzInstallControls *self, const char *key, GSettings *settings) { ensure_draw_css (self); } static void ensure_draw_css (BzInstallControls *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->pride_class != NULL && g_strcmp0 (self->pride_class, class) == 0) return; if (self->pride_class != NULL) gtk_widget_remove_css_class (self->animated_button, self->pride_class); g_clear_pointer (&self->pride_class, g_free); gtk_widget_add_css_class (self->animated_button, class); self->pride_class = g_steal_pointer (&class); } else { if (self->pride_class != NULL) gtk_widget_remove_css_class (self->animated_button, self->pride_class); g_clear_pointer (&self->pride_class, g_free); } } bazaar-org-bazaar-43ce9f7/src/bz-install-controls.h000066400000000000000000000032131520414637400223100ustar00rootroot00000000000000/* bz-install-controls.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 "bz-state-info.h" #include G_BEGIN_DECLS #define BZ_TYPE_INSTALL_CONTROLS (bz_install_controls_get_type ()) G_DECLARE_FINAL_TYPE (BzInstallControls, bz_install_controls, BZ, INSTALL_CONTROLS, GtkBox) GtkWidget * bz_install_controls_new (void); gboolean bz_install_controls_get_wide (BzInstallControls *self); void bz_install_controls_set_wide (BzInstallControls *self, gboolean wide); BzEntryGroup * bz_install_controls_get_entry_group (BzInstallControls *self); void bz_install_controls_set_entry_group (BzInstallControls *self, BzEntryGroup *group); BzStateInfo * bz_install_controls_get_state (BzInstallControls *self); void bz_install_controls_set_state (BzInstallControls *self, BzStateInfo *state); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-install-controls.wdgt000066400000000000000000000076051520414637400230370ustar00rootroot00000000000000defwidget "Install Button" { reference state : "BzTransactionEntryTracker"; var progress : "gdouble"; var lbl-install : "GtkLabel"; var lbl-cancel : "GtkLabel"; var lbl-cancelling : "GtkLabel"; var stack : "GtkStack"; var btn : "GtkButton"; var flag : "GtkFixed"; var start : "gdouble"; var end : "gdouble"; var opacity : "gdouble"; var corner : "gdouble"; var outline : "GskPath"; var outline-measure : "GskPathMeasure"; var outline-width : "gdouble"; var outline-opacity : "gdouble"; init { set progress = #transition(state:progress, 1.1, 0.1, 10.0); set stack = #( transition-type = crossfade; transition-duration = 200; %set lbl-install = #child/GtkLabel(""() label = C_("Install Controls", "Install"); ); %set lbl-cancel = #child/GtkLabel(""() label = C_("Install Controls", "Cancel"); ); %set lbl-cancelling = #child/GtkLabel(""() label = C_("Install Controls", "Cancelling"); ); ); allocate stack %width%, %height%, #(); set btn = #child/(""("pill") child = stack; margin-start = 4; margin-end = 4; margin-top = 4; margin-bottom = 4; ); allocate btn %width%, %height%, #(); set flag = #child/(""("install-button-indicator") can-target = false; ); allocate flag %width%, %height%, #(); set corner = #eval(#(%height%)/2.0); set outline = #GskPath( move-to(#eval(#(%width%)/2.0), 0.0); rel-line-to(#eval(#(%width%)/2.0-#(corner)), 0.0); rel-arc-to(corner, 0.0, corner, corner); rel-line-to(0.0, #eval(#(%height%)-#(corner)*2.0)); rel-arc-to(0.0, corner, #eval(-#(corner)), corner); rel-line-to(#eval(-(#(%width%)-#(corner)*2.0)), 0.0); rel-arc-to(#eval(-#(corner)), 0.0, #eval(-#(corner)), #eval(-#(corner))); rel-line-to(0.0, #eval(-(#(%height%)-#(corner)*2.0))); rel-arc-to(0.0, #eval(-#(corner)), corner, #eval(-#(corner))); rel-line-to(#eval(#(%width%)/2.0-#(corner)), 0.0); close(); ); set outline-measure = #measure-path(outline); snapshot { do-child btn; with opacity(outline-opacity) { with stroke( #GskPath( add-segment( outline, #path-point(outline-measure, #eval((#(start)%1.0)*#(#path-length(outline-measure)))), #path-point(outline-measure, #eval((#(end)%1.0)*#(#path-length(outline-measure)))), ); ), #GskStroke(outline-width, butt, round, 0.0), ) { do-child flag; } } } } state-default "inactive" { set btn:sensitive = true; set stack:visible-child = lbl-install; set start = 0.0; set end = 0.001; set outline-width = 5.0; set outline-opacity = 0.0; transition-spring outline-width 1.0, 0.1, 15.0; transition-spring outline-opacity 1.0, 0.1, 100.0; } state "pending" { set btn:sensitive = true; set stack:visible-child = lbl-cancel; set start = #eval((#(%tick%)/3.0)%1.0); set end = #eval((#(start)+0.2)%1.0); set outline-width = 5.0; set outline-opacity = 1.0; transition-spring outline-width 1.0, 0.1, 10.0; transition-spring outline-opacity 1.0, 0.1, 10.0; } state "fraction" { set btn:sensitive = true; set stack:visible-child = lbl-cancel; set start = 0.0; set end = #eval(0.05+#(progress)*0.95); set outline-width = 5.0; set outline-opacity = 1.0; transition-spring outline-width 1.1, 0.1, 10.0; transition-spring outline-opacity 1.1, 0.1, 10.0; } state "cancelling" { set btn:sensitive = false; set stack:visible-child = lbl-cancelling; set start = 0.0; set end = 0.001; set outline-width = 0.0; set outline-opacity = 1.0; transition-spring outline-width 1.0, 0.1, 10.0; transition-spring outline-opacity 1.0, 0.1, 10.0; } } bazaar-org-bazaar-43ce9f7/src/bz-installed-tile.blp000066400000000000000000000061761520414637400222540ustar00rootroot00000000000000using Gtk 4.0; template $BzInstalledTile: $BzListTile { accessibility { labelled-by: title_label; described-by: description_label; } child: Box { orientation: horizontal; spacing: 10; $BzTransactIcon { margin-start: 10; margin-top: 10; margin-bottom: 10; width-request: 64; height-request: 64; valign: center; halign: center; info: $BzTransactIconInfo { group: bind template.group as <$BzEntryGroup>; paintable: bind template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.icon-paintable; }; } 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" ] tooltip-text: _("Manage Add-Ons"); visible: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.n-addons as ) as ) as ; valign: center; icon-name: "application-x-addon-symbolic"; clicked => $install_addons_cb() swapped; } Button remove_button { styles [ "flat", ] tooltip-text: _("Remove"); 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"] } } }; }bazaar-org-bazaar-43ce9f7/src/bz-installed-tile.c000066400000000000000000000207061520414637400217140ustar00rootroot00000000000000/* 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" #include "bz-transact-icon.h" #include "bz-transact-icon-info.h" #include "bz-window.h" struct _BzInstalledTile { BzListTile parent_instance; BzEntryGroup *group; GtkLabel *title_label; GtkButton *support_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 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 gboolean logical_and (gpointer object, gboolean a, gboolean b) { return a && b; } static gboolean logical_or (gpointer object, gboolean a, gboolean b) { return a || b; } 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 support_cb (BzInstalledTile *self, GtkButton *button) { const char *url = NULL; if (self->group == NULL) return; url = bz_entry_group_get_donation_url (self->group); if (url == NULL) return; g_app_info_launch_default_for_uri (url, NULL, NULL); } static void permissions_cb (BzInstalledTile *self) { if (self->group == NULL) return; gtk_widget_activate_action (GTK_WIDGET (self), "window.permissions", "s", bz_entry_group_get_id (self->group)); } static void install_addons_cb (BzInstalledTile *self) { if (self->group == NULL) return; gtk_widget_activate_action (GTK_WIDGET (self), "window.addons-group", "s", bz_entry_group_get_id (self->group)); } static void remove_cb (BzInstalledTile *self, GtkButton *button) { if (self->group == NULL) return; gtk_widget_activate_action (GTK_WIDGET (self), "window.remove-group", "(sb)", bz_entry_group_get_id (self->group), FALSE); } 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); g_type_ensure (BZ_TYPE_TRANSACT_ICON); g_type_ensure (BZ_TYPE_TRANSACT_ICON_INFO); 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, title_label); gtk_widget_class_bind_template_child (widget_class, BzInstalledTile, support_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, logical_and); gtk_widget_class_bind_template_callback (widget_class, logical_or); 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_bind_template_callback (widget_class, permissions_cb); gtk_widget_class_install_action (widget_class, "installed-tile.install-addons", NULL, (GtkWidgetActionActivateFunc) install_addons_cb); gtk_widget_class_install_action (widget_class, "installed-tile.permissions", NULL, (GtkWidgetActionActivateFunc) permissions_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; } bazaar-org-bazaar-43ce9f7/src/bz-installed-tile.h000066400000000000000000000023731520414637400217210ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-internal-config.txt000066400000000000000000000003311520414637400224460ustar00rootroot00000000000000prefix=bz name=internal_config parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-search-bias.h" ensure=BZ_TYPE_SEARCH_BIAS property=search_biases GListModel G_TYPE_LIST_MODEL object bazaar-org-bazaar-43ce9f7/src/bz-io.c000066400000000000000000000316551520414637400174160ustar00rootroot00000000000000/* 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" #include "bz-size-result.h" static DexFuture * reap_file_fiber (GFile *file); static DexFuture * reap_path_fiber (char *path); static DexFuture * reap_app_dir_fiber (char *path); static DexFuture * get_directory_size_fiber (GFile *file); static DexFuture * get_user_sizes_fiber (char *app_id); static DexFuture * get_all_user_data_ids_fiber (void); char * bz_dup_user_data_path (const char *app_id) { g_return_val_if_fail (app_id != NULL, NULL); return g_build_filename (g_get_home_dir (), ".var", "app", app_id, NULL); } char * bz_dup_user_cache_path (const char *app_id) { g_return_val_if_fail (app_id != NULL, NULL); return g_build_filename (g_get_home_dir (), ".var", "app", app_id, "cache", NULL); } 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); } } 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); } 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_app_dir_fiber (char *path) { g_autoptr (GFile) file = NULL; g_autoptr (DexFuture) trash_future = NULL; g_autoptr (GError) error = NULL; gboolean result = FALSE; file = g_file_new_for_path (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)) return dex_future_new_true (); g_warning ("failed to trash directory '%s': %s", path, error->message); return dex_future_new_for_error (g_steal_pointer (&error)); } return dex_future_new_true (); } static DexFuture * reap_user_data_fiber (char *app_id) { g_autofree char *path = bz_dup_user_data_path (app_id); return reap_app_dir_fiber (path); } static DexFuture * reap_user_cache_fiber (char *app_id) { g_autofree char *path = bz_dup_user_cache_path (app_id); bz_reap_path (path); return dex_future_new_true (); } 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_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); } DexFuture * bz_reap_user_cache_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_cache_fiber, g_strdup (app_id), g_free); } DexFuture * bz_get_user_sizes_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_sizes_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_sizes_fiber (char *app_id) { g_autofree char *user_data_path = NULL; g_autofree char *user_cache_path = NULL; g_autoptr (GFile) data_file = NULL; g_autoptr (GFile) cache_file = NULL; g_autoptr (GPtrArray) futures = NULL; g_autoptr (GError) error = NULL; guint64 user_data_size = 0; guint64 cache_size = 0; user_data_path = bz_dup_user_data_path (app_id); user_cache_path = bz_dup_user_cache_path (app_id); data_file = g_file_new_for_path (user_data_path); cache_file = g_file_new_for_path (user_cache_path); futures = g_ptr_array_new_with_free_func (dex_unref); g_ptr_array_add (futures, get_directory_size_fiber (data_file)); g_ptr_array_add (futures, get_directory_size_fiber (cache_file)); dex_await (dex_future_allv ( (DexFuture *const *) futures->pdata, futures->len), NULL); user_data_size = dex_await_uint64 (dex_ref (g_ptr_array_index (futures, 0)), &error); if (error != NULL) { g_clear_error (&error); user_data_size = 0; } cache_size = dex_await_uint64 (dex_ref (g_ptr_array_index (futures, 1)), &error); if (error != NULL) { g_clear_error (&error); cache_size = 0; } return dex_future_new_for_object ( g_object_new (BZ_TYPE_SIZE_RESULT, "user-data-size", user_data_size, "cache-size", cache_size, NULL)); } static void measure_disk_usage_callback (GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr (DexPromise) promise = user_data; g_autoptr (GError) error = NULL; guint64 disk_usage = 0; if (g_file_measure_disk_usage_finish (G_FILE (object), result, &disk_usage, NULL, NULL, &error)) dex_promise_resolve_uint64 (promise, disk_usage); else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) dex_promise_resolve_uint64 (promise, 0); else dex_promise_reject (promise, g_steal_pointer (&error)); } static DexFuture * get_directory_size_fiber (GFile *file) { DexPromise *promise = NULL; promise = dex_promise_new_cancellable (); g_file_measure_disk_usage_async ( file, G_FILE_MEASURE_NONE, G_PRIORITY_DEFAULT, dex_promise_get_cancellable (promise), NULL, NULL, measure_disk_usage_callback, dex_ref (promise)); return DEX_FUTURE (promise); } 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) { GApplication *application = NULL; const char *user_cache = NULL; const char *id = NULL; user_cache = g_get_user_cache_dir (); application = g_application_get_default (); if (application != NULL) id = g_application_get_application_id (application); if (id == NULL) id = "io.github.kolunmi.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 (); } bazaar-org-bazaar-43ce9f7/src/bz-io.h000066400000000000000000000050431520414637400174130ustar00rootroot00000000000000/* 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 char * bz_dup_user_data_path (const char *app_id); char * bz_dup_user_cache_path (const char *app_id); 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_reap_user_cache_dex (const char *app_id); DexFuture * bz_get_user_sizes_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 bazaar-org-bazaar-43ce9f7/src/bz-library-page.blp000066400000000000000000000237251520414637400217170ustar00rootroot00000000000000using 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; visible: bind template.has-apps; 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; max-length: 50; placeholder-text: _("Search installed apps"); notify::text => $search_text_changed(template); activate => $search_text_activate(template); } Button clear_button { icon-name: "edit-clear-symbolic"; visible: bind $not($is_empty_string(search_bar.text) as ) as ; styles [ "flat", "circular", "searchbar-button", ] clicked => $reset_search_cb(template); accessibility { label: _("Clear search"); } } 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 ; child: Button { styles [ "pill", ] halign: center; label: _("Search Store Instead"); clicked => $global_search_cb(template); }; }; } 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", ] } }; } Box { margin-start: 12; margin-end: 4; Label { label: bind $format_install_count(filter_model.n-items) as ; xalign: 0; visible: bind template.has-apps; hexpand: true; margin-top: 4; styles [ "heading", "h4", ] } MenuButton { icon-name: "sliders-horizontal-symbolic"; popover: sort_popover; styles ["flat"] } } } ListView list_view { styles [ "navigation-sidebar", "installed-list-view", "installed-section" ] visible: bind template.has-apps; model: NoSelection { model: FilterListModel filter_model { filter: CustomFilter filter {}; model: SortListModel sort_model { sorter: CustomSorter sorter {}; model: bind template.model; }; notify::n-items => $n_filtered_items_changed(template); }; }; factory: BuilderListItemFactory { template ListItem { activatable: false; selectable: false; focusable: false; child: $BzInstalledTile { group: bind template.item as <$BzEntryGroup>; activated => $tile_activated_cb(); }; } }; } }; }; }; } } }; } Popover sort_popover { child: Box { orientation: vertical; spacing: 6; margin-top: 8; margin-bottom: 8; margin-start: 8; margin-end: 16; Label { label: _("Sort By"); wrap: true; wrap-mode: word_char; xalign: 0; margin-start: 28; styles [ "heading", "h4", "dimmed" ] } CheckButton sort_name { label: _("Name"); active: true; toggled => $sort_changed_cb(template); } CheckButton sort_size { label: _("Size"); group: sort_name; toggled => $sort_changed_cb(template); } }; } bazaar-org-bazaar-43ce9f7/src/bz-library-page.c000066400000000000000000000447471520414637400213730ustar00rootroot00000000000000/* 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.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; BzTransactionManager *transactions; BzStateInfo *state; /* Template widgets */ AdwViewStack *stack; GtkText *search_bar; GtkScrolledWindow *scroll; GtkFilterListModel *filter_model; GtkCustomFilter *filter; GtkListView *list_view; GtkSortListModel *sort_model; GtkCustomSorter *sorter; GtkCheckButton *sort_name; GtkCheckButton *sort_size; }; G_DEFINE_FINAL_TYPE (BzLibraryPage, bz_library_page, ADW_TYPE_BIN) enum { PROP_0, PROP_MODEL, PROP_TRANSACTIONS, PROP_STATE, PROP_HAS_APPS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { 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 has_transactions_changed (BzLibraryPage *self, GParamSpec *pspec, BzTransactionManager *transactions); 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); if (self->transactions != NULL) g_signal_handlers_disconnect_by_func (self->transactions, has_transactions_changed, self); g_clear_object (&self->model); g_clear_object (&self->transactions); 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_TRANSACTIONS: g_value_set_object (value, bz_library_page_get_transactions (self)); break; case PROP_STATE: g_value_set_object (value, bz_library_page_get_state (self)); break; case PROP_HAS_APPS: { guint n_apps = 0; if (self->model != NULL) n_apps = g_list_model_get_n_items (self->model); g_value_set_boolean (value, n_apps > 0); } 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_TRANSACTIONS: bz_library_page_set_transactions (self, g_value_get_object (value)); break; case PROP_STATE: bz_library_page_set_state (self, g_value_get_object (value)); break; case PROP_HAS_APPS: 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 char * format_install_count (gpointer object, gint n_items) { return g_strdup_printf (ngettext ("%u Installed App", "%u Installed Apps", n_items), n_items); } static void tile_activated_cb (BzListTile *tile) { BzLibraryPage *self = NULL; BzEntryGroup *group = NULL; g_assert (BZ_IS_LIST_TILE (tile)); self = (BzLibraryPage *) gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_LIBRARY_PAGE); if (self == NULL) return; if (BZ_IS_INSTALLED_TILE (tile)) { group = bz_installed_tile_get_group (BZ_INSTALLED_TILE (tile)); } else if (BZ_IS_TRANSACTION_TILE (tile)) { BzTransactionEntryTracker *tracker = NULL; BzEntry *entry = NULL; tracker = bz_transaction_tile_get_tracker (BZ_TRANSACTION_TILE (tile)); if (tracker == NULL) return; entry = bz_transaction_entry_tracker_get_entry (tracker); group = bz_application_map_factory_convert_one ( bz_state_info_get_application_factory (self->state), gtk_string_object_new (bz_entry_get_id (entry))); } else return; if (group == NULL) return; gtk_widget_activate_action (GTK_WIDGET (self), "window.show-group", "s", bz_entry_group_get_id (group)); } static void search_text_changed (BzLibraryPage *self, GParamSpec *pspec, GtkText *entry) { gtk_filter_changed (GTK_FILTER (self->filter), GTK_FILTER_CHANGE_DIFFERENT); set_page (self); } static void search_text_activate (BzLibraryPage *self, GtkText *entry) { const char *text = NULL; text = gtk_editable_get_text (GTK_EDITABLE (self->search_bar)); if (text != NULL && *text != '\0') gtk_widget_activate_action (GTK_WIDGET (self), "app.search", "s", text); gtk_editable_set_text (GTK_EDITABLE (self->search_bar), ""); } static void reset_search_cb (BzLibraryPage *self, GtkButton *button) { gtk_text_set_buffer (self->search_bar, NULL); } static void n_filtered_items_changed (BzLibraryPage *self, GParamSpec *pspec, GtkFilterListModel *model) { set_page (self); } static void clear_tasks_cb (BzLibraryPage *self) { BzTransactionManager *manager = NULL; if (self->state == NULL) return; manager = bz_state_info_get_transaction_manager (self->state); if (manager != NULL) 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 global_search_cb (BzLibraryPage *self, GtkButton *button) { const char *text = NULL; text = gtk_editable_get_text (GTK_EDITABLE (self->search_bar)); if (text != NULL && *text != '\0') gtk_widget_activate_action (GTK_WIDGET (self), "app.search", "s", text); gtk_editable_set_text (GTK_EDITABLE (self->search_bar), ""); } static int sort_func (BzEntryGroup *a, BzEntryGroup *b, BzLibraryPage *self) { if (gtk_check_button_get_active (self->sort_size)) { guint64 size_a = 0; guint64 size_b = 0; size_a = bz_entry_group_get_installed_size (a); size_b = bz_entry_group_get_installed_size (b); return size_a > size_b ? -1 : size_a < size_b ? 1 : 0; } return g_utf8_collate (bz_entry_group_get_title (a), bz_entry_group_get_title (b)); } static void sort_changed_cb (BzLibraryPage *self, GtkCheckButton *button) { gtk_sorter_changed (GTK_SORTER (self->sorter), GTK_SORTER_CHANGE_DIFFERENT); } 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_TRANSACTIONS] = g_param_spec_object ( "transactions", NULL, NULL, BZ_TYPE_TRANSACTION_MANAGER, 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); props[PROP_HAS_APPS] = g_param_spec_boolean ( "has-apps", NULL, NULL, FALSE, G_PARAM_READABLE | 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_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_model); 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_child (widget_class, BzLibraryPage, sort_model); gtk_widget_class_bind_template_child (widget_class, BzLibraryPage, sorter); gtk_widget_class_bind_template_child (widget_class, BzLibraryPage, sort_name); gtk_widget_class_bind_template_child (widget_class, BzLibraryPage, sort_size); 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, format_install_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, search_text_activate); gtk_widget_class_bind_template_callback (widget_class, n_filtered_items_changed); gtk_widget_class_bind_template_callback (widget_class, clear_tasks_cb); gtk_widget_class_bind_template_callback (widget_class, updates_card_update_cb); gtk_widget_class_bind_template_callback (widget_class, global_search_cb); gtk_widget_class_bind_template_callback (widget_class, sort_changed_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); gtk_custom_sorter_set_sort_func ( self->sorter, (GCompareDataFunc) sort_func, 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]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HAS_APPS]); } 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_transactions (BzLibraryPage *self, BzTransactionManager *transactions) { g_return_if_fail (BZ_IS_LIBRARY_PAGE (self)); g_return_if_fail (transactions == NULL || BZ_IS_TRANSACTION_MANAGER (transactions)); if (self->transactions != NULL) g_signal_handlers_disconnect_by_func (self->transactions, has_transactions_changed, self); g_clear_object (&self->transactions); if (transactions != NULL) { self->transactions = g_object_ref (transactions); g_signal_connect_swapped ( transactions, "notify::has-transactions", G_CALLBACK (has_transactions_changed), self); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRANSACTIONS]); } BzTransactionManager * bz_library_page_get_transactions (BzLibraryPage *self) { g_return_val_if_fail (BZ_IS_LIBRARY_PAGE (self), NULL); return self->transactions; } 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); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HAS_APPS]); } static void has_transactions_changed (BzLibraryPage *self, GParamSpec *pspec, BzTransactionManager *transactions) { set_page (self); } static void set_page (BzLibraryPage *self) { guint n_apps = 0; guint n_filtered = 0; gboolean has_transactions = FALSE; if (self->model != NULL) { n_apps = g_list_model_get_n_items (self->model); n_filtered = g_list_model_get_n_items (G_LIST_MODEL (self->filter_model)); } if (self->state != NULL) { BzTransactionManager *manager = NULL; manager = bz_state_info_get_transaction_manager (self->state); has_transactions = bz_transaction_manager_get_has_transactions (manager); } if (n_apps == 0 && !has_transactions) { gtk_editable_set_text (GTK_EDITABLE (self->search_bar), ""); adw_view_stack_set_visible_child_name (self->stack, "empty"); } else if (n_apps > 0 && n_filtered == 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; if (bz_entry_group_is_addon (group)) return FALSE; 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; } bazaar-org-bazaar-43ce9f7/src/bz-library-page.h000066400000000000000000000033411520414637400213610ustar00rootroot00000000000000/* 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_transactions (BzLibraryPage *self, BzTransactionManager *transactions); BzTransactionManager * bz_library_page_get_transactions (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 bazaar-org-bazaar-43ce9f7/src/bz-license-dialog.blp000066400000000000000000000060171520414637400222130ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzLicenseDialog: Adw.Bin { 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 { 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 ; } } ListBox { visible: bind $should_show_eula(template.entry as <$BzEntry>) as ; selection-mode: none; styles [ "boxed-list", ] Adw.ButtonRow { title: _("Learn More"); end-icon-name: "external-link-symbolic"; activated => $eula_cb(template); has-tooltip: true; tooltip-text: bind $eula_tooltip(template.entry) as ; } } } }; }; }; } bazaar-org-bazaar-43ce9f7/src/bz-license-dialog.c000066400000000000000000000225041520414637400216570ustar00rootroot00000000000000/* 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 #include "bz-entry.h" #include "bz-license-dialog.h" #include "bz-lozenge.h" #include "bz-spdx.h" #include "bz-url.h" struct _BzLicenseDialog { AdwBin parent_instance; BzEntry *entry; }; G_DEFINE_FINAL_TYPE (BzLicenseDialog, bz_license_dialog, ADW_TYPE_BIN) 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 char * get_eula_url (BzEntry *entry) { g_autofree char *license = NULL; const char *url = NULL; if (entry == NULL) return NULL; g_object_get (entry, "project-license", &license, NULL); if (license == NULL || !g_str_has_prefix (license, "LicenseRef-proprietary=")) return NULL; url = license + strlen ("LicenseRef-proprietary="); return (*url != '\0') ? g_strdup (url) : NULL; } static gboolean should_show_eula (gpointer object, BzEntry *entry) { g_autofree char *url = get_eula_url (entry); return url != NULL; } static char * eula_tooltip (gpointer object, BzEntry *entry) { return get_eula_url (entry); } static void eula_cb (BzLicenseDialog *self) { g_autofree char *url = get_eula_url (self->entry); if (url != NULL) 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, should_show_eula); gtk_widget_class_bind_template_callback (widget_class, eula_tooltip); gtk_widget_class_bind_template_callback (widget_class, contribute_cb); gtk_widget_class_bind_template_callback (widget_class, eula_cb); } static void bz_license_dialog_init (BzLicenseDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } AdwDialog * bz_license_dialog_new (BzEntry *entry) { BzLicenseDialog *widget = NULL; AdwDialog *dialog = NULL; widget = g_object_new (BZ_TYPE_LICENSE_DIALOG, "entry", entry, NULL); dialog = adw_dialog_new (); adw_dialog_set_content_width (dialog, 400); adw_dialog_set_child (dialog, GTK_WIDGET (widget)); return dialog; } AdwNavigationPage * bz_license_page_new (BzEntry *entry) { BzLicenseDialog *widget = NULL; AdwNavigationPage *page = NULL; widget = g_object_new (BZ_TYPE_LICENSE_DIALOG, "entry", entry, NULL); page = adw_navigation_page_new (GTK_WIDGET (widget), _ ("License")); adw_navigation_page_set_tag (page, "license"); return page; } bazaar-org-bazaar-43ce9f7/src/bz-license-dialog.h000066400000000000000000000021301520414637400216550ustar00rootroot00000000000000/* 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, AdwBin) AdwDialog * bz_license_dialog_new (BzEntry *entry); AdwNavigationPage * bz_license_page_new (BzEntry *entry); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-linear-function.txt000066400000000000000000000002561520414637400224720ustar00rootroot00000000000000prefix=bz name=linear_function parent-prefix=g parent-name=object author=AUTOGEN property=slope double G_TYPE_DOUBLE double property=y_intercept double G_TYPE_DOUBLE double bazaar-org-bazaar-43ce9f7/src/bz-list-tile.c000066400000000000000000000150471520414637400207120ustar00rootroot00000000000000/* 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); } } bazaar-org-bazaar-43ce9f7/src/bz-list-tile.h000066400000000000000000000023361520414637400207140ustar00rootroot00000000000000/* 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_DECLSbazaar-org-bazaar-43ce9f7/src/bz-login-page.blp000066400000000000000000000055711520414637400213620ustar00rootroot00000000000000using 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 ; wrap: true; wrap-mode: word_char; justify: center; styles [ "title-1", ] } } Box { orientation: horizontal; spacing: 10; halign: center; margin-top: 20; Button { label: _("Finish"); clicked => $on_close_clicked(); styles [ "pill", ] } } }; }; }; } }; }; }bazaar-org-bazaar-43ce9f7/src/bz-login-page.c000066400000000000000000000540001520414637400210160ustar00rootroot00000000000000/* 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-global-net.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 (); soup_session_set_proxy_resolver (self->session, bz_get_default_proxy_resolver ()); 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); } bazaar-org-bazaar-43ce9f7/src/bz-login-page.h000066400000000000000000000020411520414637400210210ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-lozenge.c000066400000000000000000000240041520414637400204400ustar00rootroot00000000000000/* 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); } } bazaar-org-bazaar-43ce9f7/src/bz-lozenge.h000066400000000000000000000031301520414637400204420ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-main-config.txt000066400000000000000000000013321520414637400215600ustar00rootroot00000000000000prefix=bz name=main_config parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-hook.h" include="bz-search-bias.h" ensure=BZ_TYPE_HOOK ensure=BZ_TYPE_HOOK_DIALOG ensure=BZ_TYPE_HOOK_DIALOG_OPTION ensure=BZ_TYPE_SEARCH_BIAS 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 property=search_biases GListModel G_TYPE_LIST_MODEL object bazaar-org-bazaar-43ce9f7/src/bz-malcontent-service.c000066400000000000000000000154011520414637400226000ustar00rootroot00000000000000/* bz-malcontent-service.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 #include #include "bz-malcontent-service.h" struct _BzMalcontentService { GObject parent_instance; MctManager *manager; BzStateInfo *state; GDBusConnection *bus; MctAppFilter *filter; gulong changed_id; }; G_DEFINE_FINAL_TYPE (BzMalcontentService, bz_malcontent_service, G_TYPE_OBJECT) static void fetch_blocked_ids (BzMalcontentService *self); static void apply_filter (BzMalcontentService *self, MctAppFilter *filter); static void on_filter_loaded (GObject *source, GAsyncResult *result, gpointer user_data); static void on_filter_changed (MctManager *manager, guint64 user_id, gpointer user_data); static void bz_malcontent_service_dispose (GObject *object) { BzMalcontentService *self = NULL; self = BZ_MALCONTENT_SERVICE (object); g_signal_handler_disconnect (self->manager, self->changed_id); g_clear_object (&self->manager); g_clear_object (&self->state); g_clear_object (&self->bus); g_clear_pointer (&self->filter, mct_app_filter_unref); G_OBJECT_CLASS (bz_malcontent_service_parent_class)->dispose (object); } static void bz_malcontent_service_class_init (BzMalcontentServiceClass *klass) { G_OBJECT_CLASS (klass)->dispose = bz_malcontent_service_dispose; } static void bz_malcontent_service_init (BzMalcontentService *self) { } BzMalcontentService * bz_malcontent_service_new (GDBusConnection *bus, BzStateInfo *state) { BzMalcontentService *self = NULL; self = g_object_new (BZ_TYPE_MALCONTENT_SERVICE, NULL); self->state = g_object_ref (state); self->bus = g_object_ref (bus); self->manager = mct_manager_new (bus); self->changed_id = g_signal_connect (self->manager, "app-filter-changed", G_CALLBACK (on_filter_changed), self); return self; } void bz_malcontent_service_start (BzMalcontentService *self) { mct_manager_get_app_filter_async (self->manager, getuid (), MCT_MANAGER_GET_VALUE_FLAGS_INTERACTIVE, NULL, on_filter_loaded, self); } static void fetch_blocked_ids (BzMalcontentService *self) { g_autoptr (GError) local_error = NULL; g_autoptr (GVariant) result = NULL; g_autoptr (GVariant) prop = NULL; g_autoptr (GVariant) filter_tuple = NULL; g_autoptr (GtkStringList) blocked = NULL; g_autofree char *object_path = NULL; gboolean is_allowlist = FALSE; GVariantIter *iter = NULL; const char *ref = NULL; object_path = g_strdup_printf ("/org/freedesktop/Accounts/User%d", (int) getuid ()); result = g_dbus_connection_call_sync ( self->bus, "org.freedesktop.Accounts", object_path, "org.freedesktop.DBus.Properties", "Get", g_variant_new ("(ss)", "com.endlessm.ParentalControls.AppFilter", "AppFilter"), G_VARIANT_TYPE ("(v)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &local_error); if (result == NULL) { g_warning ("failed to fetch malcontent AppFilter from D-Bus: %s", local_error->message); return; } prop = g_variant_get_child_value (result, 0); filter_tuple = g_variant_get_variant (prop); g_variant_get (filter_tuple, "(bas)", &is_allowlist, &iter); blocked = gtk_string_list_new (NULL); while (g_variant_iter_next (iter, "s", &ref)) gtk_string_list_append (blocked, ref); g_variant_iter_free (iter); bz_state_info_set_parental_blocked_ids (self->state, G_LIST_MODEL (blocked)); } static void apply_filter (BzMalcontentService *self, MctAppFilter *filter) { const char *const *oars_sections = NULL; int max_age = -1; g_clear_pointer (&self->filter, mct_app_filter_unref); self->filter = mct_app_filter_ref (filter); oars_sections = mct_app_filter_get_oars_sections (self->filter); for (gsize i = 0; oars_sections[i] != NULL; i++) { MctAppFilterOarsValue filter_value; int section_age; filter_value = mct_app_filter_get_oars_value (self->filter, oars_sections[i]); if (filter_value == MCT_APP_FILTER_OARS_VALUE_UNKNOWN) continue; section_age = as_content_rating_attribute_to_csm_age (oars_sections[i], (AsContentRatingValue) filter_value); if (section_age > max_age) max_age = section_age; } bz_state_info_set_parental_age_rating (self->state, max_age); fetch_blocked_ids (self); } static void on_filter_loaded (GObject *source, GAsyncResult *result, gpointer user_data) { BzMalcontentService *self = NULL; g_autoptr (MctAppFilter) filter = NULL; g_autoptr (GError) local_error = NULL; self = user_data; filter = mct_manager_get_app_filter_finish (self->manager, result, &local_error); if (filter != NULL) apply_filter (self, filter); else g_warning ("Failed to load malcontent app filter: %s", local_error->message); } static void on_filter_changed (MctManager *manager, guint64 user_id, gpointer user_data) { BzMalcontentService *self = NULL; self = user_data; if (user_id != (guint64) getuid ()) return; mct_manager_get_app_filter_async (self->manager, getuid (), MCT_MANAGER_GET_VALUE_FLAGS_NONE, NULL, on_filter_loaded, self); } bazaar-org-bazaar-43ce9f7/src/bz-malcontent-service.h000066400000000000000000000023301520414637400226020ustar00rootroot00000000000000/* bz-malcontent-service.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 #include G_BEGIN_DECLS #define BZ_TYPE_MALCONTENT_SERVICE bz_malcontent_service_get_type () G_DECLARE_FINAL_TYPE (BzMalcontentService, bz_malcontent_service, BZ, MALCONTENT_SERVICE, GObject) BzMalcontentService * bz_malcontent_service_new (GDBusConnection *bus, BzStateInfo *state); void bz_malcontent_service_start (BzMalcontentService *self); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-marshalers.list000066400000000000000000000026251520414637400216740ustar00rootroot00000000000000# 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 bazaar-org-bazaar-43ce9f7/src/bz-metainfo-preview.c000066400000000000000000000167531520414637400222720ustar00rootroot00000000000000/* bz-metainfo-preview.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-group.h" #include "bz-featured-carousel.h" #include "bz-metainfo-preview.h" #include "bz-rich-app-tile.h" #include "bz-util.h" BZ_DEFINE_DATA ( pick_files, PickFiles, { DexPromise *promise; GFile *metainfo_file; }, BZ_RELEASE_DATA (promise, dex_unref); BZ_RELEASE_DATA (metainfo_file, g_object_unref)) static void on_icon_chosen (GtkFileDialog *dialog, GAsyncResult *result, PickFilesData *data); static void on_metainfo_chosen (GtkFileDialog *dialog, GAsyncResult *result, DexPromise *promise); static BzMetainfoPickResult * bz_metainfo_pick_result_copy (BzMetainfoPickResult *result); GType bz_metainfo_pick_result_get_type (void) { static GType type = 0; if (type == 0) type = g_boxed_type_register_static ( "BzMetainfoPickResult", (GBoxedCopyFunc) bz_metainfo_pick_result_copy, (GBoxedFreeFunc) bz_metainfo_pick_result_free); return type; } void bz_metainfo_pick_result_free (BzMetainfoPickResult *result) { g_clear_object (&result->metainfo_file); g_clear_object (&result->icon_file); g_free (result); } DexFuture * bz_metainfo_preview_pick_files (void) { g_autoptr (DexPromise) promise = dex_promise_new (); g_autoptr (GtkFileDialog) dialog = NULL; g_autoptr (GtkFileFilter) filter = NULL; g_autoptr (GListStore) filters = NULL; dialog = gtk_file_dialog_new (); gtk_file_dialog_set_title (dialog, _ ("Select Metainfo File")); filter = gtk_file_filter_new (); gtk_file_filter_set_name (filter, _ ("Metainfo Files")); gtk_file_filter_add_pattern (filter, "*.metainfo.xml*"); gtk_file_filter_add_pattern (filter, "*.appdata.xml*"); filters = g_list_store_new (GTK_TYPE_FILE_FILTER); g_list_store_append (filters, filter); gtk_file_dialog_set_filters (dialog, G_LIST_MODEL (filters)); gtk_file_dialog_open ( dialog, NULL, NULL, (GAsyncReadyCallback) on_metainfo_chosen, dex_ref (promise)); return DEX_FUTURE (g_steal_pointer (&promise)); } static BzMetainfoPickResult * bz_metainfo_pick_result_copy (BzMetainfoPickResult *result) { BzMetainfoPickResult *copy = NULL; copy = g_new0 (BzMetainfoPickResult, 1); copy->metainfo_file = result->metainfo_file ? g_object_ref (result->metainfo_file) : NULL; copy->icon_file = result->icon_file ? g_object_ref (result->icon_file) : NULL; return copy; } static void on_metainfo_chosen (GtkFileDialog *dialog, GAsyncResult *result, DexPromise *promise) { g_autoptr (DexPromise) owned_promise = promise; g_autoptr (GError) local_error = NULL; g_autoptr (GFile) metainfo_file = NULL; g_autoptr (GtkFileDialog) icon_dialog = NULL; g_autoptr (GtkFileFilter) filter = NULL; g_autoptr (GListStore) filters = NULL; PickFilesData *data = NULL; metainfo_file = gtk_file_dialog_open_finish (dialog, result, &local_error); if (metainfo_file == NULL) { dex_promise_reject (owned_promise, g_steal_pointer (&local_error)); return; } data = pick_files_data_new (); data->promise = g_steal_pointer (&owned_promise); data->metainfo_file = g_steal_pointer (&metainfo_file); icon_dialog = gtk_file_dialog_new (); gtk_file_dialog_set_title (icon_dialog, _ ("Select Icon (Optional)")); filter = gtk_file_filter_new (); gtk_file_filter_set_name (filter, _ ("Image Files")); gtk_file_filter_add_pattern (filter, "*.png"); gtk_file_filter_add_pattern (filter, "*.svg"); gtk_file_filter_add_pattern (filter, "*.jpg"); gtk_file_filter_add_pattern (filter, "*.jpeg"); filters = g_list_store_new (GTK_TYPE_FILE_FILTER); g_list_store_append (filters, filter); gtk_file_dialog_set_filters (icon_dialog, G_LIST_MODEL (filters)); gtk_file_dialog_open ( icon_dialog, NULL, NULL, (GAsyncReadyCallback) on_icon_chosen, data); } static void on_icon_chosen (GtkFileDialog *dialog, GAsyncResult *result, PickFilesData *data) { g_autoptr (PickFilesData) owned_data = data; g_autoptr (GFile) icon_file = NULL; BzMetainfoPickResult *pick = NULL; icon_file = gtk_file_dialog_open_finish (dialog, result, NULL); pick = g_new0 (BzMetainfoPickResult, 1); pick->metainfo_file = g_object_ref (owned_data->metainfo_file); pick->icon_file = g_steal_pointer (&icon_file); dex_promise_resolve_boxed ( owned_data->promise, bz_metainfo_pick_result_get_type (), g_steal_pointer (&pick)); } AdwNavigationPage * create_entry_group_preview_page (BzEntryGroup *group) { AdwNavigationPage *page = NULL; GtkWidget *toolbar_view = NULL; AdwHeaderBar *header_bar = NULL; GtkBox *box = NULL; BzFeaturedCarousel *carousel = NULL; BzRichAppTile *tile = NULL; GtkWidget *carousel_clamp = NULL; GtkWidget *tile_clamp = NULL; GtkWidget *scroll = NULL; g_autoptr (GListStore) store = NULL; store = g_list_store_new (BZ_TYPE_ENTRY_GROUP); g_list_store_append (store, group); carousel = bz_featured_carousel_new (); bz_featured_carousel_set_model (carousel, G_LIST_MODEL (store)); gtk_widget_set_can_target (GTK_WIDGET (carousel), FALSE); carousel_clamp = adw_clamp_new (); adw_clamp_set_maximum_size (ADW_CLAMP (carousel_clamp), 1500); adw_clamp_set_tightening_threshold (ADW_CLAMP (carousel_clamp), 1400); adw_clamp_set_child (ADW_CLAMP (carousel_clamp), GTK_WIDGET (carousel)); tile = BZ_RICH_APP_TILE (bz_rich_app_tile_new ()); bz_rich_app_tile_set_group (tile, group); tile_clamp = adw_clamp_new (); adw_clamp_set_maximum_size (ADW_CLAMP (tile_clamp), 350); adw_clamp_set_child (ADW_CLAMP (tile_clamp), GTK_WIDGET (tile)); box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 12)); gtk_widget_set_margin_top (GTK_WIDGET (box), 24); gtk_widget_set_margin_bottom (GTK_WIDGET (box), 24); gtk_widget_set_margin_start (GTK_WIDGET (box), 24); gtk_widget_set_margin_end (GTK_WIDGET (box), 24); gtk_box_append (box, GTK_WIDGET (carousel_clamp)); gtk_box_append (box, GTK_WIDGET (tile_clamp)); scroll = gtk_scrolled_window_new (); gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scroll), GTK_WIDGET (box)); gtk_widget_set_vexpand (scroll, TRUE); header_bar = ADW_HEADER_BAR (adw_header_bar_new ()); toolbar_view = adw_toolbar_view_new (); adw_toolbar_view_add_top_bar (ADW_TOOLBAR_VIEW (toolbar_view), GTK_WIDGET (header_bar)); adw_toolbar_view_set_content (ADW_TOOLBAR_VIEW (toolbar_view), scroll); page = adw_navigation_page_new (toolbar_view, _ ("Preview")); return page; } bazaar-org-bazaar-43ce9f7/src/bz-metainfo-preview.h000066400000000000000000000023411520414637400222630ustar00rootroot00000000000000/* bz-metainfo-preview.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 #include #include #include "bz-entry-group.h" G_BEGIN_DECLS typedef struct { GFile *metainfo_file; GFile *icon_file; } BzMetainfoPickResult; void bz_metainfo_pick_result_free (BzMetainfoPickResult *result); GType bz_metainfo_pick_result_get_type (void); DexFuture * bz_metainfo_preview_pick_files (void); AdwNavigationPage * create_entry_group_preview_page (BzEntryGroup *group); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-newline-parser.c000066400000000000000000000112501520414637400217270ustar00rootroot00000000000000/* 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); } bazaar-org-bazaar-43ce9f7/src/bz-newline-parser.h000066400000000000000000000020601520414637400217330ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-parser.c000066400000000000000000000026651520414637400203020ustar00rootroot00000000000000/* 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); } bazaar-org-bazaar-43ce9f7/src/bz-parser.h000066400000000000000000000023721520414637400203020ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-preferences-dialog.blp000066400000000000000000000050551520414637400230730ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzPreferencesDialog: Adw.PreferencesDialog { content-height: 500; search-enabled: true; width-request: 350; height-request: 100; 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 refresh is paused"); button-label: _("Refresh 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 End-of-Life 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(); } } } } bazaar-org-bazaar-43ce9f7/src/bz-preferences-dialog.c000066400000000000000000000274351520414637400225460ustar00rootroot00000000000000/* 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); } bazaar-org-bazaar-43ce9f7/src/bz-preferences-dialog.h000066400000000000000000000021151520414637400225370ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-pride-flag-config.txt000066400000000000000000000003401520414637400226440ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-pride-flag-spec.txt000066400000000000000000000006311520414637400223340ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-pride-flag-stripe-spec.txt000066400000000000000000000003001520414637400236310ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-progress-bar.blp000066400000000000000000000001371520414637400217370ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzProgressBar: Adw.Bin { child: ProgressBar bar {}; } bazaar-org-bazaar-43ce9f7/src/bz-progress-bar.c000066400000000000000000000116541520414637400214120ustar00rootroot00000000000000/* 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; } bazaar-org-bazaar-43ce9f7/src/bz-progress-bar.h000066400000000000000000000022301520414637400214050ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-release.txt000066400000000000000000000004201520414637400210060ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-releases-dialog.blp000066400000000000000000000013031520414637400223650ustar00rootroot00000000000000using 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; }; }; }; }; }bazaar-org-bazaar-43ce9f7/src/bz-releases-list.blp000066400000000000000000000011211520414637400220770ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzReleasesList: Adw.Bin { visible: false; 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"); use-underline: true; activated => $show_all_releases_cb(); end-icon-name: "go-next-symbolic"; } } }; } bazaar-org-bazaar-43ce9f7/src/bz-releases-list.c000066400000000000000000000435521520414637400215620ustar00rootroot00000000000000/* 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; } // From gs-common.c static char * format_timestamp (guint64 unix_time) { g_autoptr (GDateTime) then = NULL; g_autoptr (GDateTime) now = NULL; gint days, weeks, months, years; if (unix_time == 0) return NULL; then = g_date_time_new_from_unix_utc (unix_time); now = g_date_time_new_now_local (); if (then == NULL || now == NULL) return NULL; days = (gint) (g_date_time_difference (now, then) / G_TIME_SPAN_DAY); weeks = days / 7; months = days / 30; years = weeks / 52; if (days < 1) /* Translators: something happened less than a day ago */ return g_strdup (_ ("Today")); else if (days < 2) /* Translators: something happened more than a day ago but less than 2 days ago */ return g_strdup (_ ("Yesterday")); else if (days < 15) /* Translators: something happened days ago */ return g_strdup_printf (ngettext ("%d day ago", "%d days ago", days), days); else if (weeks < 8) /* Translators: something happened weeks ago */ return g_strdup_printf (ngettext ("%d week ago", "%d weeks ago", weeks), weeks); else if (years < 1) /* Translators: something happened months ago */ return g_strdup_printf (ngettext ("%d month ago", "%d months ago", months), months); else /* Translators: something happened years ago */ return g_strdup_printf (ngettext ("%d year ago", "%d years ago", years), years); } static char * format_timestamp_tooltip (guint64 unix_time) { g_autoptr (GDateTime) then = NULL; if (unix_time == 0) return NULL; then = g_date_time_new_from_unix_utc (unix_time); if (then == NULL) return NULL; /* TRANSLATORS: This is the date string with: day number, month name, year. i.e. "22 March 2026" */ return g_date_time_format (then, _ ("%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 *date_tooltip = NULL; g_autofree char *version_text = NULL; g_autofree char *markup = NULL; date_str = format_timestamp (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)); gtk_widget_set_size_request (GTK_WIDGET (header_box), -1, 24); 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); date_tooltip = format_timestamp_tooltip (timestamp); if (date_tooltip != NULL) gtk_widget_set_tooltip_text (GTK_WIDGET (date_label), date_tooltip); 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, url, _ ("Get More Information")); more_info_label = GTK_LABEL (gtk_label_new (NULL)); gtk_label_set_markup (more_info_label, markup); gtk_widget_set_tooltip_text (GTK_WIDGET (more_info_label), url); 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 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); gtk_widget_set_visible (GTK_WIDGET (self), g_list_model_get_n_items (version_history) > 0); } else { clear_preview_box (self); gtk_widget_set_visible (GTK_WIDGET (self), 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; } bazaar-org-bazaar-43ce9f7/src/bz-releases-list.h000066400000000000000000000025251520414637400215620ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-repository.txt000066400000000000000000000003661520414637400216160ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-result.c000066400000000000000000000166661520414637400203320ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-result.h000066400000000000000000000024331520414637400203220ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-rich-app-tile.blp000066400000000000000000000141471520414637400217750ustar00rootroot00000000000000using Gtk 4.0; template $BzRichAppTile: $BzListTile { overflow: hidden; accessibility { 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; height-request: 64; $BzTransactIcon { valign: center; halign: center; width-request: 64; height-request: 64; info: $BzTransactIconInfo transact_icon_info { group: bind template.group as <$BzEntryGroup>; paintable: bind template.ui_entry as <$BzEntry>.icon-paintable; }; } 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; accessibility { label: _("Verified"); } } } 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", ] } } Stack { transition-type: crossfade; valign: center; hhomogeneous: false; interpolate-size: true; visible-child-name: bind try { $get_visible_page( template.group as <$BzEntryGroup>.installable, template.group as <$BzEntryGroup>.removable, template.removable-at-start as , template.tracker as <$BzTransactionEntryTracker>, template.tracker as <$BzTransactionEntryTracker>.status as <$BzTransactionEntryStatus> ) as , $get_visible_page( template.group as <$BzEntryGroup>.installable, template.group as <$BzEntryGroup>.removable, template.removable-at-start as , null as <$BzTransactionEntryTracker>, null as <$BzTransactionEntryStatus> ) as }; StackPage { name: "get"; child: Button get_button { sensitive: bind $invert_boolean( $is_zero(template.group as <$BzEntryGroup>.installable-and-available) as ) as ; styles [ "medium-pill", ] valign: center; clicked => $install_button_clicked_cb(template); }; } StackPage { name: "open"; child: Button { sensitive: bind $invert_boolean( $is_zero(template.group as <$BzEntryGroup>.removable-and-available) as ) as ; styles [ "medium-pill", ] label: _("Open"); valign: center; clicked => $run_button_clicked_cb(template); }; } StackPage { name: "uninstall"; child: Button { sensitive: bind $invert_boolean( $is_zero(template.group as <$BzEntryGroup>.removable-and-available) as ) as ; styles [ "circular", ] icon-name: "user-trash-symbolic"; has-tooltip: true; tooltip-text: _("Uninstall"); valign: center; clicked => $remove_button_clicked_cb(template); }; } StackPage { name: "cancel"; child: Button { styles [ "circular", ] icon-name: "cross-large-circle-filled-symbolic"; has-tooltip: true; tooltip-text: _("Cancel"); valign: center; clicked => $cancel_button_clicked_cb(template); }; } StackPage { name: "empty"; child: Box {}; } } } }; } bazaar-org-bazaar-43ce9f7/src/bz-rich-app-tile.c000066400000000000000000000323621520414637400214410ustar00rootroot00000000000000/* 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-application.h" #include "bz-entry.h" #include "bz-rounded-picture.h" #include "bz-themed-entry-group-rect.h" #include "bz-transact-icon.h" #include "bz-util.h" #include struct _BzRichAppTile { BzListTile parent_instance; BzEntryGroup *group; BzEntry *ui_entry; DexFuture *ui_entry_resolve; gboolean removable_at_start; BzTransactionEntryTracker *tracker; GListModel *all_trackers; GtkWidget *picture_box; GtkWidget *get_button; BzTransactIconInfo *transact_icon_info; }; G_DEFINE_FINAL_TYPE (BzRichAppTile, bz_rich_app_tile, BZ_TYPE_LIST_TILE); enum { PROP_0, PROP_GROUP, PROP_UI_ENTRY, PROP_REMOVABLE_AT_START, PROP_TRACKER, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void update_ui_entry (BzRichAppTile *self); static void update_tracker (BzRichAppTile *self) { BzTransactionManager *manager = NULL; g_autoptr (GListModel) all = NULL; const char *group_id = NULL; g_autoptr (BzTransactionEntryTracker) found = NULL; manager = bz_state_info_get_transaction_manager (bz_state_info_get_default ()); if (manager != NULL) g_object_get (manager, "all-trackers", &all, NULL); if (self->group != NULL) group_id = bz_entry_group_get_id (self->group); if (all != NULL && group_id != NULL) { for (guint i = 0; i < g_list_model_get_n_items (all); i++) { g_autoptr (BzTransactionEntryTracker) tracker = NULL; BzEntry *entry = NULL; tracker = g_list_model_get_item (all, i); entry = bz_transaction_entry_tracker_get_entry (tracker); if (g_strcmp0 (entry != NULL ? bz_entry_get_id (entry) : NULL, group_id) == 0) { found = g_steal_pointer (&tracker); break; } } } if (g_set_object (&self->tracker, found)) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRACKER]); } static void on_all_trackers_changed (GListModel *model, guint position, guint removed, guint added, BzRichAppTile *self) { update_tracker (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); if (self->all_trackers != NULL) { g_signal_handlers_disconnect_by_func (self->all_trackers, on_all_trackers_changed, self); g_clear_object (&self->all_trackers); } g_clear_object (&self->group); g_clear_object (&self->ui_entry); g_clear_object (&self->tracker); 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; case PROP_REMOVABLE_AT_START: g_value_set_boolean (value, self->removable_at_start); break; case PROP_TRACKER: g_value_set_object (value, self->tracker); 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: case PROP_REMOVABLE_AT_START: case PROP_TRACKER: 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_visible_page (gpointer object, int installable, int removable, gboolean removable_at_start, BzTransactionEntryTracker *tracker, BzTransactionEntryStatus status) { if (tracker != NULL && (bz_transaction_entry_tracker_get_active (tracker) || bz_transaction_entry_tracker_get_pending (tracker)) && status != BZ_TRANSACTION_ENTRY_STATUS_CANCELLED && status != BZ_TRANSACTION_ENTRY_STATUS_DONE) return g_strdup ("cancel"); if (removable > 0) return g_strdup (removable_at_start ? "uninstall" : "open"); if (installable > 0) return g_strdup ("get"); return g_strdup ("empty"); } static void install_button_clicked_cb (BzRichAppTile *self, GtkButton *button) { gtk_widget_activate_action (GTK_WIDGET (self), "window.install-group", "(sb)", bz_entry_group_get_id (self->group), TRUE); } static void remove_button_clicked_cb (BzRichAppTile *self, GtkButton *button) { gtk_widget_activate_action (GTK_WIDGET (self), "window.remove-group", "(sb)", bz_entry_group_get_id (self->group), FALSE); } static void run_button_clicked_cb (BzRichAppTile *self, GtkButton *button) { gtk_widget_activate_action (GTK_WIDGET (self), "window.launch-group", "s", bz_entry_group_get_id (self->group)); } static void cancel_button_clicked_cb (BzRichAppTile *self, GtkButton *button) { if (self->group == NULL) return; gtk_widget_activate_action (GTK_WIDGET (self), "window.cancel-group", "s", bz_entry_group_get_id (self->group)); } 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); props[PROP_REMOVABLE_AT_START] = g_param_spec_boolean ( "removable-at-start", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_TRACKER] = g_param_spec_object ( "tracker", NULL, NULL, BZ_TYPE_TRANSACTION_ENTRY_TRACKER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_TRANSACT_ICON); 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, get_visible_page); gtk_widget_class_bind_template_callback (widget_class, install_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, remove_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, run_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, cancel_button_clicked_cb); gtk_widget_class_bind_template_child (widget_class, BzRichAppTile, picture_box); gtk_widget_class_bind_template_child (widget_class, BzRichAppTile, get_button); gtk_widget_class_bind_template_child (widget_class, BzRichAppTile, transact_icon_info); gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_BUTTON); } static void bz_rich_app_tile_init (BzRichAppTile *self) { BzStateInfo *state = NULL; BzTransactionManager *manager = NULL; const char *get_label = NULL; gtk_widget_init_template (GTK_WIDGET (self)); /* Translators: If you can't find a short enough translation, use "/" to use an icon instead. */ get_label = _ ("Get"); if (get_label != NULL && *get_label != '\0' && g_strcmp0 (get_label, "/") != 0) gtk_button_set_label (GTK_BUTTON (self->get_button), get_label); else gtk_button_set_icon_name (GTK_BUTTON (self->get_button), "folder-download-symbolic"); state = bz_state_info_get_default (); manager = bz_state_info_get_transaction_manager (state); if (manager != NULL) g_object_get (manager, "all-trackers", &self->all_trackers, NULL); if (self->all_trackers != NULL) g_signal_connect (self->all_trackers, "items-changed", G_CALLBACK (on_all_trackers_changed), self); update_tracker (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) { const char *title = NULL; gboolean verified = FALSE; gboolean removable_at_start = FALSE; g_autofree char *label = NULL; g_return_if_fail (BZ_IS_RICH_APP_TILE (self)); g_clear_object (&self->group); if (group != NULL) { self->group = g_object_ref (group); title = bz_entry_group_get_title (self->group); verified = bz_entry_group_get_is_verified (self->group); removable_at_start = bz_entry_group_get_removable (self->group) != 0; if (self->removable_at_start != removable_at_start) { self->removable_at_start = removable_at_start; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REMOVABLE_AT_START]); } if (verified) { label = g_strdup_printf ("%s, %s", title, _ ("Verified")); gtk_accessible_update_property (GTK_ACCESSIBLE (self), GTK_ACCESSIBLE_PROPERTY_LABEL, label, -1); } else { gtk_accessible_update_property (GTK_ACCESSIBLE (self), GTK_ACCESSIBLE_PROPERTY_LABEL, title, -1); } } update_ui_entry (self); update_tracker (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_GROUP]); } /* End of bz-rich-app-tile.c */ bazaar-org-bazaar-43ce9f7/src/bz-rich-app-tile.h000066400000000000000000000024401520414637400214400ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-root-blocklist.txt000066400000000000000000000003211520414637400223350ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-root-curated-config.txt000066400000000000000000000004021520414637400232410ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-rounded-picture.c000066400000000000000000000216441520414637400221150ustar00rootroot00000000000000/* 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; } bazaar-org-bazaar-43ce9f7/src/bz-rounded-picture.h000066400000000000000000000026111520414637400221130ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-row-view.blp000066400000000000000000000006051520414637400211100ustar00rootroot00000000000000using 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; }; } bazaar-org-bazaar-43ce9f7/src/bz-row-view.c000066400000000000000000000121431520414637400205550ustar00rootroot00000000000000/* 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) { gtk_widget_activate_action (GTK_WIDGET (view), "window.show-group", "s", bz_entry_group_get_id (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; } bazaar-org-bazaar-43ce9f7/src/bz-row-view.h000066400000000000000000000022201520414637400205550ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-safety-calculator.c000066400000000000000000000646021520414637400224270ustar00rootroot00000000000000/* 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; BzImportance fs_importance = BZ_IMPORTANCE_WARNING; 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); fs_importance = (perm_flags & BZ_APP_PERMISSIONS_FLAGS_NETWORK) ? BZ_IMPORTANCE_WARNING : BZ_IMPORTANCE_INFORMATION; 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, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_NETWORK) ? BZ_IMPORTANCE_WARNING : BZ_IMPORTANCE_INFORMATION, "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))), fs_importance, "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))), fs_importance, "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); if (perm_flags & BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL) continue; if ((perm_flags & BZ_APP_PERMISSIONS_FLAGS_HOME_FULL) && path->type == BZ_FILESYSTEM_PATH_HOME_SUBDIR) continue; add_row_if_permission (store, TRUE, fs_importance, 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); if (perm_flags & BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL) continue; if ((perm_flags & (BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ | BZ_APP_PERMISSIONS_FLAGS_HOME_FULL | BZ_APP_PERMISSIONS_FLAGS_HOME_READ)) && path->type == BZ_FILESYSTEM_PATH_HOME_SUBDIR) continue; add_row_if_permission (store, TRUE, fs_importance, 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); } bazaar-org-bazaar-43ce9f7/src/bz-safety-calculator.h000066400000000000000000000026351520414637400224320ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-safety-dialog.blp000066400000000000000000000055171520414637400220700ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzSafetyDialog: Adw.Bin { 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.entry as <$BzEntry>.project-license; subtitle-selectable: true; styles [ "property", ] } Adw.ActionRow { title: _("App ID"); subtitle: bind template.entry as <$BzEntry>.id; subtitle-selectable: true; styles [ "property", ] } Adw.ActionRow { title: _("SDK"); subtitle: bind template.entry as <$BzFlatpakEntry>.runtime as <$BzResult>.object as <$BzEntry>.title; subtitle-selectable: true; has-tooltip: true; tooltip-text: bind template.entry as <$BzFlatpakEntry>.application-runtime; visible: bind $invert_boolean($is_null(template.entry as <$BzFlatpakEntry>.runtime as <$BzResult>.object) as ) as ; styles [ "property", ] [suffix] MenuButton { visible: bind $invert_boolean($is_null(template.entry as <$BzEntry>.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."); }; }; } } } } } }; }; } bazaar-org-bazaar-43ce9f7/src/bz-safety-dialog.c000066400000000000000000000166651520414637400215430ustar00rootroot00000000000000/* 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-context-row.h" #include "bz-entry.h" #include "bz-lozenge.h" #include "bz-safety-calculator.h" #include "bz-safety-dialog.h" #include "bz-safety-row.h" #include "bz-template-callbacks.h" struct _BzSafetyDialog { AdwBin parent_instance; BzEntry *entry; BzLozenge *lozenge; GtkListBox *permissions_list; }; G_DEFINE_FINAL_TYPE (BzSafetyDialog, bz_safety_dialog, ADW_TYPE_BIN) enum { PROP_0, PROP_ENTRY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static AdwActionRow *create_permission_row (BzSafetyRow *row_data); static void update_permissions_list (BzSafetyDialog *self); static void bz_safety_dialog_dispose (GObject *object) { BzSafetyDialog *self = BZ_SAFETY_DIALOG (object); g_clear_object (&self->entry); 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 = BZ_SAFETY_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_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_ENTRY: g_clear_object (&self->entry); self->entry = 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_ENTRY] = g_param_spec_object ("entry", NULL, NULL, BZ_TYPE_ENTRY, 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"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzSafetyDialog, lozenge); gtk_widget_class_bind_template_child (widget_class, BzSafetyDialog, permissions_list); } static void bz_safety_dialog_init (BzSafetyDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } AdwDialog * bz_safety_dialog_new (BzEntry *entry) { BzSafetyDialog *widget = NULL; AdwDialog *dialog = NULL; widget = g_object_new (BZ_TYPE_SAFETY_DIALOG, "entry", entry, NULL); dialog = adw_dialog_new (); adw_dialog_set_content_height (dialog, 576); adw_dialog_set_content_width (dialog, 640); adw_dialog_set_child (dialog, GTK_WIDGET (widget)); return dialog; } AdwNavigationPage * bz_safety_dialog_page_new (BzEntry *entry) { BzSafetyDialog *widget = NULL; AdwNavigationPage *page = NULL; widget = g_object_new (BZ_TYPE_SAFETY_DIALOG, "entry", entry, NULL); page = adw_navigation_page_new (GTK_WIDGET (widget), _ ("Safety")); adw_navigation_page_set_tag (page, "safety"); return page; } 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; GtkWidget *child = NULL; 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->entry == NULL) return; app_name = bz_entry_get_title (self->entry); model = bz_safety_calculator_analyze_entry (self->entry); importance = bz_safety_calculator_calculate_rating (self->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 = NULL; AdwActionRow *row = NULL; BzImportance row_importance = 0; 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); } bazaar-org-bazaar-43ce9f7/src/bz-safety-dialog.h000066400000000000000000000021451520414637400215340ustar00rootroot00000000000000/* 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.h" #include G_BEGIN_DECLS G_BEGIN_DECLS #define BZ_TYPE_SAFETY_DIALOG (bz_safety_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzSafetyDialog, bz_safety_dialog, BZ, SAFETY_DIALOG, AdwBin) AdwDialog * bz_safety_dialog_new (BzEntry *entry); AdwNavigationPage * bz_safety_dialog_page_new (BzEntry *entry); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-safety-row.txt000066400000000000000000000004441520414637400214740ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-screenshot-page.blp000066400000000000000000000114741520414637400224260ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzScreenshotPage: Adw.NavigationPage { title: _("Screenshots"); child: Adw.BreakpointBin { width-request: 360; height-request: 100; 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: 12; styles [ "osd-box", ] Label { halign: center; hexpand: true; label: bind template.current-caption; height-request: 34; justify: center; max-width-chars: 30; wrap: true; margin-start: 8; margin-end: 8; 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(); }; }; }; }; }; }bazaar-org-bazaar-43ce9f7/src/bz-screenshot-page.c000066400000000000000000000376171520414637400221020ustar00rootroot00000000000000/* 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 != NULL && bz_zoom_is_transformed (zoom); 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); } bazaar-org-bazaar-43ce9f7/src/bz-screenshot-page.h000066400000000000000000000026321520414637400220740ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-screenshot.c000066400000000000000000000374741520414637400211710ustar00rootroot00000000000000/* 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)); } bazaar-org-bazaar-43ce9f7/src/bz-screenshot.h000066400000000000000000000037441520414637400211670ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-screenshots-carousel.blp000066400000000000000000000051031520414637400235020ustar00rootroot00000000000000using 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; $BgeCarousel carousel { vexpand: true; hexpand: true; valign: fill; height-request: bind $get_carousel_height(template.compact) as ; allow-mouse-drag: true; allow-overshoot: true; allow-scroll-wheel: true; allow-raise: bind $invert_boolean(template.compact) as ; create-widget => $on_create_widget(template); remove-widget => $on_remove_widget(template); model: SingleSelection selection { autoselect: true; model: bind template.model; notify::selected => $on_notify_selected(template); notify::n-items => $on_notify_n_items(template); }; } // $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", ] } } } } bazaar-org-bazaar-43ce9f7/src/bz-screenshots-carousel.c000066400000000000000000000474271520414637400231660ustar00rootroot00000000000000/* 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 #include #include "bz-decorated-screenshot.h" #include "bz-screenshots-carousel.h" #include "bz-template-callbacks.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; BgeCarousel *carousel; // GtkWidget *carousel_indicator; GtkButton *prev_button; GtkWidget *prev_button_revealer; GtkButton *next_button; GtkWidget *next_button_revealer; GtkSingleSelection *selection; 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 void update_button_visibility (BzScreenshotsCarousel *self) { gdouble position; guint n_pages; if (!self->carousel) return; position = gtk_single_selection_get_selected (self->selection); n_pages = g_list_model_get_n_items (G_LIST_MODEL (self->selection)); /* 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 (BzScreenshotsCarousel *self, AdwNavigationDirection direction) { guint n_children = 0; gdouble position = 0.0; n_children = g_list_model_get_n_items (G_LIST_MODEL (self->selection)); position = gtk_single_selection_get_selected (self->selection); position += (direction == ADW_NAVIGATION_DIRECTION_BACK) ? -1 : 1; position = round (position); position = MIN (position, n_children - 1); position = MAX (0, position); gtk_single_selection_set_selected (self->selection, position); } static void on_prev_clicked (BzScreenshotsCarousel *self) { if (!self->carousel) return; carousel_navigate (self, ADW_NAVIGATION_DIRECTION_BACK); } static void on_next_clicked (BzScreenshotsCarousel *self) { if (!self->carousel) return; carousel_navigate (self, ADW_NAVIGATION_DIRECTION_FORWARD); } static void on_notify_selected (BzScreenshotsCarousel *self) { update_button_visibility (self); } static void on_notify_n_items (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 = g_list_model_get_n_items (G_LIST_MODEL (self->selection)); if (n_pages == 0) return; position = gtk_single_selection_get_selected (self->selection); 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))) { BzAsyncTexture *texture = NULL; guint n_items = 0; texture = bz_decorated_screenshot_get_async_texture (screenshot); 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 == texture) { gtk_single_selection_set_selected (self->selection, i); break; } } } } static GtkWidget * on_create_widget (BzScreenshotsCarousel *self, BzAsyncTexture *item, BgeCarousel *carousel) { GtkWidget *screenshot = NULL; g_autofree char *caption = NULL; guint n_items = 0; guint index = 0; screenshot = g_object_new (BZ_TYPE_DECORATED_SCREENSHOT, "async-texture", item, NULL); n_items = g_list_model_get_n_items (self->model); for (index = 0; index < n_items; index++) { g_autoptr (BzAsyncTexture) it = g_list_model_get_item (self->model, index); if (it == item) break; } caption = g_strdup_printf (_ ("Screenshot %u of %u"), index + 1, n_items); gtk_accessible_update_property (GTK_ACCESSIBLE (screenshot), GTK_ACCESSIBLE_PROPERTY_LABEL, caption, -1); 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); return screenshot; } static void on_remove_widget (BzScreenshotsCarousel *self, BzDecoratedScreenshot *screenshot, BzAsyncTexture *item, BgeCarousel *carousel) { } 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); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-screenshots-carousel.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzScreenshotsCarousel, carousel); 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_child (widget_class, BzScreenshotsCarousel, selection); 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_selected); gtk_widget_class_bind_template_callback (widget_class, on_notify_n_items); gtk_widget_class_bind_template_callback (widget_class, on_create_widget); gtk_widget_class_bind_template_callback (widget_class, on_remove_widget); 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); gtk_single_selection_set_selected (self->selection, 0); } 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); } bazaar-org-bazaar-43ce9f7/src/bz-screenshots-carousel.h000066400000000000000000000037221520414637400231610ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-search-bias.txt000066400000000000000000000007221520414637400215540ustar00rootroot00000000000000prefix=bz name=search_bias parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-linear-function.h" include="bz-exponential-function.h" property=regex char G_TYPE_STRING string property=convert_to char G_TYPE_STRING string property=linear_boost BzLinearFunction BZ_TYPE_LINEAR_FUNCTION object property=exponential_boost BzExponentialFunction BZ_TYPE_EXPONENTIAL_FUNCTION object property=boost_appids GListModel G_TYPE_LIST_MODEL object bazaar-org-bazaar-43ce9f7/src/bz-search-engine.c000066400000000000000000000653211520414637400215140ustar00rootroot00000000000000/* 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 */ #define G_LOG_DOMAIN "BAZAAR::SEARCH-ENGINE" #include "bz-search-engine.h" #include "bz-entry-group.h" #include "bz-env.h" #include "bz-finished-search-query.h" #include "bz-search-result.h" #include "bz-util.h" struct _BzSearchEngine { GObject parent_instance; GListModel *model; GListModel *biases; GPtrArray *biases_mirror; }; G_DEFINE_FINAL_TYPE (BzSearchEngine, bz_search_engine, G_TYPE_OBJECT); enum { PROP_0, PROP_MODEL, PROP_BIASES, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void biases_changed (BzSearchEngine *self, guint position, guint removed, guint added, GListModel *model); 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); enum { LINEAR, EXPONENTIAL, }; BZ_DEFINE_DATA ( bias, Bias, { gboolean invalid; GRegex *regex; char *convert_to; GHashTable *boost; int boost_kind; union { struct { double slope; double y_intercept; } linear_boost; struct { double factor; double y_intercept; } exponential_boost; }; }, BZ_RELEASE_DATA (regex, g_regex_unref); BZ_RELEASE_DATA (convert_to, g_free); BZ_RELEASE_DATA (boost, g_hash_table_unref)); BZ_DEFINE_DATA ( query_task, QueryTask, { char **terms; GPtrArray *snapshot; GPtrArray *biases; }, BZ_RELEASE_DATA (terms, g_strfreev); BZ_RELEASE_DATA (snapshot, g_ptr_array_unref); BZ_RELEASE_DATA (biases, 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; GPtrArray *active_biases; }, BZ_RELEASE_DATA (query_utf8, g_free); BZ_RELEASE_DATA (shallow_mirror, g_ptr_array_unref); BZ_RELEASE_DATA (active_biases, 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); if (self->biases != NULL) g_signal_handlers_disconnect_by_func (self->biases, biases_changed, self); g_clear_object (&self->model); g_clear_object (&self->biases); g_clear_pointer (&self->biases_mirror, g_ptr_array_unref); 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; case PROP_BIASES: g_value_set_object (value, bz_search_engine_get_biases (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; case PROP_BIASES: bz_search_engine_set_biases (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); props[PROP_BIASES] = g_param_spec_object ( "biases", 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) { self->biases_mirror = g_ptr_array_new_with_free_func (bias_data_unref); } BzSearchEngine * bz_search_engine_new (void) { return g_object_new (BZ_TYPE_SEARCH_ENGINE, NULL); } GListModel * bz_search_engine_get_biases (BzSearchEngine *self) { g_return_val_if_fail (BZ_IS_SEARCH_ENGINE (self), NULL); return self->biases; } void bz_search_engine_set_biases (BzSearchEngine *self, GListModel *biases) { g_return_if_fail (BZ_IS_SEARCH_ENGINE (self)); g_return_if_fail (biases == NULL || G_IS_LIST_MODEL (biases)); if (self->biases != NULL) g_signal_handlers_disconnect_by_func (self->biases, biases_changed, self); g_clear_object (&self->biases); g_ptr_array_set_size (self->biases_mirror, 0); if (biases != NULL) { guint n_biases = 0; self->biases = g_object_ref (biases); n_biases = g_list_model_get_n_items (biases); biases_changed (self, 0, 0, n_biases, biases); g_signal_connect_swapped ( biases, "items-changed", G_CALLBACK (biases_changed), self); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_BIASES]); } 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) results = NULL; g_autoptr (BzFinishedSearchQuery) finished = NULL; results = g_ptr_array_new_with_free_func (g_object_unref); g_ptr_array_set_size (results, n_groups); for (guint i = 0; i < results->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 (results, i) = g_steal_pointer (&result); } finished = bz_finished_search_query_new (); bz_finished_search_query_set_interpreted_query (finished, ""); bz_finished_search_query_set_results (finished, results); bz_finished_search_query_set_n_results (finished, n_groups); bz_finished_search_query_set_elapsed (finished, 0.0); return dex_future_new_for_object (finished); } 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); data->biases = g_ptr_array_ref (self->biases_mirror); 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 void biases_changed (BzSearchEngine *self, guint position, guint removed, guint added, GListModel *model) { g_autoptr (GPtrArray) new_mirror = NULL; /* Since `self->biases_mirror` is used in other threads, it should be immutable after its construction; so we have to make a new mirror upon every change */ new_mirror = g_ptr_array_new_with_free_func (bias_data_unref); g_ptr_array_set_size (new_mirror, self->biases_mirror->len + added - removed); #define COPY_OVER(_old_idx, _new_idx, _len) \ for (guint _i = 0; _i < (_len); _i++) \ { \ BiasData *_data = NULL; \ BiasData **_loc = NULL; \ \ _data = g_ptr_array_index (self->biases_mirror, (_old_idx) + _i); \ _loc = (BiasData **) &g_ptr_array_index (new_mirror, (_new_idx) + _i); \ *_loc = bias_data_ref (_data); \ } COPY_OVER (0, 0, position); COPY_OVER (position + removed, position + added, self->biases_mirror->len - (position + removed)); #undef COPY_OVER for (guint i = 0; i < added; i++) { g_autoptr (GError) local_error = NULL; BiasData **loc = NULL; g_autoptr (BzSearchBias) bias = NULL; const char *regex_string = NULL; const char *convert_to = NULL; GListModel *boost_appids = NULL; BzLinearFunction *linear_function = NULL; BzExponentialFunction *exponential_function = NULL; g_autoptr (GRegex) regex = NULL; g_autoptr (GHashTable) boost = NULL; g_autoptr (BiasData) data = NULL; loc = (BiasData **) &g_ptr_array_index (new_mirror, position + i); bias = g_list_model_get_item (model, position + i); regex_string = bz_search_bias_get_regex (bias); convert_to = bz_search_bias_get_convert_to (bias); boost_appids = bz_search_bias_get_boost_appids (bias); linear_function = bz_search_bias_get_linear_boost (bias); exponential_function = bz_search_bias_get_exponential_boost (bias); #define SKIP() \ G_STMT_START \ { \ g_autoptr (BiasData) _data = NULL; \ \ _data = bias_data_new (); \ _data->invalid = TRUE; \ *loc = bias_data_ref (_data); \ } \ G_STMT_END if (regex_string == NULL || (convert_to == NULL && (boost_appids == NULL || (linear_function == NULL && exponential_function == NULL)))) { g_critical ("Bias is incomplete! Skipping..."); SKIP (); continue; } if (linear_function != NULL && exponential_function != NULL) { g_critical ("Search bias can only have one boost function! Skipping..."); SKIP (); continue; } regex = g_regex_new ( regex_string, G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &local_error); if (regex == NULL) { g_critical ("Bias regex \"%s\" is invalid: %s", regex_string, local_error->message); SKIP (); continue; } #undef SKIP if (boost_appids != NULL) { guint n_appids = 0; n_appids = g_list_model_get_n_items (boost_appids); if (n_appids > 0) { boost = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); for (guint j = 0; j < n_appids; j++) { g_autoptr (GtkStringObject) string = NULL; const char *appid = NULL; string = g_list_model_get_item (boost_appids, j); appid = gtk_string_object_get_string (string); g_hash_table_replace (boost, g_strdup (appid), NULL); } } } data = bias_data_new (); data->regex = g_regex_ref (regex); data->convert_to = bz_maybe_strdup (convert_to); data->boost = bz_maybe_ref (boost, g_hash_table_ref); if (linear_function != NULL) { data->boost_kind = LINEAR; data->linear_boost.slope = bz_linear_function_get_slope (linear_function); data->linear_boost.y_intercept = bz_linear_function_get_y_intercept (linear_function); } if (exponential_function != NULL) { data->boost_kind = EXPONENTIAL; data->exponential_boost.factor = bz_exponential_function_get_factor (exponential_function); data->exponential_boost.y_intercept = bz_exponential_function_get_y_intercept (exponential_function); } *loc = bias_data_ref (data); } g_clear_pointer (&self->biases_mirror, g_ptr_array_unref); self->biases_mirror = g_steal_pointer (&new_mirror); } static DexFuture * query_task_fiber (QueryTaskData *data) { char **terms = data->terms; GPtrArray *shallow_mirror = data->snapshot; GPtrArray *biases = data->biases; g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autoptr (GTimer) timer = NULL; g_autofree char *query_utf8 = NULL; guint n_sub_tasks = 0; guint scores_per_task = 0; g_autoptr (GPtrArray) active_biases = NULL; g_autoptr (GPtrArray) sub_futures = NULL; g_autoptr (GArray) scores = NULL; g_autoptr (GPtrArray) results = NULL; g_autoptr (BzFinishedSearchQuery) finished = NULL; timer = g_timer_new (); 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; active_biases = g_ptr_array_new_with_free_func (bias_data_unref); for (guint i = 0; i < biases->len; i++) { BiasData *bias = NULL; bias = g_ptr_array_index (biases, i); if (bias->invalid) continue; if (!g_regex_match (bias->regex, query_utf8, G_REGEX_MATCH_DEFAULT, NULL)) continue; if (bias->convert_to != NULL) { g_autofree char *tmp = NULL; tmp = g_regex_replace ( bias->regex, query_utf8, -1, 0, bias->convert_to, G_REGEX_MATCH_DEFAULT, NULL); if (tmp != NULL) { g_clear_pointer (&query_utf8, g_free); query_utf8 = g_steal_pointer (&tmp); } } g_ptr_array_add (active_biases, bias_data_ref (bias)); } 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; sub_data->active_biases = g_ptr_array_ref (active_biases); 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); } finished = bz_finished_search_query_new (); bz_finished_search_query_set_interpreted_query (finished, query_utf8); bz_finished_search_query_set_results (finished, results); bz_finished_search_query_set_n_results (finished, results->len); bz_finished_search_query_set_elapsed (finished, g_timer_elapsed (timer, NULL)); return dex_future_new_for_object (finished); } 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; GPtrArray *active_biases = data->active_biases; 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 = (double) G_MAXINT; 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 } for (guint j = 0; j < active_biases->len; j++) { BiasData *bias = NULL; bias = g_ptr_array_index (active_biases, j); if (bias->boost == NULL) continue; if (!g_hash_table_contains (bias->boost, id)) continue; switch (bias->boost_kind) { case LINEAR: score = bias->linear_boost.slope * score + bias->linear_boost.y_intercept; break; case EXPONENTIAL: score = pow (bias->exponential_boost.factor, score) * bias->exponential_boost.y_intercept; break; default: break; } } 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 query_tok_utf8_len = 0; gsize against_tok_utf8_len = 0; UTF8_FOREACH_TOKEN_FORWARDS (query_tok_start, query_tok_end, query, &query_tok_utf8_len) { gboolean query_token_has_match = FALSE; 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) { const char *against_check_ptr = NULL; gunichar against_ch = 0; if (query_tok_utf8_len > against_tok_utf8_len - consumed) break; match = TRUE; against_check_ptr = against_ptr; 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; } against_check_ptr = g_utf8_next_char (against_check_ptr); against_ch = g_unichar_tolower (g_utf8_get_char (against_check_ptr)); } if (match) break; else consumed++; } if (match) { score += (double) (query_tok_utf8_len * query_tok_utf8_len) / (double) against_tok_utf8_len; query_token_has_match = TRUE; } } if (!query_token_has_match) { score = 0.0; break; } } 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 */ bazaar-org-bazaar-43ce9f7/src/bz-search-engine.h000066400000000000000000000027741520414637400215240ustar00rootroot00000000000000/* 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); GListModel * bz_search_engine_get_biases (BzSearchEngine *self); void bz_search_engine_set_biases (BzSearchEngine *self, GListModel *biases); DexFuture * bz_search_engine_query (BzSearchEngine *self, const char *const *terms); G_END_DECLS /* End of bz-search-engine.h */ bazaar-org-bazaar-43ce9f7/src/bz-search-filter-popover.blp000066400000000000000000000027571520414637400235630ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzSearchFilterPopover: Gtk.Popover { child: ScrolledWindow { propagate-natural-height: true; propagate-natural-width: true; child: Box { orientation: vertical; spacing: 12; margin-top: 12; margin-bottom: 12; margin-start: 12; margin-end: 12; Label { label: _("Filters"); halign: start; styles [ "heading", ] } Adw.WrapBox { justify: fill; child-spacing: 6; line-spacing: 6; natural-line-length: 320; justify-last-line: true; Button verified_button { name: "verified"; label: _("_Verified"); clicked => $on_filter_button_clicked(); use-underline: true; } Button free_button { name: "free"; label: _("_Free/Open"); clicked => $on_filter_button_clicked(); use-underline: true; } Button non_eol_button { name: "non-eol"; label: _("Non-_EOL"); clicked => $on_filter_button_clicked(); use-underline: true; tooltip-text: _("Filter out End-of-Life apps"); } } Label { label: _("Categories"); halign: start; styles [ "heading", ] } Adw.WrapBox wrap_box { justify: fill; child-spacing: 6; line-spacing: 6; natural-line-length: 320; } }; }; } bazaar-org-bazaar-43ce9f7/src/bz-search-filter-popover.c000066400000000000000000000367151520414637400232310ustar00rootroot00000000000000/* bz-search-filter-popover.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-category-flags.h" #include "bz-flathub-category.h" #include "bz-flathub-state.h" #include "bz-search-filter-popover.h" #include "bz-state-info.h" struct _BzSearchFilterPopover { GtkPopover parent_instance; BzCategoryFlags selected_categories; gboolean only_verified; gboolean only_free; gboolean only_non_eol; gboolean has_active_filters; gboolean state_forced_verified; gboolean state_forced_free; gboolean state_forced_non_eol; AdwWrapBox *wrap_box; GtkWidget *verified_button; GtkWidget *free_button; GtkWidget *non_eol_button; }; G_DEFINE_FINAL_TYPE (BzSearchFilterPopover, bz_search_filter_popover, GTK_TYPE_POPOVER) enum { PROP_0, PROP_SELECTED_CATEGORIES, PROP_ONLY_VERIFIED, PROP_ONLY_FREE, PROP_ONLY_NON_EOL, PROP_HAS_ACTIVE_FILTERS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void update_has_active_filters (BzSearchFilterPopover *self); static void apply_filter_button (BzSearchFilterPopover *self, guint prop, gboolean value); static void sync_from_state (BzSearchFilterPopover *self); static void on_state_setting_changed (BzSearchFilterPopover *self, GParamSpec *pspec, BzStateInfo *state); static void on_category_button_clicked (GtkButton *button, gpointer user_data); static void rebuild_category_buttons (BzSearchFilterPopover *self); static void on_show (GtkPopover *popover, gpointer user_data); static void on_filter_button_clicked (GtkButton *button, gpointer user_data); static void bz_search_filter_popover_dispose (GObject *object) { BzSearchFilterPopover *self = BZ_SEARCH_FILTER_POPOVER (object); BzStateInfo *state = NULL; state = bz_state_info_get_default (); if (state != NULL) g_signal_handlers_disconnect_by_data (state, self); gtk_widget_dispose_template (GTK_WIDGET (object), BZ_TYPE_SEARCH_FILTER_POPOVER); G_OBJECT_CLASS (bz_search_filter_popover_parent_class)->dispose (object); } static void bz_search_filter_popover_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzSearchFilterPopover *self = BZ_SEARCH_FILTER_POPOVER (object); switch (prop_id) { case PROP_SELECTED_CATEGORIES: g_value_set_flags (value, self->selected_categories); break; case PROP_ONLY_VERIFIED: g_value_set_boolean (value, self->only_verified); break; case PROP_ONLY_FREE: g_value_set_boolean (value, self->only_free); break; case PROP_ONLY_NON_EOL: g_value_set_boolean (value, self->only_non_eol); break; case PROP_HAS_ACTIVE_FILTERS: g_value_set_boolean (value, self->has_active_filters); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_search_filter_popover_class_init (BzSearchFilterPopoverClass *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_search_filter_popover_dispose; object_class->get_property = bz_search_filter_popover_get_property; props[PROP_SELECTED_CATEGORIES] = g_param_spec_flags ( "selected-categories", NULL, NULL, BZ_TYPE_CATEGORY_FLAGS, BZ_CATEGORY_FLAGS_NONE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_ONLY_VERIFIED] = g_param_spec_boolean ( "only-verified", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_ONLY_FREE] = g_param_spec_boolean ( "only-free", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_ONLY_NON_EOL] = g_param_spec_boolean ( "only-non-eol", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_HAS_ACTIVE_FILTERS] = g_param_spec_boolean ( "has-active-filters", NULL, NULL, FALSE, G_PARAM_READABLE | 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-search-filter-popover.ui"); gtk_widget_class_bind_template_child (widget_class, BzSearchFilterPopover, wrap_box); gtk_widget_class_bind_template_child (widget_class, BzSearchFilterPopover, verified_button); gtk_widget_class_bind_template_child (widget_class, BzSearchFilterPopover, free_button); gtk_widget_class_bind_template_child (widget_class, BzSearchFilterPopover, non_eol_button); gtk_widget_class_bind_template_callback (widget_class, on_filter_button_clicked); } static void bz_search_filter_popover_init (BzSearchFilterPopover *self) { BzStateInfo *state = NULL; gtk_widget_init_template (GTK_WIDGET (self)); g_signal_connect (self, "show", G_CALLBACK (on_show), NULL); state = bz_state_info_get_default (); if (state != NULL) { g_signal_connect_swapped (state, "notify::show-only-verified", G_CALLBACK (on_state_setting_changed), self); g_signal_connect_swapped (state, "notify::show-only-foss", G_CALLBACK (on_state_setting_changed), self); g_signal_connect_swapped (state, "notify::hide-eol", G_CALLBACK (on_state_setting_changed), self); } } GtkWidget * bz_search_filter_popover_new (void) { return g_object_new (BZ_TYPE_SEARCH_FILTER_POPOVER, NULL); } BzCategoryFlags bz_search_filter_popover_get_selected_categories (BzSearchFilterPopover *self) { g_return_val_if_fail (BZ_IS_SEARCH_FILTER_POPOVER (self), BZ_CATEGORY_FLAGS_NONE); return self->selected_categories; } gboolean bz_search_filter_popover_get_only_verified (BzSearchFilterPopover *self) { g_return_val_if_fail (BZ_IS_SEARCH_FILTER_POPOVER (self), FALSE); return self->only_verified; } gboolean bz_search_filter_popover_get_only_free (BzSearchFilterPopover *self) { g_return_val_if_fail (BZ_IS_SEARCH_FILTER_POPOVER (self), FALSE); return self->only_free; } gboolean bz_search_filter_popover_get_only_non_eol (BzSearchFilterPopover *self) { g_return_val_if_fail (BZ_IS_SEARCH_FILTER_POPOVER (self), FALSE); return self->only_non_eol; } void bz_search_filter_popover_clear (BzSearchFilterPopover *self) { GtkWidget *child = NULL; g_return_if_fail (BZ_IS_SEARCH_FILTER_POPOVER (self)); if (!self->state_forced_verified) apply_filter_button (self, PROP_ONLY_VERIFIED, FALSE); if (!self->state_forced_free) apply_filter_button (self, PROP_ONLY_FREE, FALSE); if (!self->state_forced_non_eol) apply_filter_button (self, PROP_ONLY_NON_EOL, FALSE); for (child = gtk_widget_get_first_child (GTK_WIDGET (self->wrap_box)); child != NULL; child = gtk_widget_get_next_sibling (child)) gtk_widget_remove_css_class (child, "accent"); if (self->selected_categories != BZ_CATEGORY_FLAGS_NONE) { self->selected_categories = BZ_CATEGORY_FLAGS_NONE; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SELECTED_CATEGORIES]); update_has_active_filters (self); } } static void update_has_active_filters (BzSearchFilterPopover *self) { gboolean active = FALSE; active = (self->only_verified && !self->state_forced_verified) || (self->only_free && !self->state_forced_free) || (self->only_non_eol && !self->state_forced_non_eol) || self->selected_categories != BZ_CATEGORY_FLAGS_NONE; if (self->has_active_filters == active) return; self->has_active_filters = active; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HAS_ACTIVE_FILTERS]); } static void apply_filter_button (BzSearchFilterPopover *self, guint prop, gboolean value) { struct { guint prop; gboolean *field; GtkWidget **button; } map[] = { { PROP_ONLY_VERIFIED, &self->only_verified, &self->verified_button }, { PROP_ONLY_FREE, &self->only_free, &self->free_button }, { PROP_ONLY_NON_EOL, &self->only_non_eol, &self->non_eol_button }, }; for (guint i = 0; i < G_N_ELEMENTS (map); i++) { if (map[i].prop != prop) continue; *map[i].field = value; if (value) gtk_widget_add_css_class (*map[i].button, "accent"); else gtk_widget_remove_css_class (*map[i].button, "accent"); g_object_notify_by_pspec (G_OBJECT (self), props[prop]); update_has_active_filters (self); return; } } static void sync_from_state (BzSearchFilterPopover *self) { BzStateInfo *state = NULL; gboolean state_verified = FALSE; gboolean state_free = FALSE; gboolean state_hide_eol = FALSE; state = bz_state_info_get_default (); if (state == NULL) return; g_object_get (state, "show-only-verified", &state_verified, "show-only-foss", &state_free, "hide-eol", &state_hide_eol, NULL); self->state_forced_verified = state_verified; self->state_forced_free = state_free; self->state_forced_non_eol = state_hide_eol; if (state_verified) apply_filter_button (self, PROP_ONLY_VERIFIED, TRUE); if (self->verified_button != NULL) gtk_widget_set_sensitive (self->verified_button, !state_verified); if (state_free) apply_filter_button (self, PROP_ONLY_FREE, TRUE); if (self->free_button != NULL) gtk_widget_set_sensitive (self->free_button, !state_free); if (state_hide_eol) apply_filter_button (self, PROP_ONLY_NON_EOL, TRUE); if (self->non_eol_button != NULL) gtk_widget_set_sensitive (self->non_eol_button, !state_hide_eol); } static void on_state_setting_changed (BzSearchFilterPopover *self, GParamSpec *pspec, BzStateInfo *state) { gboolean state_verified = FALSE; gboolean state_free = FALSE; gboolean state_hide_eol = FALSE; g_object_get (state, "show-only-verified", &state_verified, "show-only-foss", &state_free, "hide-eol", &state_hide_eol, NULL); if (!state_verified) apply_filter_button (self, PROP_ONLY_VERIFIED, FALSE); if (!state_free) apply_filter_button (self, PROP_ONLY_FREE, FALSE); if (!state_hide_eol) apply_filter_button (self, PROP_ONLY_NON_EOL, FALSE); sync_from_state (self); } static void on_filter_button_clicked (GtkButton *button, gpointer user_data) { BzSearchFilterPopover *self = BZ_SEARCH_FILTER_POPOVER (user_data); const char *name = NULL; name = gtk_widget_get_name (GTK_WIDGET (button)); if (g_str_equal (name, "verified")) apply_filter_button (self, PROP_ONLY_VERIFIED, !self->only_verified); else if (g_str_equal (name, "free")) apply_filter_button (self, PROP_ONLY_FREE, !self->only_free); else if (g_str_equal (name, "non-eol")) apply_filter_button (self, PROP_ONLY_NON_EOL, !self->only_non_eol); } static void on_category_button_clicked (GtkButton *button, gpointer user_data) { BzSearchFilterPopover *self = BZ_SEARCH_FILTER_POPOVER (user_data); BzCategoryFlags flag = BZ_CATEGORY_FLAGS_NONE; flag = (BzCategoryFlags) GPOINTER_TO_SIZE ( g_object_get_data (G_OBJECT (button), "category-flag")); self->selected_categories ^= flag; if (self->selected_categories & flag) gtk_widget_add_css_class (GTK_WIDGET (button), "accent"); else gtk_widget_remove_css_class (GTK_WIDGET (button), "accent"); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SELECTED_CATEGORIES]); update_has_active_filters (self); } static void rebuild_category_buttons (BzSearchFilterPopover *self) { g_autoptr (BzFlathubState) flathub = NULL; g_autoptr (GListModel) categories = NULL; BzStateInfo *state = NULL; GtkWidget *child = NULL; while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->wrap_box))) != NULL) adw_wrap_box_remove (self->wrap_box, child); sync_from_state (self); state = bz_state_info_get_default (); if (state == NULL) return; g_object_get (state, "flathub", &flathub, NULL); if (flathub == NULL) return; g_object_get (flathub, "categories", &categories, NULL); if (categories == NULL) return; for (guint i = 0; i < g_list_model_get_n_items (categories); i++) { g_autoptr (BzFlathubCategory) category = NULL; const char *name = NULL; const char *label = NULL; const char *icon = NULL; GtkWidget *button = NULL; GtkWidget *content = NULL; BzCategoryFlags flag = BZ_CATEGORY_FLAGS_NONE; category = g_list_model_get_item (categories, i); if (!bz_flathub_category_get_is_xdg (category)) continue; name = bz_flathub_category_get_name (category); label = bz_flathub_category_get_short_name (category); icon = bz_flathub_category_get_symbolic_icon_name (category); flag = bz_category_flags_from_name (name); content = g_object_new (ADW_TYPE_BUTTON_CONTENT, "label", label, "icon-name", icon ? icon : "", NULL); button = gtk_button_new (); gtk_button_set_child (GTK_BUTTON (button), content); gtk_accessible_update_property (GTK_ACCESSIBLE (button), GTK_ACCESSIBLE_PROPERTY_LABEL, label, -1); g_object_set_data (G_OBJECT (button), "category-flag", GSIZE_TO_POINTER ((gsize) flag)); if (self->selected_categories & flag) gtk_widget_add_css_class (button, "accent"); g_signal_connect (button, "clicked", G_CALLBACK (on_category_button_clicked), self); adw_wrap_box_append (self->wrap_box, button); } } static void on_show (GtkPopover *popover, gpointer user_data) { rebuild_category_buttons (BZ_SEARCH_FILTER_POPOVER (popover)); } bazaar-org-bazaar-43ce9f7/src/bz-search-filter-popover.h000066400000000000000000000027521520414637400232300ustar00rootroot00000000000000/* bz-search-filter-popover.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-category-flags.h" #include G_BEGIN_DECLS #define BZ_TYPE_SEARCH_FILTER_POPOVER (bz_search_filter_popover_get_type ()) G_DECLARE_FINAL_TYPE (BzSearchFilterPopover, bz_search_filter_popover, BZ, SEARCH_FILTER_POPOVER, GtkPopover) GtkWidget * bz_search_filter_popover_new (void); BzCategoryFlags bz_search_filter_popover_get_selected_categories (BzSearchFilterPopover *self); gboolean bz_search_filter_popover_get_only_verified (BzSearchFilterPopover *self); gboolean bz_search_filter_popover_get_only_free (BzSearchFilterPopover *self); gboolean bz_search_filter_popover_get_only_non_eol (BzSearchFilterPopover *self); void bz_search_filter_popover_clear (BzSearchFilterPopover *self); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-search-page.blp000066400000000000000000000247201520414637400215140ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzSearchPage: Adw.Bin { child: Adw.BreakpointBin { width-request: 360; height-request: 100; 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; max-length: 50; placeholder-text: _("Search Apps, Games, Software"); } Adw.Spinner search_busy { visible: false; width-request: 16; height-request: 16; } MenuButton filter_button { visible: bind $is_valid_string(search_bar.text) as ; icon-name: "sliders-horizontal-symbolic"; tooltip-text: _("Search Filters"); popover: $BzSearchFilterPopover filter_popover { notify::has-active-filters => $has_active_filters_cb(); }; styles [ "flat", "circular", "searchbar-button", ] accessibility { label: _("Filters"); } } Button clear_button { visible: bind $is_valid_string(search_bar.text) as ; icon-name: "edit-clear-symbolic"; styles [ "flat", "circular", "searchbar-button", ] clicked => $reset_search_cb(template); accessibility { label: _("Clear Search"); } } styles [ "search-box", ] }; }; } Adw.Clamp { margin-start: 12; margin-end: 12; maximum-size: 375; child: Box { margin-start: 12; margin-end: 12; margin-top: 6; margin-bottom: 6; styles [ "bz-debug", ] orientation: vertical; spacing: 5; visible: bind template.state as <$BzStateInfo>.debug_mode; Box { orientation: horizontal; spacing: 10; Label { label: "Interpreted Query:"; } Label { styles [ "caption-heading", ] label: bind template.current-query as <$BzFinishedSearchQuery>.interpreted-query; } } Box { orientation: horizontal; spacing: 10; Label { label: "# of Results:"; } Label { styles [ "caption-heading", ] label: bind $format_uint(template.current-query as <$BzFinishedSearchQuery>.n-results as ) as ; } } Box { orientation: horizontal; spacing: 10; Label { label: "Seconds Elapsed:"; } Label { styles [ "caption-heading", ] label: bind $format_double(template.current-query as <$BzFinishedSearchQuery>.elapsed as ) as ; } } }; } Stack search_stack { transition-type: crossfade; StackPage { name: "empty"; child: Box { orientation: vertical; vexpand: true; Adw.StatusPage { visible: bind $is_empty(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories) as ; hexpand: true; vexpand: true; icon-name: "system-search-symbolic"; title: _("Categories Unavailable"); description: _("Search for apps using the search bar above."); } ScrolledWindow { hscrollbar-policy: never; vexpand: true; 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: 16; margin-bottom: 50; orientation: vertical; $BzSearchPillList { margin-bottom: 25; activated => $pill_list_cb(template); } Label { label: _("Browse Categories"); halign: start; margin-bottom: 12; margin-start: 4; wrap: true; wrap-mode: word_char; styles [ "heading", ] } $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: Box { orientation: vertical; spacing: 5; $BzRichAppTile { group: bind template.item as <$BzSearchResult>.group as <$BzEntryGroup>; activated => $tile_activated_cb(template); } Box { styles [ "bz-debug", ] visible: bind template.item as <$BzSearchResult>.state as <$BzStateInfo>.debug_mode; orientation: vertical; spacing: 2; Box { orientation: horizontal; spacing: 10; Label { label: "Result Score:"; } Label { styles [ "caption-heading", ] label: bind $format_double(template.item as <$BzSearchResult>.score as ) as ; } } Separator { margin-bottom: 5; } Box { orientation: horizontal; spacing: 10; Label { styles [ "bz-monospace", ] hexpand: true; xalign: 0.0; label: bind template.item as <$BzSearchResult>.group as <$BzEntryGroup>.id; selectable: true; wrap: true; wrap-mode: char; } Button { icon-name: "edit-copy-symbolic"; clicked => $copy_id_cb(template); } } Box { orientation: horizontal; spacing: 10; Button { hexpand: true; halign: end; label: "Inspect UI Entry"; clicked => $debug_id_inspect_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 ; }; } } }; }; } bazaar-org-bazaar-43ce9f7/src/bz-search-page.c000066400000000000000000000652321520414637400211640ustar00rootroot00000000000000/* bz-search-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-apps-page.h" #include "bz-async-texture.h" #include "bz-category-tile.h" #include "bz-dynamic-list-view.h" #include "bz-entry-inspector.h" #include "bz-finished-search-query.h" #include "bz-group-tile-css-watcher.h" #include "bz-rich-app-tile.h" #include "bz-screenshot.h" #include "bz-search-filter-popover.h" #include "bz-search-page.h" #include "bz-search-pill-list.h" #include "bz-search-result.h" #include "bz-template-callbacks.h" #include "bz-util.h" struct _BzSearchPage { AdwBin parent_instance; BzStateInfo *state; BzEntryGroup *selected; gboolean remove; gboolean search_in_progress; BzFinishedSearchQuery *current_query; 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; GtkWidget *filter_button; BzSearchFilterPopover *filter_popover; }; G_DEFINE_FINAL_TYPE (BzSearchPage, bz_search_page, ADW_TYPE_BIN) enum { PROP_0, PROP_STATE, PROP_TEXT, PROP_CURRENT_QUERY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void search_changed (GtkEditable *editable, BzSearchPage *self); static void search_activate (GtkText *text, BzSearchPage *self); static void grid_activate (GtkGridView *grid_view, guint position, BzSearchPage *self); static void invalidating_state_prop_changed (BzSearchPage *self, GParamSpec *pspec, BzStateInfo *info); static void blocklists_items_changed (BzSearchPage *self, guint position, guint removed, guint added, GListModel *model); static DexFuture * search_query_then (DexFuture *future, GWeakRef *wr); static void update_filter (BzSearchPage *self); static void emit_idx (BzSearchPage *self, GListModel *model, guint selected_idx); static void bz_search_page_dispose (GObject *object) { BzSearchPage *self = BZ_SEARCH_PAGE (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->current_query); 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_page_parent_class)->dispose (object); } static void bz_search_page_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzSearchPage *self = BZ_SEARCH_PAGE (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, bz_search_page_get_state (self)); break; case PROP_TEXT: g_value_set_string (value, bz_search_page_get_text (self)); break; case PROP_CURRENT_QUERY: g_value_set_object (value, self->current_query); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_search_page_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzSearchPage *self = BZ_SEARCH_PAGE (object); switch (prop_id) { case PROP_STATE: bz_search_page_set_state (self, g_value_get_object (value)); break; case PROP_TEXT: bz_search_page_set_text (self, g_value_get_string (value)); break; case PROP_CURRENT_QUERY: 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 has_active_filters_cb (BzSearchFilterPopover *filter_popover, GParamSpec *pspec, BzSearchPage *self) { gboolean active = FALSE; g_object_get (filter_popover, "has-active-filters", &active, NULL); if (active) gtk_widget_add_css_class (self->filter_button, "accent"); else gtk_widget_remove_css_class (self->filter_button, "accent"); } static void pill_list_cb (BzSearchPage *self, const char *label, GtkWidget *pill_list) { bz_search_page_set_text (self, label); update_filter (self); } 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_PAGE); 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); adw_navigation_view_push (ADW_NAVIGATION_VIEW (nav_view), apps_page); } static void bind_category_tile_cb (BzSearchPage *self, BzCategoryTile *tile, BzFlathubCategory *category, BzDynamicListView *view) { g_signal_connect_swapped (tile, "clicked", G_CALLBACK (category_clicked), category); } static void unbind_category_tile_cb (BzSearchPage *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) { BzSearchResult *result = gtk_list_item_get_item (list_item); BzEntryGroup *group = bz_search_result_get_group (result); gtk_widget_activate_action (GTK_WIDGET (tile), "window.show-group", "s", bz_entry_group_get_id (group)); } static void reset_search_cb (BzSearchPage *self, GtkButton *button) { bz_search_page_set_text (self, ""); bz_search_filter_popover_clear (self->filter_popover); bz_search_page_refresh (self); } static void copy_id_cb (GtkListItem *list_item, GtkButton *button) { BzSearchResult *result = NULL; BzEntryGroup *group = NULL; const char *id = NULL; GdkClipboard *clipboard = NULL; result = gtk_list_item_get_item (list_item); group = bz_search_result_get_group (result); id = bz_entry_group_get_id (group); clipboard = gdk_display_get_clipboard (gdk_display_get_default ()); gdk_clipboard_set_text (clipboard, id); } static void debug_id_inspect_cb (GtkListItem *list_item, GtkButton *button) { BzSearchResult *search_result = NULL; BzStateInfo *state = NULL; BzEntryGroup *group = NULL; g_autofree char *unique_id = NULL; g_autoptr (BzResult) result = NULL; search_result = gtk_list_item_get_item (list_item); state = bz_search_result_get_state (search_result); if (state == NULL) return; group = bz_search_result_get_group (search_result); unique_id = bz_entry_group_dup_ui_entry_id (group); result = bz_application_map_factory_convert_one ( bz_state_info_get_entry_factory (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_search_page_class_init (BzSearchPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_search_page_dispose; object_class->get_property = bz_search_page_get_property; object_class->set_property = bz_search_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); props[PROP_TEXT] = g_param_spec_string ( "text", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_CURRENT_QUERY] = g_param_spec_object ( "current-query", NULL, NULL, BZ_TYPE_FINISHED_SEARCH_QUERY, 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_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); g_type_ensure (BZ_TYPE_SEARCH_PILL_LIST); g_type_ensure (BZ_TYPE_SEARCH_FILTER_POPOVER); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-search-page.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzSearchPage, search_bar); gtk_widget_class_bind_template_child (widget_class, BzSearchPage, search_busy); gtk_widget_class_bind_template_child (widget_class, BzSearchPage, content_box); gtk_widget_class_bind_template_child (widget_class, BzSearchPage, search_stack); gtk_widget_class_bind_template_child (widget_class, BzSearchPage, grid_view); gtk_widget_class_bind_template_child (widget_class, BzSearchPage, filter_button); gtk_widget_class_bind_template_child (widget_class, BzSearchPage, filter_popover); 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, 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, has_active_filters_cb); 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, pill_list_cb); gtk_widget_class_bind_template_callback (widget_class, no_results_found_subtitle); gtk_widget_class_bind_template_callback (widget_class, tile_activated_cb); gtk_widget_class_bind_template_callback (widget_class, copy_id_cb); gtk_widget_class_bind_template_callback (widget_class, debug_id_inspect_cb); } static void bz_search_page_init (BzSearchPage *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); g_signal_connect_swapped (self->filter_popover, "notify::selected-categories", G_CALLBACK (update_filter), self); g_signal_connect_swapped (self->filter_popover, "notify::only-verified", G_CALLBACK (update_filter), self); g_signal_connect_swapped (self->filter_popover, "notify::only-free", G_CALLBACK (update_filter), self); g_signal_connect_swapped (self->filter_popover, "notify::only-non-eol", G_CALLBACK (update_filter), self); } GtkWidget * bz_search_page_new (GListModel *model, const char *initial) { BzSearchPage *self = NULL; self = g_object_new ( BZ_TYPE_SEARCH_PAGE, "model", model, NULL); if (initial != NULL) gtk_editable_set_text (GTK_EDITABLE (self->search_bar), initial); return GTK_WIDGET (self); } BzEntryGroup * bz_search_page_get_selected (BzSearchPage *self, gboolean *remove) { g_return_val_if_fail (BZ_IS_SEARCH_PAGE (self), NULL); if (remove != NULL) *remove = self->remove; return self->selected; } void bz_search_page_set_state (BzSearchPage *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_SEARCH_PAGE (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_signal_connect_swapped ( state, "notify::parental-age-rating", 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_page_get_state (BzSearchPage *self) { g_return_val_if_fail (BZ_IS_SEARCH_PAGE (self), NULL); return self->state; } void bz_search_page_set_text (BzSearchPage *self, const char *text) { g_return_if_fail (BZ_IS_SEARCH_PAGE (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_page_get_text (BzSearchPage *self) { g_return_val_if_fail (BZ_IS_SEARCH_PAGE (self), NULL); return gtk_editable_get_text (GTK_EDITABLE (self->search_bar)); } void bz_search_page_refresh (BzSearchPage *self) { g_return_if_fail (BZ_IS_SEARCH_PAGE (self)); update_filter (self); } gboolean bz_search_page_ensure_active (BzSearchPage *self, const char *initial) { const char *text = NULL; g_return_val_if_fail (BZ_IS_SEARCH_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)); bz_search_page_set_text (self, initial); return TRUE; } static void search_changed (GtkEditable *editable, BzSearchPage *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, BzSearchPage *self) { GtkSelectionModel *model = NULL; guint n_items = 0; g_autoptr (BzSearchResult) result = NULL; BzEntryGroup *group = NULL; model = gtk_grid_view_get_model (self->grid_view); n_items = g_list_model_get_n_items (G_LIST_MODEL (model)); if (gtk_widget_get_visible (GTK_WIDGET (self->search_busy))) return; 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_removable_and_available (group) > 0) { gtk_widget_activate_action (GTK_WIDGET (self), "window.remove-group", "(sb)", bz_entry_group_get_id (group), FALSE); } else if (bz_entry_group_get_installable_and_available (group) > 0) { gtk_widget_activate_action (GTK_WIDGET (self), "window.install-group", "(sb)", bz_entry_group_get_id (group), FALSE); } } } static void grid_activate (GtkGridView *grid_view, guint position, BzSearchPage *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 (BzSearchPage *self, GParamSpec *pspec, BzStateInfo *info) { update_filter (self); } static void blocklists_items_changed (BzSearchPage *self, guint position, guint removed, guint added, GListModel *model) { update_filter (self); } static DexFuture * search_query_then (DexFuture *future, GWeakRef *wr) { g_autoptr (BzSearchPage) self = NULL; g_autoptr (GPtrArray) filtered = NULL; BzFinishedSearchQuery *finished = NULL; GPtrArray *results = NULL; guint old_length = 0; const char *page_name = NULL; BzCategoryFlags categories = BZ_CATEGORY_FLAGS_NONE; gboolean only_verified = FALSE; gboolean only_free = FALSE; gboolean only_non_eol = FALSE; bz_weak_get_or_return_reject (self, wr); finished = g_value_get_object (dex_future_get_value (future, NULL)); results = bz_finished_search_query_get_results (finished); categories = bz_search_filter_popover_get_selected_categories (self->filter_popover); only_verified = bz_search_filter_popover_get_only_verified (self->filter_popover); only_free = bz_search_filter_popover_get_only_free (self->filter_popover); only_non_eol = bz_search_filter_popover_get_only_non_eol (self->filter_popover); filtered = g_ptr_array_new_with_free_func (g_object_unref); for (guint i = 0; i < results->len; i++) { BzSearchResult *result = g_ptr_array_index (results, i); BzEntryGroup *group = bz_search_result_get_group (result); if (self->state != NULL) /* This is for debug mode */ bz_search_result_set_state (result, self->state); if (categories != BZ_CATEGORY_FLAGS_NONE && !(bz_entry_group_get_categories (group) & categories)) continue; if (only_verified && !bz_entry_group_get_is_verified (group)) continue; if (only_free && !bz_entry_group_get_is_floss (group)) continue; if (only_non_eol && bz_entry_group_get_eol (group)) continue; g_ptr_array_add (filtered, g_object_ref (result)); } 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 *) filtered->pdata, filtered->len); gtk_widget_set_visible (GTK_WIDGET (self->search_busy), FALSE); if (filtered->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 = NULL; search_text = gtk_editable_get_text (GTK_EDITABLE (self->search_bar)); page_name = (search_text && *search_text) ? "no-results" : "empty"; } self->current_query = g_object_ref (finished); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CURRENT_QUERY]); gtk_stack_set_visible_child_name (self->search_stack, page_name); dex_clear (&self->search_query); return NULL; } static void update_filter (BzSearchPage *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); g_clear_object (&self->current_query); self->current_query = bz_finished_search_query_new (); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CURRENT_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 (BzSearchPage *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); gtk_widget_activate_action (GTK_WIDGET (self), "window.show-group", "s", bz_entry_group_get_id (group)); } bazaar-org-bazaar-43ce9f7/src/bz-search-page.h000066400000000000000000000033231520414637400211620ustar00rootroot00000000000000/* bz-search-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_SEARCH_PAGE (bz_search_page_get_type ()) G_DECLARE_FINAL_TYPE (BzSearchPage, bz_search_page, BZ, SEARCH_PAGE, AdwBin) GtkWidget * bz_search_page_new (GListModel *model, const char *initial); void bz_search_page_set_state (BzSearchPage *self, BzStateInfo *state); BzStateInfo * bz_search_page_get_state (BzSearchPage *self); void bz_search_page_set_text (BzSearchPage *self, const char *text); const char * bz_search_page_get_text (BzSearchPage *self); BzEntryGroup * bz_search_page_get_selected (BzSearchPage *self, gboolean *remove); BzEntryGroup * bz_search_page_get_previewing (BzSearchPage *self); void bz_search_page_refresh (BzSearchPage *self); gboolean bz_search_page_ensure_active (BzSearchPage *self, const char *initial); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-search-pill-list.c000066400000000000000000000136011520414637400221520ustar00rootroot00000000000000/* bz-search-pill-list.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-search-pill-list.h" struct _BzSearchPillList { GtkBox parent_instance; }; G_DEFINE_FINAL_TYPE (BzSearchPillList, bz_search_pill_list, GTK_TYPE_BOX) enum { SIGNAL_ACTIVATED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL]; static void pill_button_clicked_cb (BzSearchPillList *self, GtkButton *button); static void bz_search_pill_list_class_init (BzSearchPillListClass *klass) { signals[SIGNAL_ACTIVATED] = g_signal_new ("activated", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); } static void bz_search_pill_list_init (BzSearchPillList *self) { GtkLayoutManager *layout = NULL; static const char *pills[] = { /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("Browser"), /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("Video"), /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("Music"), /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("Office"), /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("PDF"), /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("Calendar"), /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("Messaging"), /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("Paint"), /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("VPN"), /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("Torrent"), /* Translators: Search suggestion: the english text will be used for the search regardless of what you put here, so don't worry about the string yielding poor search results. Focus on correctness and friendliness, etc */ N_ ("Emulator"), /* This array MUST be NULL terminated */ NULL }; gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_HORIZONTAL); layout = GTK_LAYOUT_MANAGER (adw_wrap_layout_new ()); adw_wrap_layout_set_child_spacing (ADW_WRAP_LAYOUT (layout), 10); adw_wrap_layout_set_line_spacing (ADW_WRAP_LAYOUT (layout), 8); adw_wrap_layout_set_justify (ADW_WRAP_LAYOUT (layout), ADW_JUSTIFY_FILL); gtk_widget_set_layout_manager (GTK_WIDGET (self), layout); for (guint i = 0; pills[i] != NULL; i++) { GtkWidget *button = NULL; button = gtk_button_new_with_label (Q_ (pills[i])); gtk_widget_add_css_class (button, "small-pill"); gtk_widget_add_css_class (button, "search-pill"); g_signal_connect_swapped (button, "clicked", G_CALLBACK (pill_button_clicked_cb), self); g_object_set_data_full (G_OBJECT (button), "search-token", g_strdup (pills[i]), g_free); gtk_box_append (GTK_BOX (self), button); } } GtkWidget * bz_search_pill_list_new (void) { return g_object_new (BZ_TYPE_SEARCH_PILL_LIST, NULL); } static void pill_button_clicked_cb (BzSearchPillList *self, GtkButton *button) { const char *search_token = NULL; search_token = g_object_get_data (G_OBJECT (button), "search-token"); g_signal_emit (self, signals[SIGNAL_ACTIVATED], 0, search_token); } bazaar-org-bazaar-43ce9f7/src/bz-search-pill-list.h000066400000000000000000000020111520414637400221500ustar00rootroot00000000000000/* bz-search-pill-list.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 #define BZ_TYPE_SEARCH_PILL_LIST (bz_search_pill_list_get_type ()) G_DECLARE_FINAL_TYPE (BzSearchPillList, bz_search_pill_list, BZ, SEARCH_PILL_LIST, GtkBox) GtkWidget *bz_search_pill_list_new (void); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-search-result.txt000066400000000000000000000005411520414637400221530ustar00rootroot00000000000000prefix=bz name=search_result parent-prefix=g parent-name=object author=AUTOGEN include="bz-state-info.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 property=state BzStateInfo BZ_TYPE_STATE_INFO object bazaar-org-bazaar-43ce9f7/src/bz-section-view.blp000066400000000000000000000141161520414637400217470ustar00rootroot00000000000000using 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: fill; valign: fill; 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 { hexpand: true; vexpand: true; visible: bind $invert_boolean($is_null(template.section as <$BzCuratedSection>.markdown) as ) as ; $BgeMarkdownRender markdown { hexpand: true; vexpand: true; markdown: bind template.section as <$BzCuratedSection>.markdown as <$BzCuratedMarkdownInfo>.string as ; bind-inline-uri => $markdown_bind_inline_uri(template); } } 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; } } }; } bazaar-org-bazaar-43ce9f7/src/bz-section-view.c000066400000000000000000000403511520414637400214140ustar00rootroot00000000000000/* 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 #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-rich-app-tile.h" #include "bz-section-view.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; BgeMarkdownRender *markdown; }; 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 GtkWidget * markdown_bind_inline_uri (BzSectionView *self, const char *title, const char *src, BgeMarkdownRender *markdown) { if (src == NULL) return NULL; if (g_str_has_prefix (src, "appstream://")) { BzStateInfo *info = NULL; BzApplicationMapFactory *factory = NULL; g_autoptr (BzEntryGroup) group = NULL; info = bz_state_info_get_default (); factory = bz_state_info_get_application_factory (info); group = bz_application_map_factory_convert_one ( factory, gtk_string_object_new (src + strlen ("appstream://"))); if (group != NULL) { GtkWidget *tile = NULL; tile = bz_rich_app_tile_new (); bz_rich_app_tile_set_group (BZ_RICH_APP_TILE (tile), group); return tile; } } else { g_autoptr (GFile) file = NULL; file = g_file_new_for_uri (src); if (file != NULL) { g_autoptr (BzAsyncTexture) texture = NULL; GtkWidget *picture = NULL; texture = bz_async_texture_new_lazy (file, NULL); picture = gtk_picture_new (); gtk_picture_set_paintable (GTK_PICTURE (picture), GDK_PAINTABLE (texture)); gtk_widget_set_hexpand (picture, TRUE); gtk_widget_set_size_request (picture, -1, 100); return picture; } } return NULL; } 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_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_child (widget_class, BzSectionView, markdown); 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); gtk_widget_class_bind_template_callback (widget_class, markdown_bind_inline_uri); } 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); g_object_bind_property ( self->style_manager, "dark", self->markdown, "dark", G_BINDING_SYNC_CREATE); } 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); } bazaar-org-bazaar-43ce9f7/src/bz-section-view.h000066400000000000000000000023341520414637400214200ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-serializable.c000066400000000000000000000037761520414637400214600ustar00rootroot00000000000000/* 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); } bazaar-org-bazaar-43ce9f7/src/bz-serializable.h000066400000000000000000000030261520414637400214510ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-share-list.c000066400000000000000000000214301520414637400210500ustar00rootroot00000000000000/* 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 }; typedef struct { const char *id; const char *display_name; const char *icon_name; } UrlInfo; static const UrlInfo url_info[] = { { "flathub", NC_ ("Project URL Type", "Flathub Page"), "flathub-symbolic" }, { "homepage", NC_ ("Project URL Type", "Project Website"), "globe-symbolic" }, { "bugtracker", NC_ ("Project URL Type", "Issue Tracker"), "computer-fail-symbolic" }, { "faq", NC_ ("Project URL Type", "FAQ"), "help-faq-symbolic" }, { "help", NC_ ("Project URL Type", "Help"), "help-browser-symbolic" }, { "donation", NC_ ("Project URL Type", "Donate"), "heart-filled-symbolic" }, { "translate", NC_ ("Project URL Type", "Translate"), "translations-symbolic" }, { "contact", NC_ ("Project URL Type", "Contact"), "mail-send-symbolic" }, { "vcs-browser", NC_ ("Project URL Type", "Source Code"), "code-symbolic" }, { "contribute", NC_ ("Project URL Type", "Contribute"), "system-users-symbolic" }, { NULL, NULL, NULL } }; static const UrlInfo * get_url_info (const char *id) { for (int i = 0; url_info[i].id != NULL; i++) { if (g_strcmp0 (url_info[i].id, id) == 0) return &url_info[i]; } return NULL; } static void copy_cb (BzShareList *self, GtkButton *button) { const char *link = NULL; GdkClipboard *clipboard = NULL; AdwToast *toast = NULL; GtkWidget *ancestor = 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); toast = adw_toast_new (_ ("Copied!")); adw_toast_set_timeout (toast, 1); ancestor = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_TOAST_OVERLAY); if (ancestor != NULL) { adw_toast_overlay_add_toast (ADW_TOAST_OVERLAY (ancestor), toast); return; } root = gtk_widget_get_root (GTK_WIDGET (self)); if (root != NULL && BZ_IS_WINDOW (root)) 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) { const char *url_string = NULL; const char *id = NULL; const UrlInfo *info = NULL; AdwActionRow *action_row; GtkBox *suffix_box; GtkButton *copy_button; GtkButton *open_button; GtkSeparator *separator; url_string = bz_url_get_url (url_item); id = bz_url_get_id (url_item); info = get_url_info (id); 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), info ? g_dpgettext2 (NULL, "Project URL Type", info->display_name) : url_string); adw_action_row_set_subtitle (action_row, url_string); if (info != NULL && info->icon_name != NULL && info->icon_name[0] != '\0') { GtkImage *prefix_icon = GTK_IMAGE (gtk_image_new_from_icon_name (info->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); } bazaar-org-bazaar-43ce9f7/src/bz-share-list.h000066400000000000000000000017361520414637400210640ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-size-result.txt000066400000000000000000000002641520414637400216620ustar00rootroot00000000000000prefix=bz name=size_result parent-prefix=g parent-name=object author=AUTOGEN property=user_data_size guint64 G_TYPE_UINT64 uint64 property=cache_size guint64 G_TYPE_UINT64 uint64 bazaar-org-bazaar-43ce9f7/src/bz-spdx.c000066400000000000000000000031761520414637400177620ustar00rootroot00000000000000/* 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"); } bazaar-org-bazaar-43ce9f7/src/bz-spdx.h000066400000000000000000000020031520414637400177530ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-state-info.txt000066400000000000000000000063561520414637400214550ustar00rootroot00000000000000prefix=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-internal-config.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=filtered_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=has_flathub gboolean G_TYPE_BOOLEAN boolean property=have_connection gboolean G_TYPE_BOOLEAN boolean property=hide_eol gboolean G_TYPE_BOOLEAN boolean property=internal_config BzInternalConfig BZ_TYPE_INTERNAL_CONFIG object 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=system_icon_theme GtkIconTheme GTK_TYPE_ICON_THEME object 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 property=user_icon_theme GtkIconTheme GTK_TYPE_ICON_THEME object property=parental_blocked_ids GListModel G_TYPE_LIST_MODEL object property=parental_age_rating int G_TYPE_INT int bazaar-org-bazaar-43ce9f7/src/bz-stats-dialog.blp000066400000000000000000000043611520414637400217270ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzStatsDialog: Adw.BreakpointBin { width-request: 360; height-request: 450; child: Adw.ToolbarView { bottom-bar-style: raised_border; [top] Adw.HeaderBar { title-widget: Adw.ViewSwitcher switcher_title { visible: bind $logical_and($model_has_enough_points(template.model) as , $invert_boolean($is_null(template.country-model) as ) as ) as ; stack: stack; policy: wide; }; } content: Box { orientation: vertical; Adw.ViewStack stack { vexpand: true; Adw.ViewStackPage { name: "graph"; title: _("Timeline"); icon-name: "graph2-symbolic"; visible: bind $model_has_enough_points(template.model) as ; 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: Box { orientation: vertical; margin-top:10; margin-bottom: 10; $BzWorldMap world_map { model: bind template.country-model; vexpand: true; } Label { label: _("Since 4/15/2024"); halign: center; styles [ "dimmed", "caption" ] } }; } } Adw.ViewSwitcherBar switcher_bar { visible: bind $invert_boolean($is_null(template.country-model) as ) as ; stack: stack; } }; }; Adw.Breakpoint { condition ("max-width: 450sp") setters { switcher_title.stack: null; switcher_bar.reveal: true; } } }bazaar-org-bazaar-43ce9f7/src/bz-stats-dialog.c000066400000000000000000000135631520414637400214000ustar00rootroot00000000000000/* 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-template-callbacks.h" #include "bz-world-map.h" struct _BzStatsDialog { AdwBreakpointBin parent_instance; GListModel *model; GListModel *country_model; int total_downloads; /* Template widgets */ AdwViewStack *stack; BzDataGraph *graph; BzWorldMap *world_map; }; G_DEFINE_FINAL_TYPE (BzStatsDialog, bz_stats_dialog, ADW_TYPE_BREAKPOINT_BIN) 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 gboolean model_has_enough_points (gpointer object, GListModel *model) { if (model == NULL) return FALSE; return g_list_model_get_n_items (model) >= 10; } 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"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_callback (widget_class, format_total_downloads); gtk_widget_class_bind_template_callback (widget_class, model_has_enough_points); gtk_widget_class_bind_template_child (widget_class, BzStatsDialog, stack); 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)); } AdwBreakpointBin * 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_BREAKPOINT_BIN (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); } bazaar-org-bazaar-43ce9f7/src/bz-stats-dialog.h000066400000000000000000000022451520414637400214000ustar00rootroot00000000000000/* 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, AdwBreakpointBin) AdwBreakpointBin * bz_stats_dialog_new (GListModel *model, GListModel *country_model, int total_downloads); void bz_stats_dialog_animate_open (BzStatsDialog *self); G_END_DECLS bazaar-org-bazaar-43ce9f7/src/bz-subcategory-list.c000066400000000000000000000245731520414637400223100ustar00rootroot00000000000000/* 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 }; 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); 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); } 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]); } bazaar-org-bazaar-43ce9f7/src/bz-subcategory-list.h000066400000000000000000000030051520414637400223000ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-tag-list.c000066400000000000000000000252271520414637400205310ustar00rootroot00000000000000/* 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 }; 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); 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); } 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]); } bazaar-org-bazaar-43ce9f7/src/bz-tag-list.h000066400000000000000000000027341520414637400205340ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-template-callbacks.c000066400000000000000000000115141520414637400225270ustar00rootroot00000000000000/* 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 is_gt (gpointer object, int value1, int value2) { return value1 > value2; } static gboolean is_lt (gpointer object, int value1, int value2) { return value1 < value2; } static gboolean is_ge (gpointer object, int value1, int value2) { return value1 >= value2; } static gboolean is_le (gpointer object, int value1, int value2) { return value1 <= value2; } 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; } static char * format_int (gpointer object, gint integer) { return g_strdup_printf ("%d", integer); } static char * format_uint (gpointer object, guint uint) { return g_strdup_printf ("%u", uint); } static char * format_double (gpointer object, double number) { return g_strdup_printf ("%f", number); } 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, is_gt); gtk_widget_class_bind_template_callback (widget_class, is_lt); gtk_widget_class_bind_template_callback (widget_class, is_ge); gtk_widget_class_bind_template_callback (widget_class, is_le); 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); gtk_widget_class_bind_template_callback (widget_class, format_int); gtk_widget_class_bind_template_callback (widget_class, format_uint); gtk_widget_class_bind_template_callback (widget_class, format_double); } bazaar-org-bazaar-43ce9f7/src/bz-template-callbacks.h000066400000000000000000000015461520414637400225400ustar00rootroot00000000000000/* 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); bazaar-org-bazaar-43ce9f7/src/bz-themed-entry-group-rect.c000066400000000000000000000170601520414637400234730ustar00rootroot00000000000000/* 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; const char *light_color = NULL; const char *dark_color = NULL; GdkRGBA light_rgba = { 0 }; GdkRGBA dark_rgba = { 0 }; gboolean is_dark = FALSE; widget_width = (double) gtk_widget_get_width (widget); widget_height = (double) gtk_widget_get_height (widget); if (self->group != 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) gdk_rgba_parse (&light_rgba, light_color); else gdk_rgba_parse (&light_rgba, "#ebebed"); if (dark_color != NULL) gdk_rgba_parse (&dark_rgba, dark_color); else gdk_rgba_parse (&dark_rgba, "#2e2e32"); is_dark = adw_style_manager_get_dark (adw_style_manager_get_default ()); gtk_snapshot_push_opacity (snapshot, 0.70); gtk_snapshot_append_color ( snapshot, is_dark ? &dark_rgba : &light_rgba, &GRAPHENE_RECT_INIT (0.0, 0.0, widget_width, widget_height)); gtk_snapshot_pop (snapshot); 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 */ bazaar-org-bazaar-43ce9f7/src/bz-themed-entry-group-rect.h000066400000000000000000000031001520414637400234660ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-transact-icon-info.txt000066400000000000000000000005521520414637400230720ustar00rootroot00000000000000prefix=bz name=transact_icon_info parent-prefix=g parent-name=object author=AUTOGEN include="bz-state-info.h" property=state BzStateInfo BZ_TYPE_STATE_INFO object property=group BzEntryGroup BZ_TYPE_ENTRY_GROUP object property=paintable GdkPaintable GDK_TYPE_PAINTABLE object property=tracker BzTransactionEntryTracker BZ_TYPE_TRANSACTION_ENTRY_TRACKER object bazaar-org-bazaar-43ce9f7/src/bz-transact-icon.c000066400000000000000000000342411520414637400215460ustar00rootroot00000000000000/* bz-transact-icon.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 #include "bz-application.h" #include "bz-transact-icon.h" #include "progress-bar-designs/common.h" struct _BzTransactIcon { AdwBin parent_instance; BzTransactIconInfo *info; GSettings *settings; BzTransactionManager *ts_manager; GListModel *trackers; BzTransactionEntryTracker *tracker; char *pride_class; BgeWdgtRenderer *wdgt; }; G_DEFINE_FINAL_TYPE (BzTransactIcon, bz_transact_icon, ADW_TYPE_BIN); enum { PROP_0, PROP_INFO, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void apply_state (BzTransactIcon *self); static void update_tracker (BzTransactIcon *self); static void check_tracker (BzTransactIcon *self); static void ensure_draw_css (BzTransactIcon *self); static void update_icon (BzTransactIcon *self); static void info_state_notify (BzTransactIcon *self, GParamSpec *pspec, BzTransactIconInfo *info); static void info_group_notify (BzTransactIcon *self, GParamSpec *pspec, BzTransactIconInfo *info); static void info_paintable_notify (BzTransactIcon *self, GParamSpec *pspec, BzTransactIconInfo *info); static void trackers_items_changed (BzTransactIcon *self, guint position, guint removed, guint added, GListModel *model); static void tracker_notify (BzTransactIcon *self, GParamSpec *pspec, BzTransactionEntryTracker *tracker); static void pride_flag_changed (BzTransactIcon *self, const char *key, GSettings *settings); static void bz_transact_icon_dispose (GObject *object) { BzTransactIcon *self = BZ_TRANSACT_ICON (object); if (self->info != NULL) { g_signal_handlers_disconnect_by_func ( self->info, info_state_notify, self); g_signal_handlers_disconnect_by_func ( self->info, info_group_notify, self); g_signal_handlers_disconnect_by_func ( self->info, info_paintable_notify, self); } g_clear_pointer (&self->info, g_object_unref); if (self->trackers != NULL) g_signal_handlers_disconnect_by_func ( self->trackers, trackers_items_changed, self); if (self->tracker != NULL) g_signal_handlers_disconnect_by_func ( self->tracker, tracker_notify, self); if (self->settings != NULL) g_signal_handlers_disconnect_by_func ( self->settings, pride_flag_changed, self); g_clear_object (&self->settings); g_clear_object (&self->ts_manager); g_clear_object (&self->trackers); g_clear_object (&self->tracker); g_clear_pointer (&self->pride_class, g_free); G_OBJECT_CLASS (bz_transact_icon_parent_class)->dispose (object); } static void bz_transact_icon_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzTransactIcon *self = BZ_TRANSACT_ICON (object); switch (prop_id) { case PROP_INFO: g_value_set_object (value, bz_transact_icon_get_info (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_transact_icon_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzTransactIcon *self = BZ_TRANSACT_ICON (object); switch (prop_id) { case PROP_INFO: bz_transact_icon_set_info (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_transact_icon_class_init (BzTransactIconClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_transact_icon_set_property; object_class->get_property = bz_transact_icon_get_property; object_class->dispose = bz_transact_icon_dispose; props[PROP_INFO] = g_param_spec_object ( "info", NULL, NULL, BZ_TYPE_TRANSACT_ICON_INFO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_transact_icon_init (BzTransactIcon *self) { self->wdgt = bge_wdgt_renderer_new (); g_object_set ( self->wdgt, "resource", "/io/github/kolunmi/Bazaar/bz-transact-icon.wdgt", "state", "inactive", NULL); g_object_bind_property (self, "info", self->wdgt, "reference", G_BINDING_DEFAULT); adw_bin_set_child (ADW_BIN (self), GTK_WIDGET (self->wdgt)); } BzTransactIcon * bz_transact_icon_new (void) { return g_object_new (BZ_TYPE_TRANSACT_ICON, NULL); } BzTransactIconInfo * bz_transact_icon_get_info (BzTransactIcon *self) { g_return_val_if_fail (BZ_IS_TRANSACT_ICON (self), NULL); return self->info; } void bz_transact_icon_set_info (BzTransactIcon *self, BzTransactIconInfo *info) { g_return_if_fail (BZ_IS_TRANSACT_ICON (self)); g_return_if_fail (info == NULL || BZ_IS_TRANSACT_ICON_INFO (info)); if (info == self->info) return; if (self->info != NULL) { g_signal_handlers_disconnect_by_func ( self->info, info_state_notify, self); g_signal_handlers_disconnect_by_func ( self->info, info_group_notify, self); g_signal_handlers_disconnect_by_func ( self->info, info_paintable_notify, self); } g_clear_pointer (&self->info, g_object_unref); if (info != NULL) { self->info = g_object_ref (info); g_signal_connect_swapped (self->info, "notify::state", G_CALLBACK (info_state_notify), self); g_signal_connect_swapped (self->info, "notify::group", G_CALLBACK (info_group_notify), self); g_signal_connect_swapped (self->info, "notify::paintable", G_CALLBACK (info_paintable_notify), self); } apply_state (self); update_icon (self); bz_transact_icon_info_set_state ( info, bz_state_info_get_default ()); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INFO]); } static void apply_state (BzTransactIcon *self) { if (self->trackers != NULL) g_signal_handlers_disconnect_by_func ( self->trackers, trackers_items_changed, self); if (self->tracker != NULL) g_signal_handlers_disconnect_by_func ( self->tracker, tracker_notify, self); if (self->settings != NULL) g_signal_handlers_disconnect_by_func ( self->settings, pride_flag_changed, self); g_clear_object (&self->settings); g_clear_object (&self->ts_manager); g_clear_object (&self->trackers); g_clear_object (&self->tracker); if (self->info != NULL) { BzStateInfo *state = NULL; state = bz_transact_icon_info_get_state (self->info); if (state != NULL) { g_object_get ( state, "transaction-manager", &self->ts_manager, "settings", &self->settings, NULL); if (self->ts_manager != NULL) { g_object_get ( self->ts_manager, "all-trackers", &self->trackers, NULL); if (self->trackers != NULL) g_signal_connect_swapped ( self->trackers, "items-changed", G_CALLBACK (trackers_items_changed), self); } if (self->settings != NULL) { g_signal_connect_swapped ( self->settings, "changed::global-progress-bar-theme", G_CALLBACK (pride_flag_changed), self); g_signal_connect_swapped ( self->settings, "changed::rotate-flag", G_CALLBACK (pride_flag_changed), self); } } } update_tracker (self); ensure_draw_css (self); } static void update_tracker (BzTransactIcon *self) { g_autoptr (BzTransactionEntryTracker) found = NULL; if (self->trackers != NULL) { BzEntryGroup *group = NULL; group = bz_transact_icon_info_get_group (self->info); if (group != NULL) { const char *id = NULL; guint n_trackers = 0; id = bz_entry_group_get_id (group); n_trackers = g_list_model_get_n_items (self->trackers); for (guint i = 0; i < n_trackers; i++) { g_autoptr (BzTransactionEntryTracker) tracker = NULL; BzEntry *entry = NULL; tracker = g_list_model_get_item (self->trackers, i); entry = bz_transaction_entry_tracker_get_entry (tracker); if (entry == NULL) continue; if (g_strcmp0 (bz_entry_get_id (entry), id) == 0) { found = g_steal_pointer (&tracker); break; } } } } bz_transact_icon_info_set_tracker (self->info, found); if (found != self->tracker) { if (self->tracker != NULL) g_signal_handlers_disconnect_by_func ( self->tracker, tracker_notify, self); g_clear_object (&self->tracker); if (found != NULL) { self->tracker = g_object_ref (found); g_signal_connect_swapped (self->tracker, "notify::active", G_CALLBACK (tracker_notify), self); g_signal_connect_swapped (self->tracker, "notify::pending", G_CALLBACK (tracker_notify), self); g_signal_connect_swapped (self->tracker, "notify::status", G_CALLBACK (tracker_notify), self); } check_tracker (self); } } static void check_tracker (BzTransactIcon *self) { const char *state = NULL; if (self->tracker != NULL) { gboolean active = FALSE; gboolean pending = FALSE; BzTransactionEntryStatus status = 0; active = bz_transaction_entry_tracker_get_active (self->tracker); pending = bz_transaction_entry_tracker_get_pending (self->tracker); status = bz_transaction_entry_tracker_get_status (self->tracker); if ((active || pending) && status == BZ_TRANSACTION_ENTRY_STATUS_CANCELLED) state = "inactive"; else if (pending || status == BZ_TRANSACTION_ENTRY_STATUS_QUEUED) state = "pending"; else if (!active || status == BZ_TRANSACTION_ENTRY_STATUS_DONE) state = "inactive"; else state = "fraction"; } else state = "inactive"; bge_wdgt_renderer_set_state (self->wdgt, state); } static void ensure_draw_css (BzTransactIcon *self) { g_autoptr (GtkWidget) widget = NULL; g_autofree char *id = NULL; g_autofree char *final_id = NULL; g_autofree char *class = NULL; gboolean rotate = FALSE; widget = bge_wdgt_renderer_lookup_object (self->wdgt, "flag"); if (self->settings == NULL) { if (self->pride_class != NULL) gtk_widget_remove_css_class (widget, self->pride_class); g_clear_pointer (&self->pride_class, g_free); return; } 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->pride_class != NULL && g_strcmp0 (self->pride_class, class) == 0) return; if (self->pride_class != NULL) gtk_widget_remove_css_class (widget, self->pride_class); g_clear_pointer (&self->pride_class, g_free); gtk_widget_add_css_class (widget, class); self->pride_class = g_steal_pointer (&class); } static void update_icon (BzTransactIcon *self) { g_autoptr (GtkImage) icon = NULL; GdkPaintable *paintable = NULL; icon = bge_wdgt_renderer_lookup_object (self->wdgt, "icon"); if (self->info != NULL) paintable = bz_transact_icon_info_get_paintable (self->info); if (paintable != NULL) gtk_image_set_from_paintable (icon, paintable); else gtk_image_set_from_icon_name (icon, "application-x-executable"); } static void info_state_notify (BzTransactIcon *self, GParamSpec *pspec, BzTransactIconInfo *info) { apply_state (self); } static void info_group_notify (BzTransactIcon *self, GParamSpec *pspec, BzTransactIconInfo *info) { update_tracker (self); } static void info_paintable_notify (BzTransactIcon *self, GParamSpec *pspec, BzTransactIconInfo *info) { update_icon (self); } static void trackers_items_changed (BzTransactIcon *self, guint position, guint removed, guint added, GListModel *model) { update_tracker (self); } static void tracker_notify (BzTransactIcon *self, GParamSpec *pspec, BzTransactionEntryTracker *tracker) { check_tracker (self); } static void pride_flag_changed (BzTransactIcon *self, const char *key, GSettings *settings) { ensure_draw_css (self); } /* End of bz-transact-icon.c */ bazaar-org-bazaar-43ce9f7/src/bz-transact-icon.h000066400000000000000000000023551520414637400215540ustar00rootroot00000000000000/* bz-transact-icon.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-transact-icon-info.h" G_BEGIN_DECLS #define BZ_TYPE_TRANSACT_ICON (bz_transact_icon_get_type ()) G_DECLARE_FINAL_TYPE (BzTransactIcon, bz_transact_icon, BZ, TRANSACT_ICON, AdwBin) BzTransactIcon * bz_transact_icon_new (void); BzTransactIconInfo * bz_transact_icon_get_info (BzTransactIcon *self); void bz_transact_icon_set_info (BzTransactIcon *self, BzTransactIconInfo *info); G_END_DECLS /* End of bz-transact-icon.h */ bazaar-org-bazaar-43ce9f7/src/bz-transact-icon.wdgt000066400000000000000000000057131520414637400222730ustar00rootroot00000000000000defwidget "Transact Icon" { reference info : "BzTransactIconInfo"; var progress : "gdouble"; var icon-scale : "gdouble"; var flag : "GtkFixed"; var icon : "GtkImage"; var start : "gdouble"; var end : "gdouble"; var path : "GskPath"; var path-measure : "GskPathMeasure"; var path-width : "gdouble"; var path-opacity : "gdouble"; init { set progress = #transition(info:tracker:progress, 1.1, 0.1, 10.0); set flag = #child/(""("transact-icon-flag") can-target = false;); allocate flag #eval(#(%width%)+#(path-width)*2.0), #eval(#(%height%)+#(path-width)*2.0), #(translate(#GraphenePoint(#eval(-#(path-width)), #eval(-#(path-width))));); set icon = #child/(""("icon-dropshadow") pixel-size = #ifelse(#<(%height%, 1), 1, %height%); ); allocate icon %width%, %height%, #(); set path = #GskPath( add-circle( #GraphenePoint(#eval(#(%width%)/2.0), #eval(#(%height%)/2.0)), #eval(#(%height%)/2.0), ); ); set path-measure = #measure-path(path); snapshot { save { move translate(#GraphenePoint(#eval((#(%width%)/2.0)*(1.0-#(icon-scale))), #eval((#(%height%)/2.0)*(1.0-#(icon-scale))))); move scale(icon-scale, icon-scale); do-child icon; } save { move translate(#GraphenePoint(0.0, %height%)); move rotate(-90.0); with opacity(path-opacity) { with stroke( #GskPath( add-segment( path, #path-point(path-measure, #eval((#(start)%1.0)*#(#path-length(path-measure)))), #path-point(path-measure, #eval((#(end)%1.0)*#(#path-length(path-measure)))), ); ), #GskStroke(path-width, round, round, 0.0), ) { move rotate(90.0); move translate(#GraphenePoint(0.0, #eval(-#(%height%)))); do-child flag; } } } } } state-default "inactive" { set icon-scale = 1.0; transition-spring icon-scale 1.0, 0.1, 15.0; set start = 0.0; set end = 1.0; set path-opacity = 0.0; transition-spring path-opacity 1.0, 0.1, 10.0; set path-width = 3.0; transition-spring path-width 1.0, 0.1, 5.0; } state "pending" { set icon-scale = 0.6; transition-spring icon-scale 1.0, 0.1, 15.0; set start = #eval((#(%tick%)*0.5)%1.0); set end = #eval(#(start)+0.2); set path-opacity = 1.0; transition-spring path-opacity 1.0, 0.1, 5.0; set path-width = 3.0; transition-spring path-width 1.0, 0.1, 5.0; } state "fraction" { set icon-scale = 0.6; transition-spring icon-scale 1.0, 0.1, 15.0; set start = 0.0; set end = #eval(0.05+#(progress)*0.95); set path-opacity = 1.0; transition-spring path-opacity 1.0, 0.1, 5.0; set path-width = 3.0; transition-spring path-width 1.0, 0.1, 5.0; } } bazaar-org-bazaar-43ce9f7/src/bz-transaction-dialog-result.txt000066400000000000000000000004241520414637400244700ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-transaction-dialog.c000066400000000000000000000536711520414637400225730ustar00rootroot00000000000000/* 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_entry_is_reinstallable (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 User Data")); adw_action_row_set_subtitle (ADW_ACTION_ROW (keep_data_row), _ ("Allow restoring personal settings & 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 All Data")); adw_action_row_set_subtitle (ADW_ACTION_ROW (delete_data_row), _ ("Permanently erase user 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, _ ("Failed to load transaction dialog"), 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_entry_is_reinstallable (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 = NULL; 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); } bazaar-org-bazaar-43ce9f7/src/bz-transaction-dialog.h000066400000000000000000000025421520414637400225670ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-transaction-entry-tracker.txt000066400000000000000000000013021520414637400245030ustar00rootroot00000000000000prefix=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 cancelled 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 property=progress double G_TYPE_DOUBLE double property=pending gboolean G_TYPE_BOOLEAN boolean property=active gboolean G_TYPE_BOOLEAN boolean bazaar-org-bazaar-43ce9f7/src/bz-transaction-list-dialog.blp000066400000000000000000000042731520414637400240710ustar00rootroot00000000000000using 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; wrap-mode: word_char; single-line-mode: true; selectable: true; label: bind template.item as <$BzEntry>.id; } } }; } }; } Label secondary_label { styles [ "dimmed", ] visible: false; wrap: true; justify: center; } }; }; }bazaar-org-bazaar-43ce9f7/src/bz-transaction-list-dialog.c000066400000000000000000000134771520414637400235440ustar00rootroot00000000000000/* 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); } bazaar-org-bazaar-43ce9f7/src/bz-transaction-list-dialog.h000066400000000000000000000027751520414637400235500ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-transaction-manager.c000066400000000000000000000650161520414637400227420ustar00rootroot00000000000000/* 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-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, PROP_ALL_TRACKERS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_SUCCESS, SIGNAL_FAILURE, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static DexFuture * transaction_fiber (QueuedScheduleData *data); 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; case PROP_ALL_TRACKERS: g_value_set_object (value, self->all_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); props[PROP_ALL_TRACKERS] = g_param_spec_object ( "all-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; } GListModel * bz_transaction_manager_get_all_trackers (BzTransactionManager *self) { g_return_val_if_fail (BZ_IS_TRANSACTION_MANAGER (self), NULL); return G_LIST_MODEL (self->all_trackers); } 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; 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; g_autoptr (GHashTable) errored = NULL; GHashTableIter iter = { 0 }; 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]); 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]); } } } /* Finish off tasks that may not have received a final update */ g_hash_table_iter_init (&iter, op_set); for (;;) { BzBackendTransactionOpPayload *payload = NULL; gpointer dummy = NULL; if (!g_hash_table_iter_next ( &iter, (gpointer *) &payload, (gpointer *) &dummy)) break; bz_transaction_error_out_task (transaction, payload, "Cancelled"); } errored = dex_await_boxed (g_steal_pointer (&future), &local_error); if (local_error != NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); if (errored != NULL && g_hash_table_size (errored) > 0) { GHashTableIter errored_iter = { 0 }; gpointer key = NULL; gpointer val = NULL; g_hash_table_iter_init (&errored_iter, errored); g_hash_table_iter_next (&errored_iter, &key, &val); return dex_future_new_for_error (g_error_copy ((GError *) val)); } return dex_future_new_true (); } 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, "success", value != NULL, "error", local_error != NULL ? local_error->message : NULL, "finished", TRUE, 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); } bazaar-org-bazaar-43ce9f7/src/bz-transaction-manager.h000066400000000000000000000050431520414637400227410ustar00rootroot00000000000000/* 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); GListModel * bz_transaction_manager_get_all_trackers (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 bazaar-org-bazaar-43ce9f7/src/bz-transaction-task.txt000066400000000000000000000006561520414637400226660ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-transaction-tile.blp000066400000000000000000000322671520414637400226220ustar00rootroot00000000000000using 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>.bytes-transferred, template.item as <$BzTransactionTask>.op as <$BzBackendTransactionOpPayload>.download-size) as ; } }; } }; }; } Revealer { reveal-child: bind progress_bars_revealer.reveal-child inverted; child: Box { orientation: horizontal; layout-manager: Adw.WrapLayout { child-spacing: 4; line-spacing: 0; }; 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_both($is_entry_runtime(template.tracker) as , $invert_boolean($is_entry_addon(template.tracker) as ) as ) 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_cancelled(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: _("Cancelled"); } } 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>.installed-size) as ; } } }; } } Box { orientation: horizontal; spacing: 5; Button { visible: bind $is_both( $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 , template.tracker as <$BzTransactionEntryTracker>.entry as <$BzEntry>.installed as ) as ; valign: center; label: _("Open"); clicked => $run_cb(template); styles [ "medium-pill", ] } Button { visible: bind $is_ongoing(template.tracker as <$BzTransactionEntryTracker>.status as <$BzTransactionEntryStatus>) as ; icon-name: "media-playback-stop-symbolic"; has-tooltip: true; valign: center; tooltip-text: _("Cancel Transaction"); clicked => $cancel_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 ; } Button { icon-name: "info-outline-symbolic"; clicked => $error_clicked_cb(template); visible: bind $invert_boolean($is_null(template.item as <$BzTransactionTask>.error) as ) as ; has-tooltip: true; tooltip-text: _("Show Error Info"); styles [ "error", "flat", ] } } }; } }; } }; } }; }; } bazaar-org-bazaar-43ce9f7/src/bz-transaction-tile.c000066400000000000000000000306631520414637400222650ustar00rootroot00000000000000/* 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.h" #include "bz-entry-group.h" #include "bz-entry.h" #include "bz-error-dialog.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 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, guint64 bytes_transferred, guint64 total_size) { g_autofree char *downloaded_str = NULL; g_autofree char *total_str = NULL; downloaded_str = g_format_size (bytes_transferred); if (total_size == (guint64) -1) return g_strdup_printf ("%s", downloaded_str); else { 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_cancelled (gpointer object, BzTransactionEntryStatus status) { return status == BZ_TRANSACTION_ENTRY_STATUS_CANCELLED; } 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); 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) return; gtk_widget_activate_action (GTK_WIDGET (self), "window.launch-group", "s", bz_entry_get_id (entry)); } static void cancel_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) return; gtk_widget_activate_action (GTK_WIDGET (self), "window.cancel-group", "s", bz_entry_get_id (entry)); } static void error_clicked_cb (GtkListItem *item, GtkButton *button, BzTransactionTile *self) { BzTransactionTask *task = NULL; const char *error = NULL; const char *name = NULL; BzErrorDialog *dialog = NULL; task = gtk_list_item_get_item (item); if (task == NULL) return; error = bz_transaction_task_get_error (task); if (error == NULL) return; name = bz_backend_transaction_op_payload_get_name ( bz_transaction_task_get_op (task)); if (name != NULL) { g_autofree char *body = NULL; body = g_strdup_printf ("%s: %s", name, error); dialog = bz_error_dialog_new (_ ("Transaction Error"), body); } else dialog = bz_error_dialog_new (_ ("Transaction Error"), error); adw_dialog_present (ADW_DIALOG (dialog), GTK_WIDGET (self)); } 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_cancelled); gtk_widget_class_bind_template_callback (widget_class, is_both); gtk_widget_class_bind_template_callback (widget_class, run_cb); gtk_widget_class_bind_template_callback (widget_class, cancel_cb); gtk_widget_class_bind_template_callback (widget_class, error_clicked_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]); } /* End of bz-transaction-tile.c */ bazaar-org-bazaar-43ce9f7/src/bz-transaction-tile.h000066400000000000000000000025111520414637400222610ustar00rootroot00000000000000/* 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 */ bazaar-org-bazaar-43ce9f7/src/bz-transaction.c000066400000000000000000000655261520414637400213400ustar00rootroot00000000000000/* 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, BzBackendTransactionOpProgressPayload *progress_payload, gboolean transfer, gboolean set_done); 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); \ bz_transaction_entry_tracker_set_pending (tracker, TRUE); \ if ((transaction_type) == BZ_TRANSACTION_ENTRY_KIND_REMOVAL) \ bz_transaction_entry_tracker_set_active (tracker, TRUE); \ \ 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; if (bz_transaction_entry_tracker_get_kind (tracker) == BZ_TRANSACTION_ENTRY_KIND_UPDATE) bz_backend_transaction_op_payload_set_download_size (payload, (guint64) -1); 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, payload, FALSE, 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, NULL, TRUE, FALSE); } 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, NULL, TRUE, 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_active (tracker, FALSE); bz_transaction_entry_tracker_set_pending (tracker, FALSE); if (bz_transaction_entry_tracker_get_status (tracker) == BZ_TRANSACTION_ENTRY_STATUS_CANCELLED) continue; bz_transaction_entry_tracker_set_status ( tracker, priv->success ? BZ_TRANSACTION_ENTRY_STATUS_DONE : BZ_TRANSACTION_ENTRY_STATUS_CANCELLED); } } 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, BzBackendTransactionOpProgressPayload *progress_payload, gboolean transfer, gboolean set_done) { 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) { BzTransactionEntryStatus existing_status = 0; existing_status = bz_transaction_entry_tracker_get_status (tracker); if (transfer) { GListModel *from = NULL; GListModel *to = NULL; if (set_done) { bz_transaction_entry_tracker_set_active (tracker, FALSE); bz_transaction_entry_tracker_set_status (tracker, BZ_TRANSACTION_ENTRY_STATUS_DONE); bz_transaction_entry_tracker_set_pending (tracker, FALSE); } 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 { if (progress_payload != NULL) { double progress = 0.0; double scaled = 0.0; gboolean estimating = FALSE; progress = bz_backend_transaction_op_progress_payload_get_total_progress (progress_payload); scaled = progress >= 1.0 ? 1.0 : progress * 0.9; estimating = bz_backend_transaction_op_progress_payload_get_is_estimating (progress_payload); g_object_set (tracker, "progress", scaled, "pending", estimating && progress == 0.0, NULL); } bz_transaction_entry_tracker_set_active (tracker, TRUE); if (existing_status != BZ_TRANSACTION_ENTRY_STATUS_CANCELLED) bz_transaction_entry_tracker_set_status (tracker, BZ_TRANSACTION_ENTRY_STATUS_ONGOING); } } } bazaar-org-bazaar-43ce9f7/src/bz-transaction.h000066400000000000000000000047451520414637400213410ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-updates-card.blp000066400000000000000000000015271520414637400217110ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzUpdatesCard: Adw.Bin { child: ListBox { selection-mode: none; margin-start: 4; margin-end: 4; margin-bottom: 4; styles [ "boxed-list", ] Adw.ExpanderRow expander_row { title: bind $format_update_count(template.state as <$BzStateInfo>.available-updates) as ; notify::expanded => $on_expander_expanded_cb(); [suffix] Box { height-request: 60; Button { label: _("_Update All"); use-underline: true; valign: center; clicked => $update_all_cb(); styles [ "suggested-action", ] } } } }; } FilterListModel runtimes_filter_model { filter: CustomFilter runtimes_filter {}; model: bind template.state as <$BzStateInfo>.available-updates; }bazaar-org-bazaar-43ce9f7/src/bz-updates-card.c000066400000000000000000000357751520414637400213720ustar00rootroot00000000000000/* 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-entry.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 */ AdwExpanderRow *expander_row; GtkCustomFilter *runtimes_filter; GtkFilterListModel *runtimes_filter_model; GPtrArray *app_rows; GtkWidget *runtimes_row; gboolean has_closed; }; 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 void update_all_cb (GtkButton *button, BzUpdatesCard *self); static void update_runtimes_cb (GtkButton *button, BzUpdatesCard *self); static void on_expander_expanded_cb (AdwExpanderRow *row, GParamSpec *pspec, BzUpdatesCard *self); static gboolean filter_runtimes (BzEntry *entry, BzUpdatesCard *self); static void on_available_updates_changed (BzUpdatesCard *self, GParamSpec *pspec, BzStateInfo *state); static void on_runtimes_changed (GtkFilterListModel *model, guint position, guint removed, guint added, BzUpdatesCard *self); static void on_update_single_cb (GtkButton *button, BzEntry *entry) { BzUpdatesCard *self = NULL; g_autoptr (GListStore) store = NULL; self = BZ_UPDATES_CARD (gtk_widget_get_ancestor (GTK_WIDGET (button), BZ_TYPE_UPDATES_CARD)); 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 on_version_history_cb (GtkButton *button, BzEntry *entry) { GtkRoot *root = NULL; g_autoptr (GListModel) history = NULL; GtkWidget *dialog = NULL; root = gtk_widget_get_root (GTK_WIDGET (button)); if (root == NULL) return; g_object_get (entry, "version-history", &history, NULL); dialog = bz_releases_dialog_new (history, NULL); adw_dialog_present (ADW_DIALOG (dialog), GTK_WIDGET (root)); } static GtkWidget * build_app_row (BzEntry *entry, BzUpdatesCard *self) { AdwActionRow *row = NULL; GtkWidget *icon = NULL; GtkWidget *history_button = NULL; GtkWidget *update_button = NULL; GdkPaintable *paintable = NULL; g_autoptr (GListModel) history = NULL; g_autofree char *installed_ver = NULL; const char *new_ver = NULL; // This will probably the same as the installed version if using cache... row = ADW_ACTION_ROW (adw_action_row_new ()); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), bz_entry_get_title (entry)); g_object_get (entry, "icon-paintable", &paintable, NULL); icon = paintable != NULL ? gtk_image_new_from_paintable (paintable) : gtk_image_new_from_icon_name ("application-x-executable"); g_clear_object (&paintable); gtk_image_set_pixel_size (GTK_IMAGE (icon), 48); gtk_widget_set_size_request (icon, 48, 48); gtk_widget_set_margin_top (icon, 6); gtk_widget_set_margin_bottom (icon, 6); gtk_widget_set_valign (icon, GTK_ALIGN_CENTER); gtk_widget_add_css_class (icon, "icon-dropshadow"); adw_action_row_add_prefix (row, icon); g_object_get (entry, "version-history", &history, "installed-version", &installed_ver, NULL); if (history != NULL && g_list_model_get_n_items (history) > 0 && installed_ver != NULL) { g_autoptr (BzRelease) first = g_list_model_get_item (history, 0); new_ver = bz_release_get_version (first); if (new_ver != NULL && g_strcmp0 (installed_ver, new_ver) != 0) { g_autofree char *subtitle = g_strdup_printf ("%s → %s", installed_ver, new_ver); adw_action_row_set_subtitle (row, subtitle); } } history_button = gtk_button_new_from_icon_name ("view-list-bullet-symbolic"); gtk_widget_set_valign (history_button, GTK_ALIGN_CENTER); gtk_widget_set_tooltip_text (history_button, _ ("Version History")); gtk_widget_add_css_class (history_button, "flat"); gtk_widget_set_visible (history_button, history != NULL && g_list_model_get_n_items (history) > 0); g_signal_connect_data (history_button, "clicked", G_CALLBACK (on_version_history_cb), g_object_ref (entry), (GClosureNotify) g_object_unref, 0); adw_action_row_add_suffix (row, history_button); update_button = gtk_button_new_with_label (_ ("Update")); gtk_widget_set_valign (update_button, GTK_ALIGN_CENTER); g_signal_connect_data (update_button, "clicked", G_CALLBACK (on_update_single_cb), g_object_ref (entry), (GClosureNotify) g_object_unref, 0); adw_action_row_add_suffix (row, update_button); return GTK_WIDGET (row); } static GtkWidget * build_runtimes_row (BzUpdatesCard *self) { AdwActionRow *row = NULL; GtkWidget *update_button = NULL; row = ADW_ACTION_ROW (adw_action_row_new ()); gtk_widget_set_visible (GTK_WIDGET (row), FALSE); update_button = gtk_button_new_with_label (_ ("Update")); gtk_widget_set_valign (update_button, GTK_ALIGN_CENTER); g_signal_connect (update_button, "clicked", G_CALLBACK (update_runtimes_cb), self); adw_action_row_add_suffix (row, update_button); return GTK_WIDGET (row); } static void on_runtimes_changed (GtkFilterListModel *model, guint position, guint removed, guint added, BzUpdatesCard *self) { guint n_items = 0; g_autofree char *title = NULL; if (self->runtimes_row == NULL) return; n_items = g_list_model_get_n_items (G_LIST_MODEL (model)); gtk_widget_set_visible (self->runtimes_row, n_items > 0); if (n_items == 0) return; title = g_strdup_printf (ngettext ("%u Runtime Update", "%u Runtime Updates", n_items), n_items); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->runtimes_row), title); } static void repopulate_expander_row (BzUpdatesCard *self) { GListModel *updates = NULL; guint n_items = 0; guint i = 0; for (i = 0; i < self->app_rows->len; i++) adw_expander_row_remove (self->expander_row, g_ptr_array_index (self->app_rows, i)); g_ptr_array_set_size (self->app_rows, 0); if (self->runtimes_row != NULL) { adw_expander_row_remove (self->expander_row, self->runtimes_row); self->runtimes_row = NULL; } if (self->state == NULL) return; updates = bz_state_info_get_available_updates (self->state); if (updates == NULL) return; n_items = g_list_model_get_n_items (updates); for (i = 0; i < n_items; i++) { g_autoptr (BzEntry) entry = NULL; GtkWidget *row = NULL; entry = g_list_model_get_item (updates, i); if (entry == NULL || !BZ_IS_ENTRY (entry)) continue; if (!bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_APPLICATION)) continue; row = build_app_row (entry, self); adw_expander_row_add_row (self->expander_row, row); g_ptr_array_add (self->app_rows, row); } self->runtimes_row = build_runtimes_row (self); adw_expander_row_add_row (self->expander_row, self->runtimes_row); on_runtimes_changed (self->runtimes_filter_model, 0, 0, 0, self); if (!self->has_closed) adw_expander_row_set_expanded (self->expander_row, n_items <= 3); } static void on_available_updates_changed (BzUpdatesCard *self, GParamSpec *pspec, BzStateInfo *state) { gtk_filter_changed (GTK_FILTER (self->runtimes_filter), GTK_FILTER_CHANGE_DIFFERENT); repopulate_expander_row (self); } static void bz_updates_card_dispose (GObject *object) { BzUpdatesCard *self = BZ_UPDATES_CARD (object); g_clear_object (&self->state); g_clear_pointer (&self->app_rows, g_ptr_array_unref); gtk_widget_dispose_template (GTK_WIDGET (self), BZ_TYPE_UPDATES_CARD); 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); 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, expander_row); 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, update_all_cb); gtk_widget_class_bind_template_callback (widget_class, on_expander_expanded_cb); } static void bz_updates_card_init (BzUpdatesCard *self) { gtk_widget_init_template (GTK_WIDGET (self)); self->app_rows = g_ptr_array_new (); gtk_custom_filter_set_filter_func ( self->runtimes_filter, (GtkCustomFilterFunc) filter_runtimes, self, NULL); g_signal_connect (self->runtimes_filter_model, "items-changed", G_CALLBACK (on_runtimes_changed), self); } 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_signal_connect_object (state, "notify::available-updates", G_CALLBACK (on_available_updates_changed), self, G_CONNECT_SWAPPED); } gtk_filter_changed (GTK_FILTER (self->runtimes_filter), GTK_FILTER_CHANGE_DIFFERENT); repopulate_expander_row (self); 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 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 void on_expander_expanded_cb (AdwExpanderRow *row, GParamSpec *pspec, BzUpdatesCard *self) { if (!adw_expander_row_get_expanded (row)) self->has_closed = TRUE; } 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); } bazaar-org-bazaar-43ce9f7/src/bz-updates-card.h000066400000000000000000000022621520414637400213600ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-url.txt000066400000000000000000000002221520414637400201700ustar00rootroot00000000000000prefix=bz name=url parent-prefix=g parent-name=object author=AUTOGEN property=id char G_TYPE_STRING string property=url char G_TYPE_STRING string bazaar-org-bazaar-43ce9f7/src/bz-user-data-page.blp000066400000000000000000000040761520414637400221360ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzUserDataPage: Adw.NavigationPage { title: _("Manage Leftover User Data"); Adw.ToolbarView { [top] Adw.HeaderBar {} 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; } } }; } } bazaar-org-bazaar-43ce9f7/src/bz-user-data-page.c000066400000000000000000000211161520414637400215750ustar00rootroot00000000000000/* 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 (); } bazaar-org-bazaar-43ce9f7/src/bz-user-data-page.h000066400000000000000000000020761520414637400216060ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-user-data-tile.blp000066400000000000000000000050641520414637400221550ustar00rootroot00000000000000using 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>.ui-entry as <$BzResult>.object as <$BzEntry>.icon-paintable; visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.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>.ui-entry as <$BzResult>.object as <$BzEntry>.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 ) 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; } }; }; }; } bazaar-org-bazaar-43ce9f7/src/bz-user-data-tile.c000066400000000000000000000147371520414637400216310ustar00rootroot00000000000000/* 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-util.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 DexFuture * reap_user_data_done (DexFuture *future, GWeakRef *wr) { g_autoptr (BzUserDataTile) self = NULL; g_autoptr (GError) local_error = NULL; dex_future_get_value (future, &local_error); self = g_weak_ref_get (wr); if (self == NULL) return dex_future_new_true (); if (local_error != NULL) bz_show_error_for_widget ( GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (self))), _ ("Failed to Remove User Data"), local_error->message); else { g_autofree char *message = NULL; message = g_strdup_printf (_ ("Trashed User Data for %s"), bz_entry_group_get_title (self->group)); bz_window_add_toast ( BZ_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))), adw_toast_new (message)); } return dex_future_new_true (); } static void remove_cb (BzUserDataTile *self, GtkButton *button) { g_autoptr (DexFuture) future = NULL; if (self->group == NULL) return; future = bz_entry_group_reap_user_data (self->group); if (future != NULL) dex_future_disown (dex_future_finally ( dex_ref (future), (DexFutureCallback) reap_user_data_done, bz_track_weak (self), bz_weak_release)); } 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; } bazaar-org-bazaar-43ce9f7/src/bz-user-data-tile.h000066400000000000000000000023631520414637400216260ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-util.h000066400000000000000000000214741520414637400177670ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-verification-status.txt000066400000000000000000000006511520414637400233770ustar00rootroot00000000000000prefix=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 bazaar-org-bazaar-43ce9f7/src/bz-window.blp000066400000000000000000000242621520414637400206450ustar00rootroot00000000000000using Gtk 4.0; using Gio 2.0; using Adw 1; template $BzWindow: Adw.ApplicationWindow { title: bind $format_title(navigation_view.visible-page as .title); default-width: 1220; default-height: 900; width-request: 360; height-request: 294; 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 { content: 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; tooltip-text: bind template.state as <$BzStateInfo>.background-task-label; Adw.Spinner { width-request: 64; height-request: 64; margin-bottom: 18; } Label { label: _("Refreshing"); 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>; browse-flathub => $browse_flathub_cb(template); }; } Adw.ViewStackPage { name: "flathub"; title: _("Explore"); icon-name: "explore-symbolic"; child: $BzFlathubPage { state: bind template.state as <$BzStateInfo>; 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; transactions: bind template.state as <$BzStateInfo>.transaction-manager; model: bind template.state as <$BzStateInfo>.all-installed-entry-groups; update => $update_cb(template); }; } Adw.ViewStackPage { name: "search"; title: _("Search"); icon-name: "system-search-symbolic"; child: $BzSearchPage search_page { state: bind template.state; }; } }; } }; [top] Box { orientation: vertical; Adw.HeaderBar top_header_bar { [start] Box { styles [ "bz-debug", ] orientation: horizontal; spacing: 6; visible: bind template.state as <$BzStateInfo>.debug-mode; Button { has-tooltip: true; tooltip-text: "Open Bazaar Inspector"; icon-name: "bug-symbolic"; action-name: "app.bazaar-inspector"; } } [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; margin-start: 8; reveal-child: bind $logical_and($invert_boolean(template.state as <$BzStateInfo>.busy) as , $invert_boolean($is_null(template.state as <$BzStateInfo>.background-task-label) as ) as ) as ; child: Adw.Spinner { width-request: 16; height-request: 16; has-tooltip: true; tooltip-text: bind template.state as <$BzStateInfo>.background-task-label; }; } [title] Box { Adw.ViewSwitcher { stack: main_view_stack; policy: wide; visible: bind $invert_boolean(template.state as <$BzStateInfo>.busy) as ; } Label { label: _("Bazaar"); visible: bind template.state as <$BzStateInfo>.busy as ; styles [ "title", ] } } [end] MenuButton { primary: true; icon-name: "open-menu-symbolic"; has-tooltip: true; tooltip-text: _("Main Menu"); menu-model: primary_menu; } } 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: _("Refresh Manually"); button-clicked => $sync_cb(template); } } [bottom] Adw.ViewSwitcherBar { stack: main_view_stack; reveal: true; visible: bind $invert_boolean(template.state as <$BzStateInfo>.busy) as ; } }; } Adw.NavigationPage { tag: "view"; title: bind full_view.entry-group as <$BzEntryGroup>.title as ; child: $BzFullView full_view { state: bind template.state; update => $update_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: _("_Refresh"); action: "app.sync-remotes"; } 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: _("_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"; } } } bazaar-org-bazaar-43ce9f7/src/bz-window.c000066400000000000000000001141251520414637400203100ustar00rootroot00000000000000/* 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-addons-dialog.h" #include "bz-application.h" #include "bz-curated-view.h" #include "bz-entry-group-util.h" #include "bz-entry-group.h" #include "bz-env.h" #include "bz-error.h" #include "bz-flathub-page.h" #include "bz-flatpak-entry.h" #include "bz-full-view.h" #include "bz-hooks.h" #include "bz-io.h" #include "bz-library-page.h" #include "bz-progress-bar.h" #include "bz-search-page.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 */ AdwNavigationView *navigation_view; BzFullView *full_view; BzSearchPage *search_page; BzLibraryPage *library_page; AdwToastOverlay *toasts; AdwViewStack *main_view_stack; GtkStack *main_stack; }; G_DEFINE_FINAL_TYPE (BzWindow, bz_window, ADW_TYPE_APPLICATION_WINDOW) enum { PROP_0, PROP_STATE, PROP_COMPACT, 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 (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 emit_hook_disown (BzWindow *self, BzHookSignal signal, BzEntryGroup *group); 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; case PROP_COMPACT: g_value_set_boolean (value, self->breakpoint_applied); 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 update_cb (BzWindow *self, GListModel *entries, GtkWidget *widget) { 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)); 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]); } 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, BzSearchPage *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"); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_COMPACT]); } static void breakpoint_unapply_cb (BzWindow *self, AdwBreakpoint *breakpoint) { self->breakpoint_applied = FALSE; gtk_widget_remove_css_class (GTK_WIDGET (self), "narrow"); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_COMPACT]); } 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 char * format_title (gpointer object, const char *title) { if (title == NULL || *title == '\0' || g_strcmp0 (title, _ ("Bazaar")) == 0) return g_strdup (_ ("Bazaar")); /* Translators: %s is the title of the current page */ return g_strdup_printf (_ ("Bazaar — %s"), title); } static BzEntryGroup * resolve_group_from_parameter (BzWindow *self, GVariant *parameter, gboolean *auto_confirm) { const char *id = NULL; g_variant_get (parameter, "(&sb)", &id, auto_confirm); return bz_application_map_factory_convert_one ( bz_state_info_get_application_factory (self->state), gtk_string_object_new (id)); } static void action_install_group (GtkWidget *widget, const char *action_name, GVariant *parameter) { BzWindow *self = BZ_WINDOW (widget); g_autoptr (BzEntryGroup) group = NULL; gboolean auto_confirm = FALSE; group = resolve_group_from_parameter (self, parameter, &auto_confirm); if (group != NULL) try_transact (self, NULL, group, FALSE, auto_confirm, NULL); } static void action_remove_group (GtkWidget *widget, const char *action_name, GVariant *parameter) { BzWindow *self = BZ_WINDOW (widget); g_autoptr (BzEntryGroup) group = NULL; gboolean auto_confirm = FALSE; group = resolve_group_from_parameter (self, parameter, &auto_confirm); if (group != NULL) try_transact (self, NULL, group, TRUE, auto_confirm, NULL); } static void action_cancel_group (GtkWidget *widget, const char *action_name, GVariant *parameter) { BzWindow *self = BZ_WINDOW (widget); const char *id = NULL; BzTransactionManager *manager = NULL; BzBackend *backend = NULL; GListModel *trackers = NULL; guint n_items = 0; id = g_variant_get_string (parameter, NULL); manager = bz_state_info_get_transaction_manager (self->state); if (manager == NULL) return; backend = bz_state_info_get_backend (self->state); if (backend == NULL) return; trackers = bz_transaction_manager_get_all_trackers (manager); n_items = g_list_model_get_n_items (trackers); for (guint i = 0; i < n_items; i++) { g_autoptr (BzTransactionEntryTracker) tracker = NULL; BzEntry *entry = NULL; const char *entry_id = NULL; tracker = g_list_model_get_item (trackers, i); entry = bz_transaction_entry_tracker_get_entry (tracker); if (entry == NULL) continue; entry_id = bz_entry_get_id (entry); if (g_strcmp0 (entry_id, id) == 0) { if (bz_backend_cancel_task_for_entry (backend, entry)) g_object_set (tracker, "status", BZ_TRANSACTION_ENTRY_STATUS_CANCELLED, NULL); break; } } } static void action_show_group (GtkWidget *widget, const char *action_name, GVariant *parameter) { BzWindow *self = BZ_WINDOW (widget); const char *id = NULL; g_autoptr (BzEntryGroup) group = NULL; id = g_variant_get_string (parameter, NULL); group = bz_application_map_factory_convert_one ( bz_state_info_get_application_factory (self->state), gtk_string_object_new (id)); if (group == NULL) return; if (bz_entry_group_is_addon (group)) { AdwDialog *dialog = NULL; dialog = bz_addons_dialog_new_single (group); adw_dialog_present (dialog, GTK_WIDGET (self)); } else bz_window_show_group (self, group); } static void action_addons_group (GtkWidget *widget, const char *action_name, GVariant *parameter) { BzWindow *self = BZ_WINDOW (widget); const char *id = NULL; g_autoptr (BzEntryGroup) group = NULL; AdwDialog *addons_dialog = NULL; id = g_variant_get_string (parameter, NULL); group = bz_application_map_factory_convert_one ( bz_state_info_get_application_factory (self->state), gtk_string_object_new (id)); if (group == NULL) return; addons_dialog = bz_addons_dialog_new (group); adw_dialog_present (addons_dialog, GTK_WIDGET (self)); } static void action_bulk_install (GtkWidget *widget, const char *action_name, GVariant *parameter) { BzWindow *self = BZ_WINDOW (widget); g_autoptr (GListStore) ids = NULL; g_autoptr (GListModel) groups = NULL; GVariantIter iter = { 0 }; const char *id = NULL; ids = g_list_store_new (GTK_TYPE_STRING_OBJECT); g_variant_iter_init (&iter, parameter); while (g_variant_iter_next (&iter, "&s", &id)) { g_autoptr (GtkStringObject) string = gtk_string_object_new (id); g_list_store_append (ids, string); } groups = bz_application_map_factory_generate ( bz_state_info_get_application_factory (self->state), G_LIST_MODEL (ids)); if (groups != NULL && g_list_model_get_n_items (groups) > 0) bz_window_bulk_install (self, groups); } 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_flathub_page (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, "flathub"); } 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 DexFuture * launch_group_fiber (BzEntryGroup *group) { g_autoptr (GError) local_error = NULL; g_autoptr (GListStore) store = NULL; GtkWidget *window = NULL; BzStateInfo *state = NULL; state = bz_state_info_get_default (); window = GTK_WIDGET (gtk_application_get_active_window ( GTK_APPLICATION (g_application_get_default ()))); store = dex_await_object ( bz_entry_group_dup_all_into_store (group), &local_error); if (store == NULL) { if (window != NULL) bz_show_error_for_widget (window, _ ("Failed to launch application"), local_error->message); return dex_future_new_for_error (g_steal_pointer (&local_error)); } for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++) { g_autoptr (BzEntry) entry = NULL; const char *ref = NULL; gboolean result = FALSE; entry = g_list_model_get_item (G_LIST_MODEL (store), i); if (!BZ_IS_FLATPAK_ENTRY (entry) || !bz_entry_is_installed (entry)) continue; ref = bz_flatpak_entry_get_addon_extension_of_ref (BZ_FLATPAK_ENTRY (entry)); if (ref != NULL) { g_auto (GStrv) parts = NULL; BzApplicationMapFactory *factory = NULL; g_autoptr (BzEntryGroup) parent = NULL; parts = g_strsplit (ref, "/", -1); if (parts[0] != NULL && parts[1] != NULL) { factory = bz_state_info_get_application_factory (state); parent = bz_application_map_factory_convert_one ( factory, gtk_string_object_new (parts[1])); if (parent != NULL) return launch_group_fiber (parent); } } result = bz_flatpak_entry_launch ( BZ_FLATPAK_ENTRY (entry), BZ_FLATPAK_INSTANCE (bz_state_info_get_backend (state)), &local_error); if (!result && window != NULL) bz_show_error_for_widget (window, _ ("Failed to launch application"), local_error->message); return result ? dex_future_new_true () : dex_future_new_for_error (g_steal_pointer (&local_error)); } return dex_future_new_false (); } static void action_launch_group (GtkWidget *widget, const char *action_name, GVariant *parameter) { BzWindow *self = BZ_WINDOW (widget); const char *id = NULL; g_autoptr (BzEntryGroup) group = NULL; id = g_variant_get_string (parameter, NULL); group = bz_application_map_factory_convert_one ( bz_state_info_get_application_factory (self->state), gtk_string_object_new (id)); if (group == NULL) return; dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) launch_group_fiber, g_object_ref (group), g_object_unref)); } 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); props[PROP_COMPACT] = g_param_spec_boolean ( "compact", 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_SEARCH_PAGE); 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); 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, 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_page); 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_callback (widget_class, list_length); gtk_widget_class_bind_template_callback (widget_class, update_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, format_title); 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_install_action (widget_class, "window.open-flathub-page", NULL, action_open_flathub_page); gtk_widget_class_install_action (widget_class, "window.install-group", "(sb)", action_install_group); gtk_widget_class_install_action (widget_class, "window.remove-group", "(sb)", action_remove_group); gtk_widget_class_install_action (widget_class, "window.cancel-group", "s", action_cancel_group); gtk_widget_class_install_action (widget_class, "window.show-group", "s", action_show_group); gtk_widget_class_install_action (widget_class, "window.addons-group", "s", action_addons_group); gtk_widget_class_install_action (widget_class, "window.bulk-install", NULL, action_bulk_install); gtk_widget_class_install_action (widget_class, "window.launch-group", "s", action_launch_group); gtk_widget_class_add_binding_action (widget_class, GDK_KEY_d, GDK_CONTROL_MASK, "window.open-library", NULL); gtk_widget_class_add_binding_action (widget_class, GDK_KEY_w, GDK_CONTROL_MASK, "window.close", NULL); gtk_widget_class_add_binding_action (widget_class, GDK_KEY_e, GDK_CONTROL_MASK, "window.open-flathub-page", 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; gboolean was_deeper = FALSE; /* 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); was_deeper = g_list_model_get_n_items ( adw_navigation_view_get_navigation_stack (self->navigation_view)) > 1; adw_navigation_view_pop_to_tag (self->navigation_view, "main"); visible_child_name = adw_view_stack_get_visible_child_name (self->main_view_stack); if (!was_deeper && 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_page_ensure_active (self->search_page, 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_page_refresh (self->search_page); 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 (GError) local_error = NULL; g_autoptr (BzEntry) selected_entry = NULL; g_autoptr (DexFuture) transact_future = NULL; g_autofree char *id_dup = NULL; BzMainConfig *config = NULL; GListModel *hooks = NULL; gboolean delete_user_data = FALSE; GdkDisplay *display = NULL; GdkSeat *seat = NULL; GdkDevice *keyboard = NULL; GdkModifierType modifiers = GDK_NO_MODIFIER_MASK; // 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) { GtkWidget *window = NULL; window = GTK_WIDGET (gtk_application_get_active_window (GTK_APPLICATION (g_application_get_default ()))); bz_show_error_for_widget (window, _ ("You can't remove Bazaar from Bazaar!"), _ ("You can't remove Bazaar from Bazaar!")); return dex_future_new_false (); } } config = bz_state_info_get_main_config (bz_state_info_get_default ()); if (config != NULL) hooks = bz_main_config_get_hooks (config); #define RUN_HOOK(_signal) \ G_STMT_START \ { \ if (hooks != NULL && \ !dex_await ( \ bz_run_hook_emission ( \ hooks, (_signal), \ data->remove \ ? BZ_HOOK_TRANSACTION_TYPE_REMOVAL \ : BZ_HOOK_TRANSACTION_TYPE_INSTALL, \ id_dup, NULL), \ &local_error)) \ return dex_future_new_for_error (g_steal_pointer (&local_error)); \ } \ G_STMT_END RUN_HOOK (BZ_HOOK_SIGNAL_BEFORE_TRANSACTION); display = gdk_display_get_default (); seat = gdk_display_get_default_seat (display); keyboard = gdk_seat_get_keyboard (seat); if (keyboard != NULL) modifiers = gdk_device_get_modifier_state (keyboard); if (modifiers & GDK_SHIFT_MASK) /* Holding shift while invoking a transaction skips the dialog and assumes the first valid entry */ { if (data->group != NULL) { g_autoptr (GListModel) store = NULL; guint n_items = 0; store = dex_await_object ( bz_entry_group_dup_all_into_store (data->group), &local_error); if (store == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); n_items = g_list_model_get_n_items (store); for (guint i = 0; i < n_items; i++) { g_autoptr (BzEntry) entry = NULL; gboolean installed = FALSE; entry = g_list_model_get_item (store, i); installed = bz_entry_is_installed (entry); if ((data->remove && installed) || (!data->remove && !installed)) { selected_entry = g_steal_pointer (&entry); break; } } if (selected_entry == NULL) return dex_future_new_false (); } else selected_entry = g_object_ref (data->entry); } else { g_autoptr (BzTransactionDialogResult) dialog_result = NULL; // Show the dialog dialog_result = dex_await_object ( bz_transaction_dialog_show ( GTK_WIDGET (gtk_application_get_active_window ( GTK_APPLICATION (g_application_get_default ()))), 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 (); selected_entry = g_object_ref ( bz_transaction_dialog_result_get_selected_entry (dialog_result)); delete_user_data = bz_transaction_dialog_result_get_delete_user_data ( dialog_result); } // Perform the transaction transact_future = transact ( selected_entry, 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 (delete_user_data) { if (data->group != NULL) bz_entry_group_reap_user_data (data->group); else dex_future_disown (bz_reap_user_data_dex (id_dup)); } RUN_HOOK (BZ_HOOK_SIGNAL_AFTER_TRANSACTION); #undef RUN_HOOK 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; 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_window_show_group (self, group); } void bz_window_show_group (BzWindow *self, BzEntryGroup *group) { GListModel *stack = NULL; gboolean in_stack = FALSE; 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); emit_hook_disown (self, BZ_HOOK_SIGNAL_VIEW_APP, group); stack = adw_navigation_view_get_navigation_stack (self->navigation_view); for (guint i = 0; i < g_list_model_get_n_items (stack); i++) { g_autoptr (AdwNavigationPage) page = NULL; page = g_list_model_get_item (stack, i); if (g_strcmp0 (adw_navigation_page_get_tag (page), "view") == 0) { in_stack = TRUE; adw_navigation_view_pop_to_page (self->navigation_view, page); break; } } if (!in_stack) 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)); 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 (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 (bz_state_info_get_default ()), 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_page_set_text (self->search_page, 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_page)); } 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); } static void emit_hook_disown (BzWindow *self, BzHookSignal signal, BzEntryGroup *group) { BzMainConfig *config = NULL; GListModel *hooks = NULL; if (self->state == NULL) return; config = bz_state_info_get_main_config (self->state); if (config == NULL) return; hooks = bz_main_config_get_hooks (config); if (hooks == NULL) return; dex_future_disown (bz_run_hook_emission ( hooks, signal, 0, NULL, group)); } bazaar-org-bazaar-43ce9f7/src/bz-window.h000066400000000000000000000033241520414637400203130ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-world-map-parser.c000066400000000000000000000077311520414637400222010ustar00rootroot00000000000000/* 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-country.h" #include "bz-world-map-parser.h" struct _BzWorldMapParser { GObject parent_instance; GListStore *countries; }; G_DEFINE_FINAL_TYPE (BzWorldMapParser, bz_world_map_parser, G_TYPE_OBJECT) static const char *get_translated_name (GVariant *translations, const char *fallback_name); static void bz_world_map_parser_dispose (GObject *object) { BzWorldMapParser *self = BZ_WORLD_MAP_PARSER (object); 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->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); } gboolean bz_world_map_parser_load_from_resource (BzWorldMapParser *self, const char *resource_path, GError **error) { g_autoptr (GBytes) bytes = NULL; g_autoptr (GVariant) data = NULL; GVariantIter iter = { 0 }; const char *name = NULL; const char *iso_code = NULL; GVariant *translations = NULL; GVariant *coordinates = NULL; 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; data = g_variant_new_from_bytes (G_VARIANT_TYPE ("a(ssa{ss}aaa(dd))"), bytes, TRUE); g_list_store_remove_all (self->countries); g_variant_iter_init (&iter, data); while (g_variant_iter_next (&iter, "(&s&s@a{ss}@aaa(dd))", &name, &iso_code, &translations, &coordinates)) { g_autoptr (BzCountry) country = NULL; const char *display_name = NULL; display_name = get_translated_name (translations, 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); g_variant_unref (translations); g_variant_unref (coordinates); } 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); } static const char * get_translated_name (GVariant *translations, const char *fallback_name) { const char *const *language_names = NULL; language_names = g_get_language_names (); for (guint i = 0; language_names[i] != NULL; i++) { const char *translated = NULL; if (g_variant_lookup (translations, language_names[i], "&s", &translated)) return translated; } return fallback_name; } bazaar-org-bazaar-43ce9f7/src/bz-world-map-parser.h000066400000000000000000000025751520414637400222070ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-world-map.c000066400000000000000000000540611520414637400207050ustar00rootroot00000000000000/* 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 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; int last_width; int last_height; 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++) { g_autoptr (BzCountry) country = g_list_model_get_item (self->countries, i); GVariant *coordinates = bz_country_get_coordinates (country); GVariantIter poly_iter, ring_iter, point_iter; GVariant *polygon = NULL; GVariant *ring = NULL; double lon, lat; if (coordinates == NULL) continue; g_variant_iter_init (&poly_iter, coordinates); while ((polygon = g_variant_iter_next_value (&poly_iter))) { g_variant_iter_init (&ring_iter, polygon); while ((ring = g_variant_iter_next_value (&ring_iter))) { g_variant_iter_init (&point_iter, ring); while (g_variant_iter_next (&point_iter, "(dd)", &lon, &lat)) { 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_clear_pointer (&ring, g_variant_unref); } g_clear_pointer (&polygon, g_variant_unref); } } } 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_clear_pointer (&self->country_paths, g_free); } g_clear_pointer (&self->path_to_country, g_free); n_items = g_list_model_get_n_items (self->countries); self->n_paths = 0; for (guint i = 0; i < n_items; i++) { g_autoptr (BzCountry) country = NULL; GVariant *coordinates = NULL; GVariantIter poly_iter = { 0 }; GVariant *polygon = NULL; country = g_list_model_get_item (self->countries, i); coordinates = bz_country_get_coordinates (country); if (coordinates == NULL) continue; g_variant_iter_init (&poly_iter, coordinates); while ((polygon = g_variant_iter_next_value (&poly_iter))) { self->n_paths += g_variant_n_children (polygon); g_clear_pointer (&polygon, g_variant_unref); } } 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++) { g_autoptr (BzCountry) country = NULL; GVariant *coordinates = NULL; GVariantIter poly_iter = { 0 }; GVariant *polygon = NULL; country = g_list_model_get_item (self->countries, i); coordinates = bz_country_get_coordinates (country); if (coordinates == NULL) continue; g_variant_iter_init (&poly_iter, coordinates); while ((polygon = g_variant_iter_next_value (&poly_iter))) { GVariantIter ring_iter = { 0 }; GVariant *ring = NULL; g_variant_iter_init (&ring_iter, polygon); while ((ring = g_variant_iter_next_value (&ring_iter))) { g_autoptr (GskPathBuilder) builder = NULL; GVariantIter point_iter = { 0 }; double lon = 0.0; double lat = 0.0; gboolean first = TRUE; builder = gsk_path_builder_new (); g_variant_iter_init (&point_iter, ring); while (g_variant_iter_next (&point_iter, "(dd)", &lon, &lat)) { 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_clear_pointer (&ring, g_variant_unref); } g_clear_pointer (&polygon, g_variant_unref); } } 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); if (width == self->last_width && height == self->last_height) return; self->last_width = width; self->last_height = height; 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); /* Translators: As in, "1 Install" / "100 Installs" */ gtk_label_set_text (GTK_LABEL (self->tooltip_prefix_label), ngettext ("Install", "Installs", download_number)); 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 (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); } } 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.gvariant", &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); } bazaar-org-bazaar-43ce9f7/src/bz-world-map.h000066400000000000000000000021621520414637400207050ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-yaml-parser.c000066400000000000000000001222031520414637400212310ustar00rootroot00000000000000/* 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 (); } } bazaar-org-bazaar-43ce9f7/src/bz-yaml-parser.h000066400000000000000000000023321520414637400212360ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/bz-zoom.c000066400000000000000000000473361520414637400177760ustar00rootroot00000000000000/* 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 (!bz_zoom_is_transformed(self)) { 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, 1, 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 = 1.0; 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]); } gboolean bz_zoom_is_transformed (BzZoom *self) { g_return_val_if_fail (BZ_IS_ZOOM (self), FALSE); return fabs (self->zoom_level - 1.0) >= 0.001 || fabs (self->pan_x) >= 0.5 || fabs (self->pan_y) >= 0.5; } double bz_zoom_get_min_zoom (BzZoom *self) { g_return_val_if_fail (BZ_IS_ZOOM (self), 1); 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 */ bazaar-org-bazaar-43ce9f7/src/bz-zoom.h000066400000000000000000000032631520414637400177720ustar00rootroot00000000000000/* 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); gboolean bz_zoom_is_transformed (BzZoom *self); 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 bazaar-org-bazaar-43ce9f7/src/curated-config-schema.xml000066400000000000000000000007321520414637400230740ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/dl-worker.c000066400000000000000000000130141520414637400202710ustar00rootroot00000000000000/* 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 (); } bazaar-org-bazaar-43ce9f7/src/gen_gobject.sh000077500000000000000000000476631520414637400210450ustar00rootroot00000000000000#!/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) if [ "$TAKE" = take ]; then printf '%s != NULL && self->%s != NULL && g_strcmp0(%s, self->%s) == 0' "$LOC_NAME" "$LOC_NAME" "$LOC_NAME" "$LOC_NAME" else 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" fi ;; *) printf '%s == self->%s' "$LOC_NAME" "$LOC_NAME" ;; esac if [ "$TAKE" = take ]; then printf '){\n ' case "$LOC_PTYPE" in char|uchar|boolean|int|uint|long|ulong|int64|uint64|unichar|enum|flags|float|double) ;; *) if [ -n "$LOC_FREE" ]; then printf "$LOC_FREE" else case "$LOC_PTYPE" in string) printf 'g_free' ;; *) printf 'g_object_unref' ;; esac fi printf ' (%s);\n' "$LOC_NAME" ;; esac printf ' return;\n }\n\n' else printf ')\n return;\n\n' fi 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 if [ "$TAKE" = take ]; then printf ' self->%s = %s' "$LOC_NAME" "$LOC_NAME" else 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 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) $(print_set_property_methods header take) 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) $(print_set_property_methods '' take) /* End of $C_FILE */ EOF exit 0 bazaar-org-bazaar-43ce9f7/src/icons/000077500000000000000000000000001520414637400173335ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Adwaita.svg000066400000000000000000000005621520414637400261740ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Audiovideo.svg000066400000000000000000000352101520414637400267100ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Create.svg000066400000000000000000000145341520414637400260310ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Develop.svg000066400000000000000000000053621520414637400262230ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Kde.svg000066400000000000000000000030641520414637400253250ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Learn.svg000066400000000000000000000225301520414637400256620ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Mobile.svg000066400000000000000000000255131520414637400260340ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Network.svg000066400000000000000000000057551520414637400262640ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.New.svg000066400000000000000000000050101520414637400253440ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Play.svg000066400000000000000000000141651520414637400255330ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Popular.svg000066400000000000000000000075121520414637400262460ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Science.svg000066400000000000000000000566261520414637400262070ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.System.svg000066400000000000000000000164001520414637400261040ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Trending.svg000066400000000000000000000300621520414637400263720ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Updated.svg000066400000000000000000000032311520414637400262040ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Utilities.svg000066400000000000000000000135561520414637400266040ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolumni.Bazaar.Work.svg000066400000000000000000000204541520414637400255460ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolunmi.Bazaar.github.svg000066400000000000000000000027731520414637400261120ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolunmi.Bazaar.gitlab.svg000066400000000000000000000040351520414637400260630ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolunmi.Bazaar.gnome.svg000066400000000000000000000024111520414637400257220ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolunmi.Bazaar.google.svg000066400000000000000000000026351520414637400261010ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/io.github.kolunmi.Bazaar.kde.svg000066400000000000000000000034171520414637400253670ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/000077500000000000000000000000001520414637400211015ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/000077500000000000000000000000001520414637400225415ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/app-installed-symbolic.svg000066400000000000000000000014351520414637400276410ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/app-safety-ok-symbolic.svg000066400000000000000000000012551520414637400275640ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/app-safety-unknown-symbolic.svg000066400000000000000000000025621520414637400306540ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/app-safety-unsafe-symbolic.svg000066400000000000000000000015611520414637400304340ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/auditable-code-symbolic.svg000066400000000000000000000024221520414637400277430ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/bookmark-filled-symbolic.svg000066400000000000000000000007471520414637400301530ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/bookmark-outline-symbolic.svg000066400000000000000000000012471520414637400303670ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/bug-symbolic.svg000066400000000000000000000035141520414637400256610ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/check-plain-symbolic.svg000066400000000000000000000013361520414637400272620ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/circle-filled-symbolic.svg000066400000000000000000000004051520414637400275760ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/code-symbolic.svg000066400000000000000000000014061520414637400260140ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/community-symbolic.svg000066400000000000000000000026251520414637400271320ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/connected-squares-x-symbolic.svg000066400000000000000000000022541520414637400307740ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/copy-symbolic.svg000066400000000000000000000013671520414637400260620ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/cross-large-circle-filled-symbolic.svg000066400000000000000000000016201520414637400320150ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/delay-symbolic.svg000066400000000000000000000021601520414637400261760ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/device-support-adaptive-symbolic.svg000066400000000000000000000015401520414637400316450ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/device-support-desktop-symbolic.svg000066400000000000000000000010371520414637400315220ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/device-support-touch-symbolic.svg000066400000000000000000000021201520414637400311650ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/device-supported-symbolic.svg000066400000000000000000000015501520414637400303640ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/download-plus-symbolic.svg000066400000000000000000000034401520414637400276720ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/drive-harddisk-symbolic.svg000066400000000000000000000012141520414637400277770ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/earth-symbolic.svg000066400000000000000000000043301520414637400262040ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/edit-clear-all-symbolic.svg000066400000000000000000000023131520414637400276570ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/execute-to-symbolic.svg000066400000000000000000000006221520414637400271630ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/explore-symbolic.svg000066400000000000000000000021241520414637400265560ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/external-link-symbolic.svg000066400000000000000000000024241520414637400276600ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/eye-outline-filled-symbolic.svg000066400000000000000000000015401520414637400305750ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/flathub-symbolic.svg000066400000000000000000000037161520414637400265350ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/flatpak-symbolic.svg000066400000000000000000000013241520414637400265230ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/folder-download-symbolic.svg000066400000000000000000000011661520414637400301650ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/globe-symbolic.svg000066400000000000000000000052701520414637400261750ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/go-previous-symbolic.svg000066400000000000000000000011761520414637400273650ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/graph2-symbolic.svg000066400000000000000000000010761520414637400262700ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/hand-openyay-symbolic.svg000066400000000000000000000014161520414637400274770ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/heart-filled-symbolic.svg000066400000000000000000000011251520414637400274400ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/heart-outline-thick-symbolic.svg000066400000000000000000000023271520414637400307650ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/horizontal-arrows-disabled-symbolic.svg000066400000000000000000000026451520414637400323610ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/image-missing-symbolic.svg000066400000000000000000000015221520414637400276320ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/left-large-symbolic.svg000066400000000000000000000007431520414637400271270ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/library-symbolic.svg000066400000000000000000000021101520414637400265370ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/license-symbolic.svg000066400000000000000000000056411520414637400265310ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/media-playback-pause-symbolic.svg000066400000000000000000000010071520414637400310550ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/media-playback-start-symbolic.svg000066400000000000000000000010521520414637400310750ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/media-playback-stop-symbolic.svg000066400000000000000000000005311520414637400307260ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/meeting-symbolic.svg000066400000000000000000000010701520414637400265270ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/newspaper-symbolic.svg000066400000000000000000000015301520414637400271040ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/on-the-go-symbolic.svg000066400000000000000000000103371520414637400267020ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/open-book-symbolic.svg000066400000000000000000000022271520414637400267750ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/paintbrush-symbolic.svg000066400000000000000000000010671520414637400272640ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/parent-symbolic.svg000066400000000000000000000025761520414637400264040ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/people-symbolic.svg000066400000000000000000000015511520414637400263670ustar00rootroot00000000000000 permissions-legacy-windowing-system-symbolic.svg000066400000000000000000000012521520414637400341640ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/permissions-microphone-symbolic.svg000066400000000000000000000007511520414637400316200ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/permissions-sandboxed-symbolic.svg000066400000000000000000000022121520414637400314160ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/permissions-screen-contents-symbolic.svg000066400000000000000000000010631520414637400325640ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/permissions-system-devices-symbolic.svg000066400000000000000000000021471520414637400324220ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/permissions-warning-symbolic.svg000066400000000000000000000015611520414637400311220ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/person-symbolic.svg000066400000000000000000000006021520414637400264050ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/pip-out-symbolic.svg000066400000000000000000000017071520414637400265030ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/power-profile-performance-symbolic.svg000066400000000000000000000022631520414637400321750ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/proprietary-code-symbolic.svg000066400000000000000000000024131520414637400303710ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/puzzle-piece-symbolic.svg000066400000000000000000000012031520414637400275110ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/000077500000000000000000000000001520414637400242105ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/advertising-none-symbolic.svg000066400000000000000000000015721520414637400320310ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/advertising-symbolic.svg000066400000000000000000000016051520414637400310710ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/alcohol-use-none-symbolic.svg000066400000000000000000000013371520414637400317240ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/alcohol-use-symbolic.svg000066400000000000000000000012471520414637400307670ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/audio-chat-none-symbolic.svg000066400000000000000000000011521520414637400315220ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/audio-chat-symbolic.svg000066400000000000000000000007511520414637400305710ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/contacts-symbolic.svg000066400000000000000000000020201520414637400303600ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/drug-use-none-symbolic.svg000066400000000000000000000017011520414637400312370ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/drug-use-symbolic.svg000066400000000000000000000015261520414637400303070ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/gambling-none-symbolic.svg000066400000000000000000000010271520414637400312650ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/gambling-symbolic.svg000066400000000000000000000007501520414637400303320ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/human-remains-symbolic.svg000066400000000000000000000006141520414637400313150ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/messaging-none-symbolic.svg000066400000000000000000000010051520414637400314560ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/messaging-symbolic.svg000066400000000000000000000006561520414637400305340ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/money-none-symbolic.svg000066400000000000000000000011461520414637400306360ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/money-symbolic.svg000066400000000000000000000007621520414637400277040ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/nudity-none-symbolic.svg000066400000000000000000000013101520414637400310140ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/nudity-symbolic.svg000066400000000000000000000007601520414637400300670ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/smoking-none-symbolic.svg000066400000000000000000000007431520414637400311600ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/smoking-symbolic.svg000066400000000000000000000006551520414637400302250ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/social-info-symbolic.svg000066400000000000000000000017551520414637400307630ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/strong-language-none-symbolic.svg000066400000000000000000000006571520414637400326120ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/strong-language-symbolic.svg000066400000000000000000000005371520414637400316520ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/violence-none-symbolic.svg000066400000000000000000000010171520414637400313100ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/ratings/violence-symbolic.svg000066400000000000000000000005511520414637400303550ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/regex-symbolic.svg000066400000000000000000000011721520414637400262140ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/right-large-symbolic.svg000066400000000000000000000007441520414637400273130ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/sad-computer-symbolic.svg000066400000000000000000000022241520414637400275040ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/school-symbolic.svg000066400000000000000000000020131520414637400263640ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/server-pick-symbolic.svg000066400000000000000000000016521520414637400273370ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/share-alt-symbolic.svg000066400000000000000000000015711520414637400267650ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/share-symbolic.svg000066400000000000000000000021751520414637400262100ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/sidebar-show-symbolic.svg000066400000000000000000000011421520414637400274660ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/sliders-horizontal-symbolic.svg000066400000000000000000000017671520414637400307500ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/smartphone2-symbolic.svg000066400000000000000000000010161520414637400273410ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/software-update-available-symbolic.svg000066400000000000000000000021511520414637400321300ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/square-filled-symbolic.svg000066400000000000000000000004761520414637400276450ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/starred-symbolic.svg000066400000000000000000000013171520414637400265470ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/thumbs-up-outline-symbolic.svg000066400000000000000000000032701520414637400305040ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/timer-sand-symbolic.svg000066400000000000000000000010571520414637400271470ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/translations-symbolic.svg000066400000000000000000000012061520414637400276210ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/user-trash-symbolic.svg000066400000000000000000000020501520414637400271730ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/verified-checkmark-symbolic.svg000066400000000000000000000030611520414637400306240ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/view-more-horizontal-symbolic.svg000066400000000000000000000010271520414637400312020ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/view-more-symbolic.svg000066400000000000000000000007631520414637400270210ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/we-love-games-symbolic.svg000066400000000000000000000171351520414637400275600ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/zoom-minus-symbolic.svg000066400000000000000000000013371520414637400272220ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/icons/scalable/actions/zoom-plus-symbolic.svg000066400000000000000000000014031520414637400270440ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/internal-config-schema.xml000066400000000000000000000003211520414637400232530ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/internal-config.yaml000066400000000000000000000032171520414637400221660ustar00rootroot00000000000000search-biases: # Brief regex review: # `^` indicates the beginning of the string # `$` indicates the end of the string # `\b` indicates a word boundary # `(?i)` means case insensitive - regex: ^(?i)browser$ convert-to: web browser boost-appids: - app.zen_browser.zen - io.github.ungoogled_software.ungoogled_chromium - org.chromium.Chromium - org.gnome.Epiphany - org.kde.falkon - org.mozilla.firefox - org.torproject.torbrowser-launcher linear-boost: slope: 1.333 y-intercept: 40.0 - regex: \b(?i)vm\b convert-to: virtual machine boost-appids: - org.virt_manager.virt-manager - org.gnome.Boxes linear-boost: slope: 1.0 y-intercept: 50.0 - regex: \b(?i)ide\b convert-to: develop boost-appids: - com.visualstudio.code - com.vscodium.codium - dev.zed.Zed - org.gnome.Builder - org.kde.kdevelop linear-boost: slope: 1.0 y-intercept: 10.0 - regex: \b(?i)daw\b boost-appids: # these don't normally show, despite being DAWs - fm.reaper.Reaper - io.lmms.LMMS linear-boost: slope: 1.0 y-intercept: 20.0 - regex: \b(?i)photoshop\b boost-appids: - org.gimp.GIMP linear-boost: slope: 1.0 y-intercept: 20.0 - regex: \b(?i)illustrator\b boost-appids: - org.inkscape.Inkscape linear-boost: slope: 1.0 y-intercept: 20.0 - regex: \b(?i)dl\b convert-to: download - regex: \b(?i)yt\b convert-to: youtube - regex: \b(?i)vids?\b convert-to: video - regex: \b(?i)mc\b convert-to: minecraft bazaar-org-bazaar-43ce9f7/src/main-config-schema.xml000066400000000000000000000011661520414637400223730ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/main.c000066400000000000000000000034311520414637400173110ustar00rootroot00000000000000/* 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 #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_VCS_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); /* Init Bazaar GTK Extensions */ bge_init (); 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; } bazaar-org-bazaar-43ce9f7/src/meson.build000066400000000000000000000233261520414637400203700ustar00rootroot00000000000000math = cc.find_library('m', required: false) xmllint = find_program('xmllint', required: true) gtk_dep = dependency('gtk4', version: '>= 4.22.1') 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') webkit_dep = dependency('webkitgtk-6.0', version: '>= 2.50.2') libsecret_dep = dependency('libsecret-1', version: '>= 0.20') libproxy_dep = dependency('libproxy-1.0', version: '>= 0.5') malcontent_dep = dependency('malcontent-0', version: '>= 0.12.0') gtksourceview_dep = dependency('gtksourceview-5', version: '>= 5.17') dl_worker_sources = [ 'bz-env.c', 'bz-global-net.c', 'dl-worker.c', ] dl_worker_deps = [ math, libdex_dep, libsoup_dep, json_glib_dep, libproxy_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-addon-tile.c', 'bz-addons-dialog.c', 'bz-age-rating-dialog.c', 'bz-all-apps-page.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-bundle-install-dialog.c', 'bz-category-flags.c', 'bz-category-tile.c', 'bz-content-provider.c', 'bz-context-row.c', 'bz-context-tile-callbacks.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-donations-dialog.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-dialog.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-gnome-shell-search-provider.c', 'bz-group-tile-css-watcher.c', 'bz-hardware-support-dialog.c', 'bz-hooks.c', 'bz-inspector.c', 'bz-install-controls.c', 'bz-installed-tile.c', 'bz-io.c', 'bz-library-page.c', 'bz-license-dialog.c', 'bz-list-tile.c', 'bz-login-page.c', 'bz-lozenge.c', 'bz-malcontent-service.c', 'bz-metainfo-preview.c', 'bz-newline-parser.c', 'bz-parser.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-filter-popover.c', 'bz-search-page.c', 'bz-search-pill-list.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-transact-icon.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-window.c', 'bz-world-map-parser.c', 'bz-world-map.c', 'bz-yaml-parser.c', 'bz-zoom.c', ) subdir('progress-bar-designs') bz_deps = [ # Bazaar GTK Extensions; see ../bge/ bge_dep, 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, webkit_dep, libsecret_dep, libproxy_dep, malcontent_dep, gtksourceview_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-exponential-function.txt', 'bz-finished-search-query.txt', 'bz-flathub-auth-provider.txt', 'bz-flathub-sub-category.txt', 'bz-flatpak-repo.txt', 'bz-flatpak-bundle-result.txt', 'bz-hash-table-object.txt', 'bz-hook-dialog-option.txt', 'bz-hook-dialog.txt', 'bz-hook.txt', 'bz-internal-config.txt', 'bz-linear-function.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-bias.txt', 'bz-search-result.txt', 'bz-size-result.txt', 'bz-state-info.txt', 'bz-transact-icon-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-addon-tile.blp', 'bz-addons-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-bundle-install-dialog.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-donations-dialog.blp', 'bz-entry-inspector.blp', 'bz-entry-selection-row.blp', 'bz-error-dialog.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-install-controls.blp', 'bz-installed-tile.blp', 'bz-library-page.blp', 'bz-license-dialog.blp', 'bz-login-page.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-filter-popover.blp', 'bz-search-page.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-window.blp', 'shortcuts-dialog.blp', ), output: '.', command: [ find_program('blueprint-compiler', version: '>= 0.20.0'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@' ], ) release_notes = custom_target('release-notes.xml', output: 'release-notes.xml', input: meson.project_source_root() / 'data' / 'io.github.kolunmi.Bazaar.metainfo.xml.in', command: [ 'sh', '-c', xmllint.full_path() + ' --xpath "//releases/release[1]" "$1" > "$2"', '--', '@INPUT@', '@OUTPUT@', ], ) countries_gvariant = custom_target( 'countries-gvariant', input: files('../scripts/countries.json.in'), output: 'countries.gvariant', command: [ python3, meson.project_source_root() / 'scripts' / 'countries.py', '@INPUT@', meson.project_source_root() / 'po' / 'LINGUAS', '@OUTPUT@', ], ) bz_sources += gnome.compile_resources('bz-resources', 'bazaar.gresource.xml', c_name: 'bz', source_dir: meson.current_build_dir(), dependencies: [blueprints, release_notes, countries_gvariant], ) executable('bazaar', bz_sources + ['main.c'], gdbus_src, marshalers, dependencies: bz_deps, install: true, ) executable(refresh_worker_bin_name, bz_sources + ['refresh-worker.c'], gdbus_src, marshalers, dependencies: bz_deps, install: true, ) bazaar-org-bazaar-43ce9f7/src/pride-flag-config-schema.xml000066400000000000000000000003201520414637400234500ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/progress-bar-designs/000077500000000000000000000000001520414637400222605ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/src/progress-bar-designs/common.h000066400000000000000000000014421520414637400237220ustar00rootroot00000000000000/* 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" bazaar-org-bazaar-43ce9f7/src/progress-bar-designs/meson.build000066400000000000000000000000201520414637400244120ustar00rootroot00000000000000subdir('pride') bazaar-org-bazaar-43ce9f7/src/progress-bar-designs/pride/000077500000000000000000000000001520414637400233635ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/src/progress-bar-designs/pride/meson.build000066400000000000000000000000441520414637400255230ustar00rootroot00000000000000bz_sources += files( 'pride.c', ) bazaar-org-bazaar-43ce9f7/src/progress-bar-designs/pride/pride-flags.yaml000066400000000000000000000162151520414637400264510ustar00rootroot00000000000000flag-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)" bazaar-org-bazaar-43ce9f7/src/progress-bar-designs/pride/pride.c000066400000000000000000000177731520414637400246510ustar00rootroot00000000000000/* 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); } bazaar-org-bazaar-43ce9f7/src/progress-bar-designs/pride/pride.h000066400000000000000000000016571520414637400246500ustar00rootroot00000000000000/* 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 bazaar-org-bazaar-43ce9f7/src/refresh-worker.c000066400000000000000000000114151520414637400213330ustar00rootroot00000000000000/* refresh-worker.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::REFRESH-WORKER" #include "bz-backend-notification.h" #include "bz-backend.h" #include "bz-entry-cache-manager.h" #include "bz-env.h" #include "bz-flatpak-instance.h" #include "bz-util.h" BZ_DEFINE_DATA ( main, Main, { GMainLoop *loop; GIOChannel *stdout_channel; int rv; }, BZ_RELEASE_DATA (loop, g_main_loop_unref); BZ_RELEASE_DATA (stdout_channel, g_io_channel_unref)); static DexFuture * run (MainData *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); data->rv = EXIT_SUCCESS; future = dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) run, main_data_ref (data), main_data_unref); g_main_loop_run (main_loop); return data->rv; } static DexFuture * run (MainData *data) { gboolean result = FALSE; g_autoptr (GError) local_error = NULL; g_autoptr (BzEntryCacheManager) cache = NULL; g_autoptr (BzFlatpakInstance) flatpak = NULL; g_autoptr (DexChannel) channel = NULL; g_autoptr (GHashTable) installed_set = NULL; g_autoptr (DexFuture) all_notifs = NULL; guint n_notifs = 0; g_autoptr (GPtrArray) write_backs = NULL; cache = bz_entry_cache_manager_new (); flatpak = dex_await_object ( bz_flatpak_instance_new (), &local_error); if (flatpak == NULL) goto err; channel = bz_backend_create_notification_channel (BZ_BACKEND (flatpak)); if (channel == NULL) goto err; result = dex_await ( bz_backend_retrieve_remote_entries ( BZ_BACKEND (flatpak), NULL), &local_error); if (!result) goto err; installed_set = dex_await_boxed ( bz_backend_retrieve_install_ids ( BZ_BACKEND (flatpak), NULL), &local_error); if (installed_set == NULL) goto err; all_notifs = dex_channel_receive_all (channel); n_notifs = dex_future_set_get_size (DEX_FUTURE_SET (all_notifs)); write_backs = g_ptr_array_new_with_free_func (dex_unref); for (guint i = 0; i < n_notifs; i++) { DexFuture *future = NULL; g_autoptr (BzBackendNotification) notif = NULL; BzBackendNotificationKind kind = 0; future = dex_future_set_get_future_at ( DEX_FUTURE_SET (all_notifs), i); notif = dex_await_object (dex_ref (future), NULL); if (notif == NULL) continue; kind = bz_backend_notification_get_kind (notif); if (kind == BZ_BACKEND_NOTIFICATION_KIND_REPLACE_ENTRY) { BzEntry *entry = NULL; const char *unique_id = NULL; entry = bz_backend_notification_get_entry (notif); unique_id = bz_entry_get_unique_id (entry); bz_entry_set_installed (entry, g_hash_table_contains (installed_set, unique_id)); g_ptr_array_add ( write_backs, bz_entry_cache_manager_add (cache, entry)); } } if (write_backs->len > 0) dex_await ( dex_future_allv ( (DexFuture *const *) write_backs->pdata, write_backs->len), NULL); data->rv = EXIT_SUCCESS; g_main_loop_quit (data->loop); return dex_future_new_true (); err: if (local_error != NULL) g_critical ("Unable to complete refresh: %s", local_error->message); data->rv = EXIT_FAILURE; g_main_loop_quit (data->loop); return dex_future_new_false (); } bazaar-org-bazaar-43ce9f7/src/release-notes.xml.in000066400000000000000000000000001520414637400221030ustar00rootroot00000000000000bazaar-org-bazaar-43ce9f7/src/shell-search-provider-dbus-interfaces.xml000066400000000000000000000035031520414637400262210ustar00rootroot00000000000000 bazaar-org-bazaar-43ce9f7/src/shortcuts-dialog.blp000066400000000000000000000026261520414637400222200ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; Adw.ShortcutsDialog shortcuts_dialog { Adw.ShortcutsSection navigation_section { title: C_("shortcut window", "Navigation"); Adw.ShortcutsItem { title: C_("shortcut window", "Open Explore Page"); action-name: "window.open-flathub-page"; accelerator: "e"; } Adw.ShortcutsItem { title: C_("shortcut window", "Open Library Page"); action-name: "window.open-library"; accelerator: "d"; } Adw.ShortcutsItem { title: C_("shortcut window", "Open Search Page"); action-name: "app.search('')"; } } Adw.ShortcutsSection remotes_section { title: C_("shortcut window", "Remotes"); Adw.ShortcutsItem { title: C_("shortcut window", "Sync Remotes"); action-name: "app.sync-remotes"; } } Adw.ShortcutsSection general_section { title: C_("shortcut window", "General"); Adw.ShortcutsItem { title: C_("shortcut window", "Open Preferences"); action-name: "app.preferences"; } Adw.ShortcutsItem { title: C_("shortcut window", "Show Shortcuts"); action-name: "app.shortcuts"; } Adw.ShortcutsItem { title: C_("shortcut window", "Close Window"); action-name: "window.quit"; accelerator: "w"; } Adw.ShortcutsItem { title: C_("shortcut window", "Quit Bazaar"); action-name: "app.quit"; } } }bazaar-org-bazaar-43ce9f7/src/style.css000066400000000000000000000474621520414637400201070ustar00rootroot00000000000000:root { --hc-border: color(srgb 0 0 0.023 / 50%); } @media (prefers-color-scheme: dark) { :root { --hc-border: color(srgb 1 1 1 / 50%); } } .bz-monospace { font-size: smaller; font-family: monospace; } .bz-small-button { padding: 1px; margin: 0; } .bz-small-button > * { margin: 0; padding: 0; } .bz-debug { background: linear-gradient(to top, #ffaf4c, #ffc04c); border-color: black; border-radius: 6px; border-style: solid; border-width: 1px; color: black; padding: 3px; } .bz-debug button { border-color: black; border-style: dashed; border-width: 1px; border-radius: 3px; padding-top: 0px; padding-bottom: 0px; padding-left: 2px; padding-right: 2px; } .bz-donations-dialog { background: linear-gradient(to bottom left, #1f2d8f, #159eff); color: white; } .bz-donations-banner { --banner-color: var(--accent-bg-color); } .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; } @media (prefers-color-scheme: light) { .search-box { background-color: var(--shade-color); } } @media (prefers-contrast: more) { .search-box { box-shadow: inset 0 0 0 1px var(--hc-border); } .search-box:focus-within { box-shadow: none; outline-color: var(--accent-color); } } .search-box > text placeholder { opacity: 0.55; } .searchbar-button, .searchbar-button > button { min-height: 24px; min-width: 24px; } .search-pill { font-weight: 450; } .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; } .app-developer link{ color: @blue_2; text-decoration: none; } .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); } @media (prefers-contrast: more) { .circular-lozenge { box-shadow: inset 0 0 0 1px; } } .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: #323237; background-color: color-mix(in srgb, var(--window-fg-color) 10%, transparent); } @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 { color: @window_fg_color; } } .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; } .flathub-lotion { color: #fafafa; } .flathub-gunmetal { color: #251f32; } @media (prefers-color-scheme: dark) { .flathub { --accent-color: alpha(#fafafa,0.75); --accent-bg-color: #7847b8; } } .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; } @media (prefers-contrast: more) { .small-pill { box-shadow: inset 0 0 0 1px; } .small-pill:focus-within { box-shadow: none; } } .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); } } @media (prefers-contrast: more) { .card.category-tile, .card.app-tile { box-shadow: inset 0 0 0 1px var(--hc-border); } .card.category-tile:focus-within, .card.app-tile :focus-within { box-shadow: none; outline-color: var(--accent-color); } } .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; outline-offset: 2px; } @media (prefers-contrast: more) { .category-tile { box-shadow: none; } } 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.05), shade(#c4f3c9, 1.05)); } .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.13) 30%, shade(#333337, 1.13) 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.05); 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.05) 0%, shade(#deddda, 1.05) 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.15) 0%, shade(#57e289, 1.15) 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; } .installed-section { padding-top: 0; } .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(255, 255, 255, 0.040); 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); } .disable-adw-flow-box-styling { background-color: transparent; box-shadow: none; padding: 0; } curated-list-view, curated-list-view list { background: var(--bg-color); } .install-button-indicator { background: var(--flag-gradient, var(--accent-bg-color)); border-radius: 9999px; } .transact-icon-flag { background: var(--flag-gradient, var(--accent-bg-color)); } bazaar-org-bazaar-43ce9f7/translators.sh000077500000000000000000000074301520414637400203500ustar00rootroot00000000000000#!/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/bazaar-org/bazaar/blob/master/TRANSLATORS.md" echo "--------------------------------" popd || return 1 return 0 } translators_helper || echo 'An error occurred; review the above output' 2>&1 bazaar-org-bazaar-43ce9f7/version.sh000077500000000000000000000010571520414637400174600ustar00rootroot00000000000000#!/bin/sh INSTR="$1" VERSION=0.8.1 case "$INSTR" in get-version) echo "${VERSION}" ;; 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/bazaar-org/bazaar/releases/tag/${TAG}" ;; *) echo invalid arguments 1>&2 exit 1 ;; esac