pax_global_header00006660000000000000000000000064132442450500014511gustar00rootroot0000000000000052 comment=9abdb0e7f2905d16fcc8257682cc3c45f3209b11 flameshot-0.5.1/000077500000000000000000000000001324424505000134765ustar00rootroot00000000000000flameshot-0.5.1/.gitignore000066400000000000000000000005221324424505000154650ustar00rootroot00000000000000# C++ objects and libs *.slo *.lo *.o *.a *.la *.lai *.so *.dll *.dylib # Qt-es /.qmake.cache /.qmake.stash *.pro.user *.pro.user.* *.qbs.user *.qbs.user.* *.moc moc_*.cpp qrc_*.cpp ui_*.h Makefile* *build-* *.qm # QtCreator *.autosave # QtCtreator Qml *.qmlproject.user *.qmlproject.user.* # QtCtreator CMake CMakeLists.txt.user flameshot-0.5.1/.travis.yml000066400000000000000000000060121324424505000156060ustar00rootroot00000000000000dist: trusty sudo: required services: - docker language: cpp branches: only: - master cache: directories: - $HOME/.cache env: global: # Environment variables for packpack - PRODUCT=flameshot - VERSION=0.5.1 - RELEASE=1 - ARCH=x86_64 # - DOCKER_REPO=packpack/packpack - DOCKER_REPO=vitzy/packpack #The actual list of distribution is available on #https://hub.docker.com/r/packpack/packpack/tags/ #https://hub.docker.com/r/vitzy/packpack/tags/ matrix: include: - os: linux env: OS=fedora DIST=26 - os: linux env: OS=fedora DIST=27 - os: linux # trusty: only for build & test & AppImage # 14.04 LTS; Qt version is 5.2.1, flameshot not support env: OS=ubuntu DIST=trusty - os: linux # 16.04 LTS env: OS=ubuntu DIST=xenial - os: linux # 17.10 env: OS=ubuntu DIST=artful - os: linux # 8 env: OS=debian DIST=jessie - os: linux # 9 env: OS=debian DIST=stretch - os: osx compiler: clang osx_image: xcode9.2 before_install: - if [[ "${TRAVIS_OS_NAME}" == "linux" && "${DIST}" == "trusty" ]]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi - if [[ "${TRAVIS_OS_NAME}" == "linux" && "${DIST}" == "trusty" ]]; then sudo apt-get -qq update ; fi before_script: - if [[ "${TRAVIS_OS_NAME}" == "linux" && "${DIST}" == "trusty" ]]; then chmod +x .travis_linux.sh ; fi - if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then chmod +x .travis_macos.sh ; fi install: - if [[ "${TRAVIS_OS_NAME}" == "linux" && "${DIST}" == "trusty" ]]; then sudo apt-get install -qq git; sudo apt-get install -qq build-essential ; fi - if [[ "${TRAVIS_OS_NAME}" == "linux" && "${DIST}" == "trusty" ]]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install openssl libssl-dev ; fi # - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install libgl1-mesa-dev ; fi - if [[ "${TRAVIS_OS_NAME}" == "linux" && "${DIST}" == "trusty" ]]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install tree ; fi - if [[ "${TRAVIS_OS_NAME}" == "linux" && "${DIST}" == "trusty" ]]; then sudo apt-get install -qq gcc-4.9; sudo apt-get install -qq g++-4.9 ; fi - if [[ "${TRAVIS_OS_NAME}" == "linux" && "${DIST}" == "trusty" ]]; then sudo apt-get install -qq git ; fi script: # - git submodule update --init --recursive # - git describe --long - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then bash ./.travis_linux.sh ; fi - if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then bash ./.travis_macos.sh ; fi - pwd && ls # deploy: # # Deploy packages to Github Release # provider: releases # api_key: "GITHUB ENCYPTED OAUTH TOKEN" # file_glob: true # file: dist/*.{deb,rpm,AppImage,dmg} # skip_cleanup: true # on: # tags: true # branch: master flameshot-0.5.1/.travis_linux.sh000066400000000000000000000110661324424505000166430ustar00rootroot00000000000000#!/bin/bash if [[ "${DIST}" != "trusty" ]]; then git clone https://github.com/packpack/packpack.git packpack ; mkdir ./dist ; pwd && ls ; packpack/packpack ; if [ $OS == "ubuntu" ]; then curl --upload-file build/flameshot_*_*.deb "https://transfer.sh/flameshot_$VERSION-$RELEASE_ubuntu_$ARCH.deb" ; # copy deb to dist path for distribution cp build/flameshot_*_*.deb dist/flameshot_$VERSION-$RELEASE_ubuntu_$ARCH.deb ; elif [ $OS == "debian" ]; then curl --upload-file build/flameshot_*_*.deb "https://transfer.sh/flameshot_$VERSION-$RELEASE_debian_$ARCH.deb" ; cp build/flameshot_*_*.deb dist/flameshot_$VERSION-$RELEASE_debian_$ARCH.deb ; elif [ $OS == "fedora" ]; then curl --upload-file build/flameshot-$VERSION-$RELEASE.*.$ARCH.rpm "https://transfer.sh/flameshot_$VERSION-$RELEASE_fedora_$ARCH.rpm" ; cp build/flameshot-$VERSION-$RELEASE.*.$ARCH.rpm dist/flameshot_$VERSION-$RELEASE_fedora_$ARCH.rpm ; else echo ""; fi echo -e "\n" ; pwd && ls ; elif [[ "${DIST}" == "trusty" ]]; then project_dir=$(pwd) DIST_PATH='dist' BUILD_DST_PATH='build-test' APPIMAGE_DST_PATH='build-appimage' # Install qt5.3.2 sudo add-apt-repository ppa:beineri/opt-qt532-trusty -y sudo apt-get update -qq sudo apt-get -y install qt53base qt53tools source /opt/qt53/bin/qt53-env.sh && qmake --version export CC=gcc-4.9 CXX=g++-4.9 # Install fcitx-frontend-qt5 sudo apt-get -y install fcitx-frontend-qt5 mkdir build-test qmake QMAKE_CXX=$CXX QMAKE_CC=$CC QMAKE_LINK=$CXX DESTDIR=$BUILD_DST_PATH # Building flameshot make -j$(nproc) # Running flameshot tests make check -j$(nproc) ls -alhR # # Packaging AppImage using linuxdeployqt # mkdir build-appimage mkdir -p ./build-appimage/appdir/usr/bin mkdir -p ./build-appimage/appdir/usr/share/applications mkdir -p ./build-appimage/appdir/usr/share/dbus-1/interfaces mkdir -p ./build-appimage/appdir/usr/share/dbus-1/services mkdir -p ./build-appimage/appdir/usr/share/metainfo mkdir -p ./build-appimage/appdir/usr/share/bash-completion/completions mkdir -p ./build-appimage/appdir/usr/share/flameshot/translations cp $BUILD_DST_PATH/flameshot $APPIMAGE_DST_PATH/appdir/usr/bin cp ${project_dir}/dbus/org.dharkael.Flameshot.xml $APPIMAGE_DST_PATH/appdir/usr/share/dbus-1/interfaces cp ${project_dir}/dbus/package/org.dharkael.Flameshot.service $APPIMAGE_DST_PATH/appdir/usr/share/dbus-1/services cp ${project_dir}/docs/appdata/flameshot.appdata.xml $APPIMAGE_DST_PATH/appdir/usr/share/metainfo cp ${project_dir}/docs/bash-completion/flameshot $APPIMAGE_DST_PATH/appdir/usr/share/bash-completion/completions cp ${project_dir}/translations/*.qm $APPIMAGE_DST_PATH/appdir/usr/share/flameshot/translations cp ${project_dir}/docs/desktopEntry/package/* $APPIMAGE_DST_PATH/appdir/usr/share/applications cp ${project_dir}/img/flameshot.png $APPIMAGE_DST_PATH/appdir ls -alhR $APPIMAGE_DST_PATH/appdir # Copy other project files cp "${project_dir}/README.md" "$APPIMAGE_DST_PATH/appdir/README.md" cp "${project_dir}/LICENSE" "$APPIMAGE_DST_PATH/appdir/LICENSE" echo ${VERSION} > ./$APPIMAGE_DST_PATH/appdir/version echo "${TRAVIS_COMMIT}" >> ./$APPIMAGE_DST_PATH/appdir/version # Configure env vars unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH tree $APPIMAGE_DST_PATH/appdir # Get linuxdeployqt tool wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" -O linuxdeployqt chmod +x linuxdeployqt # Packaging # -verbose=2 ./linuxdeployqt $APPIMAGE_DST_PATH/appdir/usr/bin/flameshot -bundle-non-qt-libs rm -f $APPIMAGE_DST_PATH/appdir/usr/lib/libatk-1.0.so.0 cp /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so $APPIMAGE_DST_PATH/appdir/usr/plugins/platforminputcontexts/ cd $APPIMAGE_DST_PATH/appdir/usr/bin ln -sf ../plugins/platforms/ . # An unknown bug cd ${project_dir} # -verbose=2 ./linuxdeployqt $APPIMAGE_DST_PATH/appdir/usr/share/applications/flameshot.desktop -appimage ls -alhR ./*.AppImage cp *.AppImage $APPIMAGE_DST_PATH/ tree $APPIMAGE_DST_PATH/ ls -l $APPIMAGE_DST_PATH/*.AppImage mkdir dist # Rename AppImage and move AppImage to DIST_PATH cd $APPIMAGE_DST_PATH && mv Take_graphical_screenshot-${VERSION}-x86_64.AppImage flameshot_x86_64_${VERSION}.AppImage cd .. && cp $APPIMAGE_DST_PATH/flameshot_x86_64_${VERSION}.AppImage $DIST_PATH/flameshot_x86_64_${VERSION}.AppImage pwd curl --upload-file $DIST_PATH/flameshot_x86_64_${VERSION}.AppImage "https://transfer.sh/flameshot_x86_64_${VERSION}.AppImage" ; exit 0 ; else echo "" ; fi flameshot-0.5.1/.travis_macos.sh000066400000000000000000000024051324424505000166030ustar00rootroot00000000000000#!/bin/bash project_dir=$(pwd) brew update > /dev/null brew install qt QTDIR="/usr/local/opt/qt" PATH="$QTDIR/bin:$PATH" LDFLAGS=-L$QTDIR/lib CPPFLAGS=-I$QTDIR/include # Build your app cd ${project_dir} mkdir dist mkdir build cd build qmake -version qmake CONFIG-=debug CONFIG+=release CONFIG+=packaging ../flameshot.pro make -j$(nproc) git clone https://github.com/aurelien-rainone/macdeployqtfix.git pwd && ls ls /Users/travis/build/ZetaoYang/flameshot # Package DMG from build/flamshot.app directory $QTDIR/bin/macdeployqt flameshot.app python ${project_dir}/build/macdeployqtfix/macdeployqtfix.py flameshot.app/Contents/MacOS/flameshot $QTDIR cd ${project_dir}/build mkdir -p distrib/Flameshot cd distrib/Flameshot mv ${project_dir}/build/flameshot.app ${project_dir}/build/distrib/Flameshot/ cp "${project_dir}/LICENSE" "LICENSE" cp "${project_dir}/README.md" "README.md" echo ${VERSION} > version echo "${TRAVIS_COMMIT}" >> version ln -s /Applications ./Applications cd .. hdiutil create -srcfolder ./Flameshot -format UDBZ ./flameshot.dmg mv flameshot.dmg flameshot_X64_$VERSION.dmg mv flameshot_X64_$VERSION.dmg ${project_dir}/dist/flameshot_X64_$VERSION.dmg curl --upload-file ./flameshot_X64_$VERSION.dmg "https://transfer.sh/flameshot_X64_$VERSION.dmg" cd .. exit 0flameshot-0.5.1/LICENSE000066400000000000000000001045051324424505000145100ustar00rootroot00000000000000 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. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 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: {project} Copyright (C) {year} {fullname} 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 . flameshot-0.5.1/README.md000066400000000000000000000254001324424505000147560ustar00rootroot00000000000000# Flameshot ![image](./img/flameshot.png) > Powerful yet simple to use screenshot software. [![Build Status](https://img.shields.io/travis/lupoDharkael/flameshot.svg)](https://travis-ci.org/lupoDharkael/flameshot) [![Build status](https://ci.appveyor.com/api/projects/status/github/lupoDharkael/flameshot?svg=true)](https://ci.appveyor.com/project/lupoDharkael/flameshot) [![License](https://img.shields.io/github/license/lupoDharkael/flameshot.svg)](https://github.com/lupoDharkael/flameshot/blob/master/LICENSE) [![Release](https://img.shields.io/github/release/lupoDharkael/flameshot.svg)](https://github.com/lupoDharkael/flameshot/releases) ## Usage Preview ![image](./img/appPreview/animatedUsage.gif) ## Index - [Features](#features) - [Usage](#usage) - [Keyboard Shortcuts](#keyboard-shortcuts) - [Considerations](#considerations) - [Installation](#installation) - [Compilation](#compilation) - [Debian](#debian) - [Fedora](#fedora) - [Arch](#arch) - [Install](#install) - [Packaging](#packaging) - [License](#license) - [Donations](#donations) ## Features - Customizable appearance. - Easy to use. - In-app screenshot edition. - DBus interface. - Upload to Imgur. ## Usage Example commands: - capture with GUI: `flameshot gui` - capture with GUI with custom save path: `flameshot gui -p ~/myStuff/captures` - open GUI with a delay of 2 seconds: `flameshot gui -d 2000` - fullscreen capture (asking savepath): `flameshot full` - fullscreen capture with custom save path (no GUI) and delayed: `flameshot full -p ~/myStuff/captures -d 5000` - fullscreen capture with custom save path copying to clipboard: `flameshot full -c -p ~/myStuff/captures` In case of doubt choose the first or the second command as shortcut in your favorite desktop environment. A systray icon will be in your system's panel while Flameshot is running. Do a right click on the tray icon and you'll see some menu items to open the configuration window and the information window. Check out the information window to see all the available shortcuts in the graphical capture mode. ### CLI configuration You can use the graphical menu to configure Flameshot, but alternatively you can use your terminal or scripts to do so. - open the confguration menu: `flameshot config` - show the initial help message in the capture mode: `flameshot config --showhelp true` - for more information about the available options use the help flag: `flameshot config -h` ## Keyboard shortcuts ### Local These shortcuts are available in GUI mode: | Keys | Description | |--- |--- | | , , , | Move selection 1px | | Shift + , , , | Resize selection 1px | | Esc | Quit capture | | Ctrl + C | Copy to clipboard | | Ctrl + S | Save selection as a file | | Ctrl + Z | Undo the last modification | | Right Click | Show color picker | | Mouse Wheel | Change the tool's thickness | Shift + drag a handler of the selection area: mirror redimension in the opposite handler. ### Global If you want use Flameshot as a default screenshot utility, chanses are you want to launch it using the Prt Sc key. Flameshot doesn't yet offer a fully-automated option to do so, but you can configure your system to do so. #### On KDE Plasma desktop To make configuration easier, there's a [file](docs/shortcuts-config/flameshot-shortcuts-kde) in the repository that more or less automates this process. This file will assign the following keys to the following actions by default: | Keys | Description | |--- |--- | | Prt Sc | Start the Flameshot screenshot tool and take a screenshot | | Ctrl + Prt Sc | Wait for 3 seconds, then start the Flameshot screenshot tool and take a screenshot | | Shift + Prt Sc | Take a full-screen (all monitors) screenshot and save it | | Ctrl + Shift + Prt Sc | Take a full-screen (all monitors) screenshot and copy it to the clipboard | If you don't like the defaults, you can change them manually later. Steps for using the configuration: 1. The configuration file configures shortcuts so that Flameshot automatically saves (without opening the save dialog) screenshots to _~/Pictures/Screenshots_ folder. Make sure you have that folder by running the following command: ``` mkdir -p ~/Pictures/Screenshots ``` (If you don't like the default location, you can skip this step and configure your preferred directory later.) 2. Download the configuration file: ``` cd ~/Desktop; wget https://raw.githubusercontent.com/lupoDharkael/flameshot/master/docs/shortcuts-config/flameshot-shortcuts-kde ``` 3. Go to _System Settings_ → _Shortcuts_ → _Custom Shortcuts_. 4. If there's one, you'll need to disable an entry for Spectacle, the default KDE screenshot utility first because its shortcuts might collide with Flameshot's ones; so, just uncheck the _Spectacle_ entry. 5. Click _Edit_ → _Import..._, navigate to the Desktop folder (or wherever you saved the configuration file) and open the configuration file. 6. Now the Flameshot entry should appear in the list. Click _Apply_ to apply the changes. 7. If you want to change the defaults, you can expand the entry, select the appropriate action and modify it as you wish; the process is pretty mush self-explanatory. ## Considerations - Experimental Gnome Wayland and Plasma Wayland support. - If you are using Gnome you need to install the [TopIcons](https://extensions.gnome.org/extension/1031/topicons/) extension in order to see the systemtray icon. - In order to speed up the first launch of Flameshot (DBus init of the app can be slow), consider starting the application automatically on boot. - Press Enter or Ctrl + C when you are in a capture mode and you don't have an active selection and the whole desktop will be copied to your clipboard! Pressing Ctrl + S will save your capture in a file! Check the [Shortcuts](#shortcuts) for more information. - Execute the command `flameshot` without parameters or use the "Launch Flameshot" desktop entry to launch a running instance of the program without taking actions. ## Installation There are a packages available for a few distros: - [Arch](https://aur.archlinux.org/packages/flameshot/) - [openSUSE](https://software.opensuse.org/package/flameshot) - [Void Linux](https://github.com/voidlinux/void-packages/tree/master/srcpkgs/flameshot) (`xbps-install flameshot`) - [Docker](https://github.com/ManuelLR/docker-flameshot) - Fedora: dnf install flameshot ## Compilation The compilation requires Qt version 5.3 or higher and GCC 4.9.2 or higher. ### Debian Compilation Dependencies: ```` apt install git g++ build-essential qt5-qmake qt5-default qttools5-dev-tools ```` Compilation: run `qmake && make` in the main directory. ### Fedora Compilation Dependencies: ```` dnf install qt5-devel gcc-c++ git qt5-qtbase-devel qt5-linguist ```` Compilation: run `qmake-qt5 && make` in the main directory. ### Arch Compilation Dependencies: ```` pacman -S git qt5-base base-devel qt5-tools ```` Compilation: run `qmake && make` in the main directory. ### Install Simply use `make install` with privileges. ## Packaging In order to generate the makefile installing in `/usr` instead of in `/usr/local` you can use the `packaging` option to generate the proper makefile (`qmake CONFIG+=packaging` instead of just `qmake`). If you want to install in a custom directory you can define the `BASEDIR` variable. **Example**: You want to install Flameshot in ~/myBuilds/test. You would execute the following to do so: `qmake CONFIG+=packaging BASEDIR=~/myBuilds/test && make install` ### Runtime Dependencies **Debian**: ```` libqt5dbus5, libqt5network5, libqt5core5a, libqt5widgets5, libqt5gui5 ```` Optional: ``` openssl, ca-certificates ``` **Fedora**: ```` qt5-qtbase ```` Optional: ``` openssl, ca-certificates ``` **Arch**: ```` qt5-base ```` Optional: ``` openssl, ca-certificates ``` ## License - The main code is licensed under [GPLv3](./LICENSE) - The logo of Flameshot is licensed under [Free Art License v1.3](./img/flameshotLogoLicense.txt) - The button icons are licensed under Apache License 2.0. See: https://github.com/google/material-design-icons - The code at capture/capturewidget.cpp is based on https://github.com/ckaiser/Lightscreen/blob/master/dialogs/areadialog.cpp (GPLv2) - The code at capture/capturewidget.h is based on https://github.com/ckaiser/Lightscreen/blob/master/dialogs/areadialog.h (GPLv2) - I copied a few lines of code from KSnapshot regiongrabber.cpp revision 796531 (LGPL) - Qt-Color-Widgets taken and modified from https://github.com/mbasaglia/Qt-Color-Widgets (see their license and exceptions in the project) (LGPL/GPL) Info: If I take code from your project and that implies a relicense to GPLv3, you can reuse my changes with the original previous license of your project applied. ## Donations I improve Flameshot in my free time because I want to create something good for everyone to use. If you want you can donate some bucks [here](https://www.paypal.me/lupoDharkael). ## Acknowledgment I really appreciate those who have shown interest in the early development process: - [Cosmo](https://github.com/philpem) - [XerTheSquirrel](https://github.com/XerTheSquirrel) - [The members of Sugus GNU/Linux](https://github.com/SUGUS-GNULinux) - ismatori flameshot-0.5.1/appveyor.yml000066400000000000000000000055041324424505000160720ustar00rootroot00000000000000image: Visual Studio 2015 version: 0.5.{build}.0 # Major_Version_Number.Minor_Version_Number.Build_Number.Revision_Number branches: only: - master environment: COMPILER: msvc VSVER: 14 matrix: - QT: C:\Qt\5.9\msvc2015_64 PLATFORM: amd64 - QT: C:\Qt\5.9\msvc2015 PLATFORM: x86 init: - ps: | $version = new-object System.Version $env:APPVEYOR_BUILD_VERSION $packageVersion = "{0}.{1}.{2}" -f $version.Major, $version.Minor, $version.Revision $env:build_number = $version.Build $env:flameshot_version = $packageVersion # scripts that run after cloning repository install: - set PATH=%QT%\bin\;C:\Qt\Tools\QtCreator\bin\;C:\Qt\QtIFW3.0.1\bin\;%PATH% # scripts that run before build before_build: - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %PLATFORM% # After calling vcvarsall.bat, %PLATFORM% will be X64 or x86 - qmake --version - mkdir build - cd build - if "%PLATFORM%" EQU "X64" (qmake -r -spec win32-msvc CONFIG+=x86_64 CONFIG-=debug CONFIG+=release ../flameshot.pro) - if "%PLATFORM%" EQU "x86" (qmake -r -spec win32-msvc CONFIG+=Win32 CONFIG-=debug CONFIG+=release ../flameshot.pro) # custom build scripts build_script: - nmake # scripts that run after build after_build: # Clone OpenSSL DLLs - git clone https://github.com/tamlok/openssl-utils.git openssl-utils.git - mkdir distrib\flameshot - windeployqt.exe --dir .\distrib\flameshot %APPVEYOR_BUILD_FOLDER%\build\release\flameshot.exe - copy "%APPVEYOR_BUILD_FOLDER%\build\release\flameshot.exe" "distrib\flameshot\flameshot.exe" - copy "%APPVEYOR_BUILD_FOLDER%\README.md" "distrib\flameshot\README.md" - copy "%APPVEYOR_BUILD_FOLDER%\LICENSE" "distrib\flameshot\LICENSE.txt" - echo %flameshot_version% > "distrib\flameshot\version.txt" - echo Build:%build_number% >> "distrib\flameshot\version.txt" - echo %APPVEYOR_REPO_COMMIT% >> "distrib\flameshot\version.txt" - copy "distrib\flameshot\flameshot.exe" "distrib\flameshot_win_%PLATFORM%.exe" # Delete translations\qt_*.qm # - del /F /Q "distrib\flameshot\translations\qt_*.qm" # Copy OpenSSL DLLs - if "%PLATFORM%" EQU "X64" (xcopy "openssl-utils.git\win64\*.dll" "distrib\flameshot") - if "%PLATFORM%" EQU "x86" (xcopy "openssl-utils.git\win32\*.dll" "distrib\flameshot") - cd distrib - 7z a flameshot_win_%PLATFORM%_portable_%flameshot_version%.zip flameshot - curl --upload-file ./flameshot_win_%PLATFORM%_portable_%flameshot_version%.zip https://transfer.sh/flameshot_win_%PLATFORM%_portable_%flameshot_version%.zip # artifacts: # - path: build\distrib\flameshot_win_%PLATFORM%_portable_%flameshot_version%.zip # name: portable # - path: build\distrib\flameshot_win_%PLATFORM%.exe # name: exe_only flameshot-0.5.1/dbus/000077500000000000000000000000001324424505000144335ustar00rootroot00000000000000flameshot-0.5.1/dbus/make/000077500000000000000000000000001324424505000153505ustar00rootroot00000000000000flameshot-0.5.1/dbus/make/org.dharkael.Flameshot.service000066400000000000000000000001121324424505000232060ustar00rootroot00000000000000[D-BUS Service] Name=org.dharkael.Flameshot Exec=/usr/local/bin/flameshot flameshot-0.5.1/dbus/org.dharkael.Flameshot.xml000066400000000000000000000052451324424505000214450ustar00rootroot00000000000000 flameshot-0.5.1/dbus/org.freedesktop.Notifications.xml000066400000000000000000000024441324424505000230720ustar00rootroot00000000000000 flameshot-0.5.1/dbus/other-path/000077500000000000000000000000001324424505000165065ustar00rootroot00000000000000flameshot-0.5.1/dbus/other-path/service-gen.sh000066400000000000000000000004021324424505000212450ustar00rootroot00000000000000#!/usr/bin/bash DIR=$(pwd) TARGET="/usr/bin" if [ -n "$1" ] then TARGET=${1%/} fi FILE='[D-BUS Service]\nName=org.dharkael.Flameshot\nExec=##REPLACE##/flameshot' FILE=${FILE//##REPLACE##/$TARGET} echo -e $FILE > $DIR/org.dharkael.Flameshot.service flameshot-0.5.1/dbus/package/000077500000000000000000000000001324424505000160265ustar00rootroot00000000000000flameshot-0.5.1/dbus/package/org.dharkael.Flameshot.service000066400000000000000000000001041324424505000236650ustar00rootroot00000000000000[D-BUS Service] Name=org.dharkael.Flameshot Exec=/usr/bin/flameshot flameshot-0.5.1/debian/000077500000000000000000000000001324424505000147205ustar00rootroot00000000000000flameshot-0.5.1/debian/changelog000066400000000000000000000002311324424505000165660ustar00rootroot00000000000000flameshot (0.4-1) xenial; urgency=medium * Initial package release -- Juanma Navarro Mañez Thu, 21 Sep 2017 09:01:13 +0200 flameshot-0.5.1/debian/compat000066400000000000000000000000021324424505000161160ustar00rootroot000000000000009 flameshot-0.5.1/debian/control000066400000000000000000000011341324424505000163220ustar00rootroot00000000000000Source: flameshot Section: admin Priority: optional Maintainer: Juanma Navarro Mañez Build-Depends: debhelper (>=9), qt5-qmake, qt5-default, qttools5-dev-tools Standards-Version: 3.9.6 Homepage: https://github.com/lupoDharkael/flameshot Vcs-Browser: https://github.com/lupoDharkael/flameshot.git Package: flameshot Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libqt5dbus5, libqt5network5, libqt5core5a, libqt5widgets5, libqt5gui5 Suggests: openssl, ca-certificates Description: screenshot software Powerful yet simple to use screenshot software for GNU/Linux flameshot-0.5.1/debian/copyright000066400000000000000000000020501324424505000166500ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: flameshot Source: Files: * Copyright: 2016 lupoDharkael License: GPL-3.0+ Files: debian/* Copyright: 2017 Juanma Navarro Mañez License: GPL-3.0+ License: GPL-3.0+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . . On Debian systems, the complete text of the GNU General Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". flameshot-0.5.1/debian/rules000077500000000000000000000012461324424505000160030ustar00rootroot00000000000000#!/usr/bin/make -f # See debhelper(7) (uncomment to enable) # output every command that modifies files on the build system. #export DH_VERBOSE = 1 # see FEATURE AREAS in dpkg-buildflags(1) #export DEB_BUILD_MAINT_OPTIONS = hardening=+all # see ENVIRONMENT in dpkg-buildflags(1) # package maintainers to append CFLAGS #export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic # package maintainers to append LDFLAGS #export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed %: dh $@ # dh_make generated override targets # This is example for Cmake (See https://bugs.debian.org/641051 ) #override_dh_auto_configure: # dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH) flameshot-0.5.1/debian/source/000077500000000000000000000000001324424505000162205ustar00rootroot00000000000000flameshot-0.5.1/debian/source/format000066400000000000000000000000141324424505000174260ustar00rootroot000000000000003.0 (quilt) flameshot-0.5.1/docs/000077500000000000000000000000001324424505000144265ustar00rootroot00000000000000flameshot-0.5.1/docs/appdata/000077500000000000000000000000001324424505000160405ustar00rootroot00000000000000flameshot-0.5.1/docs/appdata/flameshot.appdata.xml000066400000000000000000000020251324424505000221540ustar00rootroot00000000000000 flameshot.desktop CC0-1.0 GPLv3+ and ASL 2.0 and GPLv2 and LGPLv3 and Free Art Flameshot Powerful and simple to use screenshot software

Powerful and simple to use screenshot software with built-in editor with advanced features.

https://raw.githubusercontent.com/lupoDharkael/flameshot/master/img/appPreview/usageStatic.png https://raw.githubusercontent.com/lupoDharkael/flameshot/master/img/appPreview/animatedUsage.gif https://github.com/lupoDharkael/flameshot https://github.com/lupoDharkael
flameshot-0.5.1/docs/bash-completion/000077500000000000000000000000001324424505000175125ustar00rootroot00000000000000flameshot-0.5.1/docs/bash-completion/flameshot000066400000000000000000000024741324424505000214260ustar00rootroot00000000000000# bash-completion for flameshot command # To be installed in "/usr/share/bash-completion/completions/flameshot" _flameshot() { local prev cur cmd gui_opts full_opts config_opts COMPREPLY=() prev="${COMP_WORDS[COMP_CWORD-1]}" cur="${COMP_WORDS[COMP_CWORD]}" cmd="gui full config" gui_opts="--path --delay --raw -p -d -r" full_opts="--path --delay --clipboard --raw -p -d -c -r" config_opts="--contrastcolor --filename --maincolor --showhelp --trayicon -k -f -m -s -t" case "${prev}" in gui) COMPREPLY=( $(compgen -W "$gui_opts --help -h" -- ${cur}) ) return 0 ;; full) COMPREPLY=( $(compgen -W "$full_opts --help -h" -- ${cur}) ) return 0 ;; config) COMPREPLY=( $(compgen -W "$config_opts --help -h" -- ${cur}) ) return 0 ;; -f|--filename|-p|--path) _filedir -d return 0 ;; -s|--showhelp|-t|--trayicon) COMPREPLY=( $(compgen -W "true false" -- ${cur}) ) return 0 ;; -d|--delay|-h|--help|-c|--clipboard|--version|-v) return 0 ;; *) ;; esac # Options case "${cur}" in -*) COMPREPLY=( $( compgen -W "--version --help -v -h" -- ${cur}) ) return 0 ;; --*) COMPREPLY=( $( compgen -W "--version --help" -- ${cur}) ) return 0 ;; *) COMPREPLY=( $( compgen -W "${cmd}" -- ${cur}) ) return 0 ;; esac } complete -F _flameshot flameshot flameshot-0.5.1/docs/desktopEntry/000077500000000000000000000000001324424505000171215ustar00rootroot00000000000000flameshot-0.5.1/docs/desktopEntry/package/000077500000000000000000000000001324424505000205145ustar00rootroot00000000000000flameshot-0.5.1/docs/desktopEntry/package/flameshot-config.desktop000066400000000000000000000010551324424505000253350ustar00rootroot00000000000000[Desktop Entry] Name=Configure Flameshot Name[es]=Configurar Flameshot Name[zh_CN]=配置 Flameshot GenericName=Screenshot tool GenericName[es]=Herramienta de captura de pantalla GenericName[zh_CN]=截图工具 Comment=Powerful yet simple to use screenshot software. Comment[es]=Potente pero simple de usar software de capturas. Comment[zh_CN]=强大又易用的截图软件 Keywords=flameshot;screenshot;capture; Keywords[zh_CN]=flameshot;screenshot;capture;截图; Exec=flameshot config Icon=flameshot Terminal=false Type=Application Categories=Graphics; flameshot-0.5.1/docs/desktopEntry/package/flameshot-init.desktop000066400000000000000000000011631324424505000250330ustar00rootroot00000000000000[Desktop Entry] Name=Launch Flameshot Name[es]=Iniciar Flameshot Name[tr]=Flameshot Başlat Name[zh_CN]=启动 Flameshot GenericName=Screenshot tool GenericName[es]=Herramienta de captura de pantalla GenericName[tr]=Ekran kayıt aracı GenericName[zh_CN]=截图工具 Comment=Powerful yet simple to use screenshot software. Comment[es]=Potente pero simple de usar software de capturas. Comment[zh_CN]=强大又易用的截图软件 Keywords=flameshot;screenshot;capture; Keywords[zh_CN]=flameshot;screenshot;capture;截图; Exec=flameshot Icon=flameshot Terminal=false Type=Application Categories=Graphics; StartupNotify=false flameshot-0.5.1/docs/desktopEntry/package/flameshot.desktop000066400000000000000000000012721324424505000240730ustar00rootroot00000000000000[Desktop Entry] Name=Take graphical screenshot Name[es]=Tomar captura gráfica Name[zh_CN]=进行图形截图 GenericName=Screen capture tool GenericName[es]=Herramienta de captura de pantalla GenericName[tr]=Ekran kayıt aracı GenericName[zh_CN]=屏幕截图工具 Comment=Powerful yet simple to use screenshot software. Comment[es]=Potente pero simple de usar software de capturas. Comment[tr]=Güçlü ve kullanımı kolay ekran kayıt yazılımı. Comment[zh_CN]=强大又易用的截图软件 Keywords=flameshot;screenshot;capture; Keywords[zh_CN]=flameshot;screenshot;capture;截图; Exec=flameshot gui Icon=flameshot Terminal=false Type=Application Categories=Graphics; StartupNotify=false flameshot-0.5.1/docs/dev/000077500000000000000000000000001324424505000152045ustar00rootroot00000000000000flameshot-0.5.1/docs/dev/package.md000066400000000000000000000002351324424505000171210ustar00rootroot00000000000000# Debian How to build the debian package based on the `./debian` folder: 1. Install the build dependencies. 2. apt install debhelper 3. dpkg-buildpackage -B flameshot-0.5.1/docs/dev/release.md000066400000000000000000000003331324424505000171450ustar00rootroot00000000000000 What to do in every release? - Update translations. - Update travis version - Releases always use annotated tags as in `git tag -a v0.5.1 -m "version 0.5.1"` - Add a changelog description in the Github's release. flameshot-0.5.1/docs/shortcuts-config/000077500000000000000000000000001324424505000177275ustar00rootroot00000000000000flameshot-0.5.1/docs/shortcuts-config/flameshot-shortcuts-kde000066400000000000000000000045041324424505000244340ustar00rootroot00000000000000[Data] DataCount=1 [Data_1] Comment=Shortcuts for taking screenshots with Flameshot DataCount=4 Enabled=true Name=Flameshot SystemGroup=0 Type=ACTION_DATA_GROUP [Data_1Conditions] Comment= ConditionsCount=0 [Data_1_1] Comment=Start the Flameshot screenshot tool and take a screenshot Enabled=true Name=Take screenshot Type=SIMPLE_ACTION_DATA [Data_1_1Actions] ActionsCount=1 [Data_1_1Actions0] Arguments='Pictures/Screenshots' 0 0 Call=graphicCapture RemoteApp=org.dharkael.Flameshot RemoteObj=/ Type=DBUS [Data_1_1Conditions] Comment= ConditionsCount=0 [Data_1_1Triggers] Comment=Simple_action TriggersCount=1 [Data_1_1Triggers0] Key=Print Type=SHORTCUT Uuid={65ecb470-7d89-497a-9f9d-406b068f7207} [Data_1_2] Comment=Wait for 3 seconds, then start the Flameshot screenshot tool and take a screenshot Enabled=true Name=Take screenshot with delay Type=SIMPLE_ACTION_DATA [Data_1_2Actions] ActionsCount=1 [Data_1_2Actions0] Arguments='Pictures/Screenshots' 3000 0 Call=graphicCapture RemoteApp=org.dharkael.Flameshot RemoteObj=/ Type=DBUS [Data_1_2Conditions] Comment= ConditionsCount=0 [Data_1_2Triggers] Comment=Simple_action TriggersCount=1 [Data_1_2Triggers0] Key=Ctrl+Print Type=SHORTCUT Uuid={cea82966-75d5-437d-afaf-aeba83a4abfd} [Data_1_3] Comment=Take a full-screen (all monitors) screenshot and save it Enabled=true Name=Take full-screen screenshot and save Type=SIMPLE_ACTION_DATA [Data_1_3Actions] ActionsCount=1 [Data_1_3Actions0] Arguments='Pictures/Screenshots' false 0 0 Call=fullScreen RemoteApp=org.dharkael.Flameshot RemoteObj=/ Type=DBUS [Data_1_3Conditions] Comment= ConditionsCount=0 [Data_1_3Triggers] Comment=Simple_action TriggersCount=1 [Data_1_3Triggers0] Key=Shift+Print Type=SHORTCUT Uuid={3c7ead73-00ad-4f90-bdba-5d15a70b8b43} [Data_1_4] Comment=Take a full-screen (all monitors) screenshot and copy it to the clipboard Enabled=true Name=Take full-screen screenshot and copy it to clipboard Type=SIMPLE_ACTION_DATA [Data_1_4Actions] ActionsCount=1 [Data_1_4Actions0] Arguments='' true 0 0 Call=fullScreen RemoteApp=org.dharkael.Flameshot RemoteObj=/ Type=DBUS [Data_1_4Conditions] Comment= ConditionsCount=0 [Data_1_4Triggers] Comment=Simple_action TriggersCount=1 [Data_1_4Triggers0] Key=Ctrl+Shift+Print Type=SHORTCUT Uuid={a724b514-0cb6-40f0-bf14-c08db726b320} [Main] AllowMerge=false ImportId=flameshot Version=2 flameshot-0.5.1/flameshot.pro000066400000000000000000000177131324424505000162130ustar00rootroot00000000000000#------------------------------------------------- # # Project created by Dharkael 2017-04-21T00:42:49 # #------------------------------------------------- win32:LIBS += -luser32 -lshell32 TAG_VERSION = $$system(git --git-dir $$PWD/.git --work-tree $$PWD describe --always --tags) DEFINES += APP_VERSION=\\\"$$TAG_VERSION\\\" QT += core gui widgets network unix:!macx { QT += dbus } CONFIG += c++11 link_pkgconfig #CONFIG += packaging # Enables "make install" for packaging paths TARGET = flameshot TEMPLATE = app win32:RC_ICONS += img/flameshot.ico #release: DESTDIR = build/release #debug: DESTDIR = build/debug #OBJECTS_DIR = $$DESTDIR/.obj #MOC_DIR = $$DESTDIR/.moc #RCC_DIR = $$DESTDIR/.qrc #UI_DIR = $$DESTDIR/.ui TRANSLATIONS = translations/Internationalization_es.ts \ translations/Internationalization_ca.ts \ translations/Internationalization_ru.ts \ translations/Internationalization_zh_CN.ts \ translations/Internationalization_zh_TW.ts \ translations/Internationalization_tr.ts \ translations/Internationalization_ka.ts \ translations/Internationalization_fr.ts \ translations/Internationalization_pl.ts # Generate translations in build TRANSLATIONS_FILES = qtPrepareTool(LRELEASE, lrelease) for(tsfile, TRANSLATIONS) { qmfile = $$shadowed($$tsfile) qmfile ~= s,.ts$,.qm, qmdir = $$dirname(qmfile) !exists($$qmdir) { mkpath($$qmdir)|error("Aborting.") } command = $$LRELEASE -removeidentical $$tsfile -qm $$qmfile system($$command)|error("Failed to run: $$command") TRANSLATIONS_FILES += $$qmfile } DEFINES += QT_DEPRECATED_WARNINGS include(src/third-party/singleapplication/singleapplication.pri) include(src/third-party/Qt-Color-Widgets//color_widgets.pri) DEFINES += QAPPLICATION_CLASS=QApplication SOURCES += src/main.cpp \ src/capture/widgets/buttonhandler.cpp \ src/infowindow.cpp \ src/config/configwindow.cpp \ src/capture/screenshot.cpp \ src/capture/widgets/capturewidget.cpp \ src/capture/capturemodification.cpp \ src/capture/widgets/colorpicker.cpp \ src/config/buttonlistview.cpp \ src/config/uicoloreditor.cpp \ src/config/geneneralconf.cpp \ src/core/controller.cpp \ src/config/clickablelabel.cpp \ src/config/filenameeditor.cpp \ src/config/strftimechooserwidget.cpp \ src/capture/tools/capturetool.cpp \ src/capture/widgets/capturebutton.cpp \ src/capture/tools/penciltool.cpp \ src/capture/tools/undotool.cpp \ src/capture/tools/arrowtool.cpp \ src/capture/tools/circletool.cpp \ src/capture/tools/copytool.cpp \ src/capture/tools/exittool.cpp \ src/capture/tools/imguruploadertool.cpp \ src/capture/tools/linetool.cpp \ src/capture/tools/markertool.cpp \ src/capture/tools/movetool.cpp \ src/capture/tools/rectangletool.cpp \ src/capture/tools/savetool.cpp \ src/capture/tools/selectiontool.cpp \ src/capture/tools/sizeindicatortool.cpp \ src/capture/tools/toolfactory.cpp \ src/utils/filenamehandler.cpp \ src/utils/screengrabber.cpp \ src/utils/confighandler.cpp \ src/utils/systemnotification.cpp \ src/cli/commandlineparser.cpp \ src/cli/commandoption.cpp \ src/cli/commandargument.cpp \ src/capture/workers/screenshotsaver.cpp \ src/capture/workers/imgur/imguruploader.cpp \ src/widgets/loadspinner.cpp \ src/widgets/imagelabel.cpp \ src/widgets/notificationwidget.cpp \ src/core/resourceexporter.cpp \ src/capture/widgets/notifierbox.cpp \ src/utils/desktopinfo.cpp \ src/capture/workers/launcher/applauncherwidget.cpp \ src/capture/tools/applauncher.cpp \ src/utils/desktopfileparse.cpp \ src/capture/workers/launcher/launcheritemdelegate.cpp \ src/capture/tools/blurtool.cpp \ src/capture/workers/launcher/terminallauncher.cpp \ src/config/visualseditor.cpp \ src/config/extendedslider.cpp \ src/capture/workers/launcher/openwithprogram.cpp \ src/utils/pathinfo.cpp HEADERS += src/capture/widgets/buttonhandler.h \ src/infowindow.h \ src/config/configwindow.h \ src/capture/screenshot.h \ src/capture/widgets/capturewidget.h \ src/capture/capturemodification.h \ src/capture/widgets/colorpicker.h \ src/config/buttonlistview.h \ src/config/uicoloreditor.h \ src/config/geneneralconf.h \ src/config/clickablelabel.h \ src/config/filenameeditor.h \ src/utils/filenamehandler.h \ src/config/strftimechooserwidget.h \ src/utils/screengrabber.h \ src/capture/tools/capturetool.h \ src/capture/widgets/capturebutton.h \ src/capture/tools/penciltool.h \ src/capture/tools/undotool.h \ src/capture/tools/arrowtool.h \ src/capture/tools/circletool.h \ src/capture/tools/copytool.h \ src/capture/tools/exittool.h \ src/capture/tools/imguruploadertool.h \ src/capture/tools/linetool.h \ src/capture/tools/markertool.h \ src/capture/tools/movetool.h \ src/capture/tools/rectangletool.h \ src/capture/tools/savetool.h \ src/capture/tools/selectiontool.h \ src/capture/tools/sizeindicatortool.h \ src/capture/tools/toolfactory.h \ src/utils/confighandler.h \ src/core/controller.h \ src/utils/systemnotification.h \ src/cli/commandlineparser.h \ src/cli/commandoption.h \ src/cli/commandargument.h \ src/capture/workers/screenshotsaver.h \ src/capture/workers/imgur/imguruploader.h \ src/widgets/loadspinner.h \ src/widgets/imagelabel.h \ src/widgets/notificationwidget.h \ src/core/resourceexporter.h \ src/capture/widgets/notifierbox.h \ src/utils/desktopinfo.h \ src/capture/workers/launcher/applauncherwidget.h \ src/capture/tools/applauncher.h \ src/utils/desktopfileparse.h \ src/capture/workers/launcher/launcheritemdelegate.h \ src/capture/tools/blurtool.h \ src/capture/workers/launcher/terminallauncher.h \ src/config/visualseditor.h \ src/config/extendedslider.h \ src/capture/workers/launcher/openwithprogram.h \ src/utils/pathinfo.h unix:!macx { SOURCES += src/core/flameshotdbusadapter.cpp \ src/utils/dbusutils.cpp HEADERS += src/core/flameshotdbusadapter.h \ src/utils/dbusutils.h } win32 { SOURCES += src/core/globalshortcutfilter.cpp HEADERS += src/core/globalshortcutfilter.h } RESOURCES += \ graphics.qrc # installs unix:!macx { isEmpty(PREFIX) { packaging { PREFIX = /usr } else { PREFIX = /usr/local } } DEFINES += APP_PREFIX=\\\"$$PREFIX\\\" target.path = $${BASEDIR}$${PREFIX}/bin/ qmfile.path = $${BASEDIR}$${PREFIX}/share/flameshot/translations/ qmfile.files = $${TRANSLATIONS_FILES} dbus.path = $${BASEDIR}$${PREFIX}/share/dbus-1/interfaces/ dbus.files = dbus/org.dharkael.Flameshot.xml icon.path = $${BASEDIR}$${PREFIX}/share/icons/ icon.files = img/flameshot.png completion.path = $${BASEDIR}$${PREFIX}/share/bash-completion/completions/ completion.files = docs/bash-completion/flameshot appdata.path = $${BASEDIR}$${PREFIX}/share/metainfo/ appdata.files = docs/appdata/flameshot.appdata.xml desktopentry.path = $${BASEDIR}$${PREFIX}/share/applications desktopentry.files = docs/desktopEntry/package/flameshot.desktop desktopentryinit.path = $${BASEDIR}$${PREFIX}/share/applications desktopentryinit.files = docs/desktopEntry/package/flameshot-init.desktop desktopentryconfig.path = $${BASEDIR}$${PREFIX}/share/applications desktopentryconfig.files = docs/desktopEntry/package/flameshot-config.desktop servicedbus.path = $${BASEDIR}$${PREFIX}/share/dbus-1/services/ packaging { servicedbus.files = dbus/package/org.dharkael.Flameshot.service } else { servicedbus.files = dbus/make/org.dharkael.Flameshot.service } INSTALLS += target \ icon \ desktopentry \ desktopentryinit \ desktopentryconfig \ qmfile \ servicedbus \ dbus \ completion \ appdata } flameshot-0.5.1/graphics.qrc000066400000000000000000000046011324424505000160060ustar00rootroot00000000000000 img/flameshot.svg img/buttonIconsBlack/arrow-bottom-left.png img/buttonIconsBlack/circle-outline.png img/buttonIconsBlack/close.png img/buttonIconsBlack/cloud-upload.png img/buttonIconsBlack/content-copy.png img/buttonIconsBlack/content-save.png img/buttonIconsBlack/exit-to-app.png img/buttonIconsBlack/line.png img/buttonIconsBlack/marker.png img/buttonIconsBlack/pencil.png img/buttonIconsBlack/square-outline.png img/buttonIconsBlack/undo-variant.png img/buttonIconsWhite/arrow-bottom-left.png img/buttonIconsWhite/square-outline.png img/buttonIconsWhite/undo-variant.png img/buttonIconsWhite/circle-outline.png img/buttonIconsWhite/close.png img/buttonIconsWhite/cloud-upload.png img/buttonIconsWhite/content-copy.png img/buttonIconsWhite/content-save.png img/buttonIconsWhite/exit-to-app.png img/buttonIconsWhite/format-text.png img/buttonIconsWhite/line.png img/buttonIconsWhite/marker.png img/buttonIconsWhite/pencil.png img/buttonIconsBlack/cursor-move.png img/buttonIconsWhite/cursor-move.png img/buttonIconsBlack/square.png img/buttonIconsWhite/square.png img/flameshot.png img/configWhite/config.png img/configWhite/graphics.png img/configWhite/name_edition.png img/configBlack/config.png img/configBlack/graphics.png img/configBlack/name_edition.png img/buttonIconsBlack/size_indicator.png img/buttonIconsWhite/size_indicator.png img/buttonIconsBlack/open_with.png img/buttonIconsWhite/open_with.png img/buttonIconsBlack/blur.png img/buttonIconsWhite/blur.png flameshot-0.5.1/img/000077500000000000000000000000001324424505000142525ustar00rootroot00000000000000flameshot-0.5.1/img/appPreview/000077500000000000000000000000001324424505000163745ustar00rootroot00000000000000flameshot-0.5.1/img/appPreview/animatedUsage.gif000066400000000000000000012102101324424505000216270ustar00rootroot00000000000000GIF89ah  9= 0  " &6 "% &)*+.#,-'*+22414 35###+++&()+02&8:444<<<2:=&+50J^s`.6%B6K,iooDQ9pp&*@+ J. V5R=L 8E/P19G4k4&rOJ4QCfG fIq[/vY&y[2uS2h`h AODQFSIVMYJVP[S^BM8EF0IRV`[d_iMd(Ze(Kidkhngg!io$el$mr+ls&rv)rw'ux+uy-y{5w|2mtCCCMMMCLLMOPGJSNTTFWYSTS^__VYUPPM\Gj_]`SNfhTtcccmmmfjksss{{{nlq\lb" 6"ae3; ?W.N#oLur2 Yov@=:WXVgas.;}TcE}[jitoN6GJЀQfhڅ͋*Χ|ïj۲\{=ITXZNgksxntΌՖԭ΄䢫ƮȶͪƛɯԧȳͻԵҠ! ! NETSCAPE2.0,h Ha7x#JH`=ixQF9jW$ɑ%Qr4RK.SR$˚19tyLiHcLHy<9TN(ɔjӏFՎ\ 4j٘ *MYaZZUՌZm(̼LZuߕdv)^XŠ];8e̔+ tࡴi}+[dj}^\ڸsͻ Nȓ+_μУUMө/w[Tڷӫ_Ͼ˟OϿ(h& 4uءevFiJ qަ.8Q*pʻ'2j{jZ =j ^'<|:<$mO<H>Y4R-5!Mj[$<ۺ7n׃劓=Aapst0ŐR x0s0܌` sH$a:αf($r<FU?.vRcv FL=1t&2MMl3%)5q#( @0ṭr86` F;将 (!9`A9ҀyJ-@2KGӓ2X2%J ό,acGG9 FY&1TT 11$@A" $8c4b0ȁZ l(j @ZnÐ10}6wmA7a4-W90sdXCؘSodSZVNfCAmmHYʭ=谌/ch E6l`9t!`t`9球!t0q:Xk8@: @ |܉ⱁe` }Rzxw?o򒥲]7.9 ڭ x1 ec(g ݘ-q{c2:Awq@aXȯfd9.d <&b1_媿Pn/6;ƑnBL UP-|(1ǑCH6p;44[^j1NGnBXF1!J[d1 2eB&RwFMu]X['Maſ\VwdKqv3biF (1 6CPjwb8s "`{6OnG:%B['t fk/#cΤC4LlnÑk i} ^0buۍ.>Հ @@nL֝ombwLD 8E?l֏:y(~y[p"ɏ%za'fF';H{+\ 6 u{8H\܅g@&GٱC-*3)~կyՏZr=0}u`l gi]4[A6  r kw1lG: nsF"c@ZGz~uzX55y5t7u򧃆֡awÀTB`$fu]Q #Atgu0h tvrshP!s5̠V(x$ESI&#B^wy?b20BfdTu5p cP'Ɓ.N0w i`pe l0N :@ìj0gW"%Xu0(_U7޷F7~A~#zuÌoz9p>Ru$∥v@``  rTq }VJUC0 `vmUt `n #s&#j0p?H26 "ǙGZd9``~~۷@P蠸뷒kK[+˸+K뷨鐸+뺸˷{ ˻[[{˷K+м+{ {۽л 훺ۻ+;Ի[˹˹ K[뻰Kp;lϻϻۿ{ 8ʩv[%1g @302L3|8:L3=<<@|CDH CpL@\P\D`Q,QlXi]h]VELX ş]QYMT]fKGqwlyHӶR0Ȼ5ґ.Қ\ŝɔL"nޞĜLӾ\^nп\̾֝п<NXp|ɦMN,]VҒloӂ|*ӝ^u܊?ɧNO+>8}B}/nDI LPa#J<QD#G*^4Fp,"Dd4i$Ȑ!MȌ"Cj';g̡4*FRLUԩ<\]U+U]~Vxv;koL@HQ<{49d&Oze\R XÊ!68qBʕ$IJh 'OH?1MtiԭQ;Z*kƍJmVxSEKMEr.^kew*T[NK,W_RJ`TEѿxe˖,/آ(Ί-6=+B' -bB 0C9d- </E.‹M@Ead?odq-o<ѻ`/;#î:v[r:&wIڢ28ݦ-nk پ451ô3T4. 'HbB+ *KN;xO ̱4h:#N:)i릛(˧zSO;mk)Ʋ*Z&RWeUgЪhhӤ`jӢ$24%B%cTҌUYMB%S">΂N:\sM4=73dָDmK׀R7(=.b;,eq}[,ȀN8b+~oA&>0<?E0B B7e_n9,BE|\gn1*^쯿*R1 ~}ȥ~F#ۮsIŠ(7,ܼ 3D7 54B\<3Ќ O 1Dj4ZU%f5.XӻztUԟuRMլ\=vj-무ΊtWρ s"X[a\BI !i=1koL[?5r4w44M"1Kc L.kmx͋Nl*׬s}hk١0,Ч8.lm aþr%bI3Qyd%He*C4Z3+Ԃ4P0,tb, x h B6,(G&q5& jQ4LT0,~ml` ^h\snjMyB6֙7)N㝠98gB,ܴBLDӘ$ "\PINY'ORv2ˬjz 䧈r^}˰^[I=B%seYpo4޶'$clm|>/8a$%;,Z ['NwA"?42Lm>_ox]Di! 1 LChPBE/O"Ģ& 9`Shɤjqlm(F 5mڧ׬LؤUl&!jǚ'2d5\ժ$0%\1L9Xy%+;"tV!J6T2fECMJP⻑$(?ɉi /*g Saqdiuł6:!lϸ.vL߄WA;oEyJ }i>? `$ q=/G֜Zc'B34We05+(*<]b4EQX_h[@ $1;DCjZ${x>"sL>$PYŲ& ,s>MH%G8+ҿۿ?򣜫7zC: qC[/ɭy{ƨ(0 0'Hݪ: ~2HĜC Jʪ8PcȀ 8YөVr Q?TF{?YT3`b[3@Q&=xCj*=;:bs x: ‚{A n: - ChۑR+ۓs-L:e *04pK= {-M Nd}MQ{ໍXiӈȣB=K 16dAAԊ(<sH#Z[ݍ,V͊VQӁM1QSuK4YuQ텖ſ`^=P**PFp5^;\w g:6̢"WF;O[zM "bkûaH d(\hB&HXx}&*嘖6]!Di[EHZBQH6CEdfix3Ɖ%cmhVp>H H uF -ZN` I JHB8Oh B$6-.<^dP\܉e'UΑjF-,*6vI=YMY#FmѦUäXK,Eސ8G {je!3?RZlRT`֩=kg\$}=mbFpqC )0[4(ƅ-]v".n4h1E˅M2!݂n` \VFǃ"M)=tndRx~:^=(SQ 4Kg{;,4<P͉-ֵu P>6eQ"TTAq4&ҩVnfyqzgYQ/z( Ot=,IV ^ťf>I#(i1H=g5HR&-wv &g',:[0-  =|ͼ\%c"M^( h5е?}S.eBjMhTK?lsXTa Oxb cx ReSNPuubUԕEŬޖZ+㿖&|k#鞧Qiϫ}O͐vh:z m rsC\[ȅNv{Y4׶#ITMEmլ'j.6(CXr\uBJ6N}.,i%ZhxTe l2<x frf w}և}}iןn IMIMz}AWIP9u^Voq"$[ޓcHd:a-ȿhj2vd+?&wr% (u4:9VZ'X: (`n (T&N|B"*5N#,UIYHfi2.gܒŦ͛6'P.[-h.J*dE->RsԡR%SO7~&+ese7\I.ˑ ?RDA.L3sใ1dx"C>̘a{ d(QyG.mt$N6=/D7s Zt©&w%2$s$xG\xa3h̘܁˖1۾ :UN}zH?dۿ_>O8` 1EAD&ELFF$Gl("%xć)J$ᢋ/*1#4N<*88$OiAcHIœOB$ ݂EYt .lrDyD]Q_~ixiL4%'.}5ZaQKIT:UU*?eV"5X_ 5\SrקpH%ATVecN:zNjΫ3Lfuƙ!w,a!klF Vlp(K4Db첤3SڷIKȸIuywʋz޽VW{g~C8 H V%h!v` "H#!,#%D0h#3c;K"L6$N"$哷 Xh_"DAV`]*prgKy8i:)RFhROEh[a(Vr*)F禗Vٝ9H+*jI|M`JZ3k:ӎ:;U^C1C!$R ݵ&`6ʹ>cz.{f%"q[!ȫ`Юv2C$ߒĵ` ZU!nv*ޜ'"EO:9[M꩙>%I4#=aё+^#] Cf<.F5MxF rřt5" qz#y'3kYƳ0;8o%oќ g]!9ϙ{|.ړ`u F{Ag(O eCx14#D!A# `8v+,4d&(E%2LG8ґd#NLY͜%THr)3,h',Ic 3*j*MzVo{"X)*Q1ĸ+F|1&V%1 6/;[3*Y#V;'I\nZ" K+F4<{$Szl4'%m cf47s!{iNӀjJΔٗn iDvt^M=!t,o I̺ҷ|oҧJ@qHƃ*F(r; {<\i@$ȃ0QK[Y#f.kt! Ns&t֗ Khݷjq:<[jNGݕZ3ȻUZӺvksj:SvY/KXp_Il}:Qpdh3{^{<#9!,p,n8Qgn'U"Trz b"TBDP/R pӝ)7DNtC+R*CMPW`JE.H/L[l ؐUYDYP QFC87p8;t>=<(F"-`ʴ ڃ&MfDeSNޭF >=bCB#!h,Ri .}SaDj\K <*G" IʵPܒTѭ E 9ʫ9ʗI B<qxYI^Z=sVQCKBDaF=]RF(K2ZI*(M#=&%C4l<(pKa wtWtP S⚲忈[%OS%H1w^,84%޵y MfHȑDT9P2(CDJ}&h.&, #1 _TM TJym YX]8p2vr*'VApBg2C9\/PgP|[l-|vr'<.\\KtLHO'@v̽h b@"C!I"UlP,VcU2C8*|j).80ȪOXAWܞ2;j9.xMEߚ'kuA9HC3.=ރ0ŢXp~Cqr*TPQ&cn Y؂=wq.඘@QY1N 8h`BBd<9C bk<4d(d:_isivk9wl`wˑp|p3uǓҳ,"L0l ?%z] {)HAM[` 9P2Pb XiԑHF' =KݢZXhqh.t.xB/K31t&@&IqHtMNpnB UPEr8hww2\Nt 7r.(n8\8pR\NJf09C ak C(7Vcgoi6kv&v:s8t d@ˮG{,beGӳ>PT GH#mi|-\kCK)6pT ;mI/Br Mr'.|99bu &^@Au{m5XDn*\U8jw:RQKn;w'1RExn8p.x5LMA3k`uiC<\k!g%n&5]_8::iW9V*6:kS<8~lva[^]pPȳEi{0W@m&b)nԒ IGd.nitB/7+-x"4Mr3jh631{-l"xԔ˭NoOk.n*Q#T-z_.8͍čB^N9d</tu oY ܧm48a5ϓ4GZ.j:'cFҟt;:ex "O3Kb@Y-W;ȶ14N&) Ѱ poIނ{yC1pA i0B- O~ZgJ\[#P\Puwy_;&ŷ*R+/.$pZOc:ꊄsXMD[fxkA^ab6g[lܟ0@( A LI'6T"D/f|".z4Җ/elRR&-T`Bʓ4q̲s")m z &0\$Uz*Y6*U;TͲ*WY2vֱgѦeKgƕw\;5o_ū mܵkٚM̥,YJ)U,Yb4 8={ APVsv<|ы:^տ>xqǑ'WysMӘ1R,[L.}t楟W~Ɛ?~}D Ad?~",#$<0B)B0C#Ȱ=#P$XT@bi$(nщv|hv! +^pN>QĤOTjrIx - l-+#J0-)6 &Ν1<`+P2jEEvy'/+QFŊ &jɅQ0@AJ/M姣̪"(.%\‚hjӴ9xnmxg'mo 5fH<;qU =o:O_{?` /\b\b 1 1QcM,QE]|F$` Z(!-Nj<2 #)rM|aURF4U0K/&1A ,@I%[MZj8l*9錬t,2бj E%o44.Sv Tm[]lIU/fU]|eؤ[ry31r{Rw G|+y55h?@4 -a$54C">䢐M0dQhQ Jde1l#e H"ar P&)Di8RGƴ65L0DMP! Sv]AqbӓYD(>Jmma[[䒋q1jڱ‰H=j8ETHF`dP[.*9Ghn+PFXU}UтP!d肒j|j2pᔑΤ4N=bKyx9'R8(D1Siшf$;~kHe>oi3yYX<5gP|>:_7N PBSx³b'Ǡ Ad/#h>2h2b("X/zB…"6%$q&_aHC J!(ET&rDT8;OeJpL]jKB*oRG-%n`ʁGqZ_f, `đ sn09ڎo“^]J$Q0PRd)`Eh%gr Ϣ&I!Ts#/QÖ?2{i[/?8s-a$nt ZOYDt#(-{1Rx D nD*r%P sቔ4h_.DU~AW2헿("Q65c=1NF`؉֢d BA.7Pj}A&c_v86H,@V#%ȠxM\rk݁;q G\~ i-Szc6u br/능<i"5D4egDCj' $" ai"fNG$Y@"5f Jr-Ǭ4[Ǧcxٞv>־v԰5OL?*8ũbN?1ּ~gń=ϋ=5]b0 A !(!5RЛ[(BEqnH]|nxӲ XZ.N[b$q,Ӛ1"բFJLT^.RQLN/0A0bgꔼ`,XpasT4)G(5 k`@N,(v!Lqf(Ypb6IZ7#"7.-LΦ!&- ,2n8! a!"aбPP#", !k!! l ,P q,+)-$q =:{B9g=H|aIt&BKh6hm-zsp/%$3hv)tE++2ehUPJH. Ee/ 0402ƁG,0B` JOap Fp nP rhv nrʞC|ɗ64 aR! ),:k7.$m87:LF !$Ѳ!y !(-#o lѤp2MӳA2 PcTZ;RZʧԲIv?rKD Bĝܩ˞:!E@ddjD!G"Bef‘"d 6tJ -ȏg)tIsl /2O|ro~ ,nT e$ on$ %ȼj$r,$|`+ V|!v h) E!eowAJQc-ݲ0!R/K15Js. , % 3!0QҡM, ]NL,Lu52N,50sRRCOAc6#C-7Mo=p_Zz?8#EsCV@':)cm~́FEZFd;M JD*< `w!@j W g*lNl1H!r,,Ш4/f8t#E.2o*S:Ro 8!U , tA 6/j+ZO_(d2N Ho MЯcR. M$sL4N1qРNLN;sT %QOa QairOO  7.Ж@1V 4MAlp 65mz4]A]TcQuU}\OVYl_ |@(ub1X 7:sd" Y5hH2" 2[S\7 t\#KIq):!ttQla/2h ȦF,‹~%h*/v,E"e6T|Ar΢|AQ Ha R1e[+@ |JcqHwVAưF=JG Q AR a͐ M%m U%Ē6Qm" 7 O50Q#oSK/ |R큈]T#qg@{C(79R,w77g`UVk?BtQW'@/XCmئA^ .Ɇ/⒊g*d`"eD9 /:AL 0!dy  NlAW;!{{Gqߒ,/L2ҳ@vxͪ SS!< QS QSnRVA[0z2 Oj7kK'/(\)cC9^zU]MAt1_j_VOt@~ a  ĸ:Yb7Qwz5ESw1H8(Z<3De@ |!gԑI`&@ij&vLUrkΉ*.2,/}l(LB EcBQ𦨔J)EnD)tC{FWt! .  w`UZm9X3b%3l!O?Ehgp'xO)k OP~z5,԰= iP,A0L;s^ 1eZԦ% oAL4; 6떩ש]8%^R; =<#n"nAQi7A{gg2{Ytnt5lA :C%*觨_$0ܗPo27;pjj„ 6|pwuق1.(6,]1$cM+1Gd\ ƣoTy3o)EJ*W d/ԩTZ5֭\z 6رdb 4:7n\tθ7޽w;dƐ>l`D;~ HE1bdFeE\|3Н-GGVquٴkIr;ݺޭw$;)'̛;y ҩWNe\xŋ*̭P"] [ԉ0 E- v oTȶBэ+o\hFR*cf4#xp9A3ܩ,wrB_89Z.6mY̆7Ͱ^WN9jnxBz1<\t" )%|N" Ph|p.н\vw`…d>b/vѥ,p! _Dt1hc T" %`E!-c`-6o CAʳ V w} )7j1*+ʑ [bʈim-"k>dq&ME0G)q$-IR(^I@dK RJ0*LQ TL*Ǚ#XA6"bAv,s 1Wha o!Z`PF,MO q-p|L]ST/ƒ&| iQ:?jEH'oFl8iNtB  OyZGقABpH'TH8MBG.[I^؆:9ǚH RRtmyѽ[>x9_88LS9V=թUJHҵ&6  q(J+ęth;(ՆvDLo.{@3{6%U0/x^b <(klּlZyJ/v#+raЙ̳G/t"+$ J2*3~%iJNTDl vݤbp@ʡ 26Ok/i.[P7'O4=uL#'fr1p;ڱLh`쬖.]֍v0GQ|U)HxvZl'hJp񢖻 e d]'Fx^iAѬBtD(kR&-4%/TZlI kE`Ϗ|cʞ4Ђ`[z0)d [ytQeԤCAN&8LyO+*J=t@.)]KD{o~ƯRZ#Ru&V^tG06q.eUYv6Ȫ. lkXҹWɅ[ ưrixG{>"1}4ԏALXYpў3Bjd| ;qɶ(Y-jHgF@>]~ 0{8$%KE h!DC4QT`Q<:o)V:Y2u*+5-surA@F7^gF{Qv*vEkckOk9H`tU8FU,^VIaal,SV&n1na0 -yWsՂ=R`. p =V.Fz'P& o>d"dY1T?? 1!3# pr |fs2FbK3$qk#!#f}p )%x6&a@g}`53D2d~;/{h@Q?xNGqth艟(HhȊ芯h(,R 83PgD)janvf*jvVLkG9TbUU\efaaaI݈x,R5x-v-O`0b`JP@` gJ>Lci^ TXLɔY"Y…TFMTMdeer[]v\w#sdu|>g}84i6P_P~s%` )OSsZ%.y5!aN\& *c\~6MO Q)8S9U R[EEzCSyFS8gـ㋌)qqvGpIUkva3azU(wlQbRllyl-p}qXȎNPJ?=<V0X^rtRHG LFzSp1L11/MW#su|<2|d\2Cr5$7OfŜ (&sJiP@5E%[` >WCK9z<ߢIy7nqŢg_ uV`ޫ5 A`SCoI!zɗ̼4#K|)laaQUzƠj,6HЌ,q% p U-~p10Y`GG>¾P^!@eM #1ai>b ߀Сq 0  }3 "0 ߐP!pdd' T>@ې xb<7ӭkrJՁ2^mIL¡Q:zҸ9+* fuyvBE.?))u@>)*5׶u ~!)'ʯ*DTFUD wOU}LˬaĠ42WR 推lyQn͐䠔LDc< H0weS1gcKZb?D.PnvAƴrGL\K|ANTAҐJp%ZI'Rn)ū10X>rWX9rP *x{ .\PBJ*|);W[\L<9˘\9ϝAk 3\6֯eeKm+].M}{{eviٛls}^Tt\P΢͕WK|t ] +P@(4p@jp,ʪ$d P):$'iDhIXR:Z)%$F"裒Fqr(f 2rLrl ')gJ)i.K<s14L4TsM6tr&rN:kI<Ɇ!?}T#rGf餑ZɥGEMIn0| 3𪡨B c+^Z%P 0n%\A'rlq0/ 0,;l\֗ 2lL [<Tn lsڜMr;εx^d{ζuK7 sm#>CX4*6+泸#ؽ@$9'Pp§0lã^թST(DiL/ͩ&QtEf1#(ƎB"# ըC!ԡ":P?s&LNR8tM{$L{4Dn&sO# ȇ"MjQ[D+tĠ>0)%X itb ]UJ]WEr9.b -Y6"ZiEy0l6ۉ[;R _]w{U_}%W4YSa& Q [ȼpXCB@ШRU!XATGYJl)Ls< lRYr+,P2@.Q U\mP[w'&IosSF-moݜDI KFb P[B8F\dxх,I YŸg;O@ԡq(HqRN?^(TV @AP. a `}mvJ؀\,chRbӤ H0K$ق(HA ae0{̘R 0#X!*Z"Di8rqV"BT"eIA[ߠD6*V MR"EKgk >IPaEyCO|8Tdq2NjПNhzfrB΍PsYQ2-T,)t]*\`aXB'z!s&^Mܢ-W b\q-BYg#Y߹pK|ƗAN`/ao6zd]L5 c+Ч [f˚۴I^|Ů*"2%wyBhG)SI@Q%EJdEiL#dXF`!C{4hZa .J*]4KiSٲ6x"/'$ $Ro(:"5iBtӊP5LI.^FIN&F.Kq! @ZT)F]c X- 0@x [kh^[p=t ay?YSlKYVVWf_vr-E^[#lfIlpdr۽?" W7!_#I8Š cOKbj w pp 5KE7tH2~w*)\ #@RPK!cߝEA \$@/7=31 Yv=a!nqfj-@p­[ 2#.ujA44 ޣ=u˴ɜ8JQ#풜3*2U!꼈: MЂjF%&K0=3)f22PsE5+%p?yE,Sĕ,Jl2 d:0A 1A t+-k w"r#A;{:ˉڮ(`b5JkGˋț*IBhM{بMB ġE ;Nb* + HSe@$^aAWYdttPj[PtO/ B@0F(ӖTTTdzZėwQ?Z\KͺEˑKEP9JgdD \-:ɖLj c7#:!B!"P;+5(A#0@Vǂ"<(BMTHS7弉"\0ԡ!U #ЩIGRRKI4G=*%FЂ ^,O_:sJF8es0t^ԦS\8iH-PLš`R&أ}L#Gs}z(0KP6T둄N«I5S!RY͍X96ٷ!Y:Ւa/"/B~TB5TUk0j.RNL%ZTwM>bZЕm+ϩ 0gpms(W%e Яo`Xژ^q:ӂ0Ң7[\rrY\ p*E /X~.X겹Db}XK٢dFmjLE*x>7=TC%mR#%t;55B DZCrC~X5-"8(mF|g-⼘}5CIjɰ1Y֛D5r[AqtMҘ1AK40X[0TOLu-|s .r tr pfi؆jn[gP\*%Z:J%Z.؄fq"9`2-MZx_x!MQvafb)pb@sFG t 8smZSZMrl[Op"tL|NȔL@ybI̴Ü]S.tQ5@$V<eMZ;B?c5!25%IN|ANބ]8 P7TG!7#:9bT7CI?J;LϪȪwV*H gקyZ` |+G'/؅].tU[M@,AYmXXZqhm!myZ $g`]pmr 8 ,Қ,xrJa-eԏX-ܺX ㅃrbHbb>O7_7Vs]˩o ;οA.|.Q^ CTV5v}q=*O{uT$mPj:r$8@`Ep%o~᳋)R dqewnM]0zYцMЅm^ڰy08b]۰ P3+]04եV_}p!._t[.^TMtd-\lAȒ&tH[Wdɩ3'd]EH0Y Znެ¥)ɠTbZe.^miz ٱYnVX^zB *X # _-xE'aJQ—bO?~d2ʅάYI$=wܹҝ$9z5#F\vmd׳o]l޽W$Mdw/)2·p}Dɮ]ٽG=z͗Aczw'>}<ϟ>3 ўx vUWu]g\sGs-[Fmf[lZkVZhqcedYdEdF:abK:.eD Xr |u\\v)u%WWZdAEYUnYgPUqNȄ.F O 2Tj/lSJ9m 7زbZ.8$BK-K.t/~8ȼ**A|3꨺ TPȨK!TKR"7~IKL2bM92R/vrœɘ6q( 2"-o-H3梌/ɕ2 oK2n-َZ`-lq'Ztb0:VbFEb(?jcf766X0Vk-چnYpuh\r)r]}6wE 7^z7=駟{o=(ay!SuD F̀n3gֹ1gĉ%vN5nmOK'zҟ]Fϑ%eK*N@Sҋ"cbaUcbQVW4\'vƙE7ħ_.Qib8ȖcFI_j\TOtC_h X [-ጸx-m" 2~3<1Ky9;!}rGJ@B쐆ɳ5Q}i#Y 'f9Kth9̥aGmSk .pd3# c>4Xzawgn۩Ӹ Y*ۀoYrR-CNhE,TzNiH]K(n?#葔;.& E/"^tB P-:<~I.eGdf8) )DZOZ0LEux=(Y8IN,z&jR'Ez=G9:q 'dym@T8_*I5G/3Rk[0/.bGkOB zh.~# 4>"'L4q ]؄Xp(*X-䥌lWhRХX/ @ <!0ϳЂ s1@$h jפ& O)scѵE R'-eb~ M(ЃAad@~=y6}:RY -YvmU9+HU^z^1rNc\k^'?E./sQNЅ!EtsbG,+7P1z;NWɸK,8H/tBPAOC2E.K'l28 ȅ[C\`2Vtż$:,\H%I}b(^dx?({ڹj̗F}e+)Gu]!GX.0)iS715 ]{5!-1tT oX!-׵*H֓юyM?ܹ͠]A#./BWE.xY|FI !^V\AH1I"xTTeċ8X87OUQ}/O)BHP9@RqeШPeЫ(QOP7"$^IR\X٩PP.TDSm.C;PcACyA!C'pI`UjM8eJO(ß\¶LB^lO%!m]úHC8(46/E "9F'4Fz $M|E؝+Rnӆ|ev\H&X00z$H2̀43\NSw؀ɍP΁S0YT eM;F͌8jЈem{@N]]'',tQ iT]dE%ޚH؅ID+CpU2 ,L 4l% -c3;OY-X(eu IDB8D 9DQ'RbE== RsZrRQ.D .ʲ5}CN ՂaPmeu “[Tj78.h:ȑ2-4g878p_ xiґt! 2g4e܋Qlh:&\F!YNҡ%)]^@%]Ѐ501r f&S m,YpX~|NfY ~AFe]K/$F rIA',ז\ɗ"mr mG0ޛ+ԟtqBNlH`&x [- v2~L/ 2<ղTHt z2Kx+;\DhD:ZBU N!htcS(84[u7G_D8d1P0`QD1g.p]ŧ]$-(ÿ]B$p 8Rld8d/ P (IHA MxeRf)i8)}iabjN!9ќ8e0e< Z⥝"]p!\G[J5A؋mሥXԀSmtN<}*jFf*M] Niy1ɩ.pBZN EaTE}X*`nHu'.l,bc)V8B\EEHI(C9N#xvgT@ʡJ Yo756n߲E@KERqmEDG(VQ.4hNH ]h YC_9Ѭ( dOnbEY9BK2º -@d ^^9A'xѺd/@/(-aPxQ&Lg YAed~)nH:ur$G̹%b8^&im5NvDN1xWn..~maWZ.l@ /?;eΚT L 矅~D$1ML:[qG"qj[LI%uah'=0'/3*sMyE_j?,d \A>/e?)OFjy>E=Zt:rk1MSBԞx ނWݖ5{%HL4>ˬڲmhE2K/b/. ]"4P3xmMըra_Z]P &4y \9)A t"e QTxl2< 4(?Od'f'aJn@46QIl"ZQӊVE-H[!BEIL|"/ ЅPd%b)Df Q.[ "od/q .o33>Ñ)rH9ʐ&qJH('p{\CaGxlb[n,eQ%We4y^f4y.yIY EU`{;`d@/9_{J^d.&\5_x{&^MMb~iCJJJΤS$`sJF:# k&ARA &61OBX ֧e*tТn|MA; !-Ti:LQM[$UԒ,D.'iP+WKӚ 76b/p -?%Ȉ [lAGA~PآcGYj%t K>'@$t8 Ln7R'Le\9] V\ ;Yq:kqPL; laKʣ|EVTWu9k}Xucx:W:NtdܳG@OzߟH]mQ2YaJFӨFB{8Z(`hf%bg"宻: b($ FMm]Aa((%oH_cF,]6B!j4GͶѡњmjK"hra}jЗ'6{Di@cSH(+r鴔qi$ Hfrp_Q.6aI^}rt*]+.rleH[D1Rr2\j?9m֡ NΤwhs&s*bi0 > @λDȠT#C  8 ġe ,CֲJF/m LjOHn h/>$KK" $0+FMhr,0gRЩn/9鐌~_Fivb +˼Wblf hZhΡ1> $-ƸJ E2r%*m@ <`I*ЄO*n*¯J:QcO.Ƣ;] +/x( /qZv/j@Y~r @ըLE8oV`@XK꧒Jhh8*xH13ZioZqImPVH&$XfrPGtLyBm% TKL~N:+jO+6'l/DzL2֬Q/yxB(W,WBOfyTNx')~&2SȠCs萚#v-C"2 i1.,Ϝ),P:aT*].(`0PtLJMb Q <Ľr  դ*ld"K8̋FmlY_0BBSiW2qEov3mXGX2Ȋz48 `(]#q'܂X'f" =Ho7Rc&,~Œ u7:kj5hf"~N}~G]{4C̲doh QzO7̔;IcُV 5Vtv\@v˛T+3t^ x,%*LI>Oԣ"0@o!zKM f^fBDVFoMnY@DZ5V*2-Ӆc /8muvp]m *ԮeBQH7"* :GMO7 tuo*$)Liw{{Ϊoe8<&+8'VP3Z)VWEW*u, YlV04IvM[A k~g/)22Qx3VbDq X`sar$B ދەNDKζK0jIsh ZE؇k/HyC8CugCZHyXfq%Re KŪ7Ut_C➅Aq*9nZh hgVB(頕V&|H>瘮,WN9z24bL{-v kwYړ춈@:|Zv!9a'83:[ڙ%fbHX:-  r!5 ;Ep49jCHx26{3%sA3Gq1JhSPSf\&PҲr\#C[%ptM*A/}WwJz+Ԙxȳ>Q3FyKθ S[.}(X{%VboLԒV[h# "i[b s3DH$C4+.mBӨ"0 `03m\?P0jqIHW/H o=Zl Ev h1ћ] 6DA UTbџ8XK&T[ۮFTvd眡0\\2X*=E62Hv=˜'6; k˿G?s̽{IOo3'QyvXz_갑@[\8p~-9S-M9tٍcx=p5AքԂ5;б톗-X|4Jد-ZOm}is(pzDhy챖K|f*]= "`A'Q >q Ç:DC+*QdcǍ?"2#Te˗*ĔI󈑛8s,b"<}-BСF(]TiQNg@%2dUXVʵ댪_g%"bH64ҰG]<ݻ߿ Lڷ-lcenJUթ%”gQDv6c”y*O&Airv&I"G+j|<ƍĩ(Q GT@yN-\``y=;w(g_ϞJ*߻~,U\R,X h[  f`[D rAabErn($h#!h[pb/N9w^`ڗ|LƇE{WiwY@A7]tVD7Aq 7ro)[mRKvZj|֤M?Di@vRI5D4YRdAXeREjdC|ŕ_9[m\ofO^|eꪬ[r}*bek9)U]UiKfnhfYKtIRnAG  )!Es'Ps5TPE\uO˧ٱ]mIIq ѸA-CSDofI4tXh.ha詇%{Bc_!d9; 6ˌq!CdVMa8Գ́٣BP%M ס^y֥, Q؎BgP"Z[Su.d[ O;ĆZr23DA>%Tn,@+5D TJ.z.! 2e+Ŋzܦ|n*MaQ6.'Q֟氆ldBnUNm:HΤ49B@BQKy3=,&c/+TJ=)) )+@Y /cQf侕O~%3D3^֣_GؤؐBH9YA z:xd .318)'NԢ'P; ʲ~") ]P6 SXF1 .ZܢH.lGquFI+ZK37J3j e$'8iiǂrZ?T[]rzi1#"`“65遮eX2Ӧh0z2WglC_3עe/x@_040h<'{Jyxii )q " 6NFc2OŊV KJ]We*J2JjlEDktچh{ݞ^Tiv!ڶ@L8iTuw#]a:׳ՁprzSIileϐtH6H⋫抠_ڵBWZgUd_K&O+ʹip@#~1gCkY節h hCkj_f#1\*@w3[@ԏuoOCBn4P5\̼(Va)T4(N1s+T:.H981dK)nN bcn>ufԼvvz@zZN͝R.KLdAʜh^.⥅Mz 뒷wVX6a8jK OA1sĮ?3DUъb G,3 (׸*pD6{tU=d:ɳKy%t<2Qg2Sט&W#%ĞU(Sdm={g0Lb NmT%hGnƜQғ[e*MqsCNB( 磙:Ȍ3uNՈBON&w9XC'l!J02=+=.P-dW,cu,Ka8~5渗E2ʱ=bG0GIEY'-VyDb$%M[ewk|)v| rӰ'EӔ!Foy5fJW\](@O]¯ҙ"{\MBﱄ#tT,}'xTw[e5PBZfO$.O hvodD%WB4=U gV1A@$aM>f3>U Vd#yC2Wn62DXBnxn'mKK=&8K@JVdf=aJdp!BY 4A5ă$&H[3D,HG5CHT2\;(F,'+69Tq+~QX~q~>~hjAhfb+S$kth7Ņ^ GFrPC-1_e_xH;5-ՋZB\fZ{ZO  /Z00AaV 3do% -8J22#@H#^pLn2&c#"UcK2@ c rKTdW$1KzzCC%NwFaZd1&tX&Z*Tou)a'yzu8T[ ^D1vs}wiy9#858mQ+*sG9Wir)w7K0\^AAVw_Ywc['|X{Bab aA a{X_ s'Jbd}gX0Kਃa1JmK؎ҎU?Cyn)M@1x3#\2x3!KEfzfYZ1AdY`x/% /S&N{XBkV35;&o6$q+UTX|HHsTg6r+mgs8'R#eGdd&L ^/%w2F`T:%2j^هqPxh-#1r;+W3 $MDŽLXF2"X/FL䆏-#M٘"$3zya]hHt%veHede-e k_[׉q2u.6U}bQƈ]YG\D?'t)Ep9+,3wSta(pfGAP5T'vr qXUoUSi4daIYdž 0?3эCbz? $bomRB-cbO$(#UL%no]Z##mYoKnEY l/SVeae%y.VOc"5 O2j0au2+^?[Bjq}J^fikfsItp8:iSODi Y:]^iCh6jJHۂ-.-Ff%&eD yJQ 1Jwkk'G!pUo]0 >ӥ*b!񨯔WKxXcOؚ`:$Ġ=9ڰveJEpwpk`jXUOq85b*Q}6`,\Us#\7r{\Dg@ ֽE;L]ahR8VDFC0*Քsr}s4gZruG͒_IThMkX$ew%K 94W#SRx ,o>y?\&4Xĥ6Ν;1M0o3ARb44` Vc8B벱I\\vO*644-ȵ*[T|?STjŲ}Ȓ]9G<]#M%SHS;iSFV;::e&ǒƻ*\WC__B&jk%y%JVV<`p a֚xK#s13W.bv`W0"Xnix1o>@">wllDa ]Dkle8Oաj `$gg˨@ Syщ7LܘьHFF~j_i{EEls`UQAB~2VIDy:R1ڛ,_hvVtS|QBhg{ZBTNOԱAhpSA<4GG lՉI @M؆xjn?-"p},ۖ ٶ+eE<:4Q"z`W%HS;bO֞qq'ڢȧ'}h[9f:,7 g5iS?-s~&! %թ'>)|Q[QEoTinuj,K⻫FHjhEzz ʅ.WnGpFAm%ۭplx -m K$:R{̞'x^–!?'"rm?Y?y5x kz=[= AUtiW'DOkYs:lY1f5W]'U|!:kXSK[M"5O_{+M ҭ-E!=ۣK*# :%z2ONX*$y3 :-D*<[#4&>* ;%b[ <C䢊-1D 5d'5tqS4Hoafq1-g"(.z+2j+Hၬ`~"$[sM|ߜS{+R饶+ϚS"ś9QGM8$pJVuO[KQ /=c5V[%lV 8]G'bBa vʉX­!N[e5媈!2٪ZnsZߤjyk9($C7vc]Վ$Ώ# b/l *M$喈;QD-*VMpaD#JYPb@Jf3 iH5rF3uЂ=t!IA?F J ƴ-IKTZ~$05d" iϜ܇xd$VH&M^Kb܆Be':u(DpV<S%KT9Vi@s9TnsLfeЉt$fAe3~c^Hϸ.jIM$wi@6כj-(@/z9N]Q{sW'Z&QO%Am#{Dطa9ġiaDaPU?V@1Lh 2أ}pGY~DBpLCCC4^J Dé~1(µ lkgS[vf$t|[erPPRNRdښTLmjK$Jnri]u ;T1uv4 gU>ҨUrH֥+MGcHFJŻTR$)GE9hsbE2sLQ:yM$q׈0=I?=%(5lDn" ^x ;h>cg)Nփ68؅Hl'wvI.t1-BƒjX hAW7 _Z'=aPy'j+qqkc5RXSXjƫ.+˪{%X^G p! ER[B*H婴)^V8ԫmDLV8Nʸyw{\kIdt琄I#La% Ľ痜֠'B ZZۏAhFVnR;.3g]Pl32LGDӑwN&eIfeZI ^".cXgF4"HdNe+IrmufQR/{KeRp Vo02.pf14JhNIU9/RW7`>pgikpd_GVUW] H x]5Ւv:*rq7,6E>ј:z>|| ܂G'Ӛ,CFYTLB79)Λ i ;"MR$o8aD#r]'%Mw^5fG 1\ 6$^lqp Q?'gy& 7AKf=5z7GI9 Fy6mg bYVS>t<-Mwwbr_&Iex6 )hl:cV02!(?jc$r$8ɱ k WQ6JYܠ$;MSPqc(8Vtkٹp ︱" <:4x,~c~#! Z) Qk3%y,s82b-=.x32,+=ېxR=*3#"!@#6 ™{)q4˓.2s)Nذ32j׀¿8 U?1, XY*_ B@E{8;Crc:ۡ KR Jj#mS۶I4O{G #ƒ.# H%.%蚂ꚗSb*2d22c2 A-&&2ˬo':2 Ț1=-('-*!!C<[z>[+ث !ǵ>{wI" $8Ѵ;˰4ت 3 ,@;J;BY$0E[ W鋱`0 Q5K66:ڸ66lqhS «iDld]r DYL3#'K˒9L=|J+GA#'#'St3 ՛G-;[ѣC~Y.!zs4({;As㐉z||p}0j9c(35ɘ۱DD1=N-:9Z.p1_Z6>*"9A팎:dAG)k TDf@OQYN @TةԠ:WT?`ˣ_Yi)#8zs 5Dʊ=4$E٢Lc܉q X.QLI357 QQ #'aYh!)lܤR3Mo2 ʠm%Ƚ2nR$vHdb$#\k(;Nj`(Z8(9@7*U<c?<PJϢ0 :XERHʖ-6T}T Yb-U 3O9LJ)zFi$/`ڡktɞr[Ń1¤|77eSs7ѫbцx\ٳL0]&k;=|ԛ¸,a!c3mR bu~VK+H{.8!=ͷLDGPܪUDЄu%Up-@ڤ*@-ARخ@Q*$݋UEEu]^=;*;JcX ۡUšgfޏɜd":5XD<_EIs.~1ɵcJѻ/32\BB*%Rk%.VU-r ʑk' 3&iMa.m\BBF#&<¹yaFX-7 |gN Fbà Tgf\˨6 &蘆g^h&;頎rT6FVfv꧆j&jꪶꮆ]&6F^jbv뷆븖빦f룺&6þFfvdžlSȦʶlm&6FmfvNՆ٦ڶÖ6&nFVfpn&oFV>vn爵op7G@*gw p 'G6gwqnq 7"7r&#W%w$g'rv(*)O-O^w(- O$؀w^q PwXl5gs6 `8PsHb8:Xa ØX\i5 s`@JO^xO-yt O@i[5wsR`ts:4\? xJGt6th`J1X14@ cf s:x Iu%fNO-GĘm0O(YYumw[c(iPžt# rf؀aHx1tÈ:HbayhSAvڊ-siƀ2̦_]h JbOLXU 81o=@E2kEh^E}][{NuݞZ/EJrOMoP=G>yc`n9SMbWKoA~G08V.Kyc=t?[~KLVrp`ah"+_1CS{g(vhM#l.)Z=D` 99Q%3%}}z4GŊB;0WĖC(& K˶P;OZbA #R6KNvEڧ "1) 3rdmdz&}#<+=w>D9Zwsp ~hOge2vXcIGf3 Ӧ=.Ht\6''`rLMq\D@9NU V-b1,l΂p"ٵ-;]ݼ"," mRQ'"mmPTx&l8t"mEvtQG ye^Ĭ k9fE[nk5e/Z|qGKn}zO_qiѕ  RYӥ.&̛yKp!#r zL'q͂p d'mCG{./4(9E8V[6 H-h((g`Y n:WEs ]}%{snz4m{+IL}Ҩ}l.HH/iҞOm)Jnr*P U3S]+- ;ҶG}V۸p=|b۬$1s!D x*hnx4Q$ZӚ @i[ /Y!x\tP,Gۆ1O"ٴ` 1ᨅ QPޣˉ9[A`U8\D\'uQK@bnݩ]8#)+:"|=rЃ':6{$EY֦&&^XQ.AN(X:ujs\EYtnG!˴ pXmiv8 kYȣ ~;yoz)9 '>Qx mơٳ0GQEt*'s]CNH>CH,YÊkIfZ+j$XkQplq4 iǂlzkľ]l*H)q$xʬmЖ-Y&-6>-FN.-^-fn-v-Z׆؎-ٖٞm-ڮ-۶۾-ʬ-֭-mڒ-.&:l.>.FPN^.fVv~.-.閮.Ԏ..붮,B.֮2-Vl31X.oV_H+nc@>1k!Y[bgDv׿{%t/=/}wSp/2M b-1@/ZpcoUI/c=Iu1h+kX0n(A1Y;, +opqA0G 3V^epc \oŖ_h\4d0M1gԉ`F}$؀ tKf(Eد~5(C(0C&h*$B4dzXDA3CDIgGNUID (<C!qN Dlq a7m\r&"o1*UD,YܩHt*ūs@l9V`2j2)L1ECxlΥbҲձgqUD/2m=raL8)F7lil[QoEۮpsA1s>gr_&S'E;J3#i,WD$#rXBAʡQJ~T55uLIYKdžJ~fS؎^t0 9dDP,N%X%إTtdudAtɦ0UlKZG40:Gx6hDKauON_'5QncVf^Sby9P7IQÌ6xaZP/1hEtҽɀ|x cEt DKL gWWzwEM'v1YJHNM%J'V^ IDkzԳXQHPGTxpKJln^N!_(W K8g7NON4h_ +o`>btb4=CX Oe8I$E N_\b:]7L=/q6hh7{yC۷uneu[mgI;t~1h4Vv/[ίGMǝDň+~(}AFTs_s6BR{FVQ#VߘfD@4a`CA%^BsXaB%\Yx8Tx/1=ǁCy 3&$ʇ >hgAf7TDMEc |Q&͂cTH/`ǩ$kJ甫OMչ' ać6q(W9pR=nJbA{WqcۥR*Â9 ,U61XBzd 3Ȭ9n1#AdhC ?^bdZmnƻ/Ǵ'H[gl:!{vBB q}<ׯ~-/ha)fP`s&s1,7> 1tQyǘ  aT,E[k 2/ 6H7q: ;DL 0\(JbZ>/ѡB 344'YCL)̽+PK# g4$ D#l͡!zτQ,M%ǁ>m&CTn|P=pr 0sp:9O 1 A՞JϢu*Q;4Yh}S y(Kosm?9|h9tȇـ05·' `{̀(K;6X"Vf:zy1ޢU7=QԊvED֡zFX#.&S>mgL =wpyS8u(_:9IF7犔%D{-]ykV ڡFok:YU#*:GVevX@uW3;hzJj"y{pAR3@Ӹ?"B!=]uzfNfAڜ+2{V:իM 5(;e)=-sH U|hVıcӡ%0Z ) '/tݳGbCi>  d/jbԋZh҂*TyP%K)CޞBJ̤E@&MtSt:2Cաj-x$i8+W{`sVH́tV<4(E<1āqXH*2J q@tCLY-O]P hAis٩,5ՐtY jk^J!8kAjP0  p*2f° zl&!ژO|Ö ,(! pF)MM6+#,oM$=B;ݠV("0g<-&!@pY]|PvBF1PC` B ~L @yf~ (f " OOhJB d: rQ&$)J.plIG|{a}#⋩Z.^,\Bd+`e b,&#2 ;$"9 2)@F v!c&!S)_~7 Hqf!b @R $ǫE'}>h7C7ur>a"ˊ*%3IAK$r4]@W3(ooA&) \!:Ah/.!I^(ӥְB~0M$&(B)Ae JbDS9KQRO$B)(>ǩVfł2 e*gJ}tJ;@gKFoihj=?oγ>Ayɠ2ΔҴKYf5S)_j,^MU2d>%Ivl#t;`K{䠕R{PLOZ B,cJ`.!k#q!ຒq>eBx1hHDqFKPv@T$D,tK-k^R1UBNiDSX"Y)5`>߈8m~:. @ׄNΠΐZ[+[?T#pY 6uܐ0r`!6b*a.a%6c54Ρ c7dMV-(c0Tqdda6fcefm SfuvgU0gygv}6hhph6i6viiivj ij6kjkVkvlc/ll6mٶmnm6nvnn#nvo]o7pop powqwnq%m#wr-wl+r5Wk3ws=wj;sEWiCwtM7hKtUWgSwu]7f[uewccwvmbkvuRsww}WF{wW5wx'xwy y7 wz zw{{7w|W|ww}ݗ}w~~wHWWx *dƠ@-eg+r쯁UBn!.R)$` z>x6-!FB hM\) p\S_8rcTe"B@1yKC.o!5@,⡄7ğAZ#mŐ/D!Dmvi;Ԋ^ >4!]A"ڸ:w8J1O:c  ƀD"n<.fD8(%oK 攩.PĹ7 !9xvY)V1`8"9K(PQ8 : fX\_1^N.T,$&q V[@=ߨQLP{܍UYׂY"Xß͘D6Y@insT ܐm4''P,'x U QQCͥ¦߭HoFNVi1"-ƚ'xz; Z) q(:DfŠ.J\og GI8rR۹yh .b αjU)1t E r&n(4DԱ!:>LjXǠü,A@ 7ZUfRCa#ٮԻ;GěQ-!_$X,J|A0: CG9AyQWiv3&u4Kd<7 :\\{4Eb#P\G7Z-iĎ `*GԠOQ'GGh\CA <%(ܾ7ԪJ \hCWNO4,+rT/3tqcG% ^ $;O]L蚁އ "`ZeҩFPQ^." ?!%(Bl!@&B.<Z"/2#7Ep;M")&ѓ׏EZ]'7ӛP/a408]6,ݐ9!Os+ K]G)(vie -)(f/PΡ H@+b!ṬRJh)+F+OI=K?'}>Bʳd&ƔB/TR: &#7埙'R4D`_$pY?zPb[$ fM>ȆJK6K!xU?!TifmĆy`n:(Bq6+XlØf'za6X< 9^s!&XG6cώ3Vlذ5n)tΉF&]aԂ3QnS1mr͉%4s *\8C~u@=6q_B}`7^Bt;1'F+ F7oC 1Olh8. Gaۏj*zx V޹a)@7kh=?>}`ڻw>|b6މ\!gvD4 ST! (ra aGDc(} VV)C)2`3s\!A9:y"Oac+TXlPMbƣD0BlFXcuVZJ*dcme[pSTғXlSDA*/i"mVvyr"9=m6bH3ѓoړQUtS"8!;_{=KmԧgQ=u$U \7Gcq+ 23cvX%;Q~HZCىg;:w[ePIi,E$ 0IU ujA0Tvsw 4^(YYG݊p1(sTĐy a>y/~\tƉ'/Q1JTN!VkoLMT"I} n"oBk<@:QG`f=GGcDG[KzJ^骧7!57܎Oѧ|> m4} ՞D*e7~93&뵢1Zb`:∵^Ov}`s{Fګ\w4D;إ` ="=@B^!p;+=0 ^%b= r3mWuăOds2s^ɯeGŶ*a UC! -ʩ\;&0z xd L:ݽ2>gc XҴIk# -Df &G]W=>Mل+|&-Z1v_x#TzIO ӏV6@Y7򲯽ylY]){!|h3uo>{KПk]ٿ5/o7?Q|(Hh{ Ȁ ~ (hȁ!(#H%)+Ȃ-'1(3H5h0h9;ȃ=|8A(CHE(@hIKȄ5MQ(SXOHWYg[_aH|](eh܇{gHd j$vϲp DՆ}'Ef=0p@WpucnyxlnSK(~tqPAi}|(E7e7r9gƗu\g>摉؉؀8d kRIrW3'sKȌ 0|7H:8}xڨȀX-@tVtƍ{8~fFV{%Bl{|nH  >c iJ"   p` ‏sE7#̀U lvdP _tmvr$xr, jtP 3 js4([FvE'O`b0ҎSpkUx" t0ճ"_@ }'cf*zWsToqL2?AVz(.q vj7rɡfn  *@@ "SF`l3kPQejpb%qj0L)h0h!1$Ex@k bwa lpcAj{J &W&/fj[j?Aiq-͠l0M1x1&s"ZvSOᵤo 2kD`Ezq!T[2u:t0O%z-OiZ@ʪ9cpuqfq(ELLjj E9q.Q!0jeey@*IDxb+baI!H q35nЭ-5͚ Y|JtZ/熜a2@*PR& U)#p($( 9ip&[ AɰA#!ae9u$`PrPY&Ġ$R:1bsEQFuZ˥3u:4TeT=m \2hR:q+W[+;e5R!$zKZdrT!a{'it!3Rxsb z1hJ ! 湁1bKbY$Nr«5kLuVC1HU=T{K m0l3%G}4W!y=ː8$\ JKQ{t-6q+`h:u(sNQJVx̴bx;5=aK#4! ťB>wv/F|Cf%DĂ_c23Il "ekz,TRVl&c;p|bã cGJdLT!=bv5?汽>7>dxh\:aQ Q)k|2)JkW= ۠ IE[r|#!Jk!)Pp;S*Wvc)<>RZ%_QH;\@~2AqXA#1|C_Xa8Vk[x>̛v8q+7c pQm[2-b2KJ2|H+3Pb.jSF4+._<S1m4 F-L|L xI $*< ~Eܴӱ;d4wa=3|\sЁav3Q4 _4B%T( Cc[.;\?]Vsy.R.6o_ޮ!?beFx|+Ac^ABDDOPmDoQn#_Q,! ,! ,! ,! ,! ,! ,C"gy*\yŎKpz4%bŁɹ9t>WFz>e1CEXF͊x?-79= thz𩔥իhِP E: @k2fP kf]yBz{.Œml%8= [:tBc`f`匞[5cYlY{3&o1RA\U{r4O0y! ,E  8`1w&<ώ3^"JgϠ9 8o ?֫l<OIIzx4fT8rN=ys4M3( +рtϟ3.G^7RgxU XdkTW^ɞUmUoڋ+_4&{܅_gI^wJrwR #b1WV|x *@E4g?ҐA1Z#qn{O n]~NƁK x! ,! ,! ,hըqf7n"T56\S lҨI0b  d80aDI)'v`C.mNd@9aI7h2D:%D5O TT")RR!”V"dQّ=JUU+k~:ױUs&nȤEHY ud\JĻ2۵*Ir4.څ QV0MwD=_q&4b(f:-wYw:%κO]oqߛSy۱ P}L[mG ñ{U7b6q"uo-S^m]&$SS=_jQᤝ`vitGAaZqvB՟~]]-)x=fQVژ5چK5nWmD&PPW4d&&GO7WV-YVVFchRZykK͇ @cvgtAwZ>X$ ySJXRG@9hRFP~Tj|~F(גZl%*무j뭸뮼+k&6F+V;vzŇ]by؛|SFd Ei8VpQO\RczIZ99W 驘'oqUW LZ^'EXqǐI;~I/eX/IO%<hE)߻>\fP ZaO_I4doGV/IF4,ofp<엠ZC@{*S+b3_aWڂ"8~n{b5-`Lf24T-kL0pP^rS,vI53ih5fclmixK(yUWE޳Meūk )w7My=;i}ҩ2e6>QW2Z"Ae~ ؞l]L,edgL |\h0I6'O<əi׼7G; uåF/?pm:Q4ǭ,b"MHuRdet܀iCXud8{ D]tQ<)O)[٠'_^I-R9_4U`9g4eRM" "10Cc g=~)RM>Kg!%Ut#eӢ[]# \"HD%9d$ױ<̵ܾ̉ɰ!=-ZҒ#UL?$(8MEP@@RTUuqvJ݋6+tE(R Q gV@ j0O4F}biïIvJ'$̕ɱ@Ȩd C~bu+LlN'9L 9ogxIcʨQX>fss 2{(u)Q^#W$.DI#4Q7Bymj[|B$ lXG>[',1a_+J$Z}.66]2;=JA#{ƦqJm$57yϮUw^x4kB ږiC&BԾq;vCKU_5QI0(؏,ٿCl{X0rZ)icpL*S1ob^хKNypBnEeR i24va HUMEGAX~|WS59LF>0_\rtI`WeӞ)S&==nڗxDQa-4$67lU ·p.2L)fmevh`qtMp+]MZkNSr)|M**Cx\fEA=l1|J4Ny{̧[tc l W^PPhCO7l2sY*y8pɴ4_}d|:qKC.LEncH!e˦Zł?#u{PDc9xËd% ٻG7OD`̰{2aԐy}mH;RC8m=tZMqu[|+v9;6"\8hUeL\ c0 z. @8 K gC.O{\_Fu~}23h(y }4@Սx\G(]Orwi%nO0lm˧oYkDv-8t'$uv:^uQPO]d<6TyEcoR$d*mr!U5b|V"OGJPv/w#s_1CaKaY4U4WCRUQtG 25]*Pzp00iQf"'l`^5W23')FX d^j\xdGiA4v&u!$wF:';Es=/T/G_X,]Ld0be&eRDl/'TDs<^4x4Mp7cYC?yz6213]#c~41D~CBҗ3Qk=7eB>.phHEF12s.%pKœHsQ{R7iƁ7qUEzP{U{]PU'O\E>B̘*V(CTIB@l8`wB5kduC.}}"RB<)d6ChUCLv"qx)CO"_8%[T]֥UNG{ YXy3YZ*6n@T cVR7Ayq4NknC `uGT~;3e<27v4t2aPa9?u[8#K9"i0hǘc bp!e5ey*l0lq;60jV9%4}Iw95r#c7SI;F|mI+\YdEZ^6T6BEF%Tw/R=/M֖7$ieF&6X&ঌtӒ؉#v}lۖQ™#W$bF8mJvy%2?qSw1GEK0w>ָdHL@vXDhWt/'ucHBgDɓ *bz Aw[c@Z? !iPlH![G*`gOiLkDoadWŐ3huPvyGDVFLMd#2F\5CTQR^N<$%W|nPU!'Fhw>%A|.WUx=gfLQT<~=v]j>v7Kzn=95TVQ$~VaRz8tg4.j~ h:b,vZRp&Xz6zwI(-;ZdWzX PXliZk7{g!Pq(SQXGLhҡ<$tJ_|e23 j@!5\'^Ic3ʌQ\G"LU_7")hA"j#YbabPQؓwADDY5 $. TjvI1sUW:GH=Ȕsĩal=L}qٛOihJ‡Eg),#Yo-k@1Y]`:!c :+{iLщ"Ip(Qœ -NN9aj)<($:Xp1V#_?VW3ԃ?27`Į^Td L <Ā2>IRtueddۡV_(xQsk5t)cc: K:dxe×nLHZ2U/eq\)K-b)m Xq0E-6:Ƕ`|^Z׍w:pbi@qe'ҋ&m!<^ w.N;kƖt(ک7 J$|$z> W$:=n8( %"# e:GS* S\q\9+H=Já} 3O `\\j{TTQg1EΛ4fk+ia!}| c»P~#Zki-@@ *k{|W3`4Ι&zN7mxE>XTNzEheogG!McG ɛyGmfS%v:; x OHiB9eюHUyڅ >멭'HpxhZEӢ ;u"6!&J8oKa?߳wjrÅ6GLs70-*]L `p _QQҮiWzi-[-Țnq`E[~&PL5]*l9=拢5 ]ǵF7kYCЍhd0A P!E  <r!B5&  ^4HQ×#2ҍCwִɋ ӤЍ![N(eIRmf\"ʋ7ьBGJ(GhK9`Ɏ;o$ O4MEq(X=(sZB K#Tx׮EUdsF[gg\M:R37 R)Uj=:CRvYf琘yf̻ʭC>@!СB 8DS1&lL9) "i8 (BdžZD.<(H08~Sc8-$b+K+ K諴 1\k."64KT(FH64 CLMEJ2 ܱ2$q<*-ܨȕ`kE:4O&2.\,M E!..=ʈĽlD0l1RJ٪5Һ"ѓ4ՠ>Mre3{TR)K=tFWH^eWNiB] 1% 15` {kG vݰx^1t_5( aޡ[#ᅑ/@G 6ĬD{+X4s)?=I–Q cW\,C 865Y yZHFEd$e\I%PU%p(Ln>F-N2 P4%O!o'_lƀP7^#sZ9V<;0CmF7ꢵ;Fy>6 Dw5Y iqIqx#Bs1D:uB`@!Ɛ}:XC.v!${cCEb(mIs<҈O ؀IuƇKvaj}RrRSHxf=c ̤HT%,P#Q6:Z|Bk{"İ8 g MRJ!hL**DՄ&1asPOSWSPb7=lI˟5;SHMTCR1'Ü0BLOP_v2]Ob -,)A7$Z-YjfyۢTFi.)KJٙ$%%ȪUJ*dH#HhU"uB 7fFM(ֶhn5({ඤ6νSQXΣ%a43Oª8WCJ"R"_əb^渵42MIg9bSDa&_Ϩΐ t`mu`u+,440W@+k؎V?lZUxmKʰ0j'ah@ ۮbe^[(9" fi#Urb11v܆( KPzb5`V#͘`bαw+Tjvn6O&UeYNnv0QTE4Q'޼H)+:KN6;jHa4H]Y;o]l2{&R+R7TQyy`Gaِ1A^@и *~\ *Ӏ2lA؀vrnC@&E6a$LuiR8Tlk!mB5ҖdrRԵnM#)n4T#5<5SNUdҜKNmĬ)ս,ӟ(,і|DvSD~U k}|)5l4H /JKhٻ@Vu ."=Z˘ 'Xh %6tl=wch9A|n 5/#p JvI >>7/sA_'mOucIR4=ttC}M D- 3Ȓ !^b {*늓4 0i> )(?#<<< U3]x9\c BPZ98'B m[!?أ7B*I#x#$998.ۨz4"첼Z 1W4T)XнPq O/!.K((lD4A22 $C/4t"YHs9AKLq*8lW @* Į _@Ȋ .O)B3jˌ+{51 -`*mz5etCq `8`EZ$x{.=.};94H3Ȅ /;drfE|F! 8s;ҋDId-bH3.[D21|IHC)IE4Ʀɒt˟/@i^;ƧD+QA<ǒI?0Q!i3QIt <ĠAjϓ˜A?b@G؋!88AGĔGx#{7 a+28M4(1~l/80zG.Qfæˠ(4*̥s%/HL!D?լʟ KOaʟ# uIJw4E =5B'RI \Ng:9#ӳɸJLw |I(.EH#sIt \YbYIčJ@/bR5A[OSDLs+RQ?# yC0JsFE[/SZ:z!FaϠ{&9aYRDI,r&Yh:Kk<\ԏKh)8R ҭߓ kGiylqO4гNTO:C( 5gHϖ9|isáDݮBAJ5jTd@rF7HM$9L<˦RK>=DXK+@ZE{'PҬaCυG5GVLBre$s{wSÅAz)X3UAZql}sZ(=l B(vZt\'2[t0}s2Im=ۼř5ܵ5@._JzEO~e:]ܻ{'D]\s-[%YRIg#K\Y߸۪PRE0ݮɍRX7,#ެzT1,~<\QìBha3`8-<683~53_=3 u8_5m`.21_F&M._6L ^__84_`L2a_v%4X_D _Vb 6b 3Pb =&v2H3  &&b```$c*`7=__b'N`*-~`A&_`,ac&Vdc`_1N+_ `4eeM3O`,L4_1+e5#.f"Z^`0.f&-f]_aa(c^4_<~f(a.NNa]c4(8h8.d-5eegwb|`%s#Lcc>^cndnV erb=c4ve^Pf^ޫLǙ~  iij(iijp6jijjjNNjhnf 06k(kk&k.k&jkhfF&kl~ɦʮl l̎і6FmӞNm׮Ֆ^m Xm XܞٞՎ nޞn mn nmNnnnnmvnFoVommNFmѦmlmmVl>lNlwpk뺶k~v kNkj몖jFqf6W꥖j>jvwqZzA1uLM_%_5V%%q_ꨶ~j7jWnj&j6븞kn?p l';gsV?mφl֮oD7ӦmGGmKLnNno&N䮀nnF6Unl~tݦon[BGAm`tV'pFgNĦO켖ksns4gs j6Okfq?ps.ggr騶q+q&rw iŽ$%w)*?wrvny7kn kpWy:gygs._tCo ufyӦҮ7mtކnoWtNn (>Q_uOn `n zvnUtFJKݖzHOtDAo_oAaybl^pvpk xnWqWqs/?txFwx_z}jBie @}|~x)i'Ow>ƾ+/qq긦v_vWO;yvy Ȁ h] hҮ{{׶ *T@` +H8AC&RX1a‰'j8 2&Ԑq #'RXAŘ'?Ƭ͋$ "O-PäFlhӨRJ !;rk\džU,ڴ Ԯmv[6ݹy˗߻3(0ĉ P\X ,n̒'?f gϝ? 1J3f4lѰI,ܺwV;o5Px:B$9ҧG'N=u߰GlܳO^mmֱMM{tЎUOn|[hDž#'Lyp EY_HU{W\beo1WZeb}aWF`P\@AT]uTHPdA1^5VA!X4"F5J%iD*$L+ݤL0Ieԕ%$R=dT\tDM tf*jUUTd5u!XimUWr!4ৃt%!_z)Xh_Xa5`X=rVc"&_yjZgcї^y xji|w]pp 60ve7t*\zlxkjk&= ga:cڟa䒫\=*ػh\yz/\򹯝e_ A#2ԢA Y&KTPc?"tq_#qܣM$E"39rJiF,TAK(DF31eFai%OoR"y=UEtk!VHןNx^ x( `;؈a+b 0v-&w6j؊r-zl6,V'yp=Ѐeʞ{=0wRiwڒ"Va#Vh> u<8NP ,GmH#2fLPKlR\)X#JR^R4L3E(dOrd2CwB^@9,z[tE}J;ū/f7.m1LX7t"մ>EHYܬ(W`W-Ё 8GXbsD&slS,T;ϳHBoe+>I! ]wa*vj΂Z|;AAN}J`% _K;RG@:Ț-_RJN¥=#;$Hl%/U}d8OcEA 1EyNQWdOAJ~ f:(GɿNLԤ|ߩs0)D& t*RgdJ^F[r1ю-.0۪-m>_"bógɣլؽDs@f"KV" udXb ~`y3N9Z0ZUQQW(VdD`ْm"TҥR$"P A {E( ,̢aI %KK$LƤL$M$NN$OOMPdPdo s\ B'A.&rB%h>ep)tܨSuG)K箈A >c3:nVI緭`# gJae ܴdN*]U'…-JX@I@ܙ HWyI M,(U\IjREPOaFIXđZL8$VD#!BkPǸZym NV@r@ \؊/@-u{Hi00`GUZVEI^]303P54W1>i8mrs K=ůe]s'ڞ1ox۽^ }^l"`ƳGm֋U6՘ F#.ʚu,ý O&eꅜ! t hS\A&(P\UWK{ nE֪ȨFOlKd"h%!$f6m-iEN;Gn{o6p7gq"e6r/wݎ39ms_Us+TS֓ί34 ,UXW[zNvK=7p5jYc \"O)NuT3q`. 7WdeʊΉN4P8FU,G/TDp' eWvɴ0 (AA 89C90y/AZk[tKtlK@-?yy9t9c3oWu(ٓbu/U:grA pcI|gηZQZ귰'@3rg@H}uZh膅 ь&9?*$AjFDKG]/'M Lt8GrG2$H2ȅ3 W}t Ǘ?|ԏP???L@T, >@ L8܏A<4iCHh* rh R" xH z\RHNjv  4R(Z(t `,)$VJdp H|6?+ e#$ 2P3#Spf30$<<%pl/a\;,ȕv$ iIuEkGQfAQ$< ]8,,oJ obAܰ<Є(殲!xIj)HRf ׂ3O@'D6H@*!e. TdYDߊII5  p"T~]ɥ ᚔ`iA,IO=m(2VCYdɐsegD_1-O=rzXJ0R~\ :0/RK~ʪE,d˓ٜv\tMq65:P8T6碵 0=w3~~jY~&?|cvҿ_Ê&7~ 2Gv3x ƺy͛ W@z;X GMsvv+bCr#kc6P"#>"(]LO!&F14! i dUl7F`33$~Lj†2d cM`ojuխ8y XiaQe2xTJ(EH plCZt.+,O* hEU{L &.zXct*kbC& вN8nEd 4 |/$HB%% 1 1SUr]1` 2s]jtBO2䶢X'qWOtEu@Gu<*.r3uh'Q )XW:Ю54Wg3u +4؄'^\uI7d0"N:ԇR+hr}}+##ɝbbX2c@2bTM Դ&&'m) -0: Pxd0DkKj*Di 1Q@\fF\"lEE1 T @ 212:bh#3/J" @`5TTjqJCJ4w^-RQ@UҪ8RTQ5-rK"QWQ\LY 4b*ڱؠpw6..T@Li1] eRBuꪂ2U'}n~ֳN9#0%nڃ;F HbkR%>(&N'MĄRA.'k, (YO0 !oXݶ:*m",jB` ֠ 4G,B@1H3 hE2,ҕpfIe:0 !wb3|c@''Η\'!C+ :I6`b2 Iv!ibS +Ne';k2UM>;sRk7gi9cCg_^uMW9R4XW &?@ $ Km H%S> K@Peu[5\[7p֚NQam vQB'΀ UTHh.G] @8JwI;L$*zAz.ɲW) 3`0RZV3wh6 d'yUPy:ayWEWT_xl{1 N!^9M|X"3n;ƃ>EV/&߳~}=slrȖ k/XN@JmծpnEhejE*d5p\F(1T ! =&DCXv}F*RqD/B +raa%I qH^3qܒ͈]*muRa9bFdO0^Sj#S Ā s'q 2؏EWٍ{i;QVxX6tnsI ZK+fVhX+{v} ~׷#Wh9,~ <|k6-=0$C?%fzںږ& Yσ*Z]dY[ F/B/w[1wL)gHEH5#u ."t !*/BDk0/vG`#ƶH'یw++|#˥+Zy7?-/p6sBM Z5!ǐiNz찶~>`JrЃV> mdLßHY"d!oRZ+df K8xp]DfMgM5צN!:iY׀,T"WjrTs-7̵C{mx2O*רO :Ӌz/[!S疷|G{g?|'79}6~i&|t[V~ -9?3&b ?W F+j  {"D'9dCZqf68o-Rd#ZX!9sK 45rE *: `ήGң6H2 Fl=$K g*`1]rq(Αc;Qj"xWUze61ؕ]165F{6:icC%`}yciSseu;Wyk>0 Ӗ aRxS>keT਷UlB<Ή1D J,qIU)v.*/ÕPW =XЋ@\xMZ+q-A3{No;$3^L8ƒy1ǁ! |ßB 3BNT27 P@ ph82~.D^I0axfq,•,G1GcԞ >"\TR(W"Ahkxӊ%V-X)J&΍e*POR)i)6 %)!MZ9thy jP8TeJ. A G͑#Md耎c8DM ! ꑋdRR92ʒ짪P,gKY" Њdת>imZ$VrwTL@3a@5zփ`\T}&-kzk_ۜ@wM3DC0p`L=LЗ!QGW=6Oz'ĠB'@N~>P4x_84ѳ tg<( -}#D-#9Q{^3!aa 54QRiRY:Ut"P PB.2%jR34k.Z[DԷj-D;NH|bANzf9t5<5do: T'>)"7$ Q@ʙ%ȂE'! *vj0 rѬ``7n.e3g>] ig<,Bupi^roMW{&6Ӏꖏ@ ;Z^oÀ Jh<"fX2 =K?7n뭈gF췿]$ !RrJD(#vA3"MZ DҎ1j)qY=ÁxHғ g(obN{J4Nt f4ٮx^>81i?zF朸b΄#W=OVQŢIO6M]EUZiJX0Lfh^@x{GP@ּܥr-D3ίc`a{}q7ySh}@Ygh2z2!~`O3 wI("ߩ쾙q{P0G^ Q8aap":qOTɄx_2]>,D$:lxH/Fr]c5!U4 S>b5FRDj@5N#nS9CsENE 4:X>e8&I7U`W}sfD7u]6DcPRt:aHuZ9S(%9(bWY5YE)c)prh4*3+vwinwsxA,ix,*^RN 3 N/q* l>È=7#A"BP0SQ;V^'E'!%Ptq^'TZ%s@FD.w@VAc%:}74<[T5 7aaVE-g$48%#38gSppUs2xt$)y3u(H#pf7r~X'uu(}FY%9Z:pM8JOwZZ)siiWK]XyvH4/i4 !-l />>`df ӖH|wyPa@{lPTo,*} Wј3&9TTM4~b\dbMeC;gBŒCHEPcd=FrdpWJ$d667&8  EXRCvUNs6DR*p,XIit7fق}%Đ9vyVYRv9I葚dU\qYÄ5Jh 0GSw1a6[%bq=,<A yyMۃЇ́M.Fl6005b]P@ 0.ܱ\wmF q_AQs>.{,J@BֆAaڦoF'plPs]SF4bQgUG5UU A5VCh:egSuJA~2Ch3r(RhFHUc5\3eVs5ed SO3VhD+EWbVt@"WhCc0wĪٝ.}o#-gʐ"g;vg'Y[I9v%Qh"Zrg*Ò)yf&AVx2#ZB k"=!ϵ/႗O ۤ@"1ϡb2me "qX Χ!#EQQt/?-@> "W0%{yiХHixBXHeOo޹}8q !F !e9Y_ҜQ6X7pԏ,:GQQGFaX8g`'(g5YdhmQZM؄&w+*Vجw{Zwpr-̓j=҂6i"1jcE.hkv-bM4.g͑| v"F]D+ {!r@l8jv!SQP T1 U0e!""A6`Bj 1fJku9mTk&LwMKV(^7\;=+Q;YuEgA9uI*jq*sG*sJ'y;vZV[3 t[#/= k02Q^兠#5'=u\2S.M2ei` kPP{1..Qs9!AN F@s.-Ff/tCB˝ 9۳ 9R up$4b|DbG(|e'g8 ]w4IDIBh\̄; %<+iџ:w{[c<Ԉ@<pŋ[l*5y$jM'ށ2K]/Nth6P.z6 a\22ȍy'Go GW,ʰ!x[ Lu58n9Ŋvḳ%E+,*U: *D[kdr!k [b`³\#=-D)=y7Mivh.2&e1 ұ>fP ml$ 7rOi"g`1 ;k =.q@H[ʗ9F%ܴ*fHyjC+խ21m%Gs!\{G8rX:PmՍZ_9__mh`$hw~gZ1iB[`"S,v" d\y_Q 1衒b- szUW ?M>K{B:  zS{ y ؊,Ȍ oآak7cY9f^;uͽ}ksdQުLp@+mn@iHwFgi8g9$x[)o!~IJs*Ʒ ;yY iq][7{[ǹ}P!b0dz,Lmkˁ!Sчc|LzxM]ǩ?!m^]/>aBc]@#!{]"hp{O+m PSڲ/a)ĴsnU8Ϳ60t+^+ ӕ\̪H03>LM)Ni9gqէY̥nx*Ҍ!*J+<;AQ,p6  ,e>yP,=2Ϯ޼ z}./kz! c@ v](a@qӖ c ¢- 0/3k.jNw_vܦ$#?mgJ_>F.X,ԇbNȬ)}a J'|>w1i+1[,?8<#-!j B&H,2i#4 ZK62#&9R5*ȊsK&p 3R̀1Xb⤳R@b).v+65F M-,VS85Up3>UղU7eUWmSc0T9$V5`Ubg6*cZᤓK.:ꐋN;n<.k=֫n;?{O ?E F Pk>3NЂ |GPJ|KGl4{@-(Hi> !rNR+-79J6H D'&*` T(*5\NI4`HLL4:+u&&F588o)˰! 5ZU6VN5M56W 6_$3%!2;R]td$.j<8li?i0Hc2q\ ؀ {Z4M1H* "H(֦a`mF,ȍ&/A씤*d` 00Qc$cxF4QhTF8&qcX8N/slh#@"nU 㢥5\d~k[9,;KbGH2Dz2A/iF&ibgF`x‘mQE;$ fПD-P$Oэ|nMN95 tW5bFuSa 1F˰w< zF=ž(<齇V<]yTLJاː fNWh{c5t],Rz\ц'K^ +VY&"D!A @<N|CXDT1A זHP@t" 7O$ j>DrЉ dړl=%SS,hsM6L(lD6xW)JT;fCag xzjRhr)'D'jU=}.wk* \5VW2wŞP]rޥ.O$yלi[ݪca-B7*h0r8oPImIwûxt<(:{A#c~ߥn0 e}7WdF\Z+3y7zaVHl$E'  Pc/Ak -Bӭf,:12;r %`=+@>aA-HA4-?)?35:9;.?ZZ„@yV*:6aA<X6C>rY>qq2$lS@׉ ű!Az;ʝ(4Bd3THCüOJ6xH>뻏r%+8X"SWk532^ pi51"%4RQ# j !.P,39 :Ki !F:IAk$aI: p-;ĂJӭAɻy& <.ZWˏ% /KK]sHH,1xȀSu6h7IJH/2 HZ=cBR0@7 \) ˽<ði/e6\D{ћRzH|H!B'>k;%Gڸ ؘ & ;?\S; Xl9,R ə"y3BfDL u( :Jj&sG4(;=:pʟyp4,: :Ę+h?VH!BHZ E1!;6J̗db#6:vC?TK72 =7D Hy7sӼ|7sJĬľB4%LX %۴.#*,`!GjKF43K@!Id֒J3:tG "%R|9B7:&Э8z{B"pF:c@|H-("eM P-SJ/R˹DK*{C9Y5#{Vp“Q5 L˳18|yA=lJÐ$>zt$6s=|;č܌7ϡ udY%=CPԵd\^+Ш%HuaPBMI\5OOCYYI WM ա IR[༦Bdc!Rb7㏂kþV ?5iR.Y B;5 ML #&Q"(B @Q~孟'~X8ڥ]uj3,ݥh3ft"B(#9 טz\R+5Tެ޼.WփkBg1[;%LxR[tI1 G$e /=jIUfQ0ؘTCA ʁU 0Y=6TTOlJa*UTU֪┥Y J +Y$b 1`Ŷ^XdIx1+F Ƞ9v)YЄ~" 29(}M^(?0q?+Q+;"$ӅdBe}%FzYJea070*[ [ɵʭ)>p[ړ޸> ն)e6B4ID|[1[/J[-ʁ*K$\<ЦBfaQ1H6!E5R8ِvҭ^|0ֈ(i; 4aU@qRt*"6v}!gd}]ѠL}lAn.ɻ)K5C"TS0S51%I*m9t)6K]iMUx/,v?`e؉ Ω=e n05heմ=e5T6KɞnNifNī[e}BZH1N\HT« %_!T=!4H*]Dlb SW |Q)"Rqxah~!tQż 5:^vQleĹGkJYvb"_D{8‹[ZU~ITld|D81_Hj!IR.$ۛ I3BZn 7$Jj3w;J_Hk>g8J~1LHP5.q X驈6H1-!.]R;; 3LL5 bN'hcE~vx{4_D.+G[iuq_n&#pTif/u>jb->>XU5UZO<`7UT6IE, 7cߊzhaIlP)ֳPUdE낉4 ŗKPs=p&ؿn=? *Fc8~]9] 4Vcur\qvmmum!<#32krkf ##d ۧ|sTsI* 0G60NĨo{XfUTEp?6 +wKDkHpfsfw_͛JUʶ^֕& եQuVGm.K5S2ٛ 1- q\8ue ?-l|̮"oֈR4 q3]P]h?vB9vratGtH/.tcJHQ苼鸽n`P6KE&sNVlf!7qCCDsl!fԿ]C:W7Fߵfm?ΠU}B1Ǘ88!oΛ;fA]GݦbYSc "dvZ90a A P… NP8bD bX"E,d@P *,q Xir&͚"D͛&s)gPBq"-ZRNlS 6*׫~*v,"`mfd0`-]m;w5^ ^Xc#XCn͌-{fL 4ijNN@^&p:ڶoFnԼ}ƭth9oq/.rv0 ,nuepW=[Ɇ'+/5 ]~~PE `F$I| fQNKTȄ>SO*J9dJ!ԑ!AF@@=f$A=.t@m4ё1$A=2#K7XHdL,4+XP@4Sh OBs"5SWiXi|dYWhmvz5aMuYwagYZzq­[kV@n֛jZ묶free]\\Z]c~'vY7ע^[jqۭ}uVTXEchURA0~ \pQfNT(bFb|I"b`$M%d@W%I$ei%U6YEP^$YԑFNh7*y%I.,qGhRg2eTSҙoRRYU bu׶sm{޲rI+al'V&rv ߦi.*ު7i}eܯ`)i]huYek˞Z_KAX^V U+N`N1lcFtSX &a TReY7΄I(4hd6$;Ĥ4#2 !׳!E SLB&OaHsQhҦ5^nZS*[]~c;pP)|O·Y+>l bh7R!C`9"clU״ Mde%r+QF9⦈eI9T%-\w-=x =oP'mNx 0H|*l d` E&T`O*rF/X<" ͔ixFaD"7[YK2DjȎt3fTBGE>3$ HC 5r&}NTSHMySkx #mYklhqa^(`IJ< 3bJxrhf|8԰5HlpġM %ɕ÷-F7/Hc`RBڅkOz:ew|$׹t'qZ%P d<T)ZRTD $P*M e`2TIEj@$+uؖ&=+8́JEH2kZ$YLǾu5lE@w3ANԥS`szԳڵ-ġ_$DʥpyC@GX@Q7Yvpʍlu\-q.h@o9tc zR ߺȖazDz)mNDz@?SgH)6BʋPt=!cXᩊ!&2Y8ӗ 1Hz| `=1ʻji/#1)Ł`ZR DFwb#cXIJj/|&tpp,?XڮVWigAgͪMkCO0ux^zGYI/d^<1.HDtEH7T;#LTH7Ќ:<`F45Eioew7O]TQCIQ0M \* C")ɇYՓFFxҪ_ծcߔX=b(?Dxc |ZygC2XNz@G$0f& Ҝfd;[K,)OQks 4 3=RR;fngC=35ME] ]F:j C9Q9]V]ݯܜԤ{QؽV]W<@ߗu8 IeRUHKpVN 4#ـDL `4ĒI@DU|X8ϸ]^d@  SBʸ@`a!ȘRI<X)\j҈S]"A dӮbiV~yŹxܗ]ĚZE˜KEɐz]ٝ\yְ| ?Ӧ=tEZj_`qpWs,@"=! ubU{lؼ윖Pi\PNȯ 5"`: 1PLT c0<aabEȣldIdL_DAO|4 :_H D<MJ,MVv|1Zg >ZY+J+ZF8T%YB|*fP^'Ɯ]F#R. ]iZWWu+qQDeE6Փ١>AiI&=2@pR@XHԈI&ajn$A'mZB a2AVX$]h~LjaTCă}UڣUmL~Ρ aꁛJU٦$a ܭ<*r}"OTdHL~IhVHPҁxɷ$lL퉈JL!VٕӻJ"NZʦlSD{ۨVB`(rlYch} @Xਊ - hly%-HmhvPh{l<]br aJdܬWV~+8 |cdB$ՔY Nٛ\*\H1kj>$@jFEzeHNmh}|j.H`hr=ْ 0I'UO a{Hk qm^z1t"Q#ULM[MSCDqN@|c }nP7:*C+AV4A|ll1i DcB1%?Rlϵ~=rHIh '!֦A꣆.S蒁I{RT[0A.OmV薡>.K\v(r!|bnߺ^ Y #JEtMɚ j90d;y_KwQ%p*Z4wQqnf6+TBy: 3jFhIT&Ƈ&Z4c@s?XrYNVĬetJ-RMVg6 LdE_'ds\ $J@um*AKO1VUVu.FR @|B4.LHH-'*hBt7[S$Mj'{&rnF+TܩgtqyH/.Ahnufn($U5ǃ2Y^ H D~ -cB/QcM(T^dz#: TZ z:(ʥ\5O5cskv".ƺ.M_\J9鉾E )˽ԭCWK>scBEP7bx#Ciba9 \H. ЭU9O<-~yv^$fG^m ް/A&=h.PW~K{XZ-ퟁF~#ctL'@p#$[H\qcႏ 9R!/ . &x>c 2P &3?m` 4&TxD4 0( &\lA TB5ƍ \+`%PQ? 1|֠B [d D*P BIB2!A2,Q2K` $H<>,0>A * "=ѻTP $>`KURzNX8|M)ʹtR4X+FK.ZkZ,3k1 p,r=\17^>[ڸJPsX׫ך҉2,xݭV~*7Z&Y :\Z59ǫN>@. L+`ߣYu?; B RfEШ4  ԰&pF &|03l $A\bZ&PԠj0@ 65[H,DƲMRnHF :hlPHH(M%rxT" €S̃T7f"@D&<Ҩ 4i 0 9%꟢ݖ* ٘w+ʪiKk l oKl 2}6QAT#]6d¾0eaqG\ỦL^E}L< EY`R\Ʋg=0cOj3"l>f-ivAp 5imQ=MD܈3!p{NCLj3ф'At(62(Q.ʶ# @E@4d PrPdMn?S"?͇i1h ih@&uKMxYyp#V橐8Cfy'1 G?! FbIs)dtEke!VX|^%Us^uh,O~x:6E`Ege)R^a/N8#&}I5fcOJb(j;8L`(ĚLC<4SgʏC$2NO~(DC \@IM 5H'I f 4yV)ÔE^:J6ii$2؎D;odӔ4dUj[''wM.eAfgM :C2dwVA <\K0D ,}TV޷s.I(oou[ Ouo}߫gK,"`Fa 0JutҏsNLahd!owF 8>(,eXD-s*QjT MXJ" MX刔Vul{CT4AtZԞG%5kT%7}Pkw#W?>}j0p@X7An]hvNiΎ24ADko>pvdi6lSDjoFKPf!8'>$htǐ*ib}J!(0e.&KU*9&.ؤkl{)PX`ρ¸53-x 2橞0~Ͽ"q%b_"l,(g_$ +LC-e<)֯ai9TVH9&(Z0J;(zhgpx,&>vHJɨ PpiH0Oe*2PD($q14FN5i qi*=,)o*@v<1lfQPBQdrm4,E/Bj{+ oaI76Hf*‰`C4% .^//Ejq\&URܬ_+ԩ¶"*8%XL,*7 N# ,roT kŎeDFQHHF@exetL }jgpX/0Y3.+pqRal@ر/.M,=>E/RE#B|1 P!U\t8*# ٯ{M662ߖ þ4*8),BC5~0񟮳e-*&Qz*(м^ρW42`<*.Rz$!Y奎Gc51n;8dJ 0 cFP>13ɒPrp1RriQDQR("-}2R/=. |(@%m&8Ó4",s%).-j2]ʍ:K ctOl4TZm5P۰83 ړWJ?t؈Jb&\?2ԣi.l(izDYBF!0B4#̑Vl!VlrQv0WBA5Z#>:Us&LHnwFRp\?c]'ro ff(\68EKM_ m9VM ,6<Ԡ. Ĕ3\ZFCaIYܫ=sOH҂4PfzBĦk*2^"cL+/.U:a\QfdTRVj}jFy2e5XDZvmVɖIҖ1ZY3PD!k7냩~,q~6iPWSA+RS]VĂ%& _y^6Ra~SbΫ`-` <ZjM 'uRNO]xORgEr.^%z8S#et?O}W\wTgVB)s-gU9p90x#Y Vsx2Xn%kmc?$o~2N OՄ+!}6+["tpSsk6s{^*༸+ LPZp^-:Xnw ƹONsw@}dZLw`K- E*f-8Tjg9 +';dhAS3!=8g䷃vki Yk6qE60W=[XG0UiգQ2;nGWՈ2q|KHgs"2c"7z@Hs Qsaz:,48',2=YSs~OYí'̙v@x%3^:KIt w 7GV$N 7Ǝc1ףiLS.,An- EU.!3ruXU1 3YҤX9\бC8QFq0/-{xUq[k[,gSQمOo#Y /YsƧ8xV~O3C:m/\2[O9"SdS-((5>1/wI/E1{{DVܦy0g#o1"w~ˑpO4Ta(PhSsKbUK|K8wt[xxQa;ޝcҭ:NxwC^w[r-Wd|+HQY]@aԙIY`y؜%Beb15 "]xd;i< #f43uesjei݋UEj;Ԧ0q #iݳVOIQ} \!|U0qIrBF~%3Qm6UW|m4 4L8AC'١tٵWO3MMGU g^ ;Rr`._CI>!Xэ( #jlsLQ)BD1W}-LPB9)d^3?X6焳O`Ow"Sp~lG(H\]⧧anR@ ȄuC]1CcJL/*dPLv0A0aG # 0##LL}Xv.̔0Vٓ) @Ϯ-ZNh`!NB)>-xZ[YW׌IIj )n[i^H͆ƙr6fu(w6nȣD ܞAhKB:4e*I,ލnƬ0F q"#BL{t֢Z^GR41HG"#= q1?#A<-"4zHS>JTB\Y2Jnf&hX44nbswIPBWur5,@ATcbc6hluM7*u^G1\'YZn+)MGaW+gDtO&m~c4fibiZ_ d/x?%F=F2To?V"f%^RS$pK9=`gJfF(#1qV<'0"HzFJe8FwhyŸJ'B}AVKiK$E' `(g4qmUZYO,ldBONYQ'8DuAoSx$n' lvb%ixt+Umxm''i@n86!3xwn23[._'hw2(eG&ztB\A1nT{ԄL8gHoSSS=Re!G֖SgUʈ!tJWuhXe[A5sc`Q,}OumXZa,5Jw+fCCD)cBk8tkB,9YYX`GvQWBYlɄh`sLWRwhaQ"[苆46'N";p|S&3I="͓$Hxq*=g=9@U٨t4</J_|x_ [k-MC!cA'mpQaqtldʦvbf뭐qkT 2,tzz[+56()A*4?ׯ#JIzBZJaV"UzyJ.ꘜǨZG!"!zF]j7"5s $4fz{UR#kqvoW!*㖋jhv:B(+3jE+['{Rg:W{mLAC5'w᷀ute+WRjv7hy5&`$6fjDjZ~B(R9utiE'E3\Ş_x1SI _+<I_R#psi#yY{sz]]P,ăT‡okBo1ŁJm'bJѫ'WU~}'\p(Z=HgHaȵ)M3Q*v_j){$WjQI(T'@@UK[9¶(Vxjr_٬6.۵}zm@eM/[HqnB K߳JlΑ`F}ޘXvR3+`SWMFnA)g#Cu.{6ԄU7U|˷¹ߘd=rƪDx5fq3`-ttduE$v`!%΀mdҩI>~,yޝSdPQ;3W-jF~@k5U;3, @#{!Z(zg^T /gt.bS*bTHt>Zf>R˞EdDo-vbjeC'~igӚ3Ayɞ5FJ-&k XUBPb$7(&&C*k +>I8҉DܚZ,$O.ZNjD2nD˞N53 ,a `vƳ{$şW-ݛڕ#!wp޻pg\8|GaatBĆ#8lxbD=~ A#,r)/|4O|ps$.{0f͑B#DʓBR4hTϩTVAUdJuWcˎ%;vװlײ˖@\uWo  P@`koą?V8/c7Ŝ۶BM9VH*jg?CFy OE <}%|&^ 8łrpo|Wp7ͮk6I#]R %I)X 19B<+YNӴ\MϺ8KuTRRFS- [^ 7ָz?(/ut7 fT>#p?  P 'DE߅y!zNB;[#;:yjm2eɥ{22rbiԞ)hlzȦV1`V*&jo ԶRw`5Ll:[Ɔ6OjPEAUVU4<eVxmvZjWKU8qDqܔ`9,~'q˘)j|Y1эN!܍“թ<1hz: G 0xy㋆ىHB`'7(`nDڱc"1mC(H-ek3GK7JPhIek*),rf'^Fn]-n%+~2ImfS6raE(=j[k{܅{. iL#[B]dH)CK$j{h.C2*011Fܫ&Ն,wJh$ I"G~Mne1KKbkr㳠et_WO[,`E5H n3`8Bޡ0"czP'&7MJKRy]u_h5zM5)"G|uvAK^DR‹=ׁrZ{yAXݝHvJJn!3C24J\o5Jg>% S +\;;3a1 , 9a;7,T;@ÚƂ8 ;!7,+f;< @aZ o![A] {&!993ݘz%:+͡q3)(˿_;=%:P. 4>y1> 룢۩۹>񗆑S6*S/+͙Yc-7X02;8{ |r¡wһp@=ٻ17( ˒A z\LNk"@RI&0-v DuR\Qd-!]`*8؟.鍞G-ċp*ͱ]=3\/l?2>13Ð> C3G#6RC+?k CsCD:x̢*(X%)?c%eK"B;֢-S YѶ#&ܼ H²EX,<F$j*F&KJ;h-C-$gc@3K ] : ԸЉ+;0@3/?|Ď`2" * *Ns?;|#K#>#[CѝiY/vG L<=ӵ83pUB@+9"B;PQl ~!]A.{ۼ{:-@jF47КcԌ,JtA&&b 2\D7"-xS!z:l3 0)"pdB%RI(D&qDJlMӄI>1/Ȝ`CP4~#iH4Ӵ<10Kү/a##Mȁ7 PJCy{5HQCdKQL}VjyaC%#YDK3-i[RA8 R6!֐@q!W(S1Z 8aSPYK9/tQ<ّbVC<;95g h]J0M+QBg[ [ [8ԛʕhꡉ+u]9 ΤSl,|uӪ$29J<%Jt=1`V 9O,(mnZ2 5p|ԅ_jTd;+Q-Z(M:ٖ ̎Y -yP:X9qE:mO1Q?;D"TD@Ig5F=e:Sɳbl*<[Q.᧴j1ml!EIPJܺJB eW~'avZKGo6vj?\oE EwxRW3ix =sVYA܍yyzgw.GxLϦuWf'/4y?ooAxwnO\ mozњ{gܺOz]7!#|_xgzWWS7|ggy{ Wxoi|'){|B7ďyuwz%{OFx~ ~g|w{~v|'{O5B P`5HѢĊ7r$ƎCcI)M Ň+l)sʉkzi%KzJ(^*lՖ+pjSڰJx/)mlHVr Ī&Lf*ap[䂙yU{r[Gm[C|>)3NbD#(6mޙ \э^]j[_Q_2JY,"<[mD.`C1frQ]Vq͘qmfOf^ E4d'cY9v9䑶ҋu( ޮ|#Cm;w8v^߇?}qUa!4'ո )d.+[qĆfF=}XX=igk?W9EwcdjE$6rpW%`سWtGΊ )_R?ѭTV28tR3"h)>Pנ,}!L`X1Oh#%<YjfSH+md14QtP9m|::rT*\XGқ~ʩ'7jUޅx_,JZ{XNz\S CDͱ,[' RiV Yrֲ]hjSQlSgl9U&M5 u?zYFv/}ԨTF4 .ۙ>}5QM]t5i2clù jM67Ϧ7;O@S(D췵륕,qKS&n>vKL=;1W{t4.l . mX_Az \`<YO`E0hyTviKTI*@}ΏYÏ(;8pHTŰ\eO@|]z0T9W]${wn:c,Ǽ-jmyLo]E$ yfGԼ17DDz@TjJ}q+Ni56ޝA<5GZէ{%mID㴹 %*"&QdOWYIms+kԌ5mڳz4+^;6mݺpcVi+oF-{FW|c>H+QSW)_`vGCZx1%s(1kep$&33ׅtl{ ~[.Z<Ԛ9DZ%Ŀ)MM_d^Daxo\mQ>}\ީRܾVP 6_uU֔ 4u}RiF<`[\ 5\ ۧ[4N%1܈}t)EZX_ F$Bܕ"U ͞*Jץy!\U a#e=d_ Q!%VZuQ9ejPaiDhQ1zQD/JWbZ4B eI -Y4f94MMq5ݲ-XQD~PA 5G'ph[t-吞)}b^IU7#Ud@DM|E?幚L8XbpD.3VS^QQcߩǸ(D^"l0ƛJ%@`p9N쭠=Vde>[FH8%$4#R~eA`Ce\[ԤW[]d|E ݭ#|@fGCRgeU# =MA@Y@@Dl@ id`FH 4Bn֘,@ȅ^U*0BF,l[^ !F@V[)adDbI@@@ ]d f0n^K Ȅg (djmz&" }FD&,AAA0_!LlAXhKAux}"R F,~eJZl>Wi@ ռp.fe A@$ ԥ@@xg%}amFT E yA@GTD'p8f['E&5dGIC<@piDlfFjXPi Y᭄8BDDD(NgjA!b`E< [ E[f`֣bR'Z(΄ jY((+v ^"}#lj@8mhh ]GD`^EM*jSd5kǙ@XdU5U_N`8l7yPx[jft@ɪ}ggD[@`؀[_ Dfi.(@ Ĵր@ z f@ƪ|ma֧Yj@+ BlZDgzČx @ʦ g_lnjlBQ xxfpq*lJh U@MF Rj_"%,(h@_nAx&r)/6 _I@ gmE8jnivAln_@.Ư-jZ(/N>-rPk_V'.oČ-DdA6A'm*}f3vr$R2K[n%؀D["{[A@x\D%[Fm+*N jkn@P(>f}@dmmH\-@Â*EA_BmD*i&_aV1f*%S$@~ERru"iFh@HN jp k:@dpfUĹf,pjAv@"XH)KlD.{0'_n;ìFhHZd//gsA":Gh+#rs&+nh֯*i1%+0_r1Jr_VrD<Ǘij.[&lΝr_XA>Ȓ*M t 񰢧WDxb^@(D5G D h.(&X-XY^[ifjނirĂRRs2uh6.olfJaDCeJ s2K(E.>Dcפp/Dl:4He:Fkccˈeog"dDmL(ZD_.d(̯b>@l8J <7mj Dw3.aqh+&g6%APo{i:/*7N~ײ;iщ4Oʱ%fS*'z.uwLxd@ZKW@bWlA7va1mh'hA6|nKd0L`i+rVD7Ci/d.)ap9.8E+iasLDz:AzKDx2"7p,n@hvNzbF/v'ەCA1W[bQCWtX$A@5Vyg 1~ϔ&|@ .2@m&Da 굕f5j@y F5/.b`CHn}LnD-/Č:ѿ-ilF5.0: 5"V 16V" 1UޑAcXUK8@^53[۬N8tN uMo.(Q΀Il )5+x5DN\2MLj+%<5X)srT3/S7;a;păF TwK(JT7-_BAUR_}si;+uj$Ƽ$PO=rnVwnW.#xC};eGu5Fn C}4f6h q!Čhy{0dS4`Tb7X;Q6#؈CJcr$NM 6aUL"`.Ť_ߊZ(MڜnæPjX0]s+l2!`Xz̯.֠HAx <9#TEjj$c.J$,mrSc(%BJ"AKX<<9AҼ 8kԆO CV7L`) Z;cȣ_囜1㞈 ` >qfa 4 7 R>3J>G%wnv2G É ~#g(uN0ҞXBlCi`( _jV*ܽGX" )X[P2C$ "#PI}@&:K Y!Iv@p\R`E&BڶeLȉ`+%:UޠJ4kKzg9OVR^[Ds+u@S7 %[:'R1YZn/Ń?+ vIj̙#s 2 ? "IZ׎LyS$dɅ 1@8 (gk`8ĝFMH p/7F9ys!EolvCaԲ,Lr]7Nm9LB_*mLʉi#.˹S8d9FNH꿗 )dL}CzU9MX"XT-8!cBWJ^Vsߘ*ҁ!+۹uS-.~TL Atq[B7tjn]~Ir(f '6Tjt$1UtlmKCvM*.)('PMP!,r"umt"qwD,1R>04BNCA\d*ތz%fu&@$o?xyL-uA̳ iZϖa:2@{Z6̠V3R/j5jl w0zqwð02=.a7!SbYOUҢ^P@w!ROC>=ݎ1k kOO̧?R=>4$ę4ܣ@$dbf p0>npQ10LFJMG L0GJKWS0^p:iB'D#J2D:Bf*h"5J|*/,I_hc%*ҏRNia$OFo -CoeҎ + =i,&g Gω4&dOM0Rdo "io|p3 )9 jC,΍ si,Ċ\D '..B I Lo0jq.ZT/}o `q{/=S+Rb*Sq,esBU2 S1%>. -k82BsCkn6cS")m3d8;H1&3R1TB dzA8A8G@eg-5MmR~R?;J!tCAt9Q)13ylMAmU,S!9ELW5T TO4$W25C2/F.Xc~*s'C[2Y}',U21Pu8Dt4Et@T?51= 0.+se0@G4^|09IPsQ U[P`+3T`c57UZ vcqee Z[R9sZQ)̌^5(3TX`1CuxTeUCR?Eh3C`24TQ.<ѴYVc#`<v[2ܵjɳ_2)m_b߲yXE5nKrh;-6Z^BQ5fsNYv~M_3~7x{29{Sn> ~ }VWŔ_(U2Elio&ꀽG|#j6}KwcWc^1SKWcG n6hTPoaCXi"LtiB8wu`4#UZNR[y+ņMķp63C_FJXI)k2W%p\S9ZJ1vØ>P,2 A(&%9办Xm>20Ow 66@`4րyP)NU0mp07uPV%K q7TFP$1,x.}Wn:>Hu>Py8Th{<Y@颲XVSy&}u=3<وqx#Suw/+E ea5G^:i ghWw'nXOִZ:Rn:𪧠4׌W̠ZDC_7u>sWV|Tw7`c$O*BP<\V>L~L<@5I' wL@ehJ8@% * J.;E0綬(- $;&F L6\"}ҿIЧЯԟR'm:@]LZKvL /Je٬g/ "ʹ*HG<׋g" ̀]1L*b+=]<\cD]%D\6oJ+ 6`zX^ æYsLݔ< ŠE% 'kDDQxCBL乢Kw EK؜DJB=55h,$j]ܽOe ry/7z wvjTpy Έ/$B Ngy' 1#bhhZtbll9B R&zb+-1޾,Нg#F\G%8bf6t\%$8H_p :Hnb&ԂcmB bJr+IʢiC .G6*,L B0" ExUNiZ@(n3Bp^,JEr^N"֨9j2DP!D "4p@E6<87 "YsR66eN 6M;hq"/z fM%M-p(¡E  mIhK.ޫhi $w՚=̃KvfI4<62,Lq $ $}"qJ˶.!j?Fښu9=@l/G?X^qtRbAQ uem ]5b B鶜q+݇Kfev"Z\͑݋@ CG`C6WVJ:d~^YÝ5*\%c]jfVq r1L(dAdXz>]eY{D\nE|ՉrHgfDgPLq/UTeu#AyiR< ZaL"a4AHvWRGH"V>1O,vhIFft Z똿!y5|e mPb@Tnta%Pj ..{ֲh'CQAtA.v !4d*JN{HQ!`doĥ] E#hy>VPqLQy!Ml]DLl63hA}YSɒtI1 2jS$[(W}i^w%uqIP-T%~8ZSz[nAAdbrtvxFNTߕ'll8s:AXyVzn\N؂.jLde:BZS@) yG;?!^lm2mA9-藻ye\"N1m}^X:XԪ8+KL8yMJh9|D&70dV>a%l` +N#[i/~Zx6UD9Ӻz1b\m5%+a'CLZP݇Uݙ0uaT& }׀c1K u#l$7Aל6IrJn )FM)GC!CA)Sa{ 0`It0ր 'e1 PG$}o0!eT¹6.)N0b"I*$ RI(20N;S7DN7 Ii'K t:qz@FQ gƀx9L250ӑ/7#(S!Гׯ+&t<ݓ^suQb D(fxYFb}FdWYy1uveىB`D[U+~ )CO U+i]-5$1 !@ {U k> +b0:7&8k[(D9vVͪqX"rj!ѣ~u)ZZ`2Ö"Um΀ta5y{GxX7YUԖ:V-RIjeC"kAA+6'âkJFq P 0Saъz)WF948`EB4#- Ѣp)< jO6K az9H5X!,Nv:#j-Z@W6x٠Dߘ f%ؖQȵ0 pXjȲU8X,CY5LRaU\Xa9$(iń4ԑ!^viptZkYouDf;F+i !%Ł58N̺uDӷ U215A!SZIQCW"`*F!TV %FVƸ mB V]4{ #}:4CJtF"nx7,644-WlD ~%fJ@HM} 4Uוf$VBD:* /})1vPn%iL):uIJw69p 栢~kI~K9pLK2v8 #n/^Z^rәiVB19ƙ.8#‚*~Uq'-< IT 8'wH-un18u-T3U1<7#@Oq<p0ȧI@4/'~;~Z^{ք75F`+*⦅l'MXB"zA7z@Sti*}X%JG{s'Gw׀d@@ܧ% |WuCjw rm^ q qԗ||&u(A\^w"Z%P~ 'V&,у xv!%ETndXkVFp7VEm'OʳD.sCEi1lBY6xNbf"bZs![%O46n-v cz2(J1wwYkNTdZ PQC*$08<xJXCR2%8 12nC!qGЄ4~<9dcP,Run##nzg*0ob "Jq1 5,c@JyB H7<9A]OU\~KU=CӎЈbӍX:W3&uy.y(KIC##< (0}&)61TeO/Ոis^X4qr^j:(~ohfkv(GjH_C 癗5k1hbe~i4($Ykfa 2YyƗ6_)_I7, IasEiff)7kP5'1`D>`ttSk#kę"169D!*Ay2E"ۙ6Xv)S٠9R*'nPȚs!ɘ'ʼn^ڞhK{fg 69 (ʡ٘xYQsR~NJ CʢOjR%IJMJk:IZ/D; I?z1Eyu-ʳ}xw%WٕS|t4iIȠiڜZn)@%@#[Yx_a>\:8MWTT\F P?K'uR:jj8i juZko (٭VbW:ʬ: *ZjL*jZ҈{Tp`s:8zͺΚOZJ"ڨ*:E욫{ڰD2ڬ)c*kܚꪪز q~rVT9)T%p+"VLiK=ʨ:*bKIhIۣڵ{ e# " r0hJ 9q'W1zb+BvXy, >)`۶z#j۞ʣkSjv\yz(`wA'Eի˦*w`yjoW wê튦z;X y{0۳!iBɳ˻뤳 ej;Bk۹{૲J([~KUt:66i ˻h̯K:+t麫[ﺳ.{W۵<[ֿj`J| ޫܪuU:\;IzƲڴ{ЊۗDI akk) I+V<̯ZyH:AmZśJq\şR% k˶R,ǰ ǩćn\k }*&[*ʨ[h|hɭ !! pA^,̗[,,d,9u\Mٺl)xM ,ɁvCkl (\Ȝl&}E{R3[ l̶YL+[~Jiκ,l_L5!ҪotjCm6J΀:ۈHrdEmAL/_PՋۘo۰k\pN(˛mn~Ij6N㓭uΦaO}Ě'&Ŧ^`#>0Ԫ^sN9țn"ђLδ -%PnNd̺v[Z#r::Vxg8#I$-ʷSOz+GIaĸã:S'wA0։51%/(KwN- lM,|^ d筮٩y+|‡/EN"W3pgtחMKᄃyd1 G_,fbG}h(4zGD/1beӁd_,rnfq\AnNMکI?m}Æ!^~K/_LM̘zI="bA!J![O@()Ovs jmT*La)8<ޔ}k=~q $XР@ "THƒ %FLp"ċ Zؐ7;䨱ȋ')IHYD$M9mR@g|:YҨ)< A6  gABTUZ0aR`CbAp 0 XcPL h#(l;oM˂mATEQ xi8(1I^x X*Eh/9Swp"ЄsSiֶܠ97&Iҽn|,ل぀oņw}(8%i#4Nl^f76}m{szjqMvӎk}zޛR9r i!Κm)M8/Oy.;#k]G|_Jg2;z2Z+lBC킮yַ;C`smL. _ w`$zQKg^/'lyʮm\hS[C!֊C8K*~Mk?:?$4SqSB"ՠ= )@$6jA|ͳ˿9"7A⽡ cY:#:i9s;qKb>%ӎ{&8!gR2Q#@2d ǻ|S0s: )kꣷ7=l<~#>23#C AB!:(.VҮ |:7A7I¥Pb3|O&6721a0! BI$: DOC'4C**a@&*u>".䪣^ S8Tŧŏ[ӴcB8T@·B\Bkĥ˼\Y/CSJga=C-IWClk@Cȳ6EsD[H󐮀󻣬C쾕lƞkI\DsK$@/˝L=yL+M+ynj$<X,0CD46۸҃ C3D֔M;lÞ%,4RNtʄϧ\BDDoG>k|+\D"J 6L;Ax9LQ̼#D[-c&QG!ѸYϜ;@J)͎=PHbV< "NTT0Ή#N}!GڈN,o[uIL! 鴓+º˶җGP K4MeFϱ? }2lR,0eF9S]c"Ce ĪUà8% B@\,@+HXٌ)Le~ҭud\E^NǢ 6`Ve$[ t[?B8(S`z%\cWaVO/{E%YmωOt-]\j;\Ƀ%@;+a!ۥ[\U4=>̳?䕯` TITC0_<_A h\|%L5~6*`x߬_(P3fhZFκ(b> G `f@bH/.ޝ>fw>Y!Wޥ\=h ]5T.O.X]jUR߮rĒf ܃K@/S]fS֥ -Sie0ަrL s4.?F%Ns^E`@ef䓬 yS`S7je;l\U*>dC⏄fA1m &g dxdg^ei^:R]Vhm"E-ؘ bU끠dݰBt 4m]4`pM\mw\\lxgu՝ u^Hm<^}o TXkYg>mo^װj\M TȦDj*VRU[^_|5u?.U_v+žfk US*{[g$Ee\l Q~4 LHhvbL۱nhQBݛ=-dir]mvh0Ya__rxae|I&TZ s%6Le/7Wx.k>/ıqS6'"bcGsmb<4FJ"oPjZ"Q[T}E\S{,[;[.\q.6[ 9i<@ǵU_bv^B$NADHw_`9 _kdKÎMRmg_bӤ&9+wG4Lvwbyg %l;MWߦOY=\hQ@t s{Nuڳdsh~Yu-o\bRVtG='cWvMp}ۓ_n#jiԞm"zz=%X!vgu>! j;p蠟jWs |"*+`fk0_]F"Kj^=T|Q<^G8fevCfE6VLoHei4nɸʹv[P_Y@m|v}yy]9o`v'`WsU5ޛJ~u?eDPP#p` L(B Bt8M7%6|QFPqŒ=p$G-WnDhJ$Yʴ9Ǚ>Si3ł;k %&Iw&ycPQ2˜V( 6,^K2vΏj`Z+8J3[zcf5UֳZu`Ámӹ~7_–3ܟm.H2ˡ7hZ6N:f @ͺ=fwhyqѻg.@ŋ%`8vq%Tz9pB\d 2;`O1i4I 5 D Wj $t irF"((`k÷P0jh]|6" Zqh pi% G/tS1hABpYhCCOFmnQ !%>2ejXRƩ-M|!zr|X,N !+h-X(KMs;KfP@`䗈x'@^VA8r"@bId"nPA 5$m{[NT$xg$k"0"e%eW"q` =fq` `Nyf@ygY s"AbabR% 75L,-co` =80lFF1GTֲ&漙xgnưo D9%;#oG:R1tk8iRAYE=XX10%UJY͋x |ڬĴgF94#7ݿs:ˇ @Yz:e5+@Rg0oiHy *p=+D;U(,HVEYeɰ "b`َ2, 6%y%H$iCLfk7\E `U&씅 Ycxa28ukc&EDvv Uejg9e5NͰ -ٻN_SCl"+|kQmw&z౱`$r ZW5vQEDF5) q,y^<}w$a,7خ@z!1h?K,P=lSBY II!d.AR.u/y;oTmw8X6ݺMDC20 ĴeM=XbgCk7^zc+p w^oK3e'f‚_9`aKMZ[>o#FXI"LϽ?KJ [.]ҜXGVIxM @|!- 5Y?Bڧ YCh_sY YA9=Ru@E$ @QRV\BALDRhDܬ4]AXA%1 DhݶL[aL1둅Lە`N4u^N+m5Y-e`7aBAJABl]-HA(`9ȡ& [u l)Au!%$=#-at(=1BQVDE49ÕJߒCWn hKaI$K1#k!&nbAX`Cܗ9`ɇ] ,q(#."E0ľ&6āt@nYuFDZ[N(Xk%`e-8)UfZTͥnv]&ߚN )-WpAOfa mbaE lczA̝DpסNn!J.] @J"d iC8hޠJ9bji0Fb*&xhz #N!4* OE2gn"쀍kIW+ͩn]1%kjT:eC\"d\CnָPΞI'<~&CԞ| @$HΨZ`UPu#~w1e"iDzWGr+_>YTa5|(n4bP%EbDC&j`5%"݊;vT}K|!pQn[bleEI.`lf\z7.66 4& Fهt6∩;c=' ԍd^Djo} aMs}^m6 d MDxHddN$jH "HN͛AyA4VW( 0hJ]s~GHi^(>YW*y 0Òګ"̍b4E,pnq [ncaIeMt'l5+q@ˬb r(B| AQ-)Ɓl0YUMJXK+KF|ڸ1Gq03_ΚyCpn@DIѾ]TC$44qaJ'-oD UV]Hإ&'R} ]ɰ]nH>k:s9{pXUX=`Y_%0BZq@!Ve- }Z}u p"! C^a1KN5[d^b 5XX,ϮW{LǁN]2 3x55ףHe^FK+:!ZDV١4DD@nD٠ܑefBswML׷KGAKt2p9Հ7JGNPՄ9ON6O \ EgS\e_f.ӀCBY>vIēE pny՝S]wL0qsvfˀ5ec&WNmUi_&R┺ p8MYeFbA %fM@X\0RNpN(5ZR]@tI  lx(0uԯ>6' $9W|&$9qP IaME sVS~MD$ *0aG,휃i9˯=66y'-9c K 4d<FrH%a9٬DwBjIjȍٹ)boN R8J*ugbҸH3Lot y)BɔyؘŏXDMy0K LHKpƢ*jͺsaww;'+z{転{y;(L:I\{%ɻ:/{ۂ;r$S{ sP{$uOG<Q(ya|>rWJη:ʫ|:PBepHpo.8<0[:=df:ҽFO?HEݟ}Û=KƤL:ܧ=ͦy˿ ͝Nҗc|V {`寅<㓼Ō~|ɾa¯ܜ~nXX ~om;'YqK039K~Kq9g~O6f SA P@#"\hE7*qc!I$Nj"Kt0ʁ1ݘ8`L7W 2O-?)!NH9ԣДNYJy̤<7E |KG6~w=D2xOQUd}d bJz2`>5H,mm`^=u+0hoOzC@׈ O;yH6~$9PV@xka7+lL |\Uf:p R}Cb_O@B &WUNF#6L4'?ٱ]< nFʕ K\^(^DT#Ɯ_/ K.,+fŷ?jR !U'!:UB$p{cɿ[ g0fho@ \H!z/.)'xiz}䛰^gUyXc&NqibDc) WntnxAPZ,,bb.;Iz3LNTۉ`y5bFDz^&% ++2@J)C)W$N Ԭ<'²B^G"o,4  X3KR1x@.M7` XZ.ѦjHl95pHn0f7Wf #Q`u@#*e 2N7!?Də8oHtJ) pJ7}.2rցw kDҺ  p iI=zUHΆrr:+|@@+dc9]8н~ ݖ80.AҰ݂UiJ l w D" v f @ @+ku't`:p KȩC_$1N\ʂw-C *" qb: 1`l4u:'\]W`y@/e8 s%_EԹj];a& mzg{' B^W-zkXRQ/;KԃbJƞJ]'L{]ÛzTnŇpzf]iߗ nw 2 tfUk݀pwN9qH[b79Gރɩ@:zP\]C\Iye `@!tۖ `ƀ|IF"@!m@8BG`,Kbm * z 6 !:‾O *ր jDh' .2 ^+M/G"lϚn j,#ؠFp ௮ bŘ8B@!Z/#K ˆ#Vv* :pzz ~1₞0$# :L m0)nn HB -12 09¹,A@!Ю$ :딪p ZFgb~HJk$,l0 hgk P+rlf$Z*z0, BNB )$X @@ <p`  ."kb" ̉ Nd 6" i\L&gT ''W T BBQ l(2 <𿾰;@+髳zi *"t 1*K-IS җԠ13BєLjrD &UbFڲ!D./J),2Q#Ҳ(,%*#)A 𲘞#3)Smj~|/`'¿R"ȋIJF7D]Utt"gK(.`:z @t l`8FfP p͠[z) t`#kZSj4rt&BGCQ "9 5UԜ 2CL%@H @o/ rjB3:o1n r%h:C L.6C@p/ 2H1ǬBHYWD)2GWԗ~b6+NH]89{K[E%H!Lz&D5b nDήJF  gEmOC.|M E +SI,B˴^G"- [2'(E[Ob bR,@TR-֤Ti&~& J:b(XK[.@C#/ @A%I R1G@A)[H &U^`bX;t'sDXmҩDNg>B"hP*&]!Ϭ~oѨaE3l.D b넞LBKb \&Ā-G1 DvI3b K'xRvQ | ,)dv6aD*% 3cZ3h16|vd0(#fmZ aIv4KY"kPqXϞrȀh6hѓQXMv- I#DV8vvvMeA،0[|U-_Ll(z, x'i :M<u"T Bɠ  %7?ŀ  $ @ HJ c_-Y8(2֐lr4U1RP qU|Su|n; kXY!Tl)؍E4fKTvV 'hFCͮnur9}i6| U!j(X!8"d;}o:Kkp|Rl6!/OaUq9=QW: W<]bpW|ph51oh_pC优VW28 ؁Y-S ."Pp%a P+kDm,{>k x44t@\2bHj!IPMpO5=$Fu rF7 &&j!xy& m;i#XP~c( ً!\2FX}qnOÙYˠV±)l9S l#X&(mUQk|TvIRe;)'l}"FOxQ58֢k7S>Mqous#:9bW+,S[8$65bM+)bs4OdM"U! ,< H0A*8'Μ#'Łt([FŅ+v1ĊI$R5kV"SF2I#f΁rxalYJgŧsiHᘫeذI͚iΔz8RI+Ou.fȑҸ&L7_xN9_Yܑ/λDlT׍cOS_˔=o1:[q!q,4G@vhow! ,: H0}k\p8(lH1TܨF+zD81$ËK$8Rƕˤ0MFYq:rj pK5s8Mװ9 qG;Exmh'E9;UҔqKt΄OpMH.22 /J†"kP! ,2 H0N1*\P1 HdHq1i"S"1k4HcFG\x@*W&4)RfC9$(' qbg D)vFA!ı&Mj7G(c q͚cĐkPo7ʱCGN]r氱#nݻsu+1‰\ pR=$txhO:5 7f9l$#j"悕w^rcX ZShs턊+! ,/ H@5j Ȱ! cQ¡E"& q>s.h5-HRJ[V|H9i;7v8bi(GbB5qH4N18rСpVLAQN:ĹJȉW|.^:cJ;\2xn9qv ! ,. Hc*\p4 #6ċƤYsFf2H%nA2ei@PŃ2('1?~d3FM ƙ&: 㤑tй:T] 1[ 3FNٙvоu֭Zl78q.! ,! ,! ,! ,.b H*\ȰÇ#JHQ3jȱƋCI!K\ɲI-cʜ)Р 8s^뉻7?}yٿha^xh yI}6X`< &MY:Zr(y[` &f݁H=`ɍ,cy؈Nnpw.jc8c=tM7 &9GCxݜCd8KG8cJi#I`gΝx:蠓g9䉧瞈 hjJn?6u~G jjꩨZ1 Cꬳ@ĭz뮼:êD!,FÜ@|)2ꩬBkjj+jDE{Ԧ>[Rmjo1@lZ\jkRKmv˭q<0{j:/CԚʴzAl \򴭲+/2CL4.+;3\CVK1+_MK.67M>n*qOf1wB4IxSVZE B&\عD})Ќt 7$$dh:Jị$AKܠEC8vQu2k#$d*N):{ Bp&&tZ!>yRyRSq+aۼ6U\X5wc-2~@4  {]SԖӀBcD<쯦%J1Vxj; .юR gjX4~ \OITfknmg;=nVLV~X ;HN츾2#ƄVv4Xmn ƖŖc-~6&?ͰӜ#9i,vm`gP^{][uXf.ˬį"͌s] Cm}{jN~0eukYz3䙎7)%Z7HaKXW϶43ƩBkօ~s2*+)SeIgioSmHb?oWv Z5x"g'U{a np3EbYQB 6#5zL%Bnicn΂ĘLma-(@a&fuB=iLpf"sK &Vʫs)Ki!~fss\o֘Z% pvyr{?77=ρLmԄf41'N[<ⷩ_/_~@dr?P\yg>tG=V iɨUOyk.eo^-f ?5ȩUK|kݶI{fn[sА.}%YG6M&e S9ϘFJ&oIwz&[~g~ 6Y6h g}BbDfVj饘f%&ar*KjL6ɩkDڑJ.u* :kN&?Fj宀=)+-`ɵ3͞+~'բiԲ%т l7t;e~IK&r)? e2 =~ol)8ZZ l+033:-;3\38s3}t+34:謣Tۼ3Vu\w,m5J(=FQDnAo6waww} D'q+xDJT>;Do޹Jh駧?AE볳>;;SC88𑊋$X89В.<9uۡRG0C<*qwDVxs,Xys.wU!D)H nK WB2ħ~d e8CzsR]`Ju.v(' W64 Z^Ȼb+hA3 0|! _܂>fޏ~՜#7yM+lbqTq|4'Ys;ŪAD3o#a#~:nr+BY4h Z92u:!QRvt+%ba$-HdOZ^.q +{c7X- ֺ.9&uDt Uzӷv ȩUMto!.[pLa #wm'{ 6 b)YVZO]TւXȯ@=&s|c^=kS,h-LZRȎt_l7w_l5\R/ۄSԩz,`-.+Xܲ "OPr*IPG\Йp WE{Qb dR*f>kEZ^O}^hm~W_ַY}_KZ~AQ]u+4JժVl*rNmo |%%77WՆ_-9eED26Ys(:g;Cvb,eu{@d2gq6ڨx V&ͪl14@.ރs9D5׵$KIp[^?7kulL;]K, P|o"گ-=2rvĸ./|Gթ C_o #.=oz36BT(G?nzRNtN5W(8c]6Cdh:{cJl|R:p8erk pDg62ǘ5xҴMc@hb(Ty8Q)IA\EzNjؔiO]X]eddzEC PnCg^ JDUp`ӈ#}&6`&'g5IsGMbFw4掐)@Ejgc3h:VOQijBWsICI/eH: ٥CXTqDu'Yp ;}D eS<%}VO }LۙisgzTCU玈4CJFj6aVhH\ʊVӅOOWzW(Lv@^ ep(D5}Gl'wE_`v @w}=x=Wi:sW՞3n)AKpvNSٔjcT]6W 耠spUJiץ94|qW;ӁGT;a |P 'il`xf(;&[s~LWy4y&&s: @jn* 5A4QA]k5XOw8W;^ٕiX:HXmkk; `;E_ ñ+`u<%;LѪ[QD;Nl+ʲ6YBu۪TPG:j@0TDь׬2ጏE|VFjuWX{cWIs PC oZ],w۱SyJ"<]:mE~/4gM|S6h{F'T%&-cAt7oHP,:pX:& g:JlϊEH;R L kk+kh rK",} ;L[R]Th>x@h3< oᔾmmSֹf3oO܊38'3ʮ8I^MqD́:Z*O ՝R]SS]D;Œm%4?b&k?bJi|@A+aܡ[M L]'MPiuʹk pGZĂقs<`;罷{lg4?gÐ)?'<5l Ia(홅4N:dά( vLdˍp |J |<"֧REIK<L.Zxn333tv4t,BGHHnҥ\7 n}{ *~U ;JO ;Lҗbp=yEy* gm6|M…ͅ螻˴ѥuNn_Xpcj JaGZD^ p \wVa &YYԓNv*P$oI|v Gķ9; <}R'mg Y'w_d=ʻ<':xE~P۽[9bZ# >mJ!fK7iNV]bHD^Xe;QD-^FH#DʕFt sK5m&9DN;(IS'P'IW]PQ>0ŖO޲.. z0Mp1 ,* +<#F(-CKqEf1j3\٭j$H##rΣ#N J#\²;t:<4/ғ̪ +7>9J ,% ^|E4M D:ԯM (. -4 BpJh YLTUF /jf7~ W_/($&H* :,PQ-,SEFn|Fgw~e_-I#uҤS,ښ 'rZn=[nR53W8 ,:[mх.}$窷oyT 626InbB!&дLUO$MV]m-I5]pe'O.Mvf)M曭Y D}(4[wiڜ9 +oQF \zG%e^*U^;11**mL0: p[ QpUYe mj+Yw%.[8,I\S$p.trMUi$u_U%+W"«<(1լ\Bkr w y a$հI51k[ ] B)7PZx "x@, ;,K{0RV! a([&uE舘"Åefo_*Θ  hXt*W./'#Fj f"ܒTugw$]ɜ[!4+t5et!T2B텔 %XFOfA2^ ]< !Ս|fPlUh(a^A_ å.E.j?p<8]N5uJ9Qs\I6w+1& r0LP"""9 \n/}i/aЂ'JIY,n%h\MB,"*<{ìOeTCG_ c&jo尬n0k+h 80Xh$ R;4*JLjғZgKLjTrL҂GjT€ x).k  T[zC$Ml(,6r T 6:ESFZlJcS\#3] `ôjg0ap%l5PiJrTQ3.qt'.Gn%-<SL8c6S\ROyE'0,FnvFQƒ&Mh0Ux'S0%}M)~%xo0Ŭ(~ Z5 'L!`\N67<,UݜcGwݖ& X[o}+vY!a 2BQO+ C/f :dw!)ژ4ۦIiV}gޤn?TXn/Y.>9 nJO׾K'j!(T 9D3X,R`42g͎.pc2;5π܄0"HГYHB39#%XK{,禋Az'U>[%=L\|ZYCJY3&0Eo2Dt(1\6c4)ʹ#]G㈦JwD7  Ӏ_-N`FBjg$e~5!}9 ܰ玀H;>;j8'A!Nc8kꖰ( w7yAKwB r3#Ce1oo;AZ*>C R$x ۊ0 )>9+%S9ʔ/HAAң* S f3^zR,1]H#ZΪ_w@ "#Ds'4;`4*>,-B37KCs?ܒ K/!>թNSj<$0PG=Y E|D\Db2@GDOy N1, -33ǒTo3mKpE])8 7 [E_q>#>^d_Ea|>34C+4b7cedf[-$c$qFa!ق[g1*l m+4AL`ДdTӴ7,14?#Py#ҿ?QJN*4r Û ',dиwą;d!Hj u<d' GB$ɛNTUU^D[d !HyrJ"/d/Hk1r3TX_iS]Sa7BSe-vP{Pg4Blʰ [ k;3^|?=FĴ XB<R;^x˅ӂ9D_XN17ކdx[*D̠ Q]ą/#ֽ-`֍3J KO}&doO &W(aBSm^w=`*WBԔ^4_F7ۧj/VXY_Fi* cZ݅pj~)_.(;eg̻tt޼ :g Bs;>վ |ĦHK*m If8ߣXJs1Jri1qYz2V*K HjcdȓPc#i*_^e4H]A>O,奞-V9b tk[)tuS&Q.^uIӌ.U;;CPǖɆ!C8od( uJNUL;. !έ`َfpp^Ђ#,[˾BƈUN ¸` 9ӽg)3,%L,2񳦍Nm/m]6}h We&^ᘔ 5^*'4PFP{ ƥs n-fR'PoWmB䊪Y+%`cdvQeA#K9uߞ ,؅cP5>j9ˋ*)U()H׃\ h+Tg:\iL[^yZp}Vx^=u.6:鑈_ul-aC0cQF'3q6Iȱß9|vп-@z^Hm$%}/w}O1ԃq/QQπѨ_0(uEAߨ |O6ޫk/Bh^|CM Uؒe`;i'^y`Ùo*޲T$J>D 'NP|H"dxqŐ RfG[R.jIF.+O &Μ4T'͟WRNZ\R,W0BuUTj5arbٴfU]ѭΗ.~K]8dʇĊ3n1l&S$( #0a‚R 9qH*tr'7Lq . Ma8cN2a`!N7T`MUԔ-^PaPOыQHIT0bSPՊS]WgѨEZ`[[AYz%3_32SN9~&X]L*?<%eaڳ 4vffVjnv'DQoC'p!\sGp]s9\ue稣yyZ $ѧ 5D}h/h1PJ v*.`07HS YaN:=PVň .(fXU_iWg8Y(n=Y[]N3N^U%]bZjI0h3԰iqhymG[q ]GuM]*/7yٜ^{D ډ2+VT IMT5V?qXQ=8a?YՔ-f6-ඥBN`HνIJe6W֙#g +,'[Zm[L[wan)gq%/]JxތUT2r"QѨZ KkҘRΤ:Maf F P]7wHҷ-U*R^F] ׎\TJ2rffMSbe,uoFOQ(똬:#!fTlg|}BƑ^l"V^M^xd&X G°s ji ʚظ` e~ Mg- r+ [2@H-*`Zd_$cሒZ)')X jP0'Fhhš,`m̀Ρ(`ʭ\t5 ۥ"!U!OqW.b|# >AFT" HEʁ199C/_1˞a2B.PeK XHYC[_nޝX323 f؀lN6݉7c7$rN@I@ܥ D#RY>FHPFG'dBY<!2H:C:HeD~)H/l]HB]!A AO.ZKCMf˅_V]KLnlTNfؔOZ qLQpO}rܠ< Fe]ce員y5}`EQDP1?ZP rb~D |\“GGM2848]MTQ=ءIw"!/eE[Hqma!2mb@ggb5 h,VF47x FR!LN[V#p&b#G݇QqZ~`AtJ'Mx2p9C :2 AQ 4p38FQAfa&{6XR"mK"U ߨ *#ynPyTzc4 :h  q%e9YsS&T&SL͉;b5YA0#>&D]z H(64pZ՟/2$ÓBit”Š .BIR"]ߨd~]eZL]g&L5ROf㵐`&l9%sMuEjW=r唹W>J(GA >tv"Q*89Hq?'8H7@iĂAGaڛ|;5!QJ*[8Z]gee>deLÌZfkF.NsZ+ 1lvhmacvH VfJD㾶Ih*G$\L-DH@ C3C6,9C8mł846l技UP$hDEpALn{ħ|RaRTԂ-g}!6+IR^I-NiƉm&fPJQtoB:JT2[(آ#EVھ P`NE2T,1Ó^,Bi-(Ej:E}o/7(0CbgB\B-XTlb=-hi0p+fηqӖ֎Dm:V !V 8r pZ>J1.YM%8$HXcEz l¬%67HCEIH#Ya~‘8~F$LLB7`)hvpi٩PN8h议 QQ.s.ɨk6 ~^ 3"I&ЇDB@"snDd ljՓl.<ނ.؂.7(/$-t27Bly߈sfqݝ:&8ϬYÝViQ&@iXB&TB&`:h4$OR 0EWf^(S(fvGj bp*L}Xj덄1/ l'/ȁH.(>}jh ' W7T,EX-&|i).DFYu&-lB(.D`m[M %,h!XhAB3A3zi28䊌87L32Q2DE&P2YBH$/V-7)C.Bו.lTiyw.`.XB`6 46&Cԃ?r#3qLP%{2 z(:RG(wG˅6"kIKxqz sJ8%4Nl~D^NHs1 u~1n+8$SCϋ2IQ/d|6ws8tzF<+'a.C98q-(u2ؓ$C.\'B@'x%X_z&tqNf#mAi`:VRQ=goGP%o2jbB\`@jL=rj&IKo񑑄Ha~,Ւ AqAr.xT8u8\.<8܂d;8BY8{ PXy^T78tsuˋ2N8l.@/w5y2ý#7`d{9z_&.'% 66By΄F?e 5G8/}zwcB7,-`7(t.H9;8ۇ.%{i{[ɵ_'=J=H'<@tRWJaC!>tc)!BLeh ;~RdIDNzrƐ+aƌId͘E̹3Ff,!H">iңH*jTU`zukV^ ;6IٲJEĬ%o*qV'rUEɓ}:y2x`‡fՋ/\-*O.Lf*1CsiӧTIZukU`rv,fv_e8ptj[q}۵)˖Y(k˗_-UK׷t~/닮v+ιprmꢠl6(J(v6hH*)CNBi">b %n"q"N ji(@4("q񨨬GJȯ*,2Kɳj2Lʷk+1°褗^{N^ '̌4.{sTz ^+0CGXVw'%IJ0Ғ .\cwa`+NM)S [hy3TF+vP#2DB%D21 E^rRvd$A*K]NǕ~%`T "h":)-H*YKU9tb xqqO<&E5es#kdVPrԙzx,hyn`%->%*.E.S*g\ p#\ۂh_ 9:e"Ae ZRC#.KB^>&[J%0, 2;ӁtikHC"ЪDQ)xzwN/cZ.xQܢaC/3q3fF7&P t LŅ \(Z՚ d s e43Z.̃/Sqc d2~!S~YsjF@- $q" e"4u]œ*1vNJPC}mEZdM -ތ]οH!/3\;b1ޙ6Vwy2YROPu6Z@҆U xɨ8щUiy2~agR4OZ c\`/( 8J d18|0o}CB 鄘Ve$ūi0q$:,m[z83&["Y_)ȉN vg+a1fT^H-|YBos(1sy-p!Tq@x -BV ܷ>S8^Nh^B!oThX}xͲlKo ۉ3C'y1})M-젋[4ZBa=sFS|t@X!JlL-di?^Vydm-غ[*F)'[Z~Qj,w9\T뻘N5Vk-ݯ N?v:}% 1- l`\t |uGX] %lA 9/|Az5Ux?^ V$old[AV*8٠$H/]t"ps_ `Pbb,zaȿ.*/1򭝜 y1lNynP.2`m:NTjM/ Md $r.$^" })'%%j kܜ j`GڋHZ,*vަ.|`$ox`Bc 2MOel{V ; 6VBN~ Y,TpJ^ Dvk hI0%J%~ ]pΐ [)46>'v,u񌛬NƉ̉$RНa:ay(M4Fc3$!]5(5>PJ-/ GN Oo|t !fi sκk4g|I]- ]%ؐ(~E qϘpg-K xK D@j| e'!wFqFf"g`Q0㐐k1#?x|Q Q0qqP!ln A CFO]p2QE^h':͠i 3+IΌu QdK.h+Q&M쩯>Ava Ҳ4Bz<-HR"M2O 8#׾R. { s S1WH>$V%H)SȬ k$pSkmP`6afg`6 J6wK$ la+yd4B a$ *7`Qm"3#IV@eRy$On3<{$ϓ!s12GX 'C [h (f0?y_2s@Q+u)!K)Д.NJȎ0DO/CM'~s@4XfePӨ@.{-/.S./ /Sej?'6S(z5Gs^J@iu-=о-ds.Np*٩Zeef.F+quN҈ܵr{0^gc^#_ f:UG vTV`S%Ö }I6D1&Bo& 5'834c$x+>V)Aޢ(CKq #C( O sG @ ҞFgKDQ Bn5dJHmPյ F^1ү_H$UNw`$\ pJ4a˰apr.g'7nt6 ,@WƛqNNP!dVzx3:A DP6d@ed ("..姁j-Ox1SkÓL16UGUIE:Kj wg'}GT 4`Tj*~."qkDYX3c0WM֎D  kTi`qYOӒVRgŌX7#ܘSTj<lU۳UaDj'Wyw3[ܐnaXFboopoY,+Yr .y rO膠qm ˆiDypfH1"OmRQ7xSֶ/Hswwk0UE%E&i&b%pܤAݲ)a>7NqW}'f07@ 6\u\' f7.L!c&|92;o6/e1YWv0w NUIX[= ֦T&r"V((L.0h`ut{bYp㪯dP[ gm+?F e9c4)ٳWD-Mq20WZʱH3'xNU {O5t#r9iWuguVjC\$CR$@{{#\,c\2ɬ )sʍL-{/]{J*6dm0N5#ᢸ+u6!]_}!%U+մҘ:ժ#2KN΅UX<T|ÖllE#kzG𐽊ұIpT.ڢd׽Pet'}g ,)ÊɵOڒ~,DEj;0x00Q`->i'Wޙ\sɍ(Q,G֬Ib.|HF~|H{'N"^9-[ fr :ܲPaĂ]T%.V6jBI$K=:QDt թS)bj#\rz֭b~z䬑#iu6ܹlQ$^x8ً׉~ v8qb%O7VBɓ''O\ٲf*Tts'P8C MZw⒅ٲ̮;7ܼ\ <,ςo\>~".\hHѣC<X03gk:T(PޏU6UDUS_YY"ad[k\uDwa^w%_y!Fw&`c~M昌3bFf:m6hBzvj&Ѷm- %nXpYnI\i\Yt΍yfCawQErnEtCzz6TM7}RU(SO URjEX9UYa jUXa[i:Z![{ `yb1آ!&cq梎}fdBFiVFmb .lEiLR1eOfeoGr\\&rˍyEәi&BZ\CݱG uQŜqjTuaޞ{4JSETR QâK9  u+LEWdipY(*塇%{EAث>/FccR1c]vkMsdԤYiVԢHa,y[fEXxiErX]P By9x9p#wK91 }G1)9UxYe层~Z^׆b:3_(k?Èke=-cd1 A $էlɆtFY,9%؜Feo rȵmnqnk AA7E QQ+ާƵd> 5`bi 8ae :PGaPe fGxCvK^œJV,,Z41ăL4# 1Ag~$ZUg-\b\Vmm [[t.$n߸R0Ip[ xh+3Fnr%B=0P HA`AT(|B]IuD݋ )VracChX)(4Y,h -xlh#,MLK71jgt2<06)#|UQwl t aB%YE0$[* g$%"\m0D c4NYQFX~jlJ-5(o[ĘIטW1 /=s<4 8pC! z|JR4&A h+R7Pqe\"lzg?;و£I13-*!ZYDgMܢD "E[$af!C"^Bg'.#)z8z&;9%qQcdžGYc T5B;R9=KTI5j [sUP3ь jU4dhW#^ \,.QtUL_d%Y ~ā@ڵY `B5/ #_iO&QkR'w );3"˼W WR$mN0l6Lƭ}.ϥ8t |{uj+cn=E$ڥV`c}W>dTBMQ;=)[A,+^imY*)~Rɦi]t3m lF&?GNy7VD,rSMY)x6-f^آ"JY% cuiV*ZvRAb8=lR,Ͷ/zԧd=܈Y 31wdz\괉:uǮm8< Gl>DmNshrh$4\H.bN\|1"bo;oIv#9",9Ij,4^Pd(hdN$!|UKPQIbk)a.ݡ=.ZlZ@1wL~V}bnffm5gG5wm_gsH1he9[SA,b&i D#tvoI4]ucO "dqj#uddA,ad6Q=s%XFE`2}a _rFx}7էB?}LQ6Z1DžRy0F@Q15nCFnEtn$G:Ҙ2E*U3{"V*u=>Hu94eJHf|Wc-|,|>bAEXBEԲf҇S7eHx98})rDZSFwC/?s[ gZHs9wMG((ňI!nQQnjH)GAbinS*I6VFVw"{x+Y7Pv4Ev,K&ɂ%Se[6DXZb>_!"aB7)R (8wggy){9|"H@h+z. %ÝG)+;;i;$u23Io;ƙC54H,xU$p|cC%XKf'>7.>~_r~&.LVxF3!IT0gcQ)t30U/i:ɀnb*Is*u8VceoEc"u4JAķ&SxԶodՋ# ?"HBUkHvYՀ\u;= '"f?Q`ZYE^qrXRyÛkb&47i~oFWyy6z㞋!WBKj<wU^3D#6OB%[_%TpR}[~QvL2Ul~\Pr'VytaTMa) #'V)­/{ɵ26I*ɸ;3TWwcIqMP;|p^#PvTX1\2Y%[ wv& 1 m[tJ(kTG0Gz'6*N!f;k!{8BOVu<p?CH{J{u!eRKK_R)1_4f1_rbjّ\:vsǻ@TEa;J/ubO<ӇCI0#ɩپPJBCliG %K &B.5.R.7sYņF mlq79y[ǛyMT$+HtlE 7jxUtzWBB ruCr+[aG^IdHEV)EY4swq,>]4|LCSZVȡXo-QmMQ} M  m.}}0]d< +-F .-3M5m7 's? A-CMEm m(>}MO Q-QJ 7Y[] pemgi}Vj q-sdt{}vmX׃M؅m(Mև؍px֏MٕmMחٝ. @֟MڥmwڭZدM۵ٱ϶ۻ]ٸy-ܐ}|ÍMc-ϭվ=s mE-ԦݍMgM F} =-FUӓM-mZۭ-N>%}t ln=ᯝ.#]S)⟽/Nޣ]9N p ݠDMݠ B>BMp m` I V8\^ R啀h W4il2p>eNmn0vN0.MT^с>v| Hn 0+=鉎|>>新*;zbdA/Bn :'rR~9?Q/"_RSYE=czmmZkOg2OsOAl`u/OCb_/0 !OojbOt{o'ai0r c!@r@rv@o3//oǏ!?qccџk?`/s/!//0j/ $XA .dC%NP5nG!E$YɈrAK1eΤY$6rlOAcCGQI.eMNZQ;9nWrD[YL̉0 ! ,5G: H*\ȰÇ#JP5nPQ6@ڬHɓ2Y3˗0#i#Ƙ8sJ,ƒJF ]ʔ[6Ju`ѣ.)ʵWj²|+âҦլۉd-b7Gզmk߿xэPjEzc}Y{k=}MGM=/ ?-i@h5iܿa.>4>S}|[_2c9>=)nӟfDz;^ ~b~ W`}ʗ|f<v4҃'S[87^V/ǫ͹硯q[ⶽfGbGQA}I[ >׈0c XBaynkz)BG{hw'oj>ZHDUiLrë?yPdD' fr^jȺ]hޛk_F(u! o6y,%[!CTHJbu\b0YE,mK!n0! :1|tdgYt9įmaNԜ07:$hHau "whNid.MbJXɘ6-d#KDfBueVV~$Pk&͖ @5bƳc-Bmns#)01So[|ޠYi2?9В% /hSo[(KvNS<+`Ƚg'Ҧ YIԍ|ӗ و9'e[!D=>NqeWxP7Y􊪻ħiZ?P5 6xe7&6R,d:GxN.읤fSY Z =0 Ⲙͬf7Y25 @VKa^)1z̜ZQv6gl߈S) YiX6rMyO\W9Qu(#ζ.xKqԧL Ory `Y/.R[|J3M^:{;'͡/ `TLg-eE* x(obnvps\)2- cM'J (4VĂHW&[39e<̳.d^{J,3r[X f׼FS(EN)wz}NL0mѼ`5p߼*T *=/w5g=F"̄>M%_+\clo2kX:aφ<`,>Pw`F1 1 HĆ'1 PІߩ\&:W% (K9Y̛m?U 9ьmF7f`7 z(?GE.W7ӧ2/9AxXϸ=k&6aKc}n8WV̢E7YrļNZьe8G:юvp3 ᳔f-j5'8 ͓LK,| kC|`E<7T2)ֵ 8XЈ}֝)EH׮8b_8[鉮},3rzۈػ5҈;|O3iʝE_MP]0c۾ś Fj2<7s=F0sjh)p$^\gں pԻ Lߠ6.ݍOe}ٍ^e ?ߐmځCŗv %/d9 Lח.Yl ;rm \;]+[s$!% 0½..WVVvDԩT^jV*V@j1EVZmݾW\uśW^}X\᜺Dۯ/?v,W-Y:2ܯZu9>8\L޴E5\ޅګ*YpĨԪR}g~,Vq\r͝?]_>3| gӐ_e 7! ]8ex5Rˡ`|.ghM\|ef*OdRj88.0C 7C ](ǰ 'dt;-oE?i=–]d2 &.~&pyr-TIF_ 0~Il *K,d0N9N;L+.%_GAƗ\j颖Q"AIƗ$ G->CI#(` ,@y3ތ n )BY:j9jjIdt? -=wk+{ɶՉg.V ŪYOh[7,d0pP]\5Sf0(~(fVmhj^մe Ӝ<#Y2+`˾E,l RØ_:ThI͖A\^ӡ]2QOt8ՈmU؄@|fEPTh?Mria$DuSdE.v0IHzWp|*ez7.t y:VF˧b8s˅2kܻ Z!*3)P \(`7sUmVCi#P4to*kd%'&cr6iѠAWb&l}ݔݐf,,l`lpۖZxZh-zG@ !HMt2D0[Bs0 &#YhnXppԪ"wd[PbPudlZLw9-3ЕJ`5FF -&l0l \Fwb‡=U\Hdp*iBQC[d@=" Ts%odSm(0d(P/+0BVnTO/-n1^&n Ջ|QnF2h%,,ʀT2!]h`ġdm|U~>Lr $ Plqu_k@7\xG!pHF_Xʌ|q3FQ#7J -DR"X-TeCO|M*fk 8QE>̵&npNNS &7&8TDqb>s9q(]𨹞L8QXZT>L.D ]G@ơl_B..6nqU4w!qG]]P*}+&UГr`xqqEr_Vw$)nD! - ǟq27X @e ?.:BP 0 u`.D\hao!;'W:?ߢ@Y@w26Q\!N4IVoa ȀIU;ׇc QKQfPZ8vQ S# ɝZM&/.k ,01K*X:h΋r=/ScCq4-;K̅mHNp#ۭ8pk¾d"S ,+'9A*#3 \+3H3_и]7Zȅ*Scc7j\X@S@7^x-{-i/e^N^ؾJ>qH X;B!0!72]((.$DqB@\؅,_ECrs[h¡e0l҉c7+1TN[Ђ .n0 -o\(K;T@D3li"Zp ?K _B \/E]؅ Pw `  YL,h@/]m6x{7^-[@mкȂN@db2mdbZ[/ЅጿJ1 :S )Ԃh\`—Z:2D.7=s$3>+^-@pP^5mZJƖbI 8I BDˏ+MuɗG_x /- 0(K:,rE*=dV$d*@e,_,E7,X+2 ,9?D]T8KX9q@PC6Ƀ~@\3e98dqHU\=ߛ9 a9 @[脣DX7a܄$1I %+CxM cd6$ӸH#.:i2_a<;ŵL6R1]X> \RidwcF ,wm:m 7d57+d,}(θD`9+C97`Nc/ {HхTɑPsaӅA,]/8$L/ _^Q\UX467QBeP m6$ R?S0XH+R}(m9!!/,o,љ Q(S1D \@[T\13\(r2k /SQr٢+\в1:C !zWǒր.̿::oe+iU=!{"."AJ;LŦӦrˡa&u7U$ t\ b"D Q,8R0ХЂz$Z|٫bB;V9BII*R\B j**!Q9@Z,\ ,(Y\ Ajڿ!+22+tt!r"U"q%u-)Z0EM.&4ኰX#֝±]]5A -t٨-+}ə Wj/FƲ Zׅވ$$=XhZƥa2!"ܔ"ڡ9 Պ( )%\ߑ2ܡs)!Հ㋾e\g.ydfk;T"Q\E"ٝ5sU*c)l>*""6K7Szmu#Sd"i&߱s(F)6ड iX6JLv8bUkhii^̱hbmn,☂KH6(pOuhsW͞]vi.&\Zd]* GoKpWqLd5e2rQm=!ƾoj^fֱ ^YghLPq΄n`9Rbz3^c)si&1:vWɖʾk2 (7pK+rmrQN!;JX(y#yi$no2't.gPp@-AE!^e,/szoK.#f^ J5IOoqxqR7S-(zyuQki7a̹vo٢s4 5JuFvAcw1_ku0tg}.]*I v_pvtOfp/ח7ko mr~vᨄK@p刃g YCY4qf2swƮD"\w2!hrNz(uW[]S rR2 9\豔)u>hiffݏrib/cf$Lw'zes~݅!n>hDj>{~u_I|g!F#z"%8wKdpV#uOwN47x![V;/go/m^ dtrT+gꝱ!}u^vk/NZw7 Q~,d!h@W&TPᕈ'RbJ*-jHG"E>yBŤɏ8bk%̘2gҬi&Μ:w'РB-j(R]vtӧQ6bլVX-+^f p!A-W6\Kr)Nh]CcJ+}0Ċ3n19RTNrpkV Re+Z؞}8"*ݘq0n'|‡/n8)_}4]r!W\̒F͐EpJ1 i%)Ln>w9fAUXa4Xe%jkETz{^n V_V@QX%x")SUhsxg}݃q䖄 ejbFt[AaPз"QJ9%H&VXId݌Yuyd=kM#䙇ѐDdwoU'NR^fy&Ved )xPh }GmAT!]ntE{՗{* ' T[z)ZmrtmW:fW鐛njau&kEt PTj-?]Y[ `AXIW֤ Yݩ٦g'2aG|THp <0bfBǜ*&2 C>Y썺op%|rvAk(3nZ5nZyi[҅i,x_fQK=}-NEk]nqɼ^ĤZmimkǷr|QB2yb97+]BZ՘:yq -QE䬳v߇#7衋f-&<.Z-J6hey8 dkW)勧}$HKR+R;k1:Rh'(V[V\pi<9ya9Jf|=<]t[-$,%Y_$j M QJRGM aΦB!TDfӱҍ7u`T ڲ(D ΣC<"%2G=()*1>!(&^"0qظӨF(n|#x5ұ#8ю~q(A}$"B2)I"ƑIMr'$(N5 %*SyQT%,SJWҲ'Z򒔸#ga$0L:zL2EgRД&63Xm&)/z8)r{S'<͈FwSy*Y}";)Ёӟ(BX{4]BχR[gC+)](HUQu~4&-HYғ4?)J[*ST1)NSSn4>Nӟu1APԤI]*TTg>5VTYUU֬juHQ Bm%kY8l- fn%hEZS&u|5kQV ֧aז5k #="H#j,h:Y}@k? Nx6AFNp,!Ay|p2ꖷͣ96@ $2#!Px t85 A0f؀9:Z uj?g3EڦvwuD]y3&8y pCdy905lx B4Kq"m8rhp! `l>XPJY0!@GΫb{< !eZQ1s=틎#þb1G΃V8Hh$ q}NcTa6 . 516`F#1cVbal ("/8C1=a_N|b-=gc:!_^{E}= 2@$lāK$1ƠIT2p m(Qỹ61`^"<p` y1prQ s@ Řt™n =ތs@ {910fbnCn!m|%?<;[C4 ԥG1Ё GLxxzx18 `_ڏn |XéSufw^/ D[ ˬ!Ax߽:/潩:$OۗӣϞ3zc&ψ:x ~9i fK98AUӠ8A bV: C^rIQw2vG/c$ü!:: |aVρ_ @n c3kz !-@|qF1 Ù~џsyrm@,9_W\jZ=aY \_Amp@T1 QyZ؍5m@C1Xm =!z `UHX9!%1%Q/pq<<~ }'j:$Xfk}ma-Qew5C}%Ѿ7Zgo)0p=уrq9薪!u!aX< '  =PIz@2AŃnU!,Q&Q]Y 841#2f/@Ń@9%Q2`]Ynu,90=H`tC8@*H9X/2.Q78@: := zi$Cc|%9pB/}ObŞ'ᗱV =d@VFq+rV=W%)=q ܕwVeaeAy}dɤm@IE f%d" ѕA"љCU7&Q)I KZ9Aq@L=x;"QEȵ=|jan"=,މmo\ Q) 1!b0|yB!O Z9eі=ٗ[Ð YJ jqə4%Q=1Ha1Tb2We(n}:[EhUd1DyyYYy &a~jjU&%4=h(jUQhBC@\k*k ƁnWk~1QE"^"*Q= #QYtݙ @Nޘ&!X} }yrPQ"Q^m!%~R @vݛ)BpoW) EZyMy6X3|jɱi<jn@CCvQn@a* ыF$ܘ-9WA*ѕQC1k*Uq)rWk2dAd ANV~ϭY|v6Қ#V=4*=g6HX1*'!C&%90@R( Q]*7 %-2)tꖗm@ `h@==2ڭ)zЬ-l =+C19]͚WF Q&0vcF&=lQp&.Q=Ȧ=zi0Q fByk֞5ti $Pl9"'$x,m}zR"ؖTJMiÕyZ)NϹ"=ْmCفڒ|"ԝ)QEZABQnήҁN=0@q%yAC6Qxfs=0Zj+!o6v^(oCͮ5=<iCCrс c*Q͚Y5졥}%6}Vn[#QxkZ 0"g؉#WɶY3tWkGwk_2׶a6=4Xk65`j2ˢ3q5CvA-_vՁ>3Qq_'Q=k-tA2t<ǃO0h1;Xu0C]fmËxm2cdܶx1pb)PBזo_C=}/=Ћ|GO}A!}S=go=cRׇ=ٗgE4=۷_={==߽>|>'p=ܧa{y ě|E>#BX2~监>5>&>-rS=y R)=db@}~M>>>Qb0#3b=Ωz9yAyJʼn "I9}˹׵݆:@ÁC8=Al8@[c +6a:hIt@+&fCbRtaJ pG lr:E`ЇErdɓEjblW:VnHÜ)1s9^gJl.y w1@r%3+0NsqaVoCr-sP^޽5=Ac}AC]}RN1:l5~aŊǡTiP# 8̶fT asқC5rH 2J=96p?++Zҫ P'1 7:{"'А5Z^4@ĈcԬ<5Ho=D)&ɓFگ':B#;"g p76N 9`<{> S1*xO6: Ӫ ;k N99zfÎ)SC 7qҽ7HcN!KTM nVC{g}lths"Z!8@!Buh:|G:epIvG5mSR*pg۹7ء]f}hD9KVK鞋\^zۭlxVͥVr2fU8%Bb<ÀT,%қ" 5V9ߵAs@whxd |Îh,vH ZU~z׌Ω/SZ>r (7ʿө&y|D* 0!m+^ ;9@)z@{]H%{y#7vA 5j@⢲kjLIBá̃0S=$0w@y [ 7Y]E/'_ sC,$'lqP,n*s=/0'hK3Qԡ@Nj^"&\ ĨC(4:hqD&%M1%piڥ×MEѝB'hZZ2.PĆ`!Ξ Hp ⑪qʼnHGG)HYIN6̜V692bdiI=;0wvDY*ّmZqo(궲 @lpPGR9Tq>>| !hKs2TGᠧB8OC;ՉE QNRg?j0i0,h;HL8%*W:L`@B⨔1-rQ$֢`[21+JRtȫ]VMTNwɭ5.:Iu]+^Yrϳc7U[ʝCdvZp(%YTf*Dc]z=žeJEJHJ9׀k|㻐-ǞۀE7yj "/!qya!e)pR_CZs ''sH3DGj|(<&܈<lĭ,:رse.&ճ=`:ӾEʼxD0%1$m#n;8"A(C7Ϲw\~wd]S7r}uNX@\3Yy0!&Um)9ܞ5̡>l ײ"u`bעFrZu()|}|g{]Jƃ(SkD{n*'cHQs"-⠱1q, qU90!#bvJtr1ױqnqQ q^@LN!)"-"1!!'oV 0 Bc!pNjƠRr&i&gR#Q "CmG$!(Ō2)r))1(I(r**** } ݲ+2,r,,r-ٲ-R)M-..(+P(cZ/30-r031s1S0n.32%s2)325s39320=s4I44+3Ms5Y55J4]s6i66J6ms7y77I7}s881/C599Q(S9 ~s:4!;9. ܀:*2@i<$52!?S>>3, ` Zֳ=473_h6?=ف?}sB+@ sC+=`|y,ТlM2.)E) yC8cO8h#&f&t8Cu''w#"*BŪ+5VKI18tT p"HDCMIts%AI43ʧN ;-X:¦FVLC R,OT(ڣ GG8 *:`FmwI$B`d p5AO*TKQa*,N!B7O65M Z MaZ55db!~@RZy@Z#d Ze9x \][e@:5Ե[{@@Zѕ\5^56z\e@vZ#^6@Az\ٵZc!^sd[[c!d\Q\G_O6fd56_CV^5]fvhhNa[ii6jvjjjhc!6ZSsEtDI|ؖmeжma@ڶYm}9mooߖvp6bWmnW"6n+m9` m`7p| b`mvpCooopSrp6.wp`tSuDuۖs r{t7x̶B-67xyWx}ywuy7zzyW{wz w{w{yWz xCŖ DWA/!=s~~~}48x 8ZNvC!8%x N)85x9X9,=1XsY4@AX};8Ux 7@CexiX֓=6'kxÇXxX=iQȶ8W^oxB(E QD8x@ـ `}Ӏ x ؠ@ٸ9#@#E>T!9%y)jy6+95y9yA9EyxQ9Uy xN1a9ey}iq9gP^Y}!xyDy'̘9! ,5C H*\ȰÇ#JHEjԬY"6@Hɓ(S̸Fʗ/ 9͛8s ScF7njƒJ.ʴӧ-5r*QFZʵם,7ifhJhZZ۶Q3jٴH˷oWr9ݹ(^B*^L2O[tcȒ3k!? di-̺5?"x,{tۢqslmm7rkFVNJ bay:Sk;{ݿ~>~}w_{g^i% W4`4S7PI7 fՃ8rH"&h !*%jIeY`sPTV&6Mp)e=x扐Muɍ` M"!R)OC:UStM7d**E(S*؍&1ꬴjW:OV_rkZdβ̢ì9.(PdN sלs 7B}Jm4Pm݌K)[ݯ/;v8 e; 0vColqH-wwnU6NXu1/p 3.l_l1psҚ{r.[ͯJmzamc~xJ 1c^1/KuU_=̷}mf-;@g=o{/#H>o G~u6˙0av]. Fh>oc_V5obh'1َh^<d赼pk`pq40X5{%L}ҚBIfg8iz:ڱVU#־ N_Ħ nX1ww$1<O V8!-QPb q/$W pClWG+$ 3Q-XÎtl2A8Ќ4IjZf5pEfzѦ8IrS:ש{g}f\ @ςMh=:CQD'JфbͨF_RюzFGJR(=HKҖ>$0B1Қڔ Lwҕ5%0 A BR |)PJRrW6Ui4C*E#hPTTM+Dt#l+< cs$!{5dY'V6XVbqtc 0h™H_YV=h50GdqxVVD" LCl==[sU8юyGiZ8'+=R_cYqY浵MV9,/*]vp9PXŒ:~[z(ڙ޳;i]^|TvR~`1cbسǢݩorvqؑE`r|ml#QZ>2?K~%`sw\IxawC="kզ[X}43kjCSb.=(,y>Xxp%rK2#wS:>LnbX9rhbр;k~֝w^8Kss9"Py!8nwӥx4FXWUi/?6H%9 K/r؟@y7Mr??>O}%{V~UW &}qir OF&Oh{ $%}ly OTc-GRu6^]ewxDdܕs&wP烅k4%;"{䐀oyu'j pz600 Af 0mp9zƄtOl"P{;y?F]Bf6 WraP_^Ňa]J iMuءZ*x(UrP5dрgYHT6:sRe~&XOb( `H ʸ qOx@cFg8p~hV|5pns0`V?w$h]6h[!QGN Hu`vNh8q^!xdkX6aP?fk8~!QNe_ȍdH(O0OC&ebX0_!Q˜ru՘~c!IuX$kmXR8X (TӠ]u9 y-Ŕt_Ah@D)hȉYri Q8z w~yy}}y }y)I|S٘Iy{9)}i)/uu [$/紛ٛڔNYD])R2{SBtD:-KK:8LkC$G87+II+DF8CAKFtA?FsJJ;)*s5dCE :9AC C;JJ 7<٤28:H`c?0RG8!FJ6Z1t;î K/KI6&j?4JC110:ꭖtIӦ *Er1=9/ :}tKZK=U*EZ9F{2)jQKٳ3C 9pD9]ʲ{Z˘JI;j:[)4tG 19 /#t2E_TKR*?Z?*4˼1EO a@/T9<׹:i Lk]zJrJc @C Ğy[:f[ADEʛZY T X R5-3b/T6~ZSDʢsOL p a@ p "/X`MZP4+aZ R0H:j8[zm?@K ɰ p Pp Yap Ƞ ʀ ŝ Ⱦ 0ǽ` a= 0NTCi1B?+o $ E P  t  P  #JfDCj97; GYɀ] ʷ R P۠ʨ<:l Cû?zJ;|xWX м ߠR`O0 R J  ?0 c3;7?XZJXG,5$ 0λ  N0J `ܬfӦ@ڽdȫ*Ȁ Z I|@Z  ۀ-P/L] 83SҸjjۨ==]- ` W ȶN0{]138 ,Z9x  ':=ζ}` ~ |=JTK? ͗,HMfW 0a7ګ  eSC{:Gޭڌ X ΀TOʠO ʝN! :8;05C8*ۍt?< Z pa ѹŝ r۰zܨLL8}AZ^:/N `@ u ΀  !| 0`ɠ *;EKcWNm 5Y` fX  ~ n+:*y'ӽ$J",5a5ix Hk0RmAݙ-GF^/c.1th|՞۫V.:::$ g>SnzcE{sw;}mӺ;^y>\d|B#ڦz?'ζ;>p7<-Ft@>F8K U?}<صZ/G,zj{; /O$D/I[çY @,n0ۣV;G|9۾R#d4F1c4+3Q@=溺+_~sʭ,+O)Ɖ 11z4FpFunaojgDaf>E_lJ ~/ÂDfK*ﲤ_v2ٵD3%T0;nzEHg_{@\2gD MP$o;,Co|?v0@c 1)l*( 7L=*r<;#B40DG$D o +K!κ (-+Cz뮓@I ǞdI';)o+ȒF`Gd=˹N'5$N;Vl0Z ,Aɳ ,HLnO4ӢsS8%9SO?n¢A 7ӻtF3O4;Ț,}HM75Xa%v62> *nE3bCJKC5< ]izMLUXue]R*E. ̰`VsVpSbܙތN95u7b'vԨB*PV%U7b5UC8V%PM78Wo9g&@0(7|-ԢRPQ1,RKNfVO{[c0HU4V,hJB997@-HB:(uU5\͘uG> ,Ʉw<" ږ\ɮ`DMt37&O i[XF5ӌEmjB21UJɢl|4NR3M+UU;\E)Vj EN/9g23-I4'W-nxśYbX.39g8:o~_R&˖J mk ̽wGG[)V"yKi;a>N<xP*8w9W+pkIa*QHWE5g&5{W*r]XFzjx-frG%]5WF5#ggu .Rsُ>tw?g79g*-3{r ]l4]7a"@'Cf@Wzt5.zltE=jLcFuII$կ5MjZ/4ַua=ZҺvm^؎v-Sk\vb?%v]kwmrg/˽ݸV7ݵw¼8{{woo:G8 pt<%NfC8~q) xE<#GJN"Z[r(yu;;uz^~t&^zӥ^;S:`~g{zu/%{nk;k{Pڞ<+~w;%Ү{?G;GK '~?@>ٍ-?lg>v=vЧ[G=MJlѧu]uZ9Ww7\Gl<t rhƯQtj`6{0c az1zocAΡ}$Y??ycb#Tps=xT9X@5rؽ5?: 5 yH(;( P:@ Ms(,b 8X1X?M?b @Ի9PB{W3\)x@1xHs 03AM)P_ݛ$Ty Tp+t< DMX>M1 L+CI9L{ 03t[BLL@?@Df6@yX( (sDM bs[$!3D",LdL=z`$=ӔEt [t9#,I[8^4;pUT_1xDK$3ܿ_)BhdsF{={9MdɔDtq5|[v@ If\FMDT8"HF{Ħlħ -/ s C3H HKJ:D;<-:Дfؽ$ 8_؀9I{sƈtJs8555ƈcǮ[:L 7@I:<45LMNjb8?o\BXMMLK4lz(z ̼cPAbLϜ$=3a{[L8JO%;%PM8͸P=߫оPM ͽ ݵЦQ+{5e6;]5 rQRњQQ !%Rg3ROC$5%58uR[5Le[-ҵ,5)Q`Ƈ $$/5}Q1:Vۀ0SĴe0k-ܽDcS!R:*=P\;JM EL{TaPԦ5$182,JL_F!<@5u8}??V(R{$Dx+ԝ ;=cDA:Ab(^U$V$B9>5I Dm? 4dF4L5D1FsؽE;ÙM~D5gTNʹVNUKV>C/ImfDsP̔%Kl}>LK5X Hݪu6CõKd$ ΄_9EvW͌WJFQchfՁs$n~cg*:KDؘcƙHʤf`ťDlhIaMD̰DgFi> |iM ZST\g~ ($1Kv5|tHTHi.S3Q^_QZ4F}Ljz|EHQ3k Df4T.љgQzHpQ״LG59> e޵QdFG&uQP><[NO#g4\Vc` OOt+GPEgRPtl(nІQt9zS8`:`K@W2^^lW[LȄ/~'xwg8!zKϸuqxxw468($>: }8z3py]yK`xG1pf(nx"zz\s5 yڠSldžzG?gw{? S7GWgwGXLzKXa7G/gwׇ؏՗ڷ}}٠7GWէ}~!W9t/7RןL S7P53_4`8}6*$h 2l!Ĉ'Rh"ƌ7r#E "i$ʔ*WM2őcG;v rʉOg2m)ԨR"dRɩZr:QK&ZE7mq#-ܸr>-ݼzmf-4t.l0Ċ3H'ƒ'Sl2frD3ТG~HgLҪWn5̓aӮm6nr7<8ʗ_,9ҧÎ3À! ,5L H*\ȰÇ#JHŋ3qƍj &ɓ(S\ɲ%K5jtt054sɳϟ(cvXbK*YӧPJǢ;"Etׯ`ÊS8ĖcʝKWUDlӶۺ lQhY*\[ń#KqLnT%ȔCԇ S8c?H˞M8u @Lwߦ}z$պ_KcIN=VSٞνPUO~xؤ7c >vˤ4xݷK74؃. .ju%Sj䔇.:bu~o H1p*od.i?_OW=Lo?>6އ.߃>/ ㏍?t P4Lx:0 ` Z+.e|]!2H>;(σ(L!K'%b{Ѩ hh}&Twhp{ȝ!H wzܣz1!"B W=#&`4ꑎB0! 5C]$HbH40{$tgEA"^8=xvӀ@J&3!1Azd{$BH#Ios.GO{~<&GBqvD$ )x1Qm!;5 e!,JZix" Kz "p |"G""[P$K=5!l=zL{ABGiI;`0 c-4 }Тly[=jń(>1DqzDzqI7fkpf'0Nr镱Z({#SdqCkGJ3/}bN> 0b9 :Hs|?<|t|gAZ>^ $zznGEzҘLwL{:0LO0KSZ,u[WۚhźlF3Qk]Yj}b;tګf3gqNZ Mm^^7_7PmS%YNN&6q'J4:ZZ6oJl\3IlNEFn_V܄ͫv+&)luX1N4syL3us/#l;LiX 76ϱHoNη=`yҧ・.My/pr-~s'|FuϊiWJoz~j3|r.l<@+~d/ bkٓǸl,p [}z;V4ڏ&Zlb{mC|dE8rק%twk3Gw>}nۗ{:rR7 |bw|ǁ }7tl&-gzi}095{0imvQz_׃5z-QPO+ƒHiwnlEXbW(ig9kyއ|G8|~ÀF-:mkȆ(gwyyVlCzm'f~hx҅g!xkn(t|,l(g5xs+-XlVGyGtD:oi1tuWxj2y+]؉Omhxs6C-K{m(q"Shj hv n|(fhx~w36w؎Xwq/mW8/W2(0kǂ، ֋4(i6 ypx|]8 ~G.Woq)U'9k'4)hx|=)hJ06wu~:9XJ戺DŽ/Y+׸nKs3 Hw #\gWy8_C2[YUNHF@D+mzooƏ ȖXY 9}iEx.K{fȄ-y-i^Av:;s~O{FyW6hbט[h./uH+;y @ ϳU*,9|zҖYȉ Üza{.Wzjȩ٩jV3"yeQԃduG7l9p0@cc5*vW+G0 j]R=p p! 발Uhُ`XiW%Z:b+Uq57w J+967qQ =zUǟ8pG;0A%STy7ǡ[Sy5ّ 0,Wm8p*kaKIҧIPzfj7ia ʢ_i[CF, '#zU"yWo+}a q :>jdWyTY3_(-tx 10YA*tF`w3W}ӟnZOsYvK9+- z. Ur^rqp25(U }Ț2Qm:ޖo 밖0)gtxGqII.Cdq*c/M˲50gv(+&s6mZh+?D֓ 3jL>c%U~vXRKV=V{^Th\T^<55PfRhkkPm o{Pq;WUv+cyLx۷"K{+L{M۸[kO;TGaPj[IJK+{ۺ^˷B[ DԻ{A4@{[@ۼ㹧 «Am;@ϻӽޫ>F>@Ͱ [? 4@q@;@@e#>̐?ưj`qP=k͠i{b!`a3 , n@` L?@L=9Nr =|#@ut=O=5 @A<;澷=L\K@+ԃ* =L=`ekY?jPkUsJlzȐ@džlNJ̓?s@ɇ|ɉ = W<>;Ӿ ʖkʌ̬s< =ƜȜ_e|Y<9΅3l7|t\6xͳL8|Q,4{\̳[]|k uU ? ? ,^,@keT>ф&<̕ UsfғSbq ճ P`I<  2j4E> csZL>@2c )= fL= U` W] ?؏2<֔-Lx }uà Bc Tη <ɧM=C L=Bō13\=ܫ]Gl]d=om=dڽ]/3qMc#s@r@>/|tPZc}r0F=6D}j3 fzңe@!!PJN5k%^0,n.24^8):>n(@6M3H,Jk2T&V~Z*Yc`)_>=Rfgb慂l."nwr^{uR|ߌN'q>Q>hP~*pyqh1yf= >`.no8q0nnnZ^N>^+>^Ǝ>s !~>^~>grrI>^~?t0ș >^~$v0t?__ j}cKݠ gp eZ(?WN&. c l0C#B?PP$BN" VQ` ~8/zd"c_j? P^br vxz|~?_| t /ڐ ڀ Rr[/%t aAQ0ā/OopϿ̿_ӿo?O/?C@P@dS& z) 8sXQc%Kq}RH%MDRJ-]SL5mQcǛ=}TP5ոqC49t`UT:U2 ƍVXeÕ#ǯgݾW8jԌSLoPu`…  ؒ`č?l8%L:쨌H=fh͝EFZuHp\^[lڵm]N:}\pr]\r͝?}<9tխ_Ǟtݽ1şG^Y_|(+z4! ,5Q H*\ȰÇ#JHŋ3bTf7 fƓ(S\ɲ˗?YcH5aɳϟ@{Q7.UdMЧPJtЏ9'"U)կ`Ê+TP3 TmۦdʝK%Z9R\׺ sYm߶L4㷒-MZANz%ǟ/MDA~FzjOm+_ΜeУxSͳk-:Pa Uwխξ˟?o`L3u{Ͽ?UC_=8}߂ f|Ńg`R_f҃v $E|'W:_04~})(Ej&2jJD@:ȩj볩 ,)Im5Z~{<'  2*H3m<[p$+*X-v/*3[c6-tm d|{߀ǝw߄N=C7cWn)gw9矗n:86>2.;n{N]Ew4;/ȷ%=oه/TC.M$S; oJGS HHG" AA"Cv:"+ !ovK lz! "!DčG!tҠ!^"W B}+a! a ġm(i$΄ӫGGA5\?(JCϫ]4[bs9 hIUBdB;!d/?0YH/Ř5AlA쵴Ma.]]WmMd\עUMk7w^zIyW)$싽⵱M{S4~;iSi&kK:d N򷌰/iɥ FTwMڡs-br7O*͇泅ޚ͠T>#fm1 2Iݝv78̩ 9M0KLZbkV5r_dc=b[R8F7paT,:u4ӷk/Sٻ>zJ[2~;}q%٭ΩUbf4Mx[}!Ɨ0/hl[vM1]G׮VlOQ|,,3e?\sqya[J*wO: tw1x~z/_>SM/ZG,P ` Snwe6Q~7wG*M78Zeuǀc,gxH~>#x5u٢mqt!(b v(y=ǂ%g?3-g4\ &lU}^׃ĵg|;v_TFVH)p|2O{aG*g4>3<'wGf<'i'6+ t]lS11T؅hHiwVsᦁgwa臹}0S1!o}h)+tʲ~Zs¶t ÃZ+c@ CU{.lIwvF5 a8Re1Hc aqU6'sBt҈qqp wWHBy"S25@ 7 am`P$dc.ն.t>V kQv'`b)ǁ X4R_s&x=@"New^'cmQ 0}}‰_c`c|"i6y7}fDNabm4Zs8*>:ӣ>z=@3DZ+ +k#=988 I+@+:W8Z+6ڵceK8t0 tPU8a8o6 3 b+m6ڸ+;R*;) ([~r+'pҺ&u{2[ۻ»#;1ś%;"ҋ;[s+,Իѽ1;{b[\۾ ;[k˺k[%L. ffes0Ȋd# m  f|M9VV c`xƨ8:+ c@3l@6|c8Ld:c@ aQGPR`Ɂ߂ 6(<\Ys!4O7t (GB'a7@؈,J=89<㏨D HQL$7`TO: 3DY`:$NI H elޓY!ji睱IE9x*^DhIĒ}I皃6(WYYhs裘f TIy袚*jIcI韌鹄Y'*{ι8`믿‰&h:9ì&3(9P촘Yijʉ v +bdn#֛fҋoLeIp7.oWRl!bj,,(ܜ̲,38_s,e4 b4y-!㦓qLWmӂDN"FV͕Ӊ+ e,]9=[lם-7vz 2~-8߆7N(>x`;n9GKods均>碗n馧ꪷ뮧{N{y[>o!H|ҽ.o!y b ٸ~ヿ}܅R_C=A5- ^"WXɁǽA4Bj&b2ӒJE +?a*cnW& {̖'m9I*nR䥾Kb*R@[sd3DrӰtyIl _b0٭m>I$紬-iTH,^I3bg=N|I"&Z3ĄgA ZMb MIFtYd"®tn^tzvQyӒ,< X,H-j%II)kj& K")O%JŀBsډ1Sf.eP6MͨP**\6\$HTuTZ&XϚRѥl͔>I˸j*e}]e{m@cI)KsV@TUe,bZ)JH$7#{)9Vl*wVhiO頃 k%Se>y6G%ְ8[+!romq_]M]nQJ׳hh5wK&%ʺRVϝNݫ+] Chew k/6sOC㇝|e`6xjEk?&6$^8i^E)ѡ1f=ML*8q*EBOCi9iӴJp %p1q`d c9˟%À/GyLjl9Q8H9­%n0:ٗLmX&dD+:/5|Ŕtp'LSzdr=]iĤ˦Teg tkd(k,ֵ s]]+uW-Y96e  XS[2ӾNnd$6E"q͑u[#~7F-өfz["7V-98^p 8%o{K:H6nFU>n݆1.9OnNmGlFk\'LuΟ^ƺj{Ni?F;gmH!G1z"(Zwl@ XҰl@ _xadq@p ]vnِVA*Oq i oO1Qc(Yjfjio/YY6QP,.9m8+J57)0!q# m8}!M^`ٓ]Id$ucub<! ,5P H*\ȰÇ#JHŋ3jF͚5n Mȍ(S\ɲ˗0aQ5mQϟ@ JtǎnҥJ,)JիX1隆M-E4UٳhӪ#ș$bφDOر$W&u:M>.zI ωDs5@ğ%u"mS/M|υ৯~FSG;τ8/38$ 9n~ˏ79-=2':׉60Ĕ:IOyS~ )ЂfMMFSR&3EA(Eю҈W Y(퐲*d))}(3) 'N鳨E+a4CvJ(Kb%e`ZԦT5ґNiRQ!lӪXM0V^XjFֺbտV5/fYJ׿,SWH,gjbWBW,W:UbDb5+)ς?H/y}f6UImY5խK*+6ȭHjy7ЅnE/^6u$,P AʵR`ŕ[z*z+3^5S%m|^I̫º.KlTptOF* /WG8FDj^ _8/8_"lܞV[j˫تi [Q/y ]1^;ݣ"P3^2l;qYyC2pUK ?Y2nEKYZ5bl`g ӥfNv-j nF3I1Jtp yjNJS6:ҒtyхiNs ;i~ңkXHZ.s_ RW5[Җպnju2,k ,D:;XK/dC۩k*%VѩN"7-nf[(ב;b%UU|jel탣Tmkgpr5n+oz|Z*p[v:&ܟXe7Wyuͳ'ySWmU`\ՄrsvStN1N@ %2 vd=[c($0$I6@RJ`s?g]ՄE`7HS3).8H%qUt*c<AnBё!Ӄ$H&#T> (>, :o|dS)o#&U:o}'5!Q#8Q X?cLBS#dtXK*n?TBosPFs(Mn2tvbq聝dkfiH{6R|_Ep'P8xN:ԃ>M@4DxLFxJHKL؄FEFD$XB؅^XZNa`XhGjxԆnHGpo4tFvxdzE|؇X(E8JTCft8HfIH 4@x(@Z؉oh{NSH8]ĉ>1t8FXsDWH;SԋĘDxʘ9،E8h!E0$H8~3Fx@؎h8;T=昏f5}I<YD9;DӐH 8yјIcx:$7$js)c(i9* #/iC cr`TRSr.cq 05Di =Q dQ5pD\)T3@R` gS 0 ŀv5Q  aTx7ti'٘95ð)@ 099)5ny.YC705 QC yw4qp9! oc! s 95Ű==Y8tu YSc 2ۉZĈYٞ)9 )7옟vy7o3-ZT2_Z2 *2zN١Oá *:)&4"R,2+qc2:01Zr8(:E>j/=o2Dz&FzeJ:&٤ PMR:¤V$XA\j#l(_0 b2FrdcЦnZ0f e@sJ` cyjjZvq~^H W[`DPp }_:#zZZ#@$bv#çC1 A $w r:5QYTDb :p'[`qYTTݠ P>P t *qyGґ PA暮 ِ ڮaZʮ늯 k[ ˯ ۰  +Jٱؐگ k &۲z 2+#۲/K: KE˳KEk˴PA+,[[GIK 0lcel>:Pe0fr|@{}˷[{۸+ ѷ۸{Ṇ۹KQKk;ۺ뻷KZ  țؚ Zj*{!4\n۽qqp廽Ni 黾﻽ܫ;K嫽 ⫿ {+[\ѿ|ۿ Ll|< ̽˾,;HLkl&k 73L<,2<$,:MLNQS|1 $] ;[ KR|PRAH\IA@u} ,^ǀ|{tlC,Ƅl4,Lń ǒܾ6L{ǦLɟ\ɞ|ș]zQvЧ07W-cM0eފi-0Kso:],! ,5N H*\ȰÇ#JHŋ3j8͚5nTHS\ɲ˗0c C&ɳϟ@ }FMH(d6CJJUjj~Lp)ӧWÊKlլ4ՠiNKݡjEp)ܷLEj]oK\KLy֢["TȕCMz>䇏(MmQrZ5ߧaǎ{ScB6N { *Ν;4M$%қWoe[ {z7\`h`v&a2ρF8WO=0%:IᇔU:U(=X!4^ &:5)D.c1L_Ae̓MVi>,%ts6])difFEVHO,>p99tx橧9!矀*hD0 3j衈6 1 *餔VZ(0*ꨤJ)FZ*E)Ϊ뮼hrJjkF+V:kkfz説z-ku k [k'eJ"W\`W, ,d(<+q0|=4l7gӦ<<-@My>mA'M=CӤ*46;CmՁJ4XwZddBWml6c-}st7v4! q4 -uAO<"E:RR|$IZRH8=fKzL#@ORLL JyV2I^ֺ\I9j^BfY^H]B.u01&1d:3=޺eY eDҬf`D7J9*He=t]!Jr*tzT+Te@2ͩK ьT@}K1Ϡ&D nӣ:U#:h:ԧZ"'gĪzծBTQJ։84.iYz1 \e\RRjSs]k׾&D=^ՒӠ|%brRL]Sk5̀Us5iRYagjs}e.jWLQ3=jhulmmSNv-Y1 WDA<WCs9:UwOMjM+bWCmqkը2jVg+tQYM{zV]v2[JU%w;зr$NY+M*8Es 0)nc9 um{=w*5L RkTW]Q)\qQ<诀 3Qɍn|LftL.pxg}j׾K2-)(k>ٔIE}+e5ifYm~焸=l׹7`CpdG̋eh_LĎH+`hN aN[0JS Rn,=Q#8H&qBLFԖ8&l:"ftvh?; ` G9ݐ7Ch4cw,L֠1wBKzw!n1MlLu6+.R<x|˘,zO)/u,#V5/ R/_/Stֿ>}q>[H>?үm{?e_=?#5X<HA sx4E33x2D"I>'{$w(XA3.X10TԀ483x :(0<؃@EHyC}6xrcJ(;dP c 0iӄ3b q Zx7Džgcu0@pl75 73f5ӂy4CP 8@jX!D3jX S3ksP 琉X95c0 hC4 '5kSPo8`3` 838`4i j 3lR(ưVl@ 0xHdSE(7(蘎숁)Xl#(G+vԏ)y5x i ِ;9AXI 긑َA (H&.L<3,)(.2)'4Ypr8H!>Y&@c2Dy%Fy4yJ E(ٔCq0q {rr` Cv[ɕ Cr0t cHt0vImbfC h V h9%Bp e]amir [;kzbbKp-K:˾۳p+͋[ k ,ܾ; ,,< (ͫ뿕KX%QT@U9R; !M;pzT{TE  TdLAlpC̵WoL!BLalB1OBp3G\1È 3! ,5'J H*\ȰÇ#JHŋ3jP5n\H5S\ɲ˗0cdjJA9ϟ@ Jt55sZTҥ6EJJUnzy ӯPK٩5zZm[KaʝKՏn@Ejۦq L0Տka-OÐ#K,PMޣ!TsqSKq(M4>|Ig?L˞M{j QwίNxXȓ)УK? 6䨔Wc@Ou:SO^25,Ǟg߁E_ 3`cpB6ςX&T>a zhp X I&dI+h#F"w^=~rꧺ& |F+R܎ ײKݖksݺ٢ em9n/Kg6+;([ 3,G, 7lJ1b##?n $l(,̨LL㨷:C D׮{ {';[7<İ6Z|1ໍ|[s=SsVDn?|G`1YlX K` jB>p[+ WQ0r qM = fX? PlϚ(Z1MDEA9p] ~F1qHgP31K2ҽ]Ul>6UZBZD_ HkXOl$At=劐>*Dʃ eE*QW"MV摡$@Zb-w Js &m*=nQȤ)]&e! LhZ0\&ynF4ºre8hvR5'3czV%zZ';ϢĪf?:u^$Bg'љ E`9BfS݈/Iz%4&D?J҄Y,J'Os0}?ɘT}eRzӞ_:ŕӢ`ktEjSpbLhQA5 %%GuUWJQt1 9u` )&zSTtTѼSWsum%layPRLf.*W5<,RY:pl2X{͕`zZ~J e[;Z_0o%ȃVן \to[KJͪ%;F7՝&B{SnY.ce۹vm&wϛɖvdC]jS]}њ|%RLkec!jz%t»S1,mi!Sn!C_ ?8E7bI,)~x)2Q W]ՠ)oA Z랎K y &hd76kzΉz<栈 @A* 5Z z>(y[՜L(98Ȗyy88W2LLˌ{V> qPJ[,L_񳊢"$$&3.OD8BFb1Y7-X_]\g% Kr\d$/ On܄,<,w3s=.t(K<:ҏ:w.uR1:Y^!îP٫gCn_ >vhy? ^퍧#_S>|<2?A;Γ^y?R౾{=k'ϮwstNoC/Ə㓏3/S>o=/_o??X~8'zgc~ (89~ 9 X( xX؁3 ?8g#&(@%_,(3.*281Xs81:Ӄ>0@3D80FxJA+؄*hP؂O80XV8X Ä\x.^b-dX!h(Aj sn-p9Ԇt(0sxzBv؇‡H+8RX3肈X*8DXfxRl(r' 0)rcp'7؊xxrlx1,0&cS (Q'Wi m !]27"(d q> f Kddm S$Mfq :0 &eXR h׈q A QmPhQ$c"2qݠ ؏8p`v@rk| ٠ȱɑ )Iy&", i4Y6y5Y):1ْ&).>9$Iɑ8ٔNɓ#i@D)QNE ?yTYyaٓ4p aYDٕ] UɕV29GYoyG9cISɕz29E= v[Y/)~a9 c0ekAB` l0q0fFMYy)YٛI 9iIyعiYIɜ)9ɞYyY驟iݙyY9jٝ橠  @ 衘t@hq%Y[񢉡1Y8 37*;q;G,G:*4j7PRHZE>ʤAڤY`6ʤ? +qP0PڦcZ:njCn4@]ڢXz.2NJE3ڦ+w:\:zCʨ:zlڧd 6:tuʢZjMڨz*^ʨUJk G*ZPj[a!q 1iFp!eJ]Fj{:FꨑZڬڭt :隯*J:Z: z.߱nگ˯ :z*M*ʱ [yJWs*fz::s?kH+{^Ifk.<-TJ^aD/Bʵ-aob;s;˥;wp˰L_mK{kfkz+)Mojǚn纨yۯ|˷˴Im 8:i˷k۱+{ۻk{ ;ۼ˻{Q:i@Z۽K[;[++R[R|t1q'1As-0)<;S6<31Z! ,! ,! ,5+G H*\ȰÇ#JHŋ3jHq6AڸHɓ(S\ɲF5kܴ"ҥ͛8sɳgŏ* ƧѣH*]ZfKAeJիX~DѬ`ÊKN-˶۷U=Z2U ܻxmsܮ^La@.ǐ𡸠Ș3kVW˖NmMtX? Ĵװ+떉nnsLovm_w zȱ!cF<"ŒD1 {"&)uV_-rq_^(w` :%S%Fq18x+cf@Q w揕@"92d$ fHDʑ%ӣPq))I=h##,%Y x.sɽ]{);&2קeΌ4IiR~ּq&8(qL :u|) ҳ$I9,򓙟'@&Pi%BKЅD#ڰ{Rth2шY;(H%ґV&YISj4c(}\*>Ѵ)NGvӝک> N1MF=jɆԉ%fz*TSԩ.LVVڲru`[**֘y`<+ZǨֵ΋nY[.IvkWr嵯A+`v`$2}+YQz,fOvͪfC1В6D=Fڋz-l >Lns`-+\]t,rgE嶧]t;Rrǽ.]p.xӥ>(z[Q]}F+_.~] +P>pd0y0 # ֋?3 }rxZ0\B,bl91d'.F*cҘ3qTscڸ1*!wFfh7Nx7ٽ+7={8Tb7?G9%n|;-x5^{6Os4_>{+ıT it[Ax0| Lg7Ӿv}2o{.]q_;nwp.><'O񖿼3>ߑ=#_SǾ?xP3hb!rHp\ jY,q?Pw  h88WxH("(' X*8((, H8:0؃3(;x$xx8hL7Hȃ5_xaXH69H@(5jl"؁JȂ ȁ*x ]Xbh(d腀8`X.xe(m8=8hBȂqI(vs%ȇS{(.HPjG2qHDQka7>gh(Dasm? o t7"،Afg(@DX@2Hlfh*re*}tf*Xrqd*! ,F TF> m\ȰÇ#JHŋ3jȱǏ CIQM5j t3`K*lC͛8sɳO(㼌)&Ă/V*ӧPJ*PK2ur VK-Jٳh$׬aY6GZ˷߿Q>2]KOL7~ W&u˄RnS^jhѤU0t8fPj r$'b(܉*bj,(}H8Rec<`ztD޴cH&ёJ6$DL>)QNi%U^eYn%]~)fai&ei馄Z IV J衭袘)裓9 |IJgY)$VihOרJֺ Kl.kk mNK^[jچm~ .KiBn.KhJo|ދ/Kg pkL< S[ #p&L_leKqN~ "%&ZrC2(\2Hs`ƌsmz\-r MFt(.4:?RHulFWo}a^éu؋Mf`jgۏ 7==vۇw7y~-]CGxᅎ/['xfBNj_{yrX馯 tѩoz{ ;Nr|*Ĺ{{-<̻ی|9|?}J_}o~ģJԟS~6?Ԡ^O_fd& f@t&  h0@F&`8\ ,u!;j'*d`=z\C P=tOdbdįV˃)BIVh-r1q"ڼ(="XF6э_#E:ZюS#D>*яCd"4 B!6a$S8VR`&Iv_(7m*%}T_,7K2|^.Kz^07L3y4^2L5wl%"'M$#6)uvߜ]8a7֕3u4]:GNеs\Op\@6P4o[BP5mU[D6QU4lZFQujZH6R4i'5ZJRtg/YLk6SeftSi #P(ԡvF#5ӟ2-7eYTS6UUudWYV;Uub_XX#6ֆUag=XZ ր_oWNʚˮ+]1l(ruMO* Xc (,ِX&=0"G7cB5iDnxE'<- dס2`b&P V*&8$4d&:{[mXƲ!{x2)q }ֺd )%$#ݝ`#І6ὕ`6 p]RJ9 8D]lp`*41J饘"difiJi&:jzjjj9kyk^k:k9lxlָlкlԞ8m؂xm^mBm&8n xnnn7owojoGo37pwp Ӷpp{6qgvqi ?q$q(9r,wr0{r4?r8ous}Ooַ}n}nwK~ٞ~m7 Olk%ƪl2T|`xK ݐ(:4u(ARf$<oZ0Dcصz+jY!Z nky V|S 08ᴡDX"x (uXɄ 'D]L=hd%fԇwF5aABKpt[sJ\!* )AփnT 4p%7m2o"(JBr*U,ciY2q%r񲗒%0+'ab2e23t|&)Q&6[m®ޜ8iq3w<'ҩ߱ ;%<$yJ; 0|3I)P|B:(BEЅKD#ꬆR]2QiY(HS$ґZ&VIS*T[(})\* Ѵފ)NuӝR>N ,uAF=T\%z*TԩJVVꮪrU[}*Vyy"+ZߣֵnT[㊞U_pWGٵ+`#^_k26|,+Y9z,ftI hCkђa=-L1z-lٞ- nsۙM|+\<.r3ks RwнnZ݄r .xJ歨xӻׯ}+i/~Qt¥u ̖N=0Lݫ=_y0" ,P3, sgP,ՆH=1J.cX44=9N;,lȲ7 LfH~pAzn2聊2`%X;bb"ĝ 5L\ba! _:p0o0(ABCTBЃ>3^lH0 D)b(sLpqtфLxp:%NXdȆg-kWָcM^Z׻6ok\{ؽ aZپY[;Nse#Vc>7mtk{{bf6˝khs;^ng|ݿ7b˺0lg x1lmSyC67;N9/2/[*_7гqM_ܲF*0 fe`0lX|>p;w{w=ށ|;Ng!y#>~Ax?@,o~|w+w}Q'o|mz;ˇ~?K_}%|Ww= 84 ppa WfjpWGg'Ȁ*(*H hXXx#؁ n GHȀ+0h2H;؁1:8X6H>X(KhN/X)(]x&*8ZȂ"'8G(Xo$(LX`8bq8؃I(&h;H2nnȆmhP8X?xxXQP؄hAhWȃNX:؄,x6hA@P |Gmqt9BfgA}t:hG!Smp 0,fQ;7W;^ ;'xveM&GgReX&؏)&f!q0d& )&! ,? T k*\ȰÇ#JHŋ3jȱǏ C 6nicR%KڌI͛8sSd._TXB=*]ʴӧP=ji5FTׯ`ÊM֣RJzKݻJٺZUS{KÈ:uV!\ u6SĘ3kެ}<ΨS^}=|SF8:ָsNmoe}[)qLw+_n♐27[nkݩ=ϧ~Nyb8Ͼ{A~O}~(y h F(a NhcUz` ؓ"hbH$⊭}0Jb48c8xc+fzImZ^ne6 nIKn$ꮚnJo[co/ ˊpµ.0?kJq^1m\z':oȁL&a*3r mBKt4P>Ru=_5Zo=t^ vIM6Jmcj(s۽ wsrϽ\vw޹7k~}&ۂwxM/.dǎxxMN_nd/hyx}s>ZzW~V{E{Qݎ{O|RS|8=O xY2qIQ5WUjd77ic8 {&c>hߗ>ŽyIp ؿzt#rxCЇ1 B"Ј%DA&rp:λX(Rn-bXA.ZЋ#h@2 ЌC?6ύEǔ=殏~&@Rx< 6o|")IQѻ$&MED9=RBϔͣ';UĊ, *7Ւx ^.}w]0e7uL]2M5t\457Ur׌\6uq,\87οo[:ιnl[<6ϳՓl [>ϭkZ@6ЧtiEZBXr]dD1PUg (].3̣6D 3̤*CTJ2̥d1V̦t0&̧ 0˨B =j9SߤNPU_խljCmt^S=Ҡ pe!1N&0gx&`2O]ǎ";H%0a5lZW86'DC0 P,f~`.4!)JT7C("Y8!Q%"ۙ, iZ&S)@&? ms+1% ! ,IF HP)ȰA{ 0 q^=ryNŒiܘ1 ǰ17dC̽$쥱e/13FgzT:53C{SG)av6c3լ^qɆo4C!x|YKtk^SW]z~CN1L+P`|#e1Ě̑xL\j ʶ2rm]f1Sj^1q{5(V1iȥyٛj9 +4iKC7F͹beF?1c/}d)VGemyםs!@j{捡zPk1Oݽy0چkQ9q7ol@ kL5Gs C <\A'fdi$Fi,dFhSJe{&QP@! ,Y 80N.YZxG8#J( B ,Uv[@"M[|H ݷyN[-[> ^tEuÁ+_2lH-s5e+4P GMw5̥/w]n1}߬#Nr̛}3tKiZo8Yn'}wǥ oճe=?4~HӀ)h9XIQlZiHy8ĉ( GZ&FÊnZtI&3ȒB9ڸ:#6HdI)d-y+JѐU[VR%]N]8B-9c%@wYkfIo¸Мx&p%'uQ+I蚆r芙yRYhD@}-fyu)z&jqjIDYjJkV"\zk)(9IK%f %&[WvCOqly ;٘KI!lo3oR6kt+IvVȵ:t =(q-&Hj4Z7ċ=B9&Y&u-re 5^TO6gC=Dn~&im=d#[xI!"*+Q٣MLyq6ۣ9?&I&`J<߽|-MO&/)T}{qN1zhFy@O?{K*׷ z $Beojs9C_1/n4v,.X$zH(o1Q&E;Dp{ļ= 1"<,LO6Ġ 3jU"s'3 V1==MDocY mHY>@Ŀ$3#zCQOQm,:P1Jj)wynp\9&:q4%g4EÐnA&FISW)zQI XVFDZl! {0xIGY|օ1wd Y˵U6k=EW4z$kDΣJ^/qM]6#>J60fNy5|`ĨnzmtLGy;Ea-#Y .ʎvn!CQM+eM% o.ހm{8v|oE3\=.˴aL070{<6uqtޓjq&RG,%2yL6q=Pws&I*pJ*Veͣ3@Z%5 _gA7Eo&9bI? *ꯗ8WWM̿D_U4Ô<֏ m[`D%궝fM$T*~KZqqHk#Dhy}kP Ck/})gM س8vkɆ$kr #9~^&?Pyx&thn|#w,AQ‡~8|wh8#hxc(H  X"5ho4ዶAACwAӋȊ4!،xq+%HB ~8=Hn︎؎ a:C1,qnvXQva$9@1 9|w1Nq"I);+9ybطqѐ4;69m0=q#?1\SE/}C42M}OY81Tq+%HI}C) qH KYa[f~Ugdɕcy"LٕnЖ !c(a$ wy`io! ,3=/$ HP\ȰCEG^{jh#G:{3r\I<{#a3 r)dRx"ył e͋7tƒ|Y'zI QqM8DYܲf yЙc&]^[zxʒGO=yԵp@3=4FͬayAOiG |"Q< 4!ycRe8 viSO19csWs%m]=sOtb矖dK5eA#Kur0@bi7cPT 6 ) D CƱ)yწΪe CkdaI@Cí᫯iTkf;\:g kJ+-|Gcm\l_ QvȪQ ek/Fr/ "\&+pR\@֖//q lq l|q, ! , 5D# HP\ȰÇ֓x^!jqĉ#W{u\đ"ǰ9fy(U9sY1fKMSdx# Z<6 _R(r f<ږm^FcjJy蛩XSA6Jk,bk6ï+@q.6ŬR>ͪAP@! ,2L HP\ȰÇ7z)Fȱ#É#G=(ȲD$GaCrsRt2aˆ373Ɩd"=< ա{,֌cż6zQ%R]xذall#gӜδ ٲ65|K5F/$k XˁŻf:u[Sf x+gzst :QC5ev1lƑcMbbN|e&Vcsґ'OZ}uÊ{wV=4Ml4Yc!GoUVȓUir_wHV!uNePoVw1_1"QTT<MeY<2Hk O<{-tZ jdHs.zȆ9Y(eU:zi)9JzޑOk9si'/sSMψ ilcs>L5< rn )Zb*%iiDϮ+jgqJdGlz,*8,A! ,'$ H\ȰÇ#JHŅճW=/II=қW9{șɛ8sho=?ٰq9fw*]t$y抒[62cl,7fҦ`Ês^β)Vh3}q9ݛ=S2lӌ\љ_*^^yEnjTbYͣG9ƳFj:uz.gаq"١z0+J2cs];q7ȱycmQb%>ݶjlpUqoeZ(YK|4OBO<_Qk{fldq=5Fͬ߄Aq|#>͐P'NF\m"w/&"<pY^<ڏYd'=M^<I|ychAc cG>Wc xn*J3e֕ir Dk]aY*XSs9+<:X"d[Sϟ>y QBk]tcRMJmԫX V]kԭV- 6س8rE6ڵm|KTݒt1E5pDC̫1շ#'+AȏGZnT* M={7-bz#g9tUT}vk׶if1&̻k;N1ƌ_6oͽ*Uh{3y}L3}Eg>qx906e4sF_}qks\*PGutw |=jPw\uPqģO=!qtqucakSq\C1lh=3`]F5cbjLUQ=0 =wqdqqإͳswa<\CO3kMxyI玹Sye(cF*Y'=jc᧠^Z܃x<ڪEINg^,ē;&9iΖƅ 6`3O& O6m\>D* zʥƻ͠3GqF2Hk܋o[ﮱF ;p\p n<,vqg! ,g>*$ HA*LxC #*|Hċ +VўƇC~<r#-J1|Re=z8ISK{7ͫG͢X޽{E+(6\:q yư!쪱ec0UҦ5K{b6j.[S1Æ1Ӭ}Yl8ޘ2kȱm7c;exԤ%VQֈuKI,:e&I/^@a^@jaN3Q́ٷ鬡j.-~h_ 92c0Aà g̈>6#A-AYPi0XWӢ>NrAm :F}ԡbKUR%S9CǛ|矩sfZI3%;hcΠV҃hC,e= ` (=T*Т;XVƧ뫗Aj@! ,`F!1 H@{"4Ȱ‡ Jbĉ-jƍ?F|RF&ONLi%K_d(sfAl8sSgC@  dhѠ (]FMjB]JUҧTfԍDQ:Z:UcTg MVRW`IÈt.CPKV[+*mIgUCX0ȞӌaU vN֮js (ړWnmQ?m6ݼ]GrʌўƜtVơm޼xܾ]*._m٬glczq7 d Hf6-XȆv2m5_FzlRQ}&r^qcR"}=X,i^#dO=d8FK!,l/$,(-^<2f ѥ_s9yvAS^מ| $8Pk*ް3$u§*@lf&$CqU~ǐyBqt$^a-֨م}Q@! ,oZ cEP&"$Ȑ* JPbC-^qbĎ U}I B{ճGOE YcfKpb،FMjXMġ8hUnRLCΛ⨑ 1 :.UE՜Unb7[6Mj՛gM1c tOx1-/c6jSUƍ3v{-+4立/3@U5Vmv܂P\faUaZ e-PSt!o&P[C\*kwjq>! ,oacE[`B 5tPBYUhcƊ ճB#*1ykdz05cW3㪄iNUOV?7fAMj6KΛQpDȦJUqJƜUZnLs[ڰckM\}j1+P1ymeޘÇoMT#pLxƴ,uMsqB5]>BC\*qs|u՞0 ! ,nf G+*7AC՛gFn7=!jG$;U,B\IR_Io@d9F`r`:TϘ PSQHYjU7p9oԨ#T]1+٨ [Q 3VSFݿ s=2V5`g,ʖ1= W{$e3.VP5iҸ9M{2-&suָ!mnډk_]y[! ,! ,! ,`92G HKȰÃcJE/jlfGq>$HgT&GK)KƌafbÌ368k\2aE5KӋ%R )ubǪ3buu+î^ KٳhӪ]˶[j 0tqUݿtLÁ0]Ee8BKƔC9c3#zcэ7kaӴn8]#VmQa݇-kx`ǜr 6oQG c#o?]#n;߽ xkf#j5eAyaCq,5Xb(RNjـb}Fvu,\ lTFV!:(C)$!%$VH:gQ א"! ,}7K HؐÇCH1-jܨ#Ǐǀp ɓ\9K^&岚ɍٹ&bÌ368kv!abMGҌ1&U.nTUɮE(v,IJf2M˶۷pʝKݻx˷߿ LÈ]v!וL\r1 U{CMzg7^udד! ,%% H*\P#>HQĊQ_逬XH!6oM5j <"Ĺɍٙ&blS8kvI(!ê.d&V\rܰ!"1b35Zg- -G{bKݯ 6(x0†"iǐ#Wmb×gkg'W>cTae5!C8CCʔa&TÆmQ8kưaLفT;h,DHCWqC:b9^('dԹp٘Ü"4BҦZ 9 ! ,*! Hp*\Ç#J,!É'Z\Í =zPdGMfXJ,_)$͚#/)G!;3cPc<sFJ45FԈXT\KزWꈊӔ۷paBbPfiB'bIf r(Q+Bʖ3$3Ιute6Oz5I ! ,.! HK)\H Ç.TE})^܈0c) z Icƒ!GrŖ.+ŒG'҈BS>vC=z3HT*AVL5Rtic؝t=MYԔ۷oGz 5k6iBGHt;f…+הybĊ YHYSALZО@H G'uiq\\Fcl \F>ܾ}! ,! Hp` *\H`) :HQĊ/b\qă9 !Ɇ#O a)SLthJH̓4$IΙl-J#MM+Jq̒/hs+A1l,*5ņMm4$Ps֔ÆKa3C@1q* b*J{X^x a) |xe"! ,! Hp`R *\X Ç BO"Ň/.̨a 9(rdI''xԇUڜª֑xzٲ~X֔۷pG=<}a& A)%d1:q֌YLgKo0˘3kl*#]:ލZ5€! ,KW*LpCS3eJ[@! ,! ," Hp`)Z*$Xj J(!Ŋ /bqƎ?ّFK*ң)+A4&L5[f4HSi|4UFISAbTBiEmcij)!!Mm )%0:qt%GU)YeNEj*\} h^qS a@! ,! ,t HA4UJC|zHŋ`Tq#4 IpC(S6Pa)S0cӞ͛6aٙFG6(҆8k(%RS!Wl@bV'뚬`vJb@! ,H/ H*,X‡#J$ذċ1VȱcC)F&SJ$G.cd)&͚+ gN@ *J;cio)ΦNeBr*UV̪U$׮(vٳhӪHn-1n3{q.]kNW"Xl0As ˜>Nj [rc2fxĈgM1m pdB5lnᅂo'!g/hw!7zp@! ,pX( H*\Ç#JpŋVȱōCLrI%OrK-_|sMtpذa> 6fC3.)UZsJSJgCHM1 P6JVYϢv̶nƝ wɺ͈ ,H g1R:m<'.w$78t 30bt){ɶMB=1o<,##z€! ,2,S$ H*\hÇ#JdpŋVȱ#čC$rɎ%Orˇ-_Dś5odzϟ@u)(NFs"U4!,1:)©T#Z=5+Lk~G׋t̾$尶+Hn5qf,aYcwӹClr1clL+cbuΞ'0! ,;.& H!\ȰaB#T("D3"Ĩ@; q$Ɋ&OFLR0cʜr#˚ o|SΞ.$GR(1E=" iRM I1Јt:GVtG9fұ#'MZjZ 9'ΘwӰIf _i3dYڙlbr¶r,#e惙x\SѤFZ1Scb4?gڭ5 ! ,K, HP*xpÅ J$qĊbDl =:Aң(OIɒeB5+[˔4a֔I ՠ37'PjcnU4Q*U4cJ4լe^CMl+W_5-իz،9C]Uߘ1lҠ37ox>~ٜ_lUl͏Ӝ>}փ\5洕4٨7qG8pJ>Z05dU;3|W*c&9YgՍ9gqrz;xUz] =cԖ{W} ;C=6=kU}ް,2a`Tyc 5^ !ɒ9zc׊dJV1cҠƘfRy*{4cW#̟l#QI1454m[7_Î5ۼky,cܸՔeʰ18&/Qą^DƁg2#-z 8-YyF77ʤɪ%ϝ#Y]2eA{8gPVcƎCpJ=}l͞3 z7 9oK!BW6czcWc=*537o3溩Aܷ#zx9sY y̚s&WV̸q^j-ƱoӉcW̚]ljgl]mߎyq4| 5/MY=4Ο'tYKq4?^9wՁ}kA9 Auxfa ! ,! ,! ,! ,n HP*\ȰÇ#JD8fŋ3jXqǏ CRIIkN\2˗0=҉IfDb6sDxlO~ %In5qf,bYctXrC,>{ք3lXֳ%CDc1HL x'S,߇0Yˆ ƎCLx3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسk0^!CG5մ钥J.iRׁ~.(%Y;~ m'h`N5xC Nx!Mn Y`!S&nOhc>c2ƍ@VK h" b!^RI;6ȤCFR$Mq,)C ZeHlt)^*2lFN?H&m@f1c!Y%)e*å~0tI 5iҡ5 ~ēJڴxI&n͚ ^&t"ʵ=4 1q-7}?7 ^ߜ! ,-_ 8Љ)*\Ȱ@,M8H6+jč 1IiNLgK}t^$&Se'dHn5qf,aYs ݄qՍ4Vbˮ׀8fòfM)۷pʝKݻx˷߿ LÈ+^̸ǐ#KLfyngㆆ;miӦlװaN<}=l rrpn. :`U Y>ӱoz€! , 8Љ)*$I Ja0b0lZfƍ 0d”4)1QIs`4k 4f"1@ġCxƆg 1,SbU˪ׅŠgٰ|9f-˶VK^\nY5dߍ}! ,\] H! #JHQ!`q CH#F5B0cVT͛8 q 3((<\B!+`+-pD)O K Z2) K e.Lu{pE!X7HbPQ6$"ZPEV(Yh\1@h} b0p%΀;w s{]!UD5$W>A$ 3B@ 0n4xs?A j|p?z(pkRAC!vB `Wa͇^a`R[gP'PhzU]BH@uUax{^a !A)&q\>F$\ yI]f5W9JI!pSPIEUvz9 6OCAjhARAQtUMLUDE T&D+b+(DXHDAzn]j.XBH'&t*+:&*jl6g pcD,pmA]R皺o[BEXWde{)q@z% {Y+p _p xt \Pƻ;Y %x%X@ЊSI\%p*ҚrJL)+QOܴ',IФ%ciR_[i.@ K6<@/oA>iR*2@/۳x=NMw.y=wyHK_1ś3=C2x&l䫏L=L<< c1y<{=So}B uth` :o i0=طsy 9P` " P1qpBPh`=8Dc}JdMCIlC<5#zY 94EJ0Y>W*Ah=G>V'lcͱ/d6Ɓأ@)&yXĢ hBwD x̣a*VVY&78~ҐeieB ( mKW9tP(rKHѝxsP܉㆗-H^ú\!@h9 B-jPQ! (P%iT*L~k I ` [HEAXV< @:8(@΢B tpQA`}@zB !ǯ2`T!/ͧLɓg$AA 1=2'6b'CY9@@a+m'QW6[.:jMH4x~pLxX!dx8r^ޣT! ,$ (PAT$ #YLR6k)SdX%INMF½9lߤuGXaz=G^y xkGgpelɓ7ΔLΜ'σyj}L z+i;ФёӂT.ղn+{/m{n' L{/S :猡/̮Ĭ1{p t|u |=Ѥ5{T6)!`Mj6` MZ )y P0P 0R!7`DH|wKPG?ߓrSdwJ3F@l]xӒc1mk/}30 ;<@! , ԧ` ԳZ>>&4oO=f#J'C{cۣ1!KSF)@g1lDBԣҍlɆ4<t Cq;ZrR7qIcZI%'qధMԭ!@d 53=*iF\Q٬M'ON7)ѷ7qo>'N^VH7N>9Hy 8G ƛdb6СqjϷ[noY i < #H[6l{??:S7%$c@%ۯIZ%&]B%NI Yn4Pbl! ,(- cC ȦE=NSo Cѳ='?hOI6= 5mac)0A4EMD[B(z 5qUdq#'D16d1nR'pC[G^%N"'{ 8Ycy ]F$ЫG:iS>F=h6E"niϿ1DiWFSs $laH|J6;AM F=Ka /Pc]Y8Q<9lÇ{Q黵=Wbq<4s y؉Μs->*p}UD?eJxp |%ad%DV%_bJe !K Yo]kġہ+-]i ~EfÙGecO7U8dT{8 rTpf`N=7NxF1Rh *ee7Ia",x:[8`Plwr=-FVceZCG(hI@4'ЂF`Dh`ubإ 5qИGqjPהY hAgf5W**Q"AYizm=чmF7ͺDL;Dᇼ;~D\C㛟D߫_|һbۃV=[? 0' >Ow \9 ` XL{HYr@N$L8Bb+^5p [b=>!#(17ԡRG<-$X:)^o" 'i1!)1~Q"b,! ,?1 HЉ)*\ȰÇ>Hb0cXq1;F(7Jas2K _ʼq̈́aȄi3L<9F0aLT ӃAdf1d4AҤ 1eRuG ҷN,K\$Ô3wvWL<0aX>iwrdzN,k|Ӊ')z9tѨM3uk =+ydlGn]lڭkƭOݤ{sڿkÖqe;Ь`ۦœgN?nJm[i:ԣ.]}Q]wkύgy`'s =wF qFA6"A! ,8- H0$*\ȰCR">H@)cX12;(Mȑ(J9s2K_ʄH&̛XȴRJ<+H4b-$((%njac &M4iBT6`%:RGH9hӱs)ݑRjwމU%^(%B~D[I2Of?; -ͥNp5끮_#G2iIN+wݺ3 \p۹϶Sg/}ܳcG-[g//~3! ,~G  HЈ$*\ȰÇ 4ŋǎ9~IraȒ(QLң3"[ʬ(I̙8#6@<}24bC#QHYtΦP GԈ(MhʄI&3|%Cf+&NR=b!JڄڴЪ#T됭Տ5H.H2EXaQWV&LtFS>ӦJaXhUQ.zZ؅M͖C$Jl.HzxYFN2sxt.}#cH}; ! ,} H$*\OJ)CaHq1R)RE)'vd1HS0&tըN򴈳`RH+rˠ<8dƇN9Õ(H3! ,~y& HA}!\p =y6HЏ6fP⢞=|بH"xDbbč1Q TYc$c'Ae{hTIuZɒ&Ss WsS3˫Rԣh dj!DyyT+ ^M*g| &xXR4 92R,6XKr&ꂡ](Lɳ0wr6A)䐫FD¼9&ΣK[PI6c1ÄIB!}̘&J.qy&S76Ῑ/E>S1 ~-8\ff H(AU! ,sy)O HAȰC J"DZ#;N$bIKQieCE(%B,[5hcS "YذZmГ!CA{بKH=V@"~5o=N <C, ;b<2?zBx*#\G>.]dJX糂1Y>p%%X.ˆg.8Ğ? 0jG޾ ޛ|gD^ۖ?(ׯW=~`n߁eS:4x JZd!Wue~h1X|6XWJ0q hMD%cxa]3Jpĉ((1>'DHKIx`?-fs`E@3M= (%zBLLu$j!K{~"X=tw!gߐCꋼ7&CQ)#f"3l᳸e35Q|3%F Z%j˘n]{ڙCjF^;"VIT_[^~7!8>9cFt313 1tıFc>O1)ơQZR@! ,sb HK*\o'"DXdG_Ǎ ;bi=!H,GOB'VIG;ޤY$8Sߌ/qXTͦDJMgC=CX =;aFZ$U{h*Y?YϦU9['S\匢Kt虉ӬeBܘ֥8hYhz✡i={Ar/"3vYò(9tE q<Ím,62hCwqIe[΀Mw" )}EXCѝ$CfXgHggxYM "%R{GSyCCG6gOzRKE>+FBg#$#[ btώ{ܳ=L6V+Bdq% HQOQleQl`OSik6EgSt451z TL,R7lFqAL1c0cTJF0g}Q}^Q@! ,sl H5*\(p$ # D!<R!H% 'cʂD =5 ИG=? :$=tT&͞6 F?1 4gѣZAuL3 J$դ(tuܗ[-l-ڸwS@(ٚ3͹KfC8iTlZ1[lH~rH>{լgIa=ostbA3Y5<9|[h,2c!bYTfm{2'y{r]lwW#Hy"3SkGE|G`Cd gH3њVVJX==/EԤbݓ-bac!BG3Ei|R>@=SS>I $GdY}yQ=bf%ɔIYbJCgI&(h>~!lf>JjdPkXJOPnȴgMnHU|L1|C>Ř94cĺFt31J qO1 4L,ƁȲl"MI! ,! ,sBI H"L$‡#J(3NƏ rF,cH\#0!JI&B)dT܉SΚXшH mTJH}ɘcȔ!ӄɒ&d1SU)S*DnQP!{⍉3^3xʑML\RJeZ 23k̹ϠCMӨS^ͺװc˞MY{|W zo|5sֹ7?h{سkǗOZg=~uySGt{K! ,#3 HA}I 9Ȱ!C)J(eV@,l8z(ȑɖ9 !#@  &R$e6cʔ!C &F4azf̘4!q<2thC*OMejE+PlE r.ٍl[SJy Jؠ΢+^̸H#1R1e##3\d̛'KּxrŐA,šeʮ?N=tkؔN͙tCܷgiˢ7/9iŗGqE̺re[$g&l9saߦ}! ,v HP`)H *\HPC J#%E}RT,9.%GId"rUE)t"/\,իb5ƤM6=; ٙ$΍NqZ0j1_}ݘŀ! ,t% Hp=*C*a QTtcA$*XϞ~HXʁM6x9{˝4r*0&(]z9rD)U0]Z)eIiW 1kF_UXjXJ#I*7X"Z`Yth#6aú 3d4A҄ lҤaYgУA3 #RRc ۰j)\ʘ0Rf`D g'$! ,t$C HG\Р# !&Rx1H$/F$eɕ]Z 9L&3lHQ͝ AB0bLA懕c`|6d\շTYV5ZR[!Ukaāx QFH!4HDidM DL1K7Έ+F9Hb]RF_HaƖpuؗi "jr&Ry}!!j@! ,$G H \!? JDB#3̣ƏHa# }Gɕfw'h-4X_TgSW>efdP!QJLTMH|%XUURAPS&Sm8a~ ALZRab[aѤQGHZbAb\nYD$1FhD5dlh9aلyj%%P& :衆(Q[_"! ,/_ H61ÇŋP<@zY =I r%I#|2$B3=c=zlp b͛M-OUٓgVJy~EXyt={=B駈܂0{w`M>GL"`}H=,0m$aAanYL,׆=L882=: xÉ5+1EN}gYY)xp#6/<|#Ѝ#-l.Uÿ52U8wp<""qυO6]3j= çg#^L{ʸM@y62p}>#G$[ϒ&ni#<<ޥغ0<{DhuDQeF1]|x( THDh`dD5H!(ِ`}k9x j"!bE[hk XD%E!W2]EaEt t )m阤HztU=4s>>#4Z=b f|sA3brY=ZI(^ι5ڦ񱧚WD病9g34ha\ (F~W)bt1 4L9cDFtS1c 1ṯFc:W<01"lˬ̎a+\! ,7v Hԡ#J,G3lgO 3^?MDʗ+V 4_^D%ʋ=U2$JFM٣FҒ;$ Tj&{Y/|xɟ=1_tbȠoz=Lp`io6xsǼɍ$lȚ#IGч{-6손1k;TOx=e)sbo~3wy6a֘lbwaGG{84=c|`xP#! (F|_$bNj-Υ>H=8v|q"E~.f$:Y=6W>xzD{,cX\|%_Aϛz4xّ'|C r_*"a % YENCa1>&z#clfHUFzYX*ap@GAHȍ#g=x3ƲkA11@Bk,;ƥxS>nvC@tOꮡ{.x! ,8w HD!0‡#̣ċ 6ѣIƏZI} KDC#+c8Rf̍zشN'STCˡ+i"UKK2<OU1гGg֌Jb4G_KA{*[Hbغ ɚ!| qONE"FXbE|Lp0eP&s3nS$tӡzjРCojcg=O%bmh&zHܛQx8j[;Vl颤k?İ%kRVZ>Q}h∛mܾgeFDy-}Q6ۀ4fօ#W>A=Z>{qOvχ!ihgpEg"r=e=4B⎈IC=>C>x=DF꓏H֕@\sAA@C%ant$bYBqc`@5Y9@*P+"6F= G"6Ɨ (_kRQsRFGTFL6 *J&X+Y3ưkA11CGk ;93̨]k@`"GAn`cW! ,! , H*4C=^>(&M;& %M*\r 㴄"B:ɓcϝfl8l> %78t 30bti:&cC3 `Q UsmL YEH(Jw"0 ! ,vA H*\ȰÇ#4(ŋ3Ǐ9IdA(Szˆ,_ʜ/&͛)m9R'ϟ JQH# MTϦP>JdիRjE8ukӮ^ t,YfϪ]˶۷pʝKݻx˷߿ LÈ+^x0@(yrʖ#,1t>C$&AL1glb,Û71!cc 7V=yk@QO!ΡZ+ Y= ! ,57 H*\p#Jpŋ+bQ#Ǐ =I'OLp}pA'z$VeH6Qbyk:Ya{P}t xb'\sR#4veͦIqZ;fDvž/߿ LÈ+^̸qJF^,9qYLl#78t+X1bt)=9 Y3ŗ' O\! ,5', HP*\8 Ç :HqĊ%fؐ#Nj) q$I&=Dz˗03Ʊdš6 ّÝ>M'\JӅc**!ժ`-8s@:^j-,(xƑCG۷mӸm mWra3f/4פo8s0iK;m@֎]vҀyV;a'1:Da k2ؤV2^0 ! ,"K HP*$xpC J,qŊ%bDl jK@>5C50cʄ&L}cLGfϞ3e'g' 0Fg1 a3ԤS5PӨ@;ip}+A9ir|!C}mȑCN;rؙWӄ2t4ef 4פYL1q&Ѷ t簡ܹ]Z_;Y\Iu{1{۷)U! ,*R0, HA*\0 #JċVT#8=TqI%O8VRJ&PsDI@Ҕ3ዣGǨɲҦ-AJ*MFձ׮V2>jۡ+Y۲we.(N;vUˆ\CKnTbUsPX}f-ڛ>5sEXYbgW jvUbW5|CBUc{6U_H٪*}ص sh3s^L3AWMOUҼ*_(u}fA7TmIU>QFS@d (}3=TJfFrF9 Fn =:ޘ8]G| bc1FBUj&1F9F<,>nӐDFXGcb:H13j ƏyIRĒ(IR)D9lfb#6O` o <ҌY&1!36XdV5n)V˲WxrÑnp.݄Z˷߿ LÈ+^̸G<9pefogjӨSƺuְcÎv`5o[n{ߎ&2^@jt(N}_u}: ٻԋn32`J?|ٛI=>{m7·G7M$p1`*p$>~x@؝ǝ>ܥY("x  )~c*+xbv7x.؝>8cw(d4(e,crCAmX)v)|Y%Ł2R`wVCeEбq\}ȡ! ,\] H$g9#JHQ!R` xC G5JH$cʬH˛,YЙ"'B( = YB 춻*Kp~J+vtnTċPE;+2A_p !A@%t?>%T#n0r&18%x>H&B*k9"-O)Tg4Bdu @սu0@'q dN1vAÚ#FPmlxՁ 'a' PGAb̼͠+G ׎z rxAun{@ kGݑ Ab.'QOSh=#B ~BnU J٣ Oq?NW$`Ax8y=f= @ ^{ {C19Gw] (o)>@z܃3 4v! Ѐ~# "51W8F0Fa=t4cXaLD7HH6Z|"#r1!HD8%(cYNZ2Ѣ>02F 2 "1GfD 8Erk8=Qpcp,`EhqN uH!b@Ylu ರ-V&‹,(zTTo>nXA@x@qSy q nqc\4!h9@zpt% {Y+?1Ik~ư,{;љA 3Pܯ__ߘ|'< |/@/tPeJ)g!4dliS&Y)H 2 ޻7OĀ9DBxWg @)#醵?!8(/np (@TL׈~L,qsk\$[nua\$h<$U6g! ,! ,! ,! ,*;g̞A&4@zJdCzILh<}c9Q_ǏcBb$)c<)գwPKcc)SA籦c=M4͹{4vć k=נ)kPJSY $U9ػgp*^qśۥ)ĉxA{~e,oM/_?^vV` ;ǚ޲<91x#!&Lc t|YΎ8z -3WaŊ^inÆQO/AtM{z׏o~y`}' cݍ`t`TR BӜz"%}_*O@! ,07 H0\ȰÇBET=ȑ!C<]Ǔ J)p"T )`B>/c<耩mFv+ٰȢLN b*GmBfe&RU9vM4QTV<)ɘFc$~+0*F9*mN=XC1FK7QfF3!f mϐeX9dfƘ@ Ũ8͸XV9$93P' mLVZ'=DQ 40@jO˜ߓnv=E*+RL5d= :k039u dL<ZqC3OIH Y9 4 C&AzͲA 9 ;FBC@C.1m@B;ƞi5LCfhd{$1D\Ԣs hS1TdA&$Cc 0W^qkDݛԇΊt6mbȡ_$rAUztN!\ƒ h=G]bAktۦ&`<1< Ӂ=m0^CW˼sa\fy3ΤEl@@3fii4I'ېNqR3D?}u4Ys`Mnjicl0GHj͵E(׉=ArmC5~%]Xdk;9{G9t..NPxyNٲNzH^Hgsַ>.{zDYû[z<<0S_J[&N|_g/ˋ|5j J}>)FtgK֖w6OtTU"H@! ,  HIPaÇBdf"8۸QCQ#b$;4f!10ġClXxƆg 1M8XI%C T%Gb!["LʑNTnsuӍkbuج*7lhÆz(0^ (׬ Aޘ c0ef:QQzlF-S{@,fZ-mQmT}: ^uR(! , % H4aB# (!Ŋ /bDqcA ;'򡽓(STȇ/9:Q^1kgO^Ol7dƒc1|ƆgM1!2uaj$X$&f@ayr! ,) H *\HܲbA cH Cqٹy7rh0HC9ɰ^I!ְ\BΜ2g"c _ HҞQ.*LIrcC0c #F'Κc"ЁB=/-1ҁVOisM+r¾g](b@! ,/ 8p9*Էa‡ 7bąqQaFcBt8ȑ? 2eI}i82˙ҙI0@b J谢>/ h %1PġClyƆg 17eK TmҝnQvI._. ! ,3 H*䰡927&E} 6̫x 8vLXl6F&7,͘*H'L)moΝYGܘk!6Xr*Lhp‡ 9H!Eu[s t|hPHDoʈ*C8f̚8t 3X1btpx^ԗTN3ԠȨ9bUŭ! ,! ,:y HО*\XP #6BE-Fƅ:~dh0H\hJ]GM{n$Hn5qf,aYs l(uV̪$Wk:;,WO%! ,<@& H*\ȰC>HB3jtqǏ:YQ$ɓ \˄*_sJIrɳϟ<%MG(QH*e1gMs6eTN1֨LR V 9^^v,ٵmڄ1֫kw5N۽|*1oCՑ#z]JGe2Yb0c #F'Κ1*\TuNǰa/ "Dx?#9þ?/ykd<#CzC9u0 ! ,D d$ H 2ZȰÇ#2ŋJ1bƏ 3ڳ&S$ʖ01y%͛gDhsΙ$})&Т"mytҥ+EjɦTYhխ VTdZATZ՚d[O۱q 3;߿ IwpߘJX:l!Df~CYL6!^VcTL[tXbN 6Fjj$*&beu$Z,o$zqvG9r7f].vv 1BT7[3̚8tĄo0bt'ud&Qxƒu Lc#1@vE mЕxQ"BέbAƽ(>k(b6c*c{U! ,D ) H*\p #JH"DI 3jȱA CZHɍp˗'STr͛ e,XsO:)ʠ?]OLftԫ ⴊ+A7z ֦رX& 6[ 3mE5`G82VՅ 3Fe1,RL< C q1ƌd88d╋KXeɘ;pC#i>ͺ:[FAMٸ־k}ϖ-;5< btX.{s؄zgƿl~;Y&}y:z1$D8R C6F(Vh#( ($(u#3ƊkA1,1CGo"9(@)Did& IrPF)TH0$Yv`Kuٗ,'v2dŋ$$8cɕ-)4s̐5΍=\)0hDfD K4ʄSM< TO ֫PEEOGݒv)[6`t=rtމlFw4 fqR%oTcdN^YOȺ=rcƔΧa-2FN5ǐё|fAG1ot\g51 OqO&1 ! ,  ,/ HP *\HÇJ"A{,V<"Ǝ9|q$A&/fLiK/|YL5SLN=GPE;TRM->Ҧ˘nĆS+Ɖ+ͪ:DSmebշ˰ы\=v1X~ su3|fKG.F3j(ɢǏ CIdÍ(1\ɲ˗0ڳPe̛8sܩofMF< JO6*]4фIJJSQjU&M@dӪ j ڵpl[ܻxA%h7߿FB a{≠pbK"ɘVbb~z-CѤS'eհ˶>:kM4@r uQ&ˏ?Β8Գ$)!E̫(+;r4 ےcL<C qᷞ|{?dfv ($b80 uT,0(cGPe"#A8ӏ@)DiH&L6PF@(Xf\v%Dk(@-$ݘ9ЙhfBl ߛ5(}tyg! ,D  + H*\ȰÇ#JHCF3jH͢Ǐ CI$ō(1\ɲ˗0ڳPe̛8s܉pfMF< JԢO6*]ʔфIJJSQjU&M@KVՃY˪][lʽ ܹxK޿'7  ,qc; dʘZs`~zwѤSݬZ֮c!9Ge릺aM|(,B{k!"9d(,0(48:H#Id5)DiH؈xLPF)TViXf\v`)fDBclpfY&At@hgHwɷJ$oР&A*(AfE! ,9 * Hp #F *\H ÇsD^dƎ'rY#I&O LI$aّfFqBiQʈ>-9*Tb?%.ER)ԤkV5=b]g+=cYGNߘ1k!6XEщF52R[0Ei:D0>bBWy8Y3~Aa@! ,! ,D  H*\ȰÇ#JHE.jȱǏ CjQɓ(S\Y#0cʜI͛8sɳϟJ4F*]jQ ӧP#դĮjʳ\Êhٳ9:{V ۷pʝKݻx5a޼f%Wf̘5qf,ޢEYx 9cCNHӎ{yPװc˞M۸sͻ ;#I+8lBN`ثν )ty! ,! ,D   H*\ȰÇ#JHE.jȱǏ CjQɓ(S\Yq#0cʜI͛8sɳϟJ4F*]j1ӧP#դĮjʳ\Êhٳ9:{V ۷pʝKݻx˷߿fɕ3fM:Ćh1:qC˘2R˹E^ĨӨS^ͺװc˞M۸sHR/ N8DƓ+7tskKNu ]*9! ,D  - H*\ȰÇ#JHłٻȱǏ CQ#ɓ(S\ɒ"#F&[ʜI͇/cɳO97JQA*]ʴeҦPJtիX Vʵ+ӭ^Ê vٳ,ˢ](Lmʽvݻ ݻW/߿r%9b}9fl_6Y37YOgA|-S/%爑bc-zC3ٸ}&p51|e:KI:={bܽg|yc_/˟OϿ?{rcFt|21,1tıFc##yHzf"wA$$h(,0(4҆HR!!@"܏A9Pid)$c$D$Y.! ,D  . H*\ȰÇ#JHŁٻȱǏ CiQ#ɓ(S\R"#F&[ʜI͆/cɳO97JQA*]teҦPJtիXVʵҭ^Ê vٳ*ˢ](Lmʭvݻ{W/߿mlV0] #^lU1MClT2>-cl39Π$Orr1z0MuxsVok`Mcp+HIkN]ukܮq=Gq'>ӫ_Ͼ˟O}ȍٿ&b1,BGk7jHeW#E(a#8#$Kv ($h(,袋TȈ$i$g5#@t܏AEX@:&H:YkQJ ! ,B &0IO=FLpCF|("ŋ fƏAn\XA! ,! ,! ,*#" H*,Hn@{ *d6F"D ՌY"Fƨc4K'ʂt\HLL}l4R%1@̡ClxƆr 2J*#GXj]#F`}~tua؛kvD+0Z-ߢ(fź3.V^|6[0 ! ,$C HP*\ÇȁHe,&BGc68#ɓ%JQy e'cNz~PD=;ОӧPJј1l֨qk\IS GP2Z˶۷kɝKѢu1屽j `u 3/|Lѥ/-_.H;?$c@! ,$i H*\Ȱ #JH"A{+ʩǢǏ1Z#& ȓ(8&˗>|IdL3kx⚝@%1хC)9TGbM^h#4iʵ׭ŠkuYFX)~]V93cμCR1c#F'Κ1ɥTbbx,1:6 A+7,yf?;{)z4:?/̉R! ,|&G H*(N#J8Ć3jhoǏ ;IRFr$K~rI,[~|̙qtS#ϣH*=NQJJBbO)FX,֏ƼNiܘk!6XHQĊ2ژFF;^HȊcLԗI- ڛI͛ ׸|1ʐt~v$&4㰢!-Hn5qf,aYtLɂ<;re2϶u…9n]1.z7 ! ,L24 H*1#6d(1!ĊR#ƍxcKf2JZ:|Yq̉-\ܘk!6XeÈщIJjՆD(ͭiJ ؈,! HÇ1HÉ3jqLj?Trɂ%OL$˖"_¼h͛8q*$7aMcz*LAԸFҌq<ԁTQ05+ܘk!6X"m,(Sb$ IgGbF9KZ0NJ%U[Tj3+2ety$H3iҔfLP ȱCǎ]:taC׮th'餱6Ed`,f0Y4˘|\)S&! ,I!3 Hp*DxpÇBXP"ŋ/N̨!ǎ ?L(r"N\2%Jl}Ȝ)7qޤPOqQf(ѠG}sCN6p*Uj@iZՊU4T*geJًV;W(ꝫ ⪴{]h*a:̘]z;0oÉ|9p:Օ,GV]WF3v{W כ7Ͳ7nu=m1Z{V:mT.7]f6§M^oUU2l[v^Da΀-, &`5 +p i^{6pQYdǠj*zH"<Ԩ(8ֵ{f8Fa"bC@qHJ.*YeW*fZ-Jɠ=hP8=x.r*V`&m>0=iugG? SGQFq@Fdꩨ@! ,'cc5+V*\(-z"dHqJR2OHeN,x5wZ*)e<%~An`\1AǖilX=(Q*c &'eO*1P1-O>Yَq0dh,!J:˨*O3*PnB 5M[1Ȱ=PA%c=˘ij~iOc 3@멤>Rn,MG<s_~'`A t! ,<YW$ 8PM2`x!C6jJHŋ3 Աǎ:\TCRɓ'(ȲcjDDI&A-s.QL@MI!EAbYT'OHJȴ1PcN*pU0~Uiկ9 )M593S۠e>o*8@-ӗ3@wNN8[G˘/sЖsRe,e3s *OV'?Sǔ3]捖; Y7z옲KᰴJoWVfD%ku6c+zZQU`$]]%Wtw%-% 9qTȴF{c4cWb+~6T Q3cU = 9o#/uSYg%yeмǤqQ+36-;CY jPUnVӜk6[8ӕ -L9UXv٩3ͦFt`he 29F3rƱO ^hqcס1$z]ݸ1ۊٓF8hnX7di2M>Q:NB 1Pk>p9=D#SwCy!|%ƃw6ېqN*$thPR _M`6*駠~! ,W% Hp`9q *\XPN9 #*3ċ匁QFRrbŒ !rJ- YّU8oF:t~D@WҤiFP@άY͘c$7WrO9pjs7Vp Z!\V赺KpUOw[uѲz{[X`+6u^\8nm wjg7r{VyfDvaˆ\͆Iq5Ru\oA57nw*Vŧ#{Uߩ:sɍ :˻.aiSp羾8zמv1s(!@u! ,WB# H(DȰÇQE}qtR%?A(8p4ZŊUc8qZƠB 5j9Qf:r)St!G]ʡ`uVAp"P=Jæa1,UX׮]uЇ%rÒGztKHǕ$J⬭v ra-6/V2gUS㸘bi \ %%imN1uǮ[u+xkۨ+v6JM١9vOXWee~'HoVP_ ;Isa@>ibU+_V&*hf:,=*::>uɂ'3et#Py3K*4hjւd)i*c9*QP9wYYRϐCavأp2VԈS,h `]R@'IiC=yy^4<|H>.*P>k3=]a  n(z&i:zd^7l$_kt1HxLiޤ<8tAjhIl@;-MTRe+GerIHQ?d]q xʉ+E vn/g}Sn! ,acEp`A TEP7vY)P=fZ1PSDcc(*@U퍙IΛ*W&LyO1lȱVϞBT83 :{E3E?ӘG<1)y:V)vLs]ZU:qx6CŸn*1Ժc&ݺlRPIcGjhp䔠CkxIqB&02cF([MVblʼeIeN&jhΕ*^PMj! ,acET[+U&,3vJTJ*zfqBUȌi͠ēC/!V8& yyq'Oc̃=ѣWoBF97eӬZi8ӄfܰq`ѳ ˨7ۍyMWc(K[FgW[4k:/, 9' ! ,! ,<Y! 8M.YG8#JHŋ3^&;>P@PR\Y7&cʜI8s&#K,ѣH tg>Z jXf Ҵ+ӧLֳh!Œ[jڻG v`+KXf2Aj``|GnB գ)Qfzl\-[֫nu}1KB3I>}Z {l:358USУCצo`ާ7&x9t#8/U7r;tB`?51c}]x}P4ZJMu|uf~l_NBAڀ@ȞP uA6;O7#P=لm}T,-Dd(C6r76wʁ,_PXXNu7Ps0P8=ZI8ԣ=!S6ʙSx<ԸWN9]UwlYL_>tRg]i]MTGBujdnЗ@[Zэ=rÌ1Dn\Rc Dj <@(փői>|{0j B8^:PH2Zqt1AQ>$%)3ZjqG"n&O@u,v_MADUQ@! ,*#U H*\ȰÇ#Jp ŋ3jȱbǏ Chqɓ(CIɲˇq^ʜ͛8Eɳ'a> mhlќ(]a-FN5J0ݽ9>=t́gnntj |˹z 1>2]'<tՆvaHЁӁoqN7@#=hCn=,|=Dâcs=7#nK Nx2THcuA=Fn29DM*URn tqݞYwj)hGɠwjHh{^)y5) eʆ2p it*Bf:Q@! ,b0 80A*\ȰÇHŋ`ȱ#1Cqɓנ\Ra0[҉I$8Cs@CtM:Ćgl1:q31x;je8lׄ77sחfL$[nL.Pxi@홆Cؽ L!nxƎOBw! ,O H*\ȰCcJHsl,jܸY C64Fɓ\˗9͐rj4v3=]aFN5By6njq֭e~ȵ˱RTډ%N|+1\tڽ0ý| La|M,r1c22崗WZΌIC!41, ! ,z> 8P8*\ȰOeJH!z3jt̺ C NɌl;m*YVt1q2'͜\3\)' Mح5oԼycӧcXCTSK׶yl,mWϺ{H'صǸǐ1,q1ĜnȈZfh64Z'GZ _F8 ! ,a. HCȰC=H O*j|Ӻ4؋6$$H{lVr12>tr㶘9=)ME qhˉfA5e&H ! ,I  H@{*LpC J<8bÍ Hȏ\ɲʇcDSdHkLGM:>C ф !FN}u%D'fWb 3o kİd <'&xF1wQ1:8IP1E<\O,&eː13vk1 ! ,B H@{*TpÅ J$qbAr +Z8&F jȍi<~O_GkԷaec8sN!9!YSj٠F 0 a@s 6,;JssmᰘʍlӷVd蠰kAX1k4hʅPB1qK$M&) ǪUz̊rT +Ճ\ ! ,8w HP=} *\8 :Hq"E\Ĩ/F|\xHEtH}"-1k!6X5)U`ȪV;b5O#VUJ`B! ,:( H!\Ȱ1ڋ(p"D'"wO:kլ=Ę{@R[ɒ5$ r͕`l8mf֋Ej[frQ{UB:{3+KߣZ&V,]1qyP,ΦEuY87eȚ!؄ux*ZiV.F,S>EE р1 C! ,<` HA*\ȰÇ&HŋN"o#ȓDŽ9˒(cTYѥ͛"e8YCj@R(ѣH*4 EȂ5IBvҢ z5Uj׼6eIRPIU\$F,5赪z W YuRՔ BT,P9^$4elVu mzP ]v ;XkѬr.Jp襚Yd~lе䇼k /rs6*I랁VK8yC70޳US37o\G%mZ41cƬC0c0 1tđ_~3G轥^bYw][p="4O!'-x !n5oAew\ǐY}8hQSUfYB8ǂ ѶVB]Sh0Yܑ%BWCFiVX#hzm]PACd$Y[fYٖGXU"p2GMmN:1iGb*G ! ,: HP*THnÁ 6

54MgtgBEIeރ(9XbeSW`e]QFHR0 |-"5_GQA"iDR8Hю"C 9! ,= H*\ȰCJHŋ!fȱǏ #tx={(G\IQHr VfrZSNu@ѣ&ODIeK=j^ N|JO)U{^+㘅XZ&i 5ArAk?!`oߠ-T3Ľfk@C+97:YFodq\F´jCF  -b4П?^ 삎[q,j\[3gȓ$M ̯9ՒHd-{ +/yA֭cPP<ٳHQ{5ṙ߂f{Zj1w"ip ȐuFȜ$V \j,2‡"ֈyYG R5nIwӐ7q׌ #!P6@js-bdFs$Ǥ!g1#,8 zSFniAS Z+WvPV*P5ֹjȤ)obj"w2IUI`6P k2TЦƟ>;*mQ@! ,=ݻgO*\ȰÇ#JHŋb\LbԪiIu%QS˖WS7s͛ȳO{DԨ]h Ģj,YS֕XIb93ib 3u)@էPRA" $ 65!VoT5vb"T 54&BfI!! E3F l0xMWcFP,&5<5aNb5gRq`_JS42 E(RCdiI1p ؃ˆtw&.6ʞa`JT]8DL*PKJ)UcI#hn:[5jҩh %tLvVA! |e.ZlBZg43봔MDӷJ&V4H!Tζܤ5AknHn4Խ/FD! ,= H*\ȰÇ#Jŋ3jȱ#1 鱤ɓ(7{R!5bʤV&j8sV'Ϟւ J4:uF!=T)Su,X8uzիXVwU꼊*=|f VZ)ܪE+Z{ݛW _4b$I2%E]U 3KZxѵ1Q. ̠A3kCsҋ+fxdؐ@K."wkewPpEY ]83sOC* _敩n˟1& [fJ(Q@2m'LjGg16S5qVM H߅tMo6D$ֈ(5ьc!w@8A0&d'N-PAAH.M:9jS5YyP[9o2]QLth&j$_VӘ v矊II8=5Yb]V䩧}vjj]lVXU{_iVVTuM *\VS)5y"ETONN79cpZ)AVk؎ԌiAGlP^#U#ƻ$MlA￟k.VE'\! 7$! ,E H*\ȰÇ#Jhċ3jȱE{cHɓ(c3Zj`XZL6s3:k:S:ֈcѣPJJ꽨WfUW]q땬X)Ī]˖=oŽ'[)W HkQLxdÈd(>ƒ +Lk\{ YϠ?SB¡SN\ ߘM[%X75ܵ _;@6kȁTG 5 QFók |51쾽Ǻ!&|yjvO8|6 Ͽ}߀~.>#-Ƞ>@(a TuWz!ZAՇ"V55.p,EkDԌ3"P8cM;Zx?m!~&Hvե䓔唟ՃB! ,! ,! ,! ,! ,! ,! ,! ,! ,! ,! ,! ,! ,! ,h Ha7x#JH^/"Q`G jH$ƐKR$I?Zre˙k1Γ7sĉ1&ML DQ!QcR{"&Eq><ء 9:ͣ 'a{gКGΰqj&m#%Ȏ-msB YTH&fEZ$$k12@@y\F غ{4NxOt 'a|mX@qsvSS-` { 4渾15pԺAIgl[1mNj@O Ee!މ96UhHyv_sֵ;+fƄ3;; G\=;u|zhׄRѡnw0UC2fu@^Z #CguЅ>i rsi*Wq u%g$P>lF5$W"8]g"BR#A~KLj8F8H$)QCC5∕8h~;u؉sMȉ(*̀`FR$I Lp禂kЂB {r}q(O,Q RT-)DWSIƋv0W$T !@[!U!kð\j cbc`HbheUf`lƐrletmBh_qVey:Hu4`)(^ {7V! j@trQ vzsk` @bc&jpx5@ ial; 7Hy}#H f$38_"؈蹞Lb4\-𙋸(~) YgW㩠ng:N5aD͐LWPE60nP >,LU –j6 J|u$  ,ʊ#* 󹎆8"<ڔ MQ:NRyDإKꟛhH9J:LڞiP,^j$^Iː VCzڧ~*olȣ!¦ w0~$a$ )#:#!h7#4**:#*~R;ҩ^J2*zDs0ڔDѪ%Ra-ꩇeJ#j񬊚J)ŠŪ#*ښ:ꨵ:M ׺zeگ;[{ ۰;8H۱ vz**,.0` 6{8:Kg(}ʳD[F{HmL۴NP W&V[qQZ\%ҵ`b; kvjd۶nn!p;t[MkgT kv۷~; a*l@jK۸;w#`V;۹Y a_l{ۺ˚{({+[[;[;ۻkۼЛKaɠ؛ڻK֛;[۸kk۾˵[˾{+{k< [X \ G |K z"<;z L*,&)2<4<Ӌ0 5=ԝLHɱgf 6P}ɱ+w:afQՉ ` rOd\-c]j gip=m 6Xv s=||}yZuׂmփ}z b؈3\؁ؒד}قh٘\٢ٚ֜=ڨ--ԩڲ}ҳ}[όۼɥMז=}[ }-=m׽ݺ+m ]ެ;~zma[F^F`kG'~)+~G0=&nq˼%^>8.[5^p ˼4LNoK0;K>e]{E-;\^nKjQ.egicoNG[bβJ~]:j^c[Q;}dp..|.Y觛aβG@I۶nNHmꊋt,>ԮηdNӷ 9닛nN͵D{n1;>ݵ⾹~nn..ۖ /(=D0![#'[ϱ!/"Mj̎E`*/,/a3/ o7;5;>] 2}H/%^H@<$P K~' UOKI/pj??wy{o} Ѓ:~:Doђv߱+9ݪ?ϡҞѯݱ[OѿY1O_x+bvzNF[/f+6}QO>OϰFSK_aO@x@0aA >ѡ>-^ĘQF)Qd"FDRJ-]SL5męSN=})BE h" 4YrTU^ŚUV]~)hѤeF;rFHRӾW\u2б,0oE8KXbƍ?L"߱-']Lj>iڵmƝsC e`cͰ֝\r͝eh7p)R$vݽvd w=C&ſ_䧟00@G7ˬA:08f8"C?\l*\͵rDWd*o!/cl:EwGDTmF.T61I%H+3"2K-=tRF(Tl*g:r-D3DK4N#դN;c:7Jpp3PA-=oJ#PGt.CSh4RM743KNOE5U& QI)SUgV?5UW5VXm6X[Y-^}TaeTb}ՙzmZk}چkwlX{J6\umW ɍ\te^{]tGj8`.cYW``x nm%eb&x%b? cmژczAF9eD~M>YegeQ4aZgblzYfiX.Vh7Zi~ 4㷶M`&(u:[K.mԮܰ~;o[:ռ'Cn/q9Ľ^/wɹWau{?;74OWV?/P K?IAh(h !1Œ8` HC1ѐsA @0 r d X:X(-}j!} 6 C6((3ȁ1a JLAf/ k4c(HĞ$91*exPIxDX1#rFN ĜFC/~tIB`2"WCA2*ӛ)*sܩȂr,H=LKH<#QڕiɑK 2Gs $i5*MVP7jAaB6Q Xa 9@إȱVpv\ePplh(5aL,0du ieVSʪVI1GXIAٰF&SڞtLĝ AxЏEN蒆!k(⌌a.BAam]ÈD7,wNjr5{2]o~AVj~pWT*=#ž ݂]!8{p{׉? ӣQX"#އgbOz{1X1m6.ތ>Ǿ1c96oYK$H#?B1u];Tk;7⊷c Xi>^-%'%9{%;*{ e(C&z<@4&?إ1hmbz8*d#ZD3B0A3 z 73Ӂ 2ρDB+)b:{h8rۧ 8!ls# ?k7<>6l)6"Zy@&siR1(ĥ4";؀{cB.\/̜' &K(>bЁDc&;ă\Eo`H8c$r a0LJ.TrP".GGe9(;:耉:4$†LZ87%::$TbJbba//,-3]8 Kc2!b(c.bb7ו%a%c=VaEJ(;!@d8V C&bD5b'6d.Bc&KOPV&Snju(U>Y_XG"b[S]UfVV[oM`c>+d@6e`_,E gFfoeVvqvxzje{}gJ~hT&F VvN 艦hzhf&Ff>ߕv阖陶nޚ鄎ɝ_$ڧ! E 9EQ\lg]^Qҁ j - ]f֌ H]e`(24(4Lɶ~I"Z4Wꣀ4ʥVkԽ M^9&%"o+rҤƣLo}( ND@RrG%Z5?ֶ Άmy6iK"efe0\6l>nj7 ,j3Q ۀ]f>oQ+}$GfB?|<6!嶺km 5.m \pcڀ%ʴM<<nk#r +lb4d#+Wt$Gyfs#:c,51q"b@k$6cC7S15VN5lknO(sۀb`5uq:o 7lw7:bx m-X5Ht 3J4#5 r"vk:O!N]+v+I#Z*5#Agڿ0Urs *DB٪A\ !Rҩ/)+jviREp75IHf jO!j`{1%g A 6i岆t͉qv~K/Z A3C g s@pC#_(X 1M%=̱)4!k)ph~~^H앻(p!-ym`.] I‘xsHr'c 8ِ{!pTdI $ߩR*™B(Z^tW :n#:X -9ijNL)+T.Lqu`h9TEjTvt$Zu٩mУ<Ϡ^1T^ JM!(8>IȜBjVlHISV$+Du,.lY8b!N]/bCu oGK]p$Fxtz|;ܮ >;Da&ra=z[I Uڣ4 GPhGVưyH*a z-N%D,˭%Du-qsX  E8ݓv'u{`vJoћ29!f`~Appj#kT|sSİ5) 1AjpJo媁b9 %Za Af_ U1p_&A6n v(Yv+^ IX0:ā&I]NDyOB^^y]TH^@A9 ses}PHQMM]C\ݝRy@>=p@=<p1tDpqDEUCD3h"1C3CdE0<p@ Xcp@,"!S6Dx(D"~hΩ1EN=cH/<#Fbӕab(!6^a1AND5L3#$$M]}OPfP兴كQj".e݃R:%T:U^S%Vn5%W~%XW%YY%Z^V%[nX%\兼\֥]%^Z]%_Y%`&aa>^b.&c6c>&dF%dVe^&fffnWR&g~&hh&ig&jj&kZl&m֦m慜&n&oob&p'qqgQ 'r.'s6s>gA'uVu^q*'vn'wvwfv~x'yg]yz'{%z'|gY"|{V&'pB}E4t*546Dx`ch=<ѪES^\ h9!ZR(}Jf~́pt@}b刢O)ŒUQ (jFh~Ffz8*ID(YË.zLv2T 單8WBiah)dT%R% (蜺>P^YtǠիܡR'=lC/x'<;,;$'|'T;,Jj~V9L3pB/D~'p'<; ;<'P6.D«~B3*>8e3܍0À[1>A10>AmdVx@@M"F=1,IҠI@0=T+Rd"5BC*0+: C='g$&9C""3L˼Rcl9!aF_3$AdppbB>_q,jn85JZ>"Ҙl,5Aʄ,2!mʎ>v,j ,b4?A 5+VD#1<:4mJϕym rVPhm,p-k,4QG8Qj>ð:(~B/\.'[C/q3ôBzC~z6jRn/p'<如"P<&AH+΄p t BnW,ȁ#X"G@/ߌy),Lz"w>49M CE kqA_MDN)/4f d0B:ATi s '+l pddFd0 ԊTߡbRHDQ QƯԅXāܜ́f //&/S4Xp9sp11Mo陱hqQ odאZaHnQ''\@':Đ8tjzԃ>lJ6,:DBN =pj:*jCKC&D2p+?'gH[D8[p@7iP*Ǵ_̆gtĴG)S8@MXC0[3Z|XIV̩h=i H̝*5PIeK[Ger7۴@TQ\_l<_r\EŌώlE3DOEA+ŊEQ]stG7Yp_6k9sqnSqsg@0YPt3MR;C7LKuȉ6<Gt!\1'6l6+ 1F~íZC=Cgxs@xQ6'=:)3ѭ̓tilAM%Mdht!ΐ{}òWN3`Vpde,R$zC8 Xo ` }yb\#PB4ݔOu9]#se͝NܔP;ݤ{MP ViɹWM,=0zXLVMvo:bUNlȔx&%.D)[@r2'wx~B;:DF8Csx{;lCµ[f]` ,YMK}(:iJ.%Q-QU_N OJ yOOMP)?B ,3c7!;UP/ӒqWK?HzddՄ1@M@>ZRE=ֶڬ3D{IA%}~_?@سgne @芩a0m0fo:A9ҁ'OTeK*q"m Lig^`M,"]29ExB#,pߊH,Z{y !AaE.2^9FU1;^ L^Efz7x{lvAl{u7ǻ ɘ ȿs1k/$@0$4s؀\* %! ,! ,! ,! ,! ,! ,! ,! ,! ,;flameshot-0.5.1/img/appPreview/usageStatic.png000066400000000000000000002356251324424505000213730ustar00rootroot00000000000000PNG  IHDRm^\ pHYs+:PLTE6igg 8E AO=LDQFSIV'* MY6BMP[/PS^+2JVV`[d dk_ihnMd !!!!io"""###$el$mr&()&+5&8:&rv'ux(Ki(Ze)rw*@+ J++++02+ls+uy-y{019G2:=2mt34445R5w|6K,8EF;}; <<<=:=?CfCCCCLLDQ9E}FWYG fGJSGJIqIJJ4QMMMMOPNTTNN#PPMS2hSNfSTSTcTVVYUWW.XXY&yZ[/v[2u[j\Gj\lb^___]``h`.6acccfjkgghTtitkmmmnlqnoLpp&s.ssssturx{{{Qohf͜΄ƣY|èȩƪՖƫȯj۳͵ҶͶԭɯԧW9IDATx콍SW/X=.B*TJU(VAX/R MR/ȡe{2]1f&VmbP7Qw[ӭny^a$ڒh`qB~ʏw9q 00T}k׃zZ cz?{C|wo/7 ޅ^Hx*zㇴ}8w{Zix\ܚxk@vBņ9t>_'_{-n=\4im ke [HToiԴOGYatiB߾/rnœ_a/N^o{ sVC>ςoFWz??8g?yx]>>7 plrhoνB*໎{E5ρ&`!X97"vNm@3lzi:AG1qa 5zVůݷ\n_xV[l9#Hr,ٽ;ߺvsaC)c$䶥Cۖb` 0@vwE4}<G3cA< D] Nj>W=r =ƚh?wwwh"kqJ |i!ɣGJ_86i+yV{y?k kSg-~B١xu>J_L}oSc:AkyʽWn@Fܟu/<6|BRmG*yfL)7 S&k!XB{TU)Zlxtpf;~sFöGǚB:t|V=<ӅexAt>,^ m uHY}I7 e|TejF$6ܸwzx /8/peOmy 9]b|ԅ4|CA'55ur8Itr}ݛү˖!t IgA7vIg ̑38!]mzaX"S hsgBxmسBc, P}_QN$ԝ9n)8d`)ӗ33 ZLG%]OO6Xft3dd0ϖZL+XOx@_ڙ6rqAC&{s@ȴz0sn/ jgg CB5pӽ}{!Cuk@׋\4 Axd=DF}04cP҇ 7i'u1@ݢ1ٺ硈2Bo:JP{Kt`l>Q:Y{}'NS-aP0l%˸]SKZI> e #)6hZ9 %c?!׷t #8K b}f zsHPf䧓v摕c^Xغ8Bқ{KXH鑇VQO 쳐}LB_ezbP?XY|}f'$m>k64~\kuI3&,xtbBLhȞ馡s[y,IfKAbG*OBZVAl1t}/eEFgA2"=f .>dO|w]CcRS&-k2!.)$mW3 Թ0??|#4vq02pC<l-% .AI\~>>kļ K#AN6r+=ԡÐ%Y|'T(d|^/3l0-ug6Y d ff׳Ho|ÉtŴHcF_ԅ9Z!$j_y@EP/xF)enfL%&}L1B }EF>Oc$zB؎'r̠{F۳nVOF00p?!i+Y(Ie!غbŷ;z3#JA a<(d( 0>)xC_\< olUJ ᥕF1 *#=D ڇOO#>qƁֻH :<[zp_,mJ67' nFdm%`Bp^DpdlHZ*0ғ~x?LX<Ȋl!pP㧯^~}xeB6 zv>>̥P7 ʉk o ki[T=悵iĶDsH-#ςÄۑL30ȷ(d&?RJFŴ'fakb@<#YZBl2DCAϜo0?2H _CHzC#{I y6{aQ֢7ɣXڀ[?o^eIV  BWuaN`de}\)YZ9"\pVc{! >ShL|#+K_(?B#,L XO*kEfF?Cپٚ`KMsnacN^⋗8⃔n=qH BI0'wIB B1'3|KA a+&/-寨h)^ZfV!牷΍Ta3q ezFCFђXo~V=\|q @W&h>7rOSԷ 3 'vX_]o@p/&khX<îD2+ƒ2d$no0~T/W>~hװ( 7/xiܮi.Ki "uǾY^() nq3Q$vߒ};ި8>Siϓ1 y{!˟3~F˞ag#+B(/4Kĩo=v#{HmOm.^#a:=3nN/y[߷]B#79Ԗ_ H< èc2h ifP CvjCnM$JhBMl taȸ9;0\>~q%ۮ]?n蛧>x bO_|q~]xM l? 0Zka ^ "SrZ|oΉ" ;$|v)KSl*{1ۇ~!]Т`^F]qpA/^eW2G?"YKh[y5*&4T3 7 'a{|LːU~c0; 7DoHJw Ғ8Ҥ%=GI< )qV{{/+Mr`? ڥ`utpwڎ{]ՊW mzdq?IJ0a_ҕ|IS }JĦ#=Z,KpŽϝ#"~C5Cp YgD# ֮Mer/}-m$|':AI)X!"@=Nv{QLELX劈_K u1\l{=}ABW@d1|+0@HfvfX)Amq?> JѦv븒}GP56뇏\loWN+X. xWə=3.NCPRI0@&gP dEX i * $% 8- TOJܓDR4H0m %{/9.^ jbS eh0Ah-pZDmmP_0ۀ+Ze/0^dr]fťHR/ !(ȳ#OC剕zP87`io#?12$20p٫C^:6QB0~ы ƯFO=np] \zW9#/dx&Ȁ"CVF-5O2%h{tNagvegVhҁv{=B.i2sNU8#/Iw"@@ Mb9)ToZ8 ̩rГI %Ka/ q;&Jmɮx$Y:L۸QLv0{.`%L{ƿȦ]qI`+Jl|h{ӧyj/mǕl~ofѣhN_Žs:yY )nV鎾E!`@RL(B;q֏߄k6! XM.J9)X~. 68΋L2qcCv,(;9;͋I 5`a`CzbZy`heAg 9C(=!E7_~imϣ+>Lt)Z1ˆ(;|ҎR;7'Hh6m(ve|Pmy vA] P]]I*Uk}m*\~[ɼK ۴yvql'xlI$a h M9{}+̗&[L$9x"FFTSF +hCf :!YM-XoĐ'3N5<#&q67u:/7s3uV Pl21jlhdiKXdy7qIt{XtJAY9;0 PBۏhxrș~c:0KҮ.={LI|S}"hWWhS d۸fI)mXio?zg퀶D LYIJ=4¤N{<, M>TNP\)dx&* \`TbՇ33GJq3M-MCXKd")WV3/V=Ƚg>Hn#Xu2|i 5"2$ @#1NT~棅&`/p8KW0zl";6F8]Gkr7>|MQ2& *ja.l{4tR`$] *AĽ1|+@Q_`+ (^^h)/ ,[=.`<*׈iF\`(>zv<.! ''Doq$6wa`@c2~|G M8nh"H]z3>Y _r|dJ;Di 6ɋ0ۛHA!L)!зlX$ze D>o· (ڻK㐻]iv]LJm͋]@:J @h]QVv$Qf?RH[ +Qg`({56 Wd#ґ}RDw7Ф`YjLE~NCP$~Zd g 4l87sIʏ L 9O4eWS"ycVpDN#_^"YVƞzǡfx2҃8-0A.g{%H/Q^6ڔlri\fbIQ&ۿ]{y; h6^e$Ć@ xt&OPŦ )ؓA;3M #|5"PI$T%?Y`%m S-λ ߂ēZυJD~-g<7!ctl#?dEqI*k, пO~Nrד *5-i=Iiҕw& 7Apo_ӧ/7OBa?7O/S{T[] P[3w\[uC.5ʵaTSJ=c$%m$΄P=Sѧ 7嶱C X/}']{K% WeYAlUؐ+uLV)^PXI%0:O0n`s&W,f9`12o 4 ]*r"ah&X]Fلfq$IW3n&x߽6xVIBKWA\W\8pK/^|]իWv}y;7>H^އ'Vy,7?P_`z|6ooO߻Y_V߀†oNnyZo}>ǵnX;G|s|7~h٧i/F2t 7kk?h=lou]7޳{{xvv{i$߿b:Osanot_Qz6$-MԶ!k7j|W^~c}{9'Z^~>?ᵿw$or/[y5 ͯ H]OZco^z>ǵ;ik{OnXcm+E7vƒH0lF!40ȶ.ϭeGqq^6p}g}y׷n~{:neO?r;A:][&kUM|~>`m瞿܍ hk$5Kvfzo_$uwJ=?ͽ˷#Ͽy {{IEhMbƍN<200jF`մ>41% jh>wkulĽp-.qoe/:&vhSXlI^Ro@cM[/@l~޴o^{Wcg_n /=ƽI]+uMs4ŽCϲwmoƥːsdc1gIq/^"eo/v^qqk~ˑ1qP"Iz7.ݼ%^Zz{QaKhß~he( BWG\m7`{{2"u=$|C+W8^qkޔW^7 owB}l-Mj3աx/^rMs^㯺l&wM}j,7_m_l~Sz;ϭ[fyorgixm:n7/&/=DŽOn48ȶwnkF&ӕh;:RyrT#ё?|uNegwwwg:ViVI=5ݣtozK7dY|d~QK_ԒGNZ<[s!W(QX,GP*r.*rPWN/F}T*UR»*< ZrࣳϕR4g~ KUWWc3)V)WEwpI" 9fkTryXdԈ3nj蛐e^2nZoΫC}:-ЕUO%)uv觎t-|PE6θy lqIi]IYxF?5ҺOhuÒN&f6`۪7̽7Y^jY X{k-ƀԖ -'hӝFPн{x\~^Ogih^, p5 NK`,+kpfዣE.ǣ|ghż`pO} ZxnLW2T;E5z{q^t{x,>ѕݬ[?!:+ >`4T۵&ld^2lkt:laH%J6|!ن0683@׋B ^S9 #nj5aWy/r)%"J7A~/6|-@U P?B@GYQ- CZϠOb =5F;s7 4kބ7 7}Βjh$1:CmStklSKM$8)-:`IM혍6$!d$ϸ,Ij%>pe)m):NK Kw =NH'8!0ӍK@gkQ^'emq2_??k)3XˡQhQhX*`Ӏ7_U})7ʕV_/+DU.H,5DDd5rWWoj6>A"*5[\df,hcPF2#7%ٲ 77Ɯ~`C  x+S,XDEěauʨ"ܠvZ9>OЦ re|o{혥=Znk$;Sl " ڢCD [qTr[liaF,{t?ުupsپ4[.'BCH%R m^E)iZCu$K.ӍkeFN,p 6A, ʎ`s +p+j#,S0=O۴Vg\k3­Xlגn="`uIh#?*Mڒ#x4`SGl[-MgQKd$$qU' b,%-QX:Cu ?@KTw?(Hu;zF_WJ5*=:˄k >ZfVð6[9ʨKD nEtج6q0"S @E&Hֆ҈g9Md[F[o$zIñ&`A5b5 6O":zD9 Tvew NrfKl@k?$I&$"Nv0')KOҝFwVH6ud^Ih DkMSYYMsqחѶ9hl[Fƚ0%t~j(h6Dd\=_-")@=8ZcTbl"$!Q.iАBbFmBɳ [p"bdUHk!!񦰆 xI% DIm[$֐i]2H7aHNXM3FFX3[IiMKN(ndS@$c-EVetKR'堭I9^4pH@DYlA{%3֙"G<{BY*ΒR>R7S1gYm0+Rk'D+`Ce,EϦsmF'B;_V-FIcPUkBY\I/k %PޑFc ) eC,p&jtt"6ڐVr6[DnVis49'K 'ʔΠm0`#OOI4h$ҝfhNmLt:$~Hu8H͒4dM$kMf(J=WjL9iK(2]/ۦ}٪Ϗ G~P`P6@&dEot6^cI/f7B 󠦣S#Vp$=ÚdDUTvhIcBM{"$uw7nZb Vtܨ_+IsЦs޹vVm1ED6[ lS;x D. #g)3{$}Mӑ{;-d$!Q&֓eٖ![Fd[.Q-W{reV=t#yLBm>*Fv+ Vſ tC `?CF%lFUnCո.Ɍ DFm%6rt" e3[d-',`C?MADwDD.pʥ3J يo&WϚMNI iRݬV86ٺ-fF3noGmJf{=YQ6Z.#$ zD{ߢ-F | l()\SQ}@T@@kbR#_bg @2T-ѽvPّlJMTQ1T76 mqob$  # 2Eavi`:S"n l"Dmc;}haR:!DwwT ;8RRTKX̻-h $+$}XcqE4 oeJ @lKS4 Gb'"csN ls:h[68WC1$4>|ita^rQM\nL̀L+64@?IV 7J,CCQimHmDlfEt/ЪQbG"Ƒ%pr[m[\v"1F\Ͻk#2Ҷ[ p$ZNGօ|$$lH+ mB\_R݈mNցveGIr[GpH 63rLnj 9z- n֪Z[62%9s%K4"C,(R, ϵP5 !-W7hC!v i ^ xyXEZ@g[!]}ednYnhen5l.צ$Y|5%%-~Ķ0Ζ5Ěl&v+mz #نL1mnk7 mgLfk[rdM득d#7MЦ$:A[Gfȭ^<@Eq;u9I2✤-4>S_6=7Zbtbuhbzn26ck5DZš VVJ%!qCVpMDJ4 Tj-ߪ gP k%} :6X6l{d%"^q>pYqm21o[jIgXaCEky ։i7mõ$t~Y8^fjt&$dNF"NHMR I n iބ[FeU--NR-Z^mKTÁl`y@̕] w>^*nS63ƻJ"/ƒ8v"wbז"E2&)/z9 K&GKpV@Tʻ^) a@Ip4I.#|6*{XRk4?9_yX.#Pzdb^$Lbhȉ$mE$2[m%J!3RwK"ڴvzRBXw|gIXp')-ƒI O`S?Pn+FBi<l%:0JlB Cnp6Tl;.Bj͍ , o0H(٦zdmZ]=`kp{/HkU~qB q$/ "6X(3}2|JR#NDHI I(Qx{EΒ&іsM )^[B5?YlLݜ2$Hdlb Y)&_+erQd>ʒd֘8DJqJ28-V+՘>IAe%!R9KR`}@['yD;g Dk em8&- r>iQeM Ix': JHo m%,In_5Ĕelk_JueQp T\T,{[-z%1#p xhˆ`mp7m03[ qnW%NlǓ,MqVl\XhK$a6]̑I6[nm1'½ݝN;-c1:䩔g,1޶tf~p$6 V57(R#g Pٴjk4r\^k.$%MU$!6w"4LhrT*,#C#&:m(n6ڞ?_/zols9Ѧ=dۙC8"|qӂ%" BAImކN+?e[mt<.N[Mzެ IJɄl2?Z!VsJ$oS5ȷAEm5: XsT0 QR-9U75ɪUNH'S`R5ɲn%$}ٟƟ?{٣G=OR+m|k d _oGh#gbٟ KrLcI>71;im HNiBEt8X@Ob$I-Hd͜,7-(éPPujjŹT. ls6[SV[_hl}\H/ /Vv&$')>גe$Nѿli8IIÎFÄ`.Y+)Vw4)e#-678+jnyL9W+AjNG2S1S&Fa,|+8,9JF)Zȭ%#Cl$1mÒ\S[ExI"yQ%Žm˶mo=|斮W϶G6@٭׈x5&h#bwsآ@IQ&hnCePh(+|Y]fbMDZĢ[-fKt눗KHYaɂ7wʢGRBR9^'ímښL6Ki|EV_’:WM5P-9'ĝVorF1%5m8 &\$6 j!6qCBlӕ'ĺ$HLB,@7eSr@%9I&5~ӧ[OKr m+󀄝J 9,|jcȶI:6i%QmؚW$TUJ֓4bl-ՒIHR)'A'zkS5"N2ZPʻIz"Mm$3&w\͍ݚD%$f|ц[ր`zת\kR$CS !RN2|,y8-RN-TN3AmOyy|gW-;o=Ⱦw6`;◸k5/$p˺ @95DNv-W!$ PO:R*HIeu[.kI8 ![YIݏ2m\w4m" 'H$56zR h5䄱 ^Ze,4rdp0 ̓lsVeI,D[m[ۿ/ղz|w@ԍ( bԪ1jѳZibXYPx=[,}z6M?5;5;rh`%vt֫$qg4d8TOX-]20-R$!MD&@(oT3%Yp-pE[00`57WDכԁ[Р dI֍;UId$%8*d*bUQ2 [n$E+2$o5闛VB@Phlk_k~ ./KH]I[oml g_+n|.6$ت7[xvCmȊx;7~ .kS0Imw;o~zW=~o,mM /^؞%m-F}x;ehN9%r u6ۭ_h=Zmig6 `Trk[|Rd1{"ȤR'i'=*+&Dwoݒ{,RȔLb[R*I3hev>k$P$ܚRhBO0FXrdCCG'7≤QUHsILOLXClqÒ S]ywyCňfb,]$ogHJ-fЦrY~ )zIh0099669"$Em_و[ d#}{׳Z:LͭKW._?+٤waK,m݈nK!udm)nc;f&JsÒTi`OԽmNkdܠ*IU۸Te)y'Fr㺸L^oLGkR#c$8IqXRUIZ)laHJNLL,^mDG6\I:pgɓO\EqqUH|NpnϷ@m=zxcr?ݶœ侣*ml}Lj&Q}ȱy-)[hH-M2Iߍ[&'3mc AlPlMqsmTs+ DYT5g\6i+qۮu"&j${]cK}8s[Mfm,PH$ `DD>e#Z7 a6(\x6晓ܞ5@AI|,V0F$ ;~a<5-<l:*YEnAFgsyݒ[ąt;d I;rOGv-&o*zĬ]\וlU$Mږճltiqa^IWjl1'fkwXh!E)jl|k5`lk5I@B2gO|Wjm[!:dA^ % (ʒx ɶu8d+_@3p&s$6ǔtʌ-ej2IL|;fJVԒr]s̯Gŷb)w404Li٦?i]\d 6bIL "IjEI=-ۖc,I)nT$ې&够bR96v̫[))ٶshMڙ%se[rD'vFB,IBv)eNmILMڍ3ncvmŋf#xX3T%id9Linqn~ku a6O?9ps%@v.m1fBP.^̠ڥIB#MUXz@Ц6 6 mcsݫ}Ϭ=s~t\8FE3LF*%|d_*Mr3T7ny_?&09N1߆yTG3J"dRNI"J5z[\U&}ԭg40EtJęۊ8:\ípG{8BRmj5FniMR;I]6&g)ii68D&$mo{xOk;I٣Rن$lԊkCݶ8ɓE$mv216=,E@vI]'@gJ쑩{3V9KM<\t L90~dLSBm^"%e]tQ(ꑅDԌ3E`Gn֚dmSɶCKijqrI@ '1E2o<}|wg٣gM2XDnlkX?)EH4vۀSV*G&eM2 &ꭑAȽiY096@-GuHKVFZNozj&hH4@5i^n-jQ?DUeV",Yz!l[fb&m "ªJirT~е`wm2nSL ՌoK8qFP[XJJySdy60 oeI-:Uǒ.IZU6_TLP mmQ|TͶfȔ^(F3so^h\,OMaB C&u4AD+M/ lu~ H6i39\E5ǒrx9-q' M$ UN[&zzb6gl̤~.{0֖6B@ Fu,o͗g&+-,L̀_`(\׹mET 횖tXeEh-Xi͐"٘/~8g ~~83BA O\:zx6|sz|V}yzfV[^80浪UO'pEMDmqBU zb#[Tk6W՞0*Yir潧rgўiYo{vwЦ)6d{l{[&1>r~lRHYƖֽkerlv}VšHm ֡_G5{6aIdfB%xLr[R+I/$&,NIr*p#-~E4Iԓ 7نX97O"@JFoZ^[4Ls49lnvSmNI7F)_my@g$+jɑM\e!woV1f2@>\&mݻ{O|`QL|sZ6>s^L/L}kn#g?zc6Kl鄶;ۺ߷жm[:Z+c58K緉h{Uqpt$O L#p$M2iULeGuɁҬImĔ8%Zd&qz-U2kovIi(х[K+vkT8i" Eʍ_(izOneC >\T'/K=JͪUsJoͻ; bm.9,Ւm>;X}"R6p2֖,OgD ᓍ[Ӌ8T)&5޶>ii󜮲=eжP}}lrv6WTlvrG|}vleGm?;3Ij++ WAޟUo1}4v{JcAw[lRj~r]W87 ?W7fw5VVvQ쎩u+uVoίm^: .an7hS;8;\ݾۗ`nWuhk$p,&޺-';0&e&ڎNr&і='"3J%MVSB@lV\1AGm_MhR--mn]Z"%}`7z^)qgza[azq7eլ 1J%pII*$&-*8>{<9]LuPmhS DEB4 txOmaD)3U*7!9OϷ3 IbUC [O_QlC0j@&9HqC](鳅蜿;y`c6d "նG5v6vM|Nv1m\ w桉n:eJ %K2Ҙf13:6Fd$H\Od팔굳I9"PGe9g,otj-H*VW:Bg@l%J#sK nT[s7(*`n$ eR OPʲm3hnOLM`DPk3ЦJ d-7ov~< FV]6A-j*fA]nU)A^=W̽Zӕx&o+Ih%4Hl[YlSxܙT²ۯlNR0/l}>9I-^+cry m%(Nx?f6}đsrX0km'WPA( ^dJ -%cK%MfKdSJҪo%4^ `ͭ,![4:ȩ9 JXm7-!3͛vFNS*'*tsʒ;7+ fs 4ɻ?\V"O)/6r030a{RGg'7DS\Y(O3Z#|٢}$!k `.ݶ`!Kٜv{lRW;/v7a1Ce-smm bnl8P=ۋyF0ԎmI;κԚd]:w!kf>TH7R26&%$n'wbtHVc!͚@g U˜ngϭ@,sB&3/J1/@, o#Ff*HJd+[8hUU"%klQh{ʾ4SI*|N` >tF"GxθHP@+PބFh{n$/-y:#Y~8I+*%H$<[9>Mmkeln͏_VѨw"B+iM]O z7Q͗"Iv$5 ONvDCHS̹˒ti&J@'kf5,=xX2wKZskI S-B,2ܧ}ۥj}^=_+;[!yЦ;uI3"Pݗ^Rjc*%MhŇ mOցqA%Øp)gV|^n&d[4{UnhuQ,lXot98,Kh{CMɶ3-%mdcc %dF)t9e9Jwv8t|4lSbey7pl:'x1\F^Fn/m-Ebzcjn,K7Z.\^Vp[knbَԶ%ke0Ѧ5II>XXd᝻wUo *b (96 ꂄJ}zν{ѻ$ myX̕E}lZj7}r-]ud3cCZy$Mҍ$$ ]o?q’j&4E3Y f;ě)` D HKf['VsK%=Fitjzjtjt|G ye)ertIP.Lƚ5OA]9FGd[-۔&Hh6l[6-6 5d[JBě݁,:[g mK4IȒʸ7%zr 6sĀ8I6)n'Nu m]5ђX;9q'7WSK3&(C˶,LU$L-7BL.ByjѨ)0QUoRm^+[I"5{DZ!%Z6X@ۼw^V%m@hiV;WJvWGfG7I5_sJ)(-ͭp7SANrJ/֫R6*jZ,iMٓJ,5`sKdpۺ`mۚ+:D[GbI 3^52FL%DL6{JnT&Ip9)a<޵[JMa,@لd~tZDQNe*'zGm0-Ds:¥ 1ImCҦ':F=I<{CK2{C)7:)FnJO , h*Zٲ3pi=r|WH6v&9pfښ 9k-bKYrQ:"ݜI$7{fxGXF>o"ٹm6_JͭNM?q!b)>7ܦ J%/Y*02 &iE7$)*H&kҀXj*zkնu!Kfx r;rdw6hC5""lg2"qn00d8R96l= Rߕ%E|BfC9l ]2Ym-$s` rmE'aD.DN. 2c íznvd9䣞ʡR "J@h.S1 AiO4HSڇVnz hKW)`B#mf0J7YrFr!SR9%sK@IrW2/qƓx݈h5Զm{~ܻU֗oC$u% [#T&o&qZ[w;JV?dp_#/PHWk8).Tf[ wA)&n=`I($%4z svę_3ٍziJ`=ݥo%o4VI4%M1pmo@T)j.)$mGD2Y\|${<`Z-mVM("(1Iz;`wUߒ6l>=h s|ؖ|7l`ҋjwonPΒ&I s[[Drq;ZH(n(@q-ev鉀JL Eypp=+ZS|m",?7-MD=┤ސ\HKIp!l 4%mԎ.tf+lE4ݜ$] 8* Xz+ $(RD9o$dn;SӒJ2/]2NqP`3npFNѷKXJ£u5_5J>mH% dK٤$:-^7 u5@n e%9(E =a*6][[[6(J 8jɢz0&1Y_6tnƣBbO֬oJpD%Bqj&L&eʜMT>A @i:@s3xe`#Hs,&yf.ujakLQBo)rM3􋟉h{f’2FH/UR6mpӋo;n5=g$Z*Aenmu୦ 6DHqwnFRSykN.a>w%=AՙݿA(J|[rYB%30C #B=&ӹU3`];&%&tI3,ܴ/?E~6v yUJn{ 4o#ƍ$Ykvj;)^![$^ޞGum!ϡ*$Jf[ n(iTK8jhMGcnA eZWL{[IP{nVB=ʾMF[~a gHĶ?$\Qev%ڸNFFe{X.oczo7i63ٰb6L曇f&\o6oo {}V'l irTt'#z +ID(>X:`v/uU&' U " 4-T{mq&Xp<~w/B냛ruz7$˾^ i3vnnڝcݒ&5z+*cST *Ս=FZݩ#C͈p`[S.%AH9mUVHRMU3rfߦ}\P)iOGx6nz,ҖjGi[S/.6wm}J BӸvXHb֐ u;ؽ\GP)Q#j?/lrU!d([w|ﯺ\&Y\k)tEHi^'r[̊7܉&4H{#*gSMXI{Й74[]\hO%b+4*@OCݽ!$W}J5h+jÆěՖv UKxօ6ޤ|rv4ԏRGND%c^ 86VȼeXѷK.*IPKGN޷$_i68co;Ȇ$ӽ jXFm $Ǎntk1\rl7L b;;;J`t\E% 3ɞjeO"QwoBLa7fVb߼lzۅRna_V&K^&}WxMe6!DYb`F:A5Œȭklgbf5lC3iUe{D\v$6(ΆRt+ xׇs3y*#Ia ٙngj'ifn+dKWo= Qjpk GJ5p)qm 33 1寅۶H/(+zIp~mPg8ULCÒE1, FTDMm-0_鳓ݛKٳ%t)vzJr[36Ei[J6+e[M}#|frO'$Փϳ*̀0GM%6.ovdZWvd&X@KpLp-6IՕrbedKa$ 99MZCEz=$L9Ze7$#;SIgmoojVd`xona$ : ;Ip~w[ێP(ՒM_~Oc28?֑D!4(k48TtR5 -ioܼoy`F{\zjwPxbRۊdWolJTb[*V\4tJӓ&MwLpJ^eF^^ R^m&9 nm7YUtە`+$?qf,%zVA ҖoTxvSmlhKnĚHzԼhwmƆmcL=ftV0V]`JRVDzoݛ[% 967Uu{]/^-.17^oIC#(;8ad&7' dvڻZmיǎYaߦ\f2[v*`ǍrDJtEXΖHP(@'yhВ!IX ;z־ -!Dڊ^-SגБ W},&=}%uMty@{ғ{R, ޸> #-`.ZRlPI\nl S݂IW/j( v,$T Go'7c\$ 1aX ̢QH=)'s`9lb)EL6Ne@%nif)N} 2 mJ܂*iJ]YIwک)nxmH31mZʃ$gF{{Y> DT Qv&ϮF&W.  o!tޤEx2$60G[wQPUӭA4P j۱3_ލ_}Bo7❞ 6 PMmbb4Үnq涊)z&[?Zg0oL۶z?Ws}޺57q1##Y [JS2ݔ ]<9XplNXd_-''0y9w Y6ྭ'q@ݖǕRmѦ2lŖ^?)$ 5h ' JXJ{J; @~E*i5~f؆j'sT&v;T7z/ݷ>|ZMzpIxa-N$ɼǙ>3Mrxi6MP쑤_]d䶦n A+n6ǝfy8I1"$aAS*o9UQ6*oJjfi %k}TIߦᒨP0"pfݐ3`,n??=,-m*=n$E(\5T(+2BxU9T'66AmF\npkCkH.{QHW6~|^/NR9mXo7yۊ4HqjtaC[˷K$Mr7wntFq/^|H.'WI7,2Ԥ 0ldZ[TcKina){Xrf2m-uaQ֊ߩ`g* a4L $e*ꀖD\1ӷ}A wGLDIOI:ÿ-s8ImV .ZF $ C)DՔ<'YfiXrɾ:L!ddvc˞l &[-\QґA/#K6p4~||-WͰ[I& $Qj [.i&f~t{MlKJq֫=?J) &0"$Jr3 ~#E͸aRda`yX%yk'BmI⶟9jVg@2ٔP4>ɤsDD98+d$IPّ|-) ׹(lᚒ >x8TO>4n"zeF6u)v?[0G^Ѡсipql6opz܌:If`% IQϦǺf:lZ p)qMKUW,y8j БTDOJ3n& ; na=NmT#Tr-n2<l$7q:yM:R֘"piIIjv“lkv[vF)n}ZLTCz!y.^I!'OвNN(%d!=Hl6C6ݶE,4b$1޶vyUJ8Ⱥ_8zjqi-% /nwV)ME  Gzp4'Pi~R9I)idRZ@#Ek$9:6}Ak%ް!>>Kq_ 7ި_D5áH{~//Q?V?-Lf8႒l&7|Ȣ^+۽^-K-n}~wl&nW;DynWxv+ qAoH} ZZ``>ψ;h#O)J>IS+nVo|mpl҂4n* %k`M.$ ,V ܪSԄ\z+mۛ^-UXiJ^_QMnԢL GQ^qCDlZ-F"zj^ ׫a|1_FW|~w!tf>\W_WRR7+kJCr$~媔*hy1Z0ZϻY/$Zrj]oh;p<[Wl[E\.+VKV/WHZؿZΆ_/Ǔջ8r^w J__堫>O pfoi֍JTX(5P`I4K$QyQҷK$i֋3QIX,4[tm#BH ZUۼ~$4 -|W4ōULoUIWcmnC9$nE" a^'M{f$j^6o^7{^.6N/do6ȇQqq)xg{\_כ^|dW­o"uD!vEyx;] 6w7h)p_j-HTZ4?F|/z/.L\sq9,g۾Y^.^׷o| &0 |g$]HIљQtv$I<v=t=QF/$*i1,-d`w, <7,, IA;,VcD3`հ+ժfݰ&0jO6m*n7ntN?K+[$w͸3'ś7C\hkJk/./m}Xm.4rx8H2hatql-><[ yux5Z'},_O87%Jdp ^of^ E[:ܽ:_zpAwMw~\sJGaK2dí⢷Zȑ[ U0s"kI:ʷz`u[˔ I~|N>U(E~KIL^NU %CQnj `fzok6ې`_Օ!.Պ;J2 d:B&sDhq3i4gwW},F6k5盇ǕcwFh(fNJEߺl.6Qm%>y~P9?G4\~X^E\4^'I'HeXd?Fͻegv8ncLm=)8&2 p(ElaE77pܽ[u{"UVUTno}~F%\H6%LbA^IKƍ:Em uۗT Œy{`nm(ܷpip$Xؖ,=W( vpj8 7)$rM.\pB2Qܸv2QBwҘ B$ p-7 m"5agpAT\ท0k6k.EZkɩŨ5zXG";E)?<Ȉ{_@n4m٣KQI~v)ټJԊD |XF3fXMIdAnFDHRbi Wnmvxz=/&u-ofٻE~ͻEtoS {Ii]Œ}(l*\PExxTEet{7G<+?f)LUI~&"NN}Pm{Y 7D v릉7E3%QOnm0ڍ/ʮVJ0ڤ$~DUt$ߊ%FՒ=@Q4YE1I~ҋj&fwd;f# m3j6)s ƇWAԢww"v ?{Xm HnE._JZ|mw3oypU#MTۮ :͛^"r훷n7At{EJl+]ofw" v}\U~n e;JY!m`:e&|uDSONpP;&'/xᕜg8D2n^|Z3F:޺<`-'~-[)7bdnVxp6n ߪ*2%5R'WuoHD;9AjµXm&ۆmHm"ښ2 y=@-_,T&O3DiT5IK}J4lw~.ן^a%rߝ?QdR% Nm!H|%m6ϻux'BbRXֺ.-,mn'ogxz]Oa$hv߽[-nٰawK_E-e>ʷQ>I%#&R096 N+m\d伧aPJ;.qOc$,۞m4-q/$|J%[b-A֒>YVSXG6,ږsmn4JojK%7naml48JRT|Cw/$en&z ۮA%)և| ۃeu)W#DԈJSDrhdm3i6;"hFpE5{WEO(N➬$#mjJMZ"mnf1^)&7[Q/mYIān{B9䡅2l'QN!x\(/Lުnmk~fR&='4FkjWvπETrJ4R4y&R[q RnZ]e-廁jLRc4$2nR&@0j)-jHab-n$" 6.ތ^IH M ZLNI|zц كm}.esDl.Yn[Q}ZH *9\i7}mhUܧm5&5\l|؁Z}r6lun@"=3QIF)UmDžvg_H%mp}m-˿MJΰ2bja `Svykt6o{ oP+ |i|F?m{۶d[`}UI¬Ĭ:J%ӆx0~Gɷڕd;vYVEo U>kD߇6J|oQ.&2u6#{|7nzJфMfr\$ %h\TdѽWY.9D[N!ArP9Yp,JHeͽZMLZ$IVꢷzaR dtZmQyJl'v\W Z@"qX FLDIM^e;z\w97*( 29pvmqCύr`h {R8iCۢVQH I0mx+8-w Mz2F[*,dol 9r3E` =D?emQLL*V'yI ꥤq3HLn'7MkogFxfulh&yuhDr6Tz2M=K^GԔT{}kw"w]ęi:Rz}j~q&Twwr_8 'Rb-6O͛p|\e||߬Z.x,FpyܬoZ6Ғj!qൌLIn}%;sps D+`Fe|7dw"*  pKN [kqgoY|Rݷ9V?6=I;eB!ݶd&lR4# ,9sI䖦n սN{f<m-epBh}^{cDD(ND6%.lqM\֛r&rv(1UI/exa#A]"D-ީ-f5"&QxxZ-:Mܽ]gWz~0k%Wr J1,Me].V߼Y nu5ZRnsL bԑ_%֣l2p6_m:tF\-'d)X~9_,"`^LcxYf]QVnX/֯_gdܮEEի׋A{լVN^-ǵb Z"/;@{l5kn8q %ND21If" q;ГT6(rI]܏oROKYmp/J^8un+w'U͔g" Fܧ)DUr$ms>M܌EI87Jr9wJ97ajP$XWkPH;N&TTrR>SKC䖲AB5T#hfmZu0 kY~5uބVՎE?+7r3ɭ .qSu餇>&)6RXYZ*jD q6PELn%L{%&icIoSzoKk%Xad$ӑ8;o5u$*J$JN!ɨ w2ɡp=uUq_5x" {&"s[ NRj[輁RndK\7+[(>BmcHOqK9K~8œ7^1K۩Phn|hί鞭b( n~ٖn5|n4[$ȒE VIU$$,n'VIBxmj׶rjuomc%7^jưliM01VmrGQr/@%vL-92&IEJ$tTIZDvkEr2k$SKKh˩ ei[*2I gh43-?-QDp8,&#=]mfJ)AY1/P[cFy@LA֝r8hrv{)$jE`2m*($Q@[iQ2zggG'qٺѶ3I~3s'6Xצ,~Ri #!oCrm|+PU7Zݎd֍Ud%7+Mg7jMۛ4QjҟkhrJ 5DZ2){ 1*M4e2*zVrST<[m=ڪ$ɛ7w˾rZ0)ɭ +@x4JR-L.Im% α%Vr/rgzZ{ ORƂ{ԯ7>9y ɣng?շ9fR4!{jyEhhv)~2u)Q&YRLV#~m7öRdikDm1hT.i9Ia#im$NyTg06[Z9k7u#xvq]wlUM6x&*TLr*|*SFm[@pV2E gjFº6Ow8fRE['rЗcfQYr;@)M?LU۰(3 ҘF w%J.k-r[n,V'GLҀC`0Ho"ܢs%,1Hf`pDimjT%"mrMC xuCJm},zSJ栩&h6cM ̶c;++*zo5:&vMI h" -hU K:ʈ]Ǎ }d$ 2Pu5lhVoJL/Vd-q 4g0ܦm.(;c dRN(UJ oEĂjėTWG< ^M-J7 ؝0."Ƶm2[lz70n6ѣ4-VLֆ6,^"EB7Qo4~Î7isƹ:wiMΑJO/ ZC26uMƓr7fZi=I,pKV; RBct$Oi~af¹66,$ѱV[6 ݢ$"nP$16l#=/ᾬ$ o Bjd$cU-mRA+vS6.5y[[(1YM4E!\dflCeIt.7-b \WZ+C\KJx)In垀m;ZNBt ql7|I6M$uzS6;VU)gs24!;uez\LrV˹ NTh IoHo<9F*kߵYF&>l5YRT  )VVVn2C0 u@6`7[*Y"J5&q5 T mP¾('"H%>WXmK,v!KUdÒ[ 0ގ@9-!ު$Jq0R:߮Ԙl;tl@ hɒ,qa- W4K%5 壃Hhf]y0 e6l9֥d`sv(Hcfp'`[I.n|S~'#o+խ\m,^ $a#Ow6ӞI͡o+aфdw;}t{lvnU$,|E#-s6f7D֐U[qXzJmB䘨^]5a#$ĺc(zh`[OK7bKɀv1r]-TǴ5A0ÁB r%챤; XraZBZ NmfMݑdu2}yG2Y彼ӵ<@d% w[2fzfK⸋؀p*3UQWMn{y?J7X][#i* lBg(+W]nH'y@"I.IՑ&w'e(g*&"|  pFf;l k? : .z fjY }1k *$pSuəKZ. %4ٵ&i%gnh W9_j,ٳ,YݲѼ`#""fx%-KpdҲ;Nq>׼a0]a+;kz '7q_KFq;i@e]JZud#mBI(mv 湜[$r]bFΤFmGv[E-edlFmDV) ꤇UFVY1ECXdc !H8߆P6'){H?V=i ^VV;,T2TgR+4{9} 4mEmLV) eIer 4|زK6j={R"@I6MePɄqdZl%.hÝe@$9MjeRW4If.uݥVS@j$\?E׮d6ۡA&$w[)#A$~ '%жf`p0469Cw\Y/Km\OI&uc,`ndmHX.eng*IHWr&Y2}i$/N#5vMnKnLPP2 zF"O@oW)k$#?T~ݻN=1j`4e.&$@XM¥bkK4Mִٚ6WLuhOvɤ8n멑dFHI=5mA$6znMF.,DKOr [p I=Onh-me!GZ{}L0nmd8כ4[mdG(`$%JRr+y7zYP6T*TP Ց׺%LmJ )iHo շQ⡝d-7@ ,uP-i`LQ*tS5$a+junP]tns}[J$ǤmK(&-ɤk/FD ҕZ ې[.*)ӣg'GIh%xoi .ۓ7hwfMO9EfmIJO21PrnU{"Ez"P;ǬJBH18PZ Idܔ3\7[c"c;NFY`mpyDKmGGsٳPrK$4>z~)Wl{1Р`n%7-o6 Hv$UxҿMv-:T*j!Vs$[?KsmjpVG$֕db"sЖB[Έn$itLR:XkXw"Np Y n}bc"`CnvbmoX#SKKFO GR*T H̦ PǠ$[ {Ym&=}!3g=ͪ,@%)=ׄSImK&G@IB&٭z/ܛ 69MA;2P:7E8Iz6D]M2`S-RɺLZ )V G x$GZ[F7O{J,jڊ2.ݦ%IF/Ԯ nd.[͌IJۘ @LI,ִW0Sɒ7 n^S/s۵z.$rp Nےm/@^z6DxFwKz[>!Ob)1\R[Tnپ8YdR5 C-@*#Me@rCį\l7l9I%qGvJ䮭&ٶDaBͤ=z!~'Vˆ]{HRdĩA 7ĻF H\[P!߷i@Fc{(Y!䗭M+[ Fd("q"@&3Rȷk%'mMH??nדt ;* S/k,ɾٸ#4]x]E)Ud- U? -و Dp8[puAMxL#"nk:wO%咴Fd5LllL%IrT6k5CFƾQ >*IâT[kp. j&ᆅ%AlxܰF8j' E/ o- $9cStm\7PV ۧn{幻mPFKV#ȃLH[ xdnx |wJG3PHGHƢȘ 49j$m͢Nꭙ4Cu7[VDJ* f`_3eFH"禝mHk,n5@n)?c ӭ4 eBt[6 ny!gm Z0YK:TҒ h?)-Q8I3g۷]X9Fp&ImhPvo0EMaAr[l8*fFmLR: 'nS`K:m j$ԍoVȸ7f_1^`N>%=y[C>rA3{޷yE-d4SS2ܾx~I*@Go5ui*Af嶽Tۦ)n+<"=)&`]Œ @ͦS"鉣~wHXmd(dz@]JaVM3+i͸Aɬ@Ԓ;5rѺx@bX ۩kM.0%%@27I v,NT}8R9Y=h gXDq p%$WF(Z xYؖM_o GSL~fqU:?O޷ma#LRH<`kJL lגz_k6lI]ar_q[ c/T3]i(`h$m6eճTIT)kjtUZUչ\@^k:Hg$[ˀc T(7 W|M"n)Uf6~z+Qdm`K-Z٨]z5{jLT'D#$n'5qS yctRJo 80R 5KN2 xCێ PI6yDv[` H2\,@A4y 3/[nvv[C?~{YlיP׎5|KDmeaƍ z%Վuo#N<Z$ ')5\#ҙt9NX$Xg 8epkih%2 CȄ&-m 9F1ForF&$ani6jj;2L#%%$p;6ަra ذBM:zy$b6r-MΫj(,Bц%m%p  P/^v~ʶَ"CHӭz^IpTI킘^25dhp%[LUR#LMBn8Jm{,F"kxr+i<&lb1XӜm, eǾh?y CODpȽV m+ i}^'ˈ]:"uz4bfpJ3Y4'oVVɝ$!`{bCdl,nbo3dzfۆ㤚'F098! :IIumWJ062Dx5T%wRxb*I/-v}ŗD9}zH^6AP&'q-JIӜjܜ[TɒK&$IU$)uۢ $ktI`g,im$6>7 ۤƕm%ͭ[-3t@"DZb H% d2g6$Ow`I[q8̨"m_Lŝ޷iIFZNUZ.n'&pGRۦS5zIN8p[hqcۈM=[@IKeX#+f]$7Ǜ ږT%jϰI"LndBP]7Pkmɴ\ D;D%(ٲ T*$,?}kP2 [ v$ʣ4&աj C[+cڬLHm&[ߵoh"F$Z`Ez3y[Kp˧yrKI'\3%JĠFJn%JR݃jr$jF$'sP<Αos$m;ĎJkXdvQK (Ahi@'2q' ) >{q"8nNn֮[@J ̎=D{@(^ok.}G$ %lV)bPZSXwr5{㖙" pclzB lqnњcfZq%bkn#|S"cI2`!~s Poxí#}㺭lJU.Y I$oN*iGH ut&3ܙ$_O|`eǽ6o *il5WbfwEk"a\vUӦr M%%<@휦UB]4JҵG-Uehr^79rǭJN$9[(9I!fuC"hPRpԨz%z.u@$|p3,%L wf|m? MEphR(5wok~_nޤJNN5*Y(lY7hۖp5dό$P2ƛT+$IM *s+ɒjNԯj-e6F^7XEdh#VImtn6%_Ll)-!'qSC 2\&vې>e5QD|pB F5Nf`΋ $ݶp[dnX7Z¡ 0 ⡽.0{r Jn2sI~y٤t$=u_emaV$[! ,R9!2L.9fVU*IYWUԞ&Hk)E*w#PÇZ"K%蒠avזHU(Ҵ\Km7HEс[v#&CD"fng5 ˈHJK) d CwvI#b`,L'I~;0Z 5.bw4ו<%%#f+~krOpI2 .lVB4pl<opr.6m''ʛtSiVZ% 6*svd0q(I|lܑb!s H3Lm{C_m _nRzsctP2=ln'Do=*i 4Q_ցJvK06G09@[8m6n\*76nn(E-mY<:om 2/Le/$$ 2 ڶ9$x*m{ۆ|:wjHf#%K*,.JWVCV 7mRrM&izn,pmQCF2K@pC)1u"@i]@5kM?n;XYw&Nie#u9敱E$QԒL܏j6s('[2zr۹fn粬)K &{Ά`^ȢInkM#ɽ7sܒ7işn{W檲cinڛ4onbf Z(s◩^[ɷ3yHx3g%.]mj36VFʭZ&߂k?.sױm-@ mjٲ n0z0bO$e][7hIFaHӾrw̰7+! UU>(R 7ӷa'n1$h.R,p,@J-๚Kxvp|$#_Ͽ_߃uͿ7?->OoqsHGLoODm;sqgg'gOmL~jdٝ6eqs$S)a4s6mwvgw6T:rfWܶ;DM5|NOϾδ]%; %$$^}vѶ;I$m[tkuvgwFۏNR'9Z.N3n[mwvg;o pǍO#*ٝ6I>H%Yn}oѷM5M$OpVmE!mwvSHoғӧБm~ٝm6>JOoi&dE)awvgwҹ06lNOImwv緈6YNh;;uO>irٝO@,Yq~+(td6J>%i+4COrwvgw*IBn c6MIvgw)nFƾmemvgw>iVw|ڔNO(kMSb8ɮܝy2ڦ8O-wG/@D>G'[Sp&Mp$wgwL6/N#^mܶ;=]ORr_doٮ;ΧEh/=vhӏy3<ϱom!+m}4E6tI>'M<},ܲ%%mvѶ;ۣmj$Ab-kkWImwmbmrvtr2d`_s:!|6IͭOB2ӟ}=mϙ5ڞdܜ=!Ln[0T{]=_q'`(uzv)gm!ɵvsr|K:dGXݻh|4ڐf6&r֩/%*ɿ=Os)I6YVMLɮηӿ˿?_;TWI*,əT:ZOK%ۡ?|.цӓgg/Nqak3}b mCFy=;}q1џ6o|n&WϟKDɑ%9L\ӯ*O?Ϥ몳۷}ƕ$"N}%5:>ݷO@_~{?O:׳_5vh ! !1FUztQaJ s3Eդ :#D➍,GX̓+Z_WL/xlefo}sqϜ6gfc^>xw~/oOZste}>֋ iK`p<#& @c[ΝsRnSۖ&XOiF24~3>.B>#;GեYaxeք{=d p wǙnQ7\Ai2 ʸj>:No>Vc^J'{伍TTw}:c&¿2s9hmRN;og9m?\Pm< }?IPvD|fPA[gN=wQL͢d?OUV} mw lw7GPhGB<'²_JY4k^y# ^Xh;XG(; b9vHP%!嶏Mn3ޣ۫|@OF<5?sv?Cqd"]1'C:|,*m|6m Yh<4/K+Vxpʻ_׿em۩?7m̹jCf}ŧ|*0bVQgAC౰xB9snװ2VwOd6ͼdm}/1Z5{pĻl͙✛VR=,c%vph bYP.=a4tn_:;##1/kPwamNOkJ~zn}*E^=8#J9m/$u=-`&!>`Hy/WE0#j;8@A_qKoO?x5_ׯFj;Jii\*Juﱡ i{rt\T\#eLMh4q m^҆LOmv/?B{l6ޣ~?'a[GYodM2@4F<;s6tG̶yq fQnٛw}q]ۅ*gBvS 1Ծ7Og *&v?ᐴ|Z6Ymd(j(V}(n_&_S\ N&K|UhVl'^f|0E?D\d$]nPĠ{6mOr,4a΃l{TbQP)HMRr S-5ថi;lXF#mJQ|Uh8oPfvM+hr!ېm#3X3qZ:%OоRoDXubT(g l}"p]Z?J=>rIt_}IiP2O% pYB Ddۼ.R7Bmt;!Cj4:0Xs$ωv9r["d\@f}p ȑ?Qm8a#&_0/ߘdzX-Qzow?nZjҪ8B姱 锜* 6atWn3i|z}cܕ]b4vbE/ 5|M%HW F]N^.$En D#v(,^f:u*;z9SK3/]t@vInժ!4QPF+ɅA- -uV{m32da\/L+FQ2Nvv}^_IvQv!<dQonv /m7iۻ9NwbauPwR#g}Kz=v]>2dۻʕ;(gNT{2*%]e$E;.)J =G;/ƧO%lĿ&hfΞF"u[Y;Uv{s^EXEF#ȭkਟe.R,7sNӌҧ%dkO41JVlGfk n5g$MZ/^e+z!MS`<?з9ߔmnA}Zz_l}u jܦ{_vnc-,$! 2&5t)+ywhL'F9֯^jVm7HHG2<NdܪyB9#x4>eM.!<舐C6LINSMm\7s1n=}O&pK֨r_:7mgqیې.Z2Os%#R-ۦ s[96n6}O&ےfs$N)OPIoOzI)$yEKT ղ,Tũ&9}OLnDTKR1S>$)D@Lnm3Nrz=}O--_Bs "P;Ormgs텅P\) fzW ڄ#}4yez^DfJGlw|`%~ǕVB2lR³fx?۴%6P9# q%Œ$L?Jwt89-Լ<xGv߄:O.ӰGmr[!~v \ wm`i~EkB]'ЅsN)G6(3K24.t4IE-II8I_<[|\;RzS?0-2DqR3~OWRX]=7hn7QsTeVy[<#%\ILa>g5YFZy5D /.<#r)uz4>ik%)4(M˗CˡKFMސ}Cm16q=SoH5Zi6w̷Ǩ555 hN!UYyyŤ)_ys12&1y'AO4)/ɒ6MjHC&x7r8>o\p=m)36PY`2%$FJ}<:S]>XY1 gcxЏϨqg9=w8-h2v Uc:6K?";yo?Wy i.Hcϥ1yO֞,6!4}IMS0>$mRnP-fhin JP" Pm=X߫ h(~]~m,V׸ͤUQ?n N-ZdϋÅ$ w"m!RIF۠'K_?qy6w L#®q K98-m""a/O{F(L+{5I,0ڎOgxC,B"V]A`KHe^:o= o[C湠:i$kA@kks/|)e9/MnwQ Wf+czТmݦ HMS`Bov%it\ l_<:H ^-5GxP e>%K ?Vg4D>\7C Tg!RFώ#`ڳ'<`lIぇd#gz KbRq>2f[RgXK9yY@.OHW%m搂&7" jm%-HD" @B+ntu;<>6 S/diqA=8;Wo[r&u`B밅Yy!]b?|eͥ9ym Z1(3"\mK̞$l"% hA I-qv }nHH}*;[;&( <ܹjKAGCt Nxp mzj=̞cUgnw(;NPWOsZeVz\䞶0qm@?<%NV4`͋m.y {b6(8 F?OGAeFOcRMSS ¸l,oug@h#*1DIΉJ>e1A:`&#̂cn-7-m/R{/x "x^$)a?a ہue=V;wzF+VCL41 OY?ֵ1+JiW[ݬDnuTW!Wx._böQFoUy{GC#8bO!w2uꦦPԃj5RcUCfac S8dgcmxp[CC Z xv(tL#qo;S ΀ku<]Uy6)$焗$B[Yx>΀")M$L4N @mw%*MpT\<B[j'mg3< uZNIؤL7a <@_ftm6 Mn]Zh́}`i>3}ʽ$"}k &0B)fӧRq^D{p#"JM60r%7(XrÛ2L6Y1$a[vT>ӧn~|c." bT>ӧ9~ ZvSMrL ˔ cVl>ӧ&I-$عǕiTMSm"QB~#ޘr>M,]#wt5)MSmm,XHv(0ۦqHF%sTVm^pr3}~tMrF@`IEo;}6~63PpWH=[x4 K <}7n$DECD֙_h/!O~%o엑J[!038)\ͳr&BH}ԕ{#\jHߏ} "4d\>futipU Dn47x4>kZ@`紃6 }^B9'%e9MϚsO9y֮3h2}K;؇_XsNhCnmDSPj\[vL M Llˌ=2ZD析_,Tmݙʛ>ۀqLNO摃&Ή6TK T$DPH|S&#mM#_>nQ[,d^@@vM~"Gƕ!FRc#H7}@5;x{!,Tm,{Y66qM5e}6bIРf͸NRLیlt:ҟ2s(@y,PAl|X603ӻssAirh4B93v~i^Q|Xg5/)U6ۦϏg@vXhDkL 'W$>(q C9fy>nuW P;6¥YRv8p_/mG;G%3}~ &mR(4 (u2ϓϡPڋZߴ)ɄĔm:pH],T^s_Y>omSpmsD.~f=@7MJ|Y-ӇIۦϿq+m^[~|6omPdoK(K{K7zs~ |),g'7{17nb8"$&m.H~k[ۯx^mommm52k7sys%3meT&Aܴɛkٚl[|:4%PD)DO3vk%KlkkSҾt:XW(w{6f1۶Ntӱ~"(y5\A%i|\?zӧNyj߻?jy|7Z(eIOůMӪ˫_Dϣ8ݞRht7﾿'(aѷ:DO%}_o:0U:[>2QLf""J585xn)ٶoC،}}^+iTaV67uRc7[=|7-x7%Y7>6CS E~s7tmqiP%G#։m' ?Tߋ,T̈,+b*w,|'ּh<~*[XSU=9\ [|#jЂ p_[%bt޿'/cmcӍN.~-goXR_v?tP+Odn%Orנ$sl H9:9h[zbǾZx_Haŏ@`},W:?b~qC~/ |o!Dn8 kq =o[_ oXTɉeMΜ=G87}.R0.uF(o!jY\gX =.8pQ*$Q_25+`-AC?ۑIMa5-Qs!tdž nXm2dF@D2ntNG,%;^Q bB$)Am7[cSrD>fO67aRVlp rHG-m` }P%}NJ_X&6o8Id@K㚳~ڹy(TA}s\%C :OidR#w ɦ}ӕ1Ѹv|%]abpFdS#= <'6Z(<9֟JoX__qJl끷'}_QqQO`lVi-s<qEC'ʰB!.ˀGb+CޏݛԤpؤ xQn8ĦcN m Q7]hSgЬSg{V>Ҟ}Ȇ z3|:[)c\8]?zԣO Ǔ Cg[lR8&b郰*poUo.`!#/ٍv`U7(IǺ[iW>NRύMeP(2P2.QYg7ןb~31<տK8}m=C9^>G [ڝ7X3@vt89 Tqф v'ด|<v;2 }z*^&śac[ =w[WOP&cu~F tv lr:K1ǟu$F<-{}ۻ ec~MY{&7s,v2bS7ۏ<:.z {Y\_e)폘zGe3"@slT?SbF9D3c:AY+|6ikf溿)Dw>@= @>ROqznVϖ?4 b 0. .9Ųq_T}Huad"~ǀ9 ď+@?)d?v~#4E="k8'zx]z :mozNמ_ﯭ?[cDl]TO }"'|>|a YF5ZM$5T:2*.efX >UХꉊ6KQh}t]?n[wOΟ/sw|gN^uX{nmn<y>W,U>N2C\ ՠ}|Ip6/آKॹMa=\∭Olgzx:Q.鲶$kep?^|75,7ploւSfm2gB6,^zV['nomm?U%k e6 pk55%>ݒL֣wKn9*FQ;m Cs̗sz9`(sAdUWhS [XoZP Z bQ Kư_}t-ćGm?ʨդDu ܆ ¬V 빻KEJvy4c+ltw@U?b= m`̅ϮhOi_I|ǜldjۊ$z\"UjMULmxsBE<tstߚoh:#첯u$ k"˺UmŊm}㶏LųJY]2gǚ2nfbg'W mv=Pz 6$dc9./7Wr+,*W]9%.ly$dZQn3ѽ$C˗X[<yISh2/֖H Záf"zerۀg֌tPBP^'P%v -8xS'0 ;?Wa.۞鵇mzec:׉'a3InX$ ~ oP*^L"c˥G!ܽ6>K4npN\<2[lPn{MM5DY;cXsknaA<^,A`^s`C;^o[G8-]O$0rOIg1ncm?wmɦyzpjd龑Ee\MB$ľML {rMk.FGICnNU:[\/A7aztĀ?\Ș44|أqk'.KV (DY\C@v4d\m!ʒ+Dn-6'2iFn}zZWgNmG#ON^Ghp#E-DJoo۞z UL\)I\2wg #ki*~ 4 nƍ:+1 1PD|bQ JQ@yTqyE%o{TKHCnqmE"ͨduz#tKc:tԳ@lTqz{C 3m u%!vi> 1T;V"¡[ [9tEn(*ȍn{MDخ+XQfkw< l b·})tczdnaTlV*SEze[FxΡ +?py2*ɔOFyh8\# j$1/Bb7|$)7&}6AծqaHNbjSlNGm [l-WsCH ka?Egc:C}6 *`.\6&Tw}TPA`RSFLL UhuaA^;! :tI@K *Q'_l͂<݆(Ce9-Qɚ&ge Af04)+0 1^n:0jS柗%UWU䪵*Q7P^ 'sv(߅vd v2{6@xp >ThKlºWxz;DqcdE#mBJ]ߗ] 4P}C%e .)ƥvXs{'&P顤qQ-*LT禸=뽐\1Qes+)rd_a\nE֔JOcGv d$s< T8U Ii V>4fxbm-տ%@S[}kTy:^&~%1KӴޒZfV3tnϞ<-kuFN=@:q@i%ikIڲ7mDf[m^՗"|qT(uUKOb0>uԝMPϣ LHJcIӾk*8X+lTOSm0MUa NV2:"_ƝNg{sUb25j"wC/" 韫4m)'׉rY &o"#%>a[J>Yz6Afm*]cRc,_6`miߚdIE^_]M{\=;7P*!ZR/MZLsZnUۖQ׃Q7Kj-z47] :.ovn-ErʬjLO9 IJV å[R[8BʿI;f(E*!IUJ!0!ּ@l*dpPM]{#l_S56f;9<e?)g Rtɰv$%{3gڤ0Ԧ\ՓC'<~"/MQI߻M":Ir-VYm-gܪ*Ew^KkYWԉoUɱD;c?v/G-֧UDRZTOoق6 MZHZ$XdZä;2HN!b3td-6:>$#ZJMhNr $5I"FHQm/DUT#\3¾=%T5V!q}719Di%", :jtڋV1]LKjBӹ1u2ۖ QT{y1RC@I#h51J؍| _(&]h,۽\:,Ut9qeD:1+pVj%h6M0+I(RG5!$J}%awҺbc2u{6ܧLPG:Pry"%ECB捻7 ѷ5YU2E~Q3C]R~SOF$YbtJ(z,|m8i\!EOYmNi>VU,2e Fn6)5@'Q߂*|Gt!-7ٸZ t::;VZ[ՖWNh.Hamh{M:ꂢuB!%]j|l%H)[N<]|l <0ĝX>lȶy9dmӯ7P3Ժ\)F>gq@Fwd(TAgm MVMl6-Ulo%bluWuS ٤^'s{=|Hj51%zK6*:}Pjbtb3s3 51h&F5Q?ݦ2dbFg:S6Z^%>,é4J >#Q_QZ"pI7[DJ#mT L&.ԦBbl4&lzϒkE7bE7Lm>AR2O7~,UI_L4_!ͭ:&b])lbAzLL&̈́Y`5ąl7>WOdliQ"c?u:'j%q'( b.ڳ\~ҪE`vf;J;mO&ݢXR!@@I~%Wf!cQRT'6_*)ܢq6э.r is[Wlk^%)Z :##l^h b[F׎L(]:r;]}]I n̮muI&kuK";qMR/5/LɊ0Ԓ::Päz /M+C$%OGVo. ujci;beSm6pyĝ7 6%;\h$s1M5b1e,Iǖ͙U +ziB˵#VNi6b9r嚄3E$!?5OySF} `|,*y!ļ^Hgٜ BuhQ=mˠ"Lj{ԊiBV+a*6UZZ <j~0_!= +Ij&#JI<3yYn8{+ /I_T60 Z= EHE]AQr#!q?DY1kRk1-5K䅔>1Z]VfNTL,mb@>2x (⾰hVߒDD C<™^FW0i, 憤mT|P(h-Yڛ{q6oo;tuBJ:Ґ LRyg]o'5~kf=rE%#u:#C9-1kdMcV0FeVoAT%AnV:[0 & ,*am~IeQrYGGȶ$H`CnӵjlpR׎$ӾeZW&`D7Ȉ !{[tZȔuMT jKlUZ fJchq'F: V{j~#N–L]pѪ3k'u>+,ewaoZ/T;0 沭]#K w2coEI l/0Bk8+ӮNsdI/YjM(ӡU' B&dDcRZ)s-7SeJن&s0+6X,FZڶ@[DLdFn1C ڨ+s/$#q~Wq!>$b1m&z-~tNH>DQ;yal"Ū<_dv]SAǎ WtVJJI01-Dd8e?Bw&x-m-dmuNsS>3g䛚v-}@(~Tp3qCy5y͂#D.Xngp`6ԓ,kIV!vhҪ\,F&  Qk)nk:f0HyOG̤5mqZ.:uYH}LXG|WjӞQS=e ЕvJ,1lAIiނNSgąHcx\ɊJs#ֽp6"fY+UMhQSD.`iƔKg'>S^nP6Sq?L_2Wܸ!o6[]4j6#{qJ.%VahtJխ6g+ d͓NZnm.xpopcSgc҆ߚMy'+&5e[H?]+b# : 8iw|.?B7wZa-±"NIVW1#FH(Y~[87h#q mVKѲKp>Ȱ9y{D$q!FM3 SNXdiW5QD6vfn>DE`^C~lT͛v{LA7k)\%ά8^i$%0oza)@VX`WM 6,(a7ny;Kj{ѝd 36QvDRu!dP&##ya7aYm=ƗA|xȫ5Y-&ق젮Gq76Kc.Ķ΍&n%{p'hJ`o[({$PV u(Jn9sX~5TDh± [s VjTpV*niѕY$8|zuB=O}d߮؜Te:ϹRkx2Š$MU&ۤh|Gi*z @Un 8U̺HUJ[rɧ]CP43n4yW* N2NyI*鈆`ق”?J̚+JF7U WKƒM& V]o\h 3TJjmzl `@BIg&yJ?nE3U9lʌQ]@J\Q&ep`/h1W2 %pHNjKKs Z/OBhw`<$ V; d}k/!~_D80TV `2#}'(̫W#)ɴ#h#f-_Bs k3Lg  ѦqlV\PMN{eݓsP::T,J89^7Җ! 1?Kg}^*eg(GȌ0U<-rظX, [;0-ߐKwO1=~^"<(CĮ+2G5 ' ^g}!P՞HvF%U( wiDg l?bIs&6CB(wBēe`GI&PB8Jtp.iY$/Lsoi@ y5PÀ/7ITБpUrB8ѦaTFx Dr;;O PaKӎ|EZɒ0*ro5s[hȊw Z`OD&4&h4 18V}k[) :X}XLRPrŒE4JL-fy^%/oIBT (O8`zKRև4䓅]FYruv@Q/(%qԍFzڏM|mqq*GKMxbgT1Y޻J>tsna"7~ZOܥ^ZReD+tXJ,_&}P'6W4짾]dx3 ɸl0JSOVVT rZ,MQa>c!i)Td2}y?- $۝V,\D'N[V" (SzMF\Oom!O])f f!f(q)پMe<wRokj0Ƥ1$&F)||5(Db K+T;^6a1(\#yOe_ucܷöK"JIK./^]zuhMKW[C.^^m^ܶ6";)^ReZzyM8D~_K!^u8>V@~<(mlr$?'lj '11yJ:'h4C(HVy.09"LYڭ'lZ4}LP4!'M)F2g#9D&j9,OgGANN Mf+\a%D @P$,VܦUH$]&Y<66 -Ӯ7KYrެ,^ Rԡ+f&OR*6gW \FnYhH(ڦBOS3͵=guJ&&* wx\ɱYi&ەˌ>?r,gY|O(-EYlR"6!NU&"mO-Rw'3|5P MvUp9*ǯYiNVꈯ ȱzӌj2!s*3[pȄ6D@ HLvtzvQ@$u֘)M- 7&PYSZ%UEͳ8*eD ]b oQv$@d8`t r2y jj4ۜvIQԜJ0hTf} 50x_k LOJ+,WV=nJM7>k<?)/*܈Jf]], Cg,*KR ^ s̱SXfѲˌ<|킶&#؏)cIrx#̱%H:aj-GN-0(I,3Ti,gTBA`+9[6K6I> "CtKJ~!)) -zu^^S1HO3 yYNlJ{WR&7xFw|ĚmR 2vL4 )TX(Gf[&tGC2u\ɂP38nqeݸz*>O*FNQᇋD}kV~}WP^d qNJ|=`)zP @UlsAgT)1[|#gp}X9fXs?q9iZrʮXd60 Qd QS@֖ Zo z8\w[^B,LĉH*na wDaV=PtKtQm:v&+[CTy- BEؾ˜¦k#ۼccz+6%RAHGKE0|q2EBCb]n^pܧKm~?\$bq E$U,.~x|Gjܵ7vJe GL9ܲzIcF5P^n4نt| ES 2̸bS(AlvOZ r`QLk'H;Jitn*"H 3ʝܰ=,FR:9 FT8Sa2bŌ$|RCW4#RG:堌 Ra^^.Ǣs;` ʹE#ХDVI 0 ?eROq(|OE13T )Edbke;.^]j6^0܇q."g y+* Qs5BTD [xK"`bs[4t[h&Н:ޢ@ϢsWezn75#S D MAvuڧGÐkq隤!.egSɶo[H؀b$-_P`$ȭBMb:AQ6r\1&\]KtN{r2g&ClCh} Bf7(&LGœ] $B^OvŖ$5-qG ſ&CA)RZ%5Uy,\tC& p)P,LA"wemV@)9 Peft=@5'P $B!t2]>2]p/K~/6]S) Dd&4{%Q +toi< -;5fjP Fr.$R/TIENDB`flameshot-0.5.1/img/buttonIconsBlack/000077500000000000000000000000001324424505000175165ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/LICENSE.txt000066400000000000000000000261361324424505000213510ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. flameshot-0.5.1/img/buttonIconsBlack/README.md000066400000000000000000000001251324424505000207730ustar00rootroot00000000000000Google Material Design Icons are licensed under Apache License 2.0 (see LICENSE.txt) flameshot-0.5.1/img/buttonIconsBlack/arrow-bottom-left.png000066400000000000000000000003371324424505000236130ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<lIDATHc` AV_f``_~AbPib8> ,,j[@E&f͒"̂H( Gb3ⱀpD[F(E/R&#SIENDB`flameshot-0.5.1/img/buttonIconsBlack/arrow-bottom-left.svg000066400000000000000000000005321324424505000236230ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/blur.png000066400000000000000000000002461324424505000211720ustar00rootroot00000000000000PNG  IHDRJ~smIDATxݓA !˼()֠= ,4shDˋf~ӗh<}c/nT A \#kHu-vd$opC]מQץ/[GC5IENDB`flameshot-0.5.1/img/buttonIconsBlack/blur.svg000066400000000000000000000030271324424505000212050ustar00rootroot00000000000000 flameshot-0.5.1/img/buttonIconsBlack/circle-outline.png000066400000000000000000000007251324424505000231460ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<bIDATHݕAN@ E `  !NTV X B- ,肔=t$K#Gq`=/]S :.B#p4e] oБGDs.\|4 K1Ar澒{jUrMd^ HKk% gm&Y q<,+-vxPUA`[}fit/+ BEqc֠ r}9) X"}+DNnЙid*1<NKTTy S[rpԐu <#74?bhIENDB`flameshot-0.5.1/img/buttonIconsBlack/circle-outline.svg000066400000000000000000000007371324424505000231640ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/close.png000066400000000000000000000003651324424505000213350ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH1 E_GpO;qt) 1P'K?~؀@xn8`ƒp^4&iv.6I]:zulL?RPbZv^c0!\ p?E IENDB`flameshot-0.5.1/img/buttonIconsBlack/close.svg000066400000000000000000000006241324424505000213460ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/cloud-upload.png000066400000000000000000000005301324424505000226120ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH=JAߦPĜ@<IA)V9"Do! -5,ّEy~0V\cw|` 'BE|a,~S.Ǥ-- Λg]5o;{S3#4T8.W﵄יqb0I*i1dXb?T^`a~G^#Sz=kjccr:Ύ|/>}_?)-z;LIENDB`flameshot-0.5.1/img/buttonIconsBlack/cloud-upload.svg000066400000000000000000000007511324424505000226320ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/content-copy.png000066400000000000000000000003401324424505000226430ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<mIDATHc`#b``xDL4 p, Y1b9q򘁁ADn<"rCπ X،`рZJZ}>&rOHNj]AT[n\IENDB`flameshot-0.5.1/img/buttonIconsBlack/content-copy.svg000066400000000000000000000006631324424505000226660ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/content-save.png000066400000000000000000000004221324424505000226300ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATHA0 E!:HP.=rapaӐJL6i;N&gݭWrd [<D0 5wh\M{Ie`nysWzw w ZJo<($%륞%/`'M{-IENDB`flameshot-0.5.1/img/buttonIconsBlack/content-save.svg000066400000000000000000000007451324424505000226530ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/cursor-move.png000066400000000000000000000004121324424505000225020ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATHUA 0 DON/l]M@/ mb ['=JJR7!hlB{b&u;%jR !$#CDV5rEQ vbS^HθTd0MZ;ײtk<: w]. *IENDB`flameshot-0.5.1/img/buttonIconsBlack/cursor-move.svg000066400000000000000000000006471324424505000225270ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/exit-to-app.png000066400000000000000000000004321324424505000223720ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH 0 O|` 1 I` |(8q\$p|8X(iX"cjI0{R,/C 4E(]Q="⼗<8 @;GHKH"x@J1 ]7 B.o p+-*_fa}U IENDB`flameshot-0.5.1/img/buttonIconsBlack/exit-to-app.svg000066400000000000000000000007471324424505000224160ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/format-text.svg000066400000000000000000000011011324424505000225020ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/line.png000066400000000000000000000003321324424505000211510ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<gIDATH1@@EћM؄}ۄ),A1PHQȻf@5$q'g CDNtyqo%BIENDB`flameshot-0.5.1/img/buttonIconsBlack/line.svg000066400000000000000000000032031324424505000211640ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsBlack/marker.png000066400000000000000000000005151324424505000215060ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH1NAOBHGxK`,B 7 x v_X^ffio裾KG,W:aUxӶ# lSSO%:с~34Z'BwdOt3FFvo 8O9pPxM~'p,)XTC9xBW,=?ۘ.RIENDB`flameshot-0.5.1/img/buttonIconsBlack/marker.svg000066400000000000000000000011041324424505000215140ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/mouse-off.svg000066400000000000000000000011101324424505000221300ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/mouse.svg000066400000000000000000000006501324424505000213700ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/open_with.png000066400000000000000000000004161324424505000222210ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATHA GWy?" ppC՚&ka8hWaž fv,25ܝ Sx\ ,50 yKmZp6 E)8?TӀJ 3\"۩IENDB`flameshot-0.5.1/img/buttonIconsBlack/open_with.svg000066400000000000000000000003421324424505000222320ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/pencil.png000066400000000000000000000003711324424505000214770ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH; 0EoB;wB00"@󆐀 @ G@z:ʹp l >AIzmhlkTҸ]R- @xs;P6?+%m8slh+j"IENDB`flameshot-0.5.1/img/buttonIconsBlack/pencil.svg000066400000000000000000000006721324424505000215160ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/size_indicator.png000066400000000000000000000004071324424505000232330ustar00rootroot00000000000000PNG  IHDR``HIDATx1@Fөd EWb~I2Ձ!@$I$DL UnkT,8K$})F$fBvN3 ЉK 0 0 0`{l 0 08^tTg:ż _ qaǪ•'$I$I??IENDB`flameshot-0.5.1/img/buttonIconsBlack/size_indicator.svg000066400000000000000000000004171324424505000232470ustar00rootroot00000000000000 flameshot-0.5.1/img/buttonIconsBlack/square-outline.png000066400000000000000000000002571324424505000232050ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<`ԂQ F- *MU/ Q'T;PIENDB`flameshot-0.5.1/img/buttonIconsBlack/square-outline.svg000066400000000000000000000005041324424505000232130ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/square.png000066400000000000000000000002351324424505000215240ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<*IDATHc`#?e8Z0j$5IENDB`flameshot-0.5.1/img/buttonIconsBlack/square.svg000066400000000000000000000004631324424505000215420ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsBlack/undo-variant.png000066400000000000000000000004561324424505000226400ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH 0?:DABJ#{]A C$$D8pK~EKI=Y\ۯ5}8s `yzY(ِ 3)HNLtOX# B27A&FK&_L {Ě-u}!{#wSh=IENDB`flameshot-0.5.1/img/buttonIconsBlack/undo-variant.svg000066400000000000000000000007361324424505000226540ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsWhite/000077500000000000000000000000001324424505000175625ustar00rootroot00000000000000flameshot-0.5.1/img/buttonIconsWhite/LICENSE.txt000066400000000000000000000261361324424505000214150ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. flameshot-0.5.1/img/buttonIconsWhite/README.md000066400000000000000000000001261324424505000210400ustar00rootroot00000000000000 Google Material Design Icons are licensed under Apache License 2.0 (see LICENSE.txt) flameshot-0.5.1/img/buttonIconsWhite/arrow-bottom-left.png000066400000000000000000000003431324424505000236540ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<pIDATH풻 0 v_e R0Q +% _꽳8w dU^s-_?5I@m-=[JɵcsBPěTQ8n^2q$| fIENDB`flameshot-0.5.1/img/buttonIconsWhite/arrow-bottom-left.svg000066400000000000000000000030141324424505000236650ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/blur.png000066400000000000000000000002601324424505000212320ustar00rootroot00000000000000PNG  IHDRJ~swIDAT8c`2MXdN98>6SG 4?F' !n* GdHB 4a4\W TGH2iwZ:A4rqT^&IENDB`flameshot-0.5.1/img/buttonIconsWhite/blur.svg000066400000000000000000000057341324424505000212600ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/circle-outline.png000066400000000000000000000007571324424505000232170ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<|IDATHՕM2CAO'L` D1mOU%0 F D( ܦˋ2r^{> KEI5II&,(R҉k2ܓw@-8W.0 ٘VPrY< 5 mgF[<|ĩˁHbfVc[t/<659ιwIYS%8fzPkk^ _O6O σm^A`DX7Z@>5]TPa;@ᷢrarZq3fR~'*٘5y8j1@WZtdkH{2 QIs~2$]H:t{˼7YI/?IENDB`flameshot-0.5.1/img/buttonIconsWhite/circle-outline.svg000066400000000000000000000032121324424505000232170ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/close.png000066400000000000000000000003661324424505000214020ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH1  )|X1!* Ų{w T?  \ X`1lp;ϵ9嬓cb;j>g/)$J%hȢTª0$"Dz3   IENDB`flameshot-0.5.1/img/buttonIconsWhite/close.svg000066400000000000000000000030661324424505000214150ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/cloud-upload.png000066400000000000000000000005431324424505000226620ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH1JA'/! " Z^B;XB -Y!] X$ =X)x+_xS;P4"I|5JBguY-њƓvBvW+B^pN] '~!$U(&~ T} ڜKIgl$s -Jrd{Ild" ˾^k JD{m,h'$O*IENDB`flameshot-0.5.1/img/buttonIconsWhite/cloud-upload.svg000066400000000000000000000032221324424505000226720ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/content-copy.png000066400000000000000000000003631324424505000227140ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH 0 q RqCIEB4"w䨮&"M1U[QnAa&t{7#* |&yLro vDea`˙) 69FnL7y IENDB`flameshot-0.5.1/img/buttonIconsWhite/content-copy.svg000066400000000000000000000031341324424505000227260ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/content-save.png000066400000000000000000000004471324424505000227030ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH10 ECTꁸ+7YgzYR7A2IJK @?7 V4KLǍsk >$%YO[A zo?@M+xmWzUrRrQr:"-V+SуdOM+-#>ٜ("ݴGtizly}v:dIENDB`flameshot-0.5.1/img/buttonIconsWhite/content-save.svg000066400000000000000000000032161324424505000227130ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/cursor-move.png000066400000000000000000000004151324424505000225510ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH͕10 * ;@W+ԧ. ß2X!0As$;3cTݔc-3wԺ;oę<mؐD[juB̐EO*^(4!u[Mw|3<-O"5 :s7@[_IENDB`flameshot-0.5.1/img/buttonIconsWhite/cursor-move.svg000066400000000000000000000031551324424505000225700ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/exit-to-app.png000066400000000000000000000004521324424505000224400ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH풱 0Eψ m{d72#BELl),_5^-=]"shSY@ image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/format-text.png000066400000000000000000000004131324424505000225400ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH픽 0FRfhH&63 AGs26\!ʺs3$7W@{o8$@z-@2;i8&3KZ^NHZ]Hh>VA@;E;f cf97m7xIENDB`flameshot-0.5.1/img/buttonIconsWhite/format-text.svg000066400000000000000000000033511324424505000225570ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/line.png000066400000000000000000000003141324424505000212150ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<YIDATHӡ0D4A&`#@d[s)9P l*T'7> >'j@/|.pdHn7f?fe=IENDB`flameshot-0.5.1/img/buttonIconsWhite/line.svg000066400000000000000000000032271324424505000212360ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/marker.png000066400000000000000000000005261324424505000215540ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH1.DQP XRg"؂Rc@D4SZ`O1;3O~ɹ',O8BoxWfJZn&%]%xJiR >NN&VN0^.o/K^P2V2|RIolc !< xIF~^˧uu>[~؂O7>F?#D9NIENDB`flameshot-0.5.1/img/buttonIconsWhite/marker.svg000066400000000000000000000033471324424505000215730ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/mouse-off.svg000066400000000000000000000033561324424505000222120ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/mouse.svg000066400000000000000000000031121324424505000214300ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/open_with.png000066400000000000000000000004441324424505000222660ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATH10 EuaĕXP7X1 "AIZ)C?Nl+ 0S\cMs񞋙ހF٪{B0 JwPdL %h_d}6'M {fM:h5E]MNG'$v Jc@IENDB`flameshot-0.5.1/img/buttonIconsWhite/open_with.svg000066400000000000000000000055151324424505000223050ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/pencil.png000066400000000000000000000004171324424505000215440ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH퓱 04l` X 6H!2R!t4FXP#_e/[*`e-w@LJ4\?_BHyoZFwNR#i~HM }ˋ>A`Gw3y$`+Ϥx8^`QIENDB`flameshot-0.5.1/img/buttonIconsWhite/pencil.svg000066400000000000000000000031351324424505000215570ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/size_indicator.png000066400000000000000000000004241324424505000232760ustar00rootroot00000000000000PNG  IHDR``HIDATx10na @Y 8 ]wĶnľV>U^jjT}n[WS! BBom̟};bfeɐl4 Ӏ֞@@@@@p\ T4U4tzɭ>&u*}RT_ }85˞}'&iIENDB`flameshot-0.5.1/img/buttonIconsWhite/size_indicator.svg000066400000000000000000000033751324424505000233210ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/square-outline.png000066400000000000000000000002701324424505000232440ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<EIDATHc`#2b(##\&jr)[Z0j):` H $&`{IENDB`flameshot-0.5.1/img/buttonIconsWhite/square-outline.svg000066400000000000000000000027571324424505000232730ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/square.png000066400000000000000000000002451324424505000215710ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<2IDATHc`#2b(##\&jZ0jZ0j( Fe$w*IENDB`flameshot-0.5.1/img/buttonIconsWhite/square.svg000066400000000000000000000030461324424505000216060ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/buttonIconsWhite/undo-variant.png000066400000000000000000000004601324424505000226770ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH 0CT)U*ݡ8+B^M=/!\fxCf_ wpf[{Ջz 4Nj`[$ `AvH<7@\tPڵ^$ZsZLb2!7*6%p6t('IENDB`flameshot-0.5.1/img/buttonIconsWhite/undo-variant.svg000066400000000000000000000032071324424505000227140ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/configBlack/000077500000000000000000000000001324424505000164545ustar00rootroot00000000000000flameshot-0.5.1/img/configBlack/config.png000066400000000000000000000005501324424505000204270ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH=JCAb\ &.&on@k[ ܁ "A , 2yɄyx`8Ü3:8.V0-q \QNJKkR_a wI~yսx"g.RWk{SKp^)oTN"`TEېe j'>C>>sBb a7!&Oc@8:=<\T}o@yIENDB`flameshot-0.5.1/img/configBlack/config.svg000077500000000000000000000005221324424505000204440ustar00rootroot00000000000000 flameshot-0.5.1/img/configBlack/graphics.png000066400000000000000000000003761324424505000207700ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATHK @.)!,tOPূaxMm&pO]?58|Ŭq~'s08+ID瑨Xr TTrJ$sߢɋ.a\j%_y_2'N,W%NIENDB`flameshot-0.5.1/img/configBlack/graphics.svg000077500000000000000000000006001324424505000207740ustar00rootroot00000000000000 flameshot-0.5.1/img/configBlack/name_edition.png000066400000000000000000000002371324424505000216170ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<,IDATHc``0bOM3(4lJ^ 0` AisIENDB`flameshot-0.5.1/img/configBlack/name_edition.svg000066400000000000000000000001751324424505000216330ustar00rootroot00000000000000flameshot-0.5.1/img/configWhite/000077500000000000000000000000001324424505000165205ustar00rootroot00000000000000flameshot-0.5.1/img/configWhite/config.png000066400000000000000000000005511324424505000204740ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH?jQ?˞%P$*fZZx !7Xj[&8{Ó NIUIkI3Ic<pIk лX`I|/|+`t2OBq8ks.J*I~3Ot:5:x@y/*6:I 8.7Ā@l qG'ޮ- Ae}7!Og\ؐlIENDB`flameshot-0.5.1/img/configWhite/config.svg000066400000000000000000000034251324424505000205120ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/configWhite/graphics.png000066400000000000000000000004151324424505000210260ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATHTA =?Zob$q^L0Ie%`:3r Ie^³xDGՐd.%>A/'h!-A(4BzZSu罃[}7uG`>P;؏$_'냺>;IENDB`flameshot-0.5.1/img/configWhite/graphics.svg000066400000000000000000000035321324424505000210440ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/configWhite/name_edition.png000066400000000000000000000002471324424505000216640ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<4IDATHc``0 ?E22Da#a (ԒIENDB`flameshot-0.5.1/img/configWhite/name_edition.svg000066400000000000000000000030561324424505000217000ustar00rootroot00000000000000 image/svg+xml flameshot-0.5.1/img/flameshot.ico000066400000000000000000003557331324424505000167500ustar00rootroot00000000000000  + (+,@@ (BS400 %{v(( h#   3  hsPNG  IHDR\rf+\IDATxy|Td'BX=Ȧ{Vm__oH\2\mo[[˭k( &%$@ɜH ̜9gs<׋3<,EAbkga @ t:Y2T n$46S4~ nop 8PP{D~$m8*WP@7NS6`{)(lxI@Q/C(}$0PEk h(5qI$@0sXN&دK|eY1vHcJX\\hM,k4,핢/:2 Q&R,R"<;E r:D k(S %X,,bb4RBihi0 'ZX CvH @W_|%>[-HY]ADSς6;D#D|x࢞K b|c>T:l piNHBxB~,cu<^I Jn`.L1b4-0)\6.Z$*s\!i:>KdwG]y[D $Sx+09w:[_@&Zh7NyxZ$1e%b<"5%, !рAU}ň ~O򚻖 d#'G,bbI\|c4x #i [ BbE\/ qn 1 𛇸JqRzh2Bı1^Jt3O}>*Zb`H: YL Z8hhPC %mfSNr r/+SDk875g1\#p(7TE ذ]N.@v~I'^|w-<Ϋ *Ek5paC[|LE"ЦڱP _O$7³UH@ q/AxYxI:jTBǠ,B:HO Ћ'  Ov*4+-$ŋWoEHt{TPXrO>CI]d&dXn{Fru<#=p-gv@ c:$IJ{F2Ə92O(A:$Ѣ0r"/߸e⛡=,Z>Ăh[iwqT;Ąj+R7"EGri|*Z߭E5^|cDKrR/ZUQPBˢu(IkrLoz)%Jea\Q.1gsh9V#h̡P^A:CgV:My517~b}^IlHJ"5v-LRQ(;b})gF,X'(7ˋĞ>-N<7,V's.szX.C rw.u4bA*hY8`6D]*)tw5}f3NJ N[SCV=) fT7844oq;V?#=(3u4PI8y'r3i5o~_!o}]qrh7Rx1^I4 ofoEOp/}ArbJjJ%6#XWbI0'GFJLJŠ>IN k氏Ȩd՘!`.n$pŌg8`̰:ӎΙ0v(-b`1 fM^IK;όߡKm۝ @ Emw#V 9dϯ|YkE4U 0nī@ sQ4 uFqޜʐgv)coi-C^]uPvԙ~6b0*̾R־c6_t8ʧ9;'348>[i@ËnҵcMj6q'2/}4F,)vGD_i,O}2@!^opk?&phɺ8END_)(h(͊~Y˂_32qrvG?%RLQ_<_d=_e]b}V&ሎ6l3'-;" |Lo|vh̘q$I7ň _2`V}/M@raup`rӍrNa%L==#{O } #KGYW8:F"2?q#:ַ'>EF~>=>7MUiEhUq4f4ѰpyaLhۭ뻙]|}4Dѹv&}ޔ;dB=s.%|Z7'l6<(ʬLV$Uػ_Gu7 HN:MW>K5g©Uͤ6;!3v!6%<Å]kkV^h'L/3Y09H!#*j y) ;`$SYԳ4{oX=ѳW#Iq;ґS\M$ Eydže -Qk'Z9ϓn@2W$|&pߔ)^|P#S}")Nw֘}9PԨ'\\uf9M8-/in#6Y~F:!ZztY 7JRwj)mGPZ @>-@FZCVPo u@[S+զ۾5F^+~ݣ$&Tz02hҩ;aZ3V \J#E*Iim^k3 7^dZ"Ţ+|Uv3Xl1^J[ժ$P0qm`UN26ng ,EG6OBMn- SSOL630)ז0fxgf)p|s#_sq+1-bQUeflg'v#֟7R`>I,RC/{`*m%wqџ2Fb~(i&VgEr*v\^t57J0_~ CY1<0'RNSWy`a]>Fb?@a ҋzhEgp'ZÈE 0pG3C gN^{ \Qhb-Z1=3,I<[#0kZwGA 8jͶd1oUYZiYwb9]F>r~g$$[@ ?4!~bR[(o}&4.88B_pcϧ?4n/ E ɵ\7oHl6N:>5ll>/?n\S"1wH9!ZFsrmv}#bP]h\/J$g!ZƅrDE2Q9 0INVYfʳE9WFg j$=# qΡI{3rI?}I_4 iqu)T-82d+Xq2q{wgG%P+~\L}Eb8bOmΘ,XAZN![D:M(ouh(lh]*D MRz es4@h8H37@u){3/[%/2B' CESAW΅~b2U']Efu rU WQ̚$)`oL*Ih`eu+|EΞIOF:`=?Dˈ z'G^ѷ#,g8244q_k>F%JKV\SߣMeDrfs t{n[A (jfg/8{V1~\NŕP]$! `c!Qjl#u>KL[e_ୢehQRwk)* 2m΅ۙEehQa/N9k$8+ƬEӪQ6v'Z@%WCEtkҢppDžodw?$Z~*r"Pc-4?.DȐ)KDAE&|=D ]l3!8+ȴ9=pՃψ=D 'B=kq||c +)Ξ[~M9}7m9DhfWqNY3.B:%ZFl-@'8*t 9,^%b(rbw-#z_iː_A* 2=候3 };*z8y)U36cעeDO5A|1g@)lhJ1fg.UZ:-ZET|B (eĊ Ur^-#zE+o&ٶq?Ond >ZCv`%b6c  *䕢%Dz6^ -$jHwj()ٕ,j"ğK'J a }<{K(u|=muBGv977 q9K6JEhM/š??*K'Z n`hFoe I ^7h{qgvMS>-"E}l'HSz! u&)b% 73KfǪ <=~+jw)pZb&*T%.ZM$YL)_XlO 5M[f /,uۀaŝTTO `JF}BЍw (t*If)}D$$׊a$\[6tW2ڳ?e4 6yF3#脗-$G + ;1[SUyG #9@A9g@D0Ė+> nj@}b)/ 0IuSo(.F4*[Rb)wp5eq(N:^`jl%d'l:Xzz`O ϷW]x\_wry/=;`hez9u$U1 VQrx^k뜟?Rf9k4ՊݽY0KթzTqI9d=y,hDYu毳@E\ Tmyl P~M V]=:a xB?LAu6J엉,GwZlw&3-3+[ț ^a&< Oȶ z!F}=D[`'M_4W?[[R{*c;-2 ؈9:WCeot-bYFGvu?:ߤ i*LhPXFVG=(Q7}T}K TY ީvƍH[1\v\̴Mhɉ}lkPb?|X2j^E9@&o2 .C p=Gw'3ɜj Z[ z"d珌 #>ԂDjabvn) 4d@ʈԺQ#Fl]&8=O_@5 ̞O:%#T*HiߞdしC}m8nm@$uW§I&dPF; Re {uABv쇸߻D[YBFx x`<Ũ~29@&#9o3p5>M @bZ.7֔SO]m}C6d?Y$C;u@~܇ fl/^;D#P8L:;NsL@+Miӽ=^ \ŴlRWMy] دgY:)K!k$MvxANH4c?Du( ù*vnF6ҙ]ȕAC΁aBlP/͋^'‡W@a;#&CFG7f1=ZT,IY峿k>A1(ܘOv]O9)|EW6Id94]dž(Ƴ ٖϖ/p :e [ˌd>Kgm1Ӗ{pߊhТNq O4TwnНUl#iJJcݣ[ 'pE>PM"ћ(]ٮ(/Ddfs'*a unfe*2E;Dҗ0O%c%2#x< |OgxMg/у[k#Ǖ+dQc|l;PGrLg4oSi#^oz<xDUGPE~ra_dkqx{¸ -lVz#w.f-M$|Rƨ2Fϴ\ɴM`Ӫ㙤f6Wh n%ACUC9-Ѐ'Q-G2V3yw#>z6Ni#aG ڮ!j(OfrO_b,Ym#Čń$4uSX{Bj]^RYSb8 J bf2 0[-aϻS%4I(v#$D_1-bX5 vW C]U+M <(ü\fU5ɨ 3ȳ[CXZ<'==.8H*H})gR}.y|ͣ, y^$HֺbGS O%f`?5WIU':Xuu5 ,d32X`(Z<{;w4{ϕ?{l68Fh{P(LI[g96 -k ϾV\vH%Z+ ;څa`id۳BsijӂG{_ҕ"Z٬Ua7<-uI0֖T{}صD&I(q6U}g&5L <`9fn0oC7'I /f7f15l|x{8Wg?T|Cb6'1f@-Qs27g*fђ$f hD_/1) +kZO(+Hz%frZ[~"'Y"<_|fpK8];ɴ5"xVQ.^Ex^`:?8dp JDN $Rzq8|(Z$`-(w3mh!F)³Ņ{0oP\#a _C[#Bđ#bG H,q qz84 F"$a/D 4φRƁ3Be8 ̨!FM! ,ZTCň n .&S0AILEcu% ,IA+#1o `cz" @JxåQs'(H e?(/ZU5Hb?0W%0&Uc5}#ݠQ%Zb4a0+nD둄d-d Pm|5x Ws7?1CEF)̡~DSjhg1}h1vD(K ~wSњxC";@)m4`<P_.fab_`,^aHl-Ɖe 𲰧2Ek+$њ,J=xC7g%Zӑ ×U=f`1X%3-(@0^2`@R!^l6+4%_xF1_LX2  `e Ipn hp~ o!sy%%@C 5F-,7lpn);̣45讠i靀@6EH)@*A_Hll`z贈@%p((OA3 @v~7ׇIENDB`( vv!Lpª֪֪ªoL%ZŪȪZIڪڪKMO'*IJUЪҪVKϪҪL,. GߪH 0֪ת0^_ ЪѪ۪ܫ && ܪܪ ЪѪ^lE^0(X0/ תUf34֩ -#DmHYfuH ߪLpf] fyߩ )f>)ffy.!fLffft.`XfeY ffflM ff/7ffffgLҪEyff`_fffffqѪV"fff06fffffff}UѪ4fffbY fffffffhѱJ+ifffHfffffffffg|I2ffffA%fffffffffffq)&ffff`Xffffffffffffgx(?fffffSafffffffffffffffr{fffff FefffffffffffffffffgsOZ`ffffff*SfffffffffffffffffffffffffffftLqgfffffffffffffffffMF fffffffffffffffffffffffffffofffffffffffffffffffRMfffffffffffffffffffffffffh2ffffffffffffffffffff)=bffffffffffffffffffffffff{êZ`uffffffffffffffffffffTY ffffffffffffffffffffffffªתgffffffffffffffffffff \Uffffffffffffffffffffffft֪,fffffffffffffffffffff ]Yfffffffffffffffffffffff/gfffffffffffffffffffffUafffffffffffffffffffffftEzffffffffffffffffffffff&@ffffffffffffffffffffffffffffffffffffffffffffffIffffffffffffffffffffffz#jffffffffffffffffffffffWdfffffffffffffffffffffgcVfffffffffffffffffffffff>(ffffffffffffffffffffff/fffffffffffffffffffffffVffffffffffffffffffffffm ffffffffffffffffffffffffLffffffffffffffffffffffתgPffffffffffffffffffffffff'?ffffffffffffffffffffff~֪ê+ffffffffffffffffffffffff_efffffffffffffffffffffjª!fffffffffffffffffffffffffPffffffffffffffffffffffOnfffffffffffffffffffffffff70ffffffffffffffffffffffq fffffffffffffffffffffffff!EffffffffffffffffffffffloMeRfffffffffffffffffffffffffVfffffffffffffffffffffffL%fffffffffffffffffffffffffecffffffffffffffffffffff$oGffffffffffffffffffffffffffz ygffffffffffffffffffffwȪffffffffffffffffffffffffffwffffffffffffffffffhkLffffffffffffffffffffffffffs!mffffffffffffffff[f9!Rfffffffffffffffffffffffffj&uffffffffffffffZYbc+ `fffffffffffffffffffffffc+wffffffffffffz۪8 3Hffffffffffffffffffffffa,tffffffffffk9hOi'affffffffffffffffffff`-lfffffffffKz:Sfffffffffffffffffffd*ffffffffJ+;Cffffffffffffffffffj'lffffffEyfRV2fffffffffffffffffs!ufffff{O{8 i'efffffffffffffff~ffffpN@p#dfffffffffffffffffg1*n$effffffffffffffff)\](a,ffffffffffffb}ff(/v>H;fffffffffffUrfJ(Nffffffffff3GgJҪtA ^fffffffffM8yѪV7#o#fffffffffi'vVҪNn23HffffffffѭM`Y7 cffffffeLoGK9ffffffT/z:Ve bfffffC>.4F<fffffh( 31fffff J{8It$Qfff\HpF].fffrChff/7fffffffffffnx=5fff,:efffffffffffffffvܪhfffI_ffffffffffffffffz/ffff [IffffffffffffffffnWeRwfffff"DY fffffffffffffffmVUfjfffffd)=XffffffffffffffsUffffffffeGKfffffffffffffΪgPfffffffffNVfffffffffffgΪ }fffffffffaGfffffffffffv,ffffffffffdLfffffffffff ffffffffff ]_ffffffffffxhOfffffffffff,:fffffffffff4fffffffffffb_ffffffffff ffffffffffff>(ffffffffffmϪcUffffffffffff"EfffffffffffΪffffffffffff Zfffffffffffv>fffffffffffffoffffffffffsW!fffffffffffffpfffffffgVoGGqK9dfffffffffffwffffffܪ}6UffffffffffrffffLq ?@fffffffffgffz>,C{Z0fffffffflfn=ު*c+fffffffmfިy8(U3fffff aix[_z:3Gffff Sv>) ^fffVΪΪW????(0` $vv]ݪݪ^t̪̪t }~ .ϪЪ.UUppppUU.n4. Ъ43@Ъ ~mIUl} kSiOmt!Effu eF fffstVef_Ufffffst̪rf ZVffffffffglu̪*ff ]Kfffffffffffg^^[{ffe.8afffffffffffs]Eyjfff Z?'cfffffffffft?fffff Y60^fffffffffުRjffffff`;+effffffffݪ.wfffffff,:efffffffv8ffffffff>(ffffffffifffffff^_fffffff|{8vffffffff<*fffffffhު=}ffffffffIffffffffު{ffffffff_ffffffff{Nnqfffffffffyhfffffj^D?effffffffjffff]<:Xfffffffgffͪy;pE0Iffffff of̪t 8Dfffffrvt/Si,Lfff `sOm  ]ff"QdTZ`h'ffA?oGXfe*~ ЪoG/W2fЪ . Z.UI:UppppUV.ЪЪ. ~~ t̪ͪu^ުު^??????((P vv;}תת};""^^ ^.~^dTH  Ff"HueOfm"qV`ffi}YbfKbffffflv; kfO[ fffffffffr;} ff^A%effffffffg}$fffOHefffffffhת sffffV?'effffffnתhfffff Fcffffff^[ffffff)=ffffffj/ffffffeQffffff fffffff)=fffffftת]]fffffffXfffffffתfffffffewifffff}aX%Yfffffff pfff~}< mIE<efffffkfp;:h'dffff tgkLA~m$effet"  Q5ffY"C{Vf3Gl%fW2_v>a^7E{  ^_"";}תת~<??( @ vv[̪ͪ['' &ժժ&23&& ժ^Cժ [_v'Ry'B}Mehf.8fffl|[cVf+;dffffffj[:jfQRfffffffxͪ+ffe!EMffffffͪ>ffffI^fffff.lffffPdffffwRjfffff=)ffffffffffNfffffͪy:fffffchffffqͪ$$pffffff vfff[kL|\ffff of[ 2 Wfffx%}6 ^f `'@,m$f&O'Nn!VJ: ժS4u ժ &x&33&ժժ& '([ͪͪ[??(0 vv#zz#!"]^ww]]"RhT%"Nq#>B$fs#z cD"ffffk|z~5f'?[ ffffiy:rfc'?[ fffm fff [\ fffv?kfff)=fffl7qfff ]ffff!_ffff~gfz-+9Dfffvwz#bWkKB>fe#0TW"#|8p#=B"^l%^wx]^""#zz#(( @vv]^ YYYO` Y"61^>qQgv^ `C#ffffvfNF fffuoff+;fff+fffRffsFyfff;0gffRM[ffK9g^) UfQ6^ No`Ybg(Yw=F<YYY^^ p00p(  vv2ڪڪ2 ªª ]G2%R2@ bWgtڪa60`ffڪ1f_PffffQff|ڪRj ffejiڪ_Zs!bf}2$ n$ _2*K9 ª ª 2ڪڪ2flameshot-0.5.1/img/flameshot.png000066400000000000000000000101601324424505000167400ustar00rootroot00000000000000PNG  IHDRddpTsBIT|d pHYsgRtEXtSoftwarewww.inkscape.org<IDATxytTU?UU HVeo1`:-zd`Ctt93GZ q}>digX3L 8a"Bz7 +f9q{ލ6{iAb-v3q yF2ҎpZ1*տ6ؔ '?Cacf2}z|ik^?/d\3) eM [v𪪲2#2c!KP:+@e%kŵ+nn]c4}?m++[1ADd)kT Bp5pϯ^Ds܃;r.2'H"J(_A Y,H}N0SnM>ՖX;4WY"߈K}x- i*'k=}TQv ;<)HŃ[ZUqw>:fGIS3X]FW&whw܆6_RJz0fVARwx4I&]trՐ6nt Yݧ6DM$6²S~Y0]rb|å7DWBh^<&k[=!t% [ %ZK@Rr JƓ<X,izI?a7}N`M2u+ Tj>hc/Q 1/A$rBBjIHFgҒdJrF l:Ą z`]17 !D0 =. v {;WC4{&QC͊g~N2WN2h>V;\sc7rA% ɟ 4=`*>=˰쿆&k)c;I[2Kw-,1ÂŐPcLͱg$TZ  宂qZlU5q8[q1D;4UjNO͙ (\mbaTʲH CA|RԠR]iEW{Jͣr))VY]*ai!\>hBW4Ep+{DJ' o* `  6}hMaW:'d*o̰~& N8_ܬhb?JVȃN U9+' ~ W8TLlS\ׄJY Tn8OI xaJr;sAQfF-Ϗ`T%}xm>9Z(^~Y✅oExQE,69!aȻ-BA(>a\,6k|Fo>ºW8އPRX2T %!s ['ߋ_ڞWKb 4 R*G?9 ySo2-qb ;"y'* >|: ?N7eAhV[8mߢ8$yE耱e̷jé#:=py(e$5|M7"3'㣚 Wh`Y(z/37N|-s|p~˕rbDug^]ǽ{IGXOA;(" {zloTVG~0F /o]PK}ƐenW/pIhh"0P5b;"4]9N)UgPvgq9&U P`#LiϬV/8p0tE)[f*uhv~l|E.q젓!Wf> image/svg+xmlflameshot-0.5.1/img/flameshotLogoLicense.txt000066400000000000000000000232431324424505000211250ustar00rootroot00000000000000Free Art License 1.3 [ Copyleft Attitude ] Free Art License 1.3 (FAL 1.3) Preamble The Free Art License grants the right to freely copy, distribute, and transform creative works without infringing the author's rights. The Free Art License recognizes and protects these rights. Their implementation has been reformulated in order to allow everyone to use creations of the human mind in a creative manner, regardless of their types and ways of expression. While the public's access to creations of the human mind usually is restricted by the implementation of copyright law, it is favoured by the Free Art License. This license intends to allow the use of a work’s resources; to establish new conditions for creating in order to increase creation opportunities. The Free Art License grants the right to use a work, and acknowledges the right holder’s and the user’s rights and responsibility. The invention and development of digital technologies, Internet and Free Software have changed creation methods: creations of the human mind can obviously be distributed, exchanged, and transformed. They allow to produce common works to which everyone can contribute to the benefit of all. The main rationale for this Free Art License is to promote and protect these creations of the human mind according to the principles of copyleft: freedom to use, copy, distribute, transform, and prohibition of exclusive appropriation. Definitions “work” either means the initial work, the subsequent works or the common work as defined hereafter: “common work” means a work composed of the initial work and all subsequent contributions to it (originals and copies). The initial author is the one who, by choosing this license, defines the conditions under which contributions are made. “Initial work” means the work created by the initiator of the common work (as defined above), the copies of which can be modified by whoever wants to “Subsequent works” means the contributions made by authors who participate in the evolution of the common work by exercising the rights to reproduce, distribute, and modify that are granted by the license. “Originals” (sources or resources of the work) means all copies of either the initial work or any subsequent work mentioning a date and used by their author(s) as references for any subsequent updates, interpretations, copies or reproductions. “Copy” means any reproduction of an original as defined by this license. 1. OBJECT The aim of this license is to define the conditions under which one can use this work freely. 2. SCOPE This work is subject to copyright law. Through this license its author specifies the extent to which you can copy, distribute, and modify it. 2.1 FREEDOM TO COPY (OR TO MAKE REPRODUCTIONS) You have the right to copy this work for yourself, your friends or any other person, whatever the technique used. 2.2 FREEDOM TO DISTRIBUTE, TO PERFORM IN PUBLIC You have the right to distribute copies of this work; whether modified or not, whatever the medium and the place, with or without any charge, provided that you: attach this license without any modification to the copies of this work or indicate precisely where the license can be found, specify to the recipient the names of the author(s) of the originals, including yours if you have modified the work, specify to the recipient where to access the originals (either initial or subsequent). The authors of the originals may, if they wish to, give you the right to distribute the originals under the same conditions as the copies. 2.3 FREEDOM TO MODIFY You have the right to modify copies of the originals (whether initial or subsequent) provided you comply with the following conditions: all conditions in article 2.2 above, if you distribute modified copies; indicate that the work has been modified and, if it is possible, what kind of modifications have been made; distribute the subsequent work under the same license or any compatible license. The author(s) of the original work may give you the right to modify it under the same conditions as the copies. 3. RELATED RIGHTS Activities giving rise to author’s rights and related rights shall not challenge the rights granted by this license. For example, this is the reason why performances must be subject to the same license or a compatible license. Similarly, integrating the work in a database, a compilation or an anthology shall not prevent anyone from using the work under the same conditions as those defined in this license. 4. INCORPORATION OF THE WORK Incorporating this work into a larger work that is not subject to the Free Art License shall not challenge the rights granted by this license. If the work can no longer be accessed apart from the larger work in which it is incorporated, then incorporation shall only be allowed under the condition that the larger work is subject either to the Free Art License or a compatible license. 5. COMPATIBILITY A license is compatible with the Free Art License provided: it gives the right to copy, distribute, and modify copies of the work including for commercial purposes and without any other restrictions than those required by the respect of the other compatibility criteria; it ensures proper attribution of the work to its authors and access to previous versions of the work when possible; it recognizes the Free Art License as compatible (reciprocity); it requires that changes made to the work be subject to the same license or to a license which also meets these compatibility criteria. 6. YOUR INTELLECTUAL RIGHTS This license does not aim at denying your author's rights in your contribution or any related right. By choosing to contribute to the development of this common work, you only agree to grant others the same rights with regard to your contribution as those you were granted by this license. Conferring these rights does not mean you have to give up your intellectual rights. 7. YOUR RESPONSIBILITIES The freedom to use the work as defined by the Free Art License (right to copy, distribute, modify) implies that everyone is responsible for their own actions. 8. DURATION OF THE LICENSE This license takes effect as of your acceptance of its terms. The act of copying, distributing, or modifying the work constitutes a tacit agreement. This license will remain in effect for as long as the copyright which is attached to the work. If you do not respect the terms of this license, you automatically lose the rights that it confers. If the legal status or legislation to which you are subject makes it impossible for you to respect the terms of this license, you may not make use of the rights which it confers. 9. VARIOUS VERSIONS OF THE LICENSE This license may undergo periodic modifications to incorporate improvements by its authors (instigators of the “Copyleft Attitude” movement) by way of new, numbered versions. You will always have the choice of accepting the terms contained in the version under which the copy of the work was distributed to you, or alternatively, to use the provisions of one of the subsequent versions. 10. SUB-LICENSING Sub-licenses are not authorized by this license. Any person wishing to make use of the rights that it confers will be directly bound to the authors of the common work. 11. LEGAL FRAMEWORK This license is written with respect to both French law and the Berne Convention for the Protection of Literary and Artistic Works. USER GUIDE - How to use the Free Art License? To benefit from the Free Art License, you only need to mention the following elements on your work: [Name of the author, title, date of the work. When applicable, names of authors of the common work and, if possible, where to find the originals]. Copyleft: This is a free work, you can copy, distribute, and modify it under the terms of the Free Art License http://artlibre.org/licence/lal/en/ - Why to use the Free Art License? 1.To give the greatest number of people access to your work. 2.To allow it to be distributed freely. 3.To allow it to evolve by allowing its copy, distribution, and transformation by others. 4.So that you benefit from the resources of a work when it is under the Free Art License: to be able to copy, distribute or transform it freely. 5.But also, because the Free Art License offers a legal framework to disallow any misappropriation. It is forbidden to take hold of your work and bypass the creative process for one's exclusive possession. - When to use the Free Art License? Any time you want to benefit and make others benefit from the right to copy, distribute and transform creative works without any exclusive appropriation, you should use the Free Art License. You can for example use it for scientific, artistic or educational projects. - What kinds of works can be subject to the Free Art License? The Free Art License can be applied to digital as well as physical works. You can choose to apply the Free Art License on any text, picture, sound, gesture, or whatever sort of stuff on which you have sufficient author's rights. - Historical background of this license: It is the result of observing, using and creating digital technologies, free software, the Internet and art. It arose from the “Copyleft Attitude” meetings which took place in Paris in 2000. For the first time, these meetings brought together members of the Free Software community, artists, and members of the art world. The goal was to adapt the principles of Copyleft and free software to all sorts of creations. http://www.artlibre.org Copyleft Attitude, 2007. You can make reproductions and distribute this license verbatim (without any changes). Translation : Jonathan Clarke, Benjamin Jean, Griselda Jung, Fanny Mourguet, Antoine Pitrou. Thanks to framalang.org flameshot-0.5.1/rpm/000077500000000000000000000000001324424505000142745ustar00rootroot00000000000000flameshot-0.5.1/rpm/flameshot.spec000066400000000000000000000043431324424505000171360ustar00rootroot00000000000000Name: flameshot Version: 0.5.0 Release: 1%{?dist} Summary: Powerful yet simple to use screenshot software Summary(eu-ES): Potente pero simple de usar software de capturas %global sourcename flameshot Group: Application License: GPLv3 URL: https://github.com/lupoDharkael/%{sourcename} Source0: https://github.com/lupoDharkael/%{sourcename}/archive/v%{version}.tar.gz #%%define _binaries_in_noarch_packages_terminate_build 0 #BuildArch: noarch BuildRequires: gcc-c++ >= 4.9.2 BuildRequires: pkgconfig(Qt5Core) >= 5.3.0 BuildRequires: pkgconfig(Qt5Gui) >= 5.3.0 BuildRequires: pkgconfig(Qt5Widgets) >= 5.3.0 BuildRequires: qt5-qttools-devel BuildRequires: qt5-linguist BuildRequires: git Requires: qt5-qtbase >= 5.3.0 Requires: qt5-qttools %description Flameshot is a screenshot software, it's powerful yet simple to use for GNU/Linux %prep %setup -q -n v%{version} %build #%%qmake_qt5 PREFIX=%{_prefix} %qmake_qt5 CONFIG+=packaging CONFIG-=debug CONFIG+=release make %{?_smp_mflags} %install %make_install INSTALL_ROOT=%{buildroot} %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %doc README.md %license LICENSE %{_bindir}/%{name} %{_datadir}/dbus-1/interfaces/org.dharkael.Flameshot.xml %{_datadir}/metainfo/flameshot.appdata.xml %{_datadir}/dbus-1/services/org.dharkael.Flameshot.service %{_datadir}/flameshot/translations/Internationalization_*.qm %{_datadir}/applications/%{name}.desktop %{_datadir}/applications/%{name}-init.desktop %{_datadir}/applications/%{name}-config.desktop %{_datadir}/bash-completion/completions/%{name} %{_datadir}/icons/%{name}.png #%%{_datadir}/icons/hicolor/scalable/apps/%{name}.svg #%%{_datadir}/icons/flameshot/apps/scalable/%{name}.svg %changelog * Tue Jan 09 2018 Zetao Yang - 0.5.0-1 - Updated for flameshot 0.5.0 - Catalan translation. - Debian package configuration. - Add --raw flag: prints the raw bytes of the png after the capture. - Bash completion. - Blur tool. - Preview draw size on mouse pointer after tool selection. - App Launcher tool: choose an app to open the capture. - Travis integration - Configuration import, export and reset. - Experimental Wayland support (Plasma & Gnome) * Tue Jan 09 2018 Zetao Yang - 0.5.0-1 - Initial packageflameshot-0.5.1/src/000077500000000000000000000000001324424505000142655ustar00rootroot00000000000000flameshot-0.5.1/src/capture/000077500000000000000000000000001324424505000157305ustar00rootroot00000000000000flameshot-0.5.1/src/capture/capturemodification.cpp000066400000000000000000000040441324424505000224670ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . //#include "src/capture/tools/capturetool.h" #include "capturemodification.h" #include "src/capture/tools/toolfactory.h" #include "src/capture/tools/capturetool.h" #include // CaptureModification is a single modification in the screenshot drawn // by the user. CaptureModification::CaptureModification( const CaptureButton::ButtonType t, const QPoint &p, const QColor &c, const int thickness, QObject *parent) : QObject(parent), m_color(c), m_type(t), m_thickness(thickness) { m_tool = ToolFactory().CreateTool(t, this); m_coords.append(p); if (m_tool->isSelectable()) { m_coords.append(p); } } CaptureButton::ButtonType CaptureModification::buttonType() const { return m_type; } QColor CaptureModification::color() const { return m_color; } QVector CaptureModification::points() const { return m_coords; } CaptureTool* CaptureModification::tool() const{ return m_tool; } int CaptureModification::thickness() const { return m_thickness; } // addPoint adds a point to the vector of points void CaptureModification::addPoint(const QPoint p) { if (m_tool->toolType() == CaptureTool::TYPE_LINE_DRAWER) { m_coords[1] = p; } else { m_coords.append(p); } } flameshot-0.5.1/src/capture/capturemodification.h000066400000000000000000000031321324424505000221310ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "src/capture/widgets/capturebutton.h" #include #include class CaptureButton; class QPoint; class CaptureModification : public QObject { Q_OBJECT public: CaptureModification(QObject *parent = nullptr) = delete; CaptureModification( const CaptureButton::ButtonType, const QPoint &initialPoint, const QColor &color, const int thickness, QObject *parent = nullptr ); QColor color() const; QVector points() const; CaptureTool* tool() const; int thickness() const; CaptureButton::ButtonType buttonType() const; void addPoint(const QPoint); protected: QColor m_color; CaptureButton::ButtonType m_type; QVector m_coords; CaptureTool *m_tool; int m_thickness; }; flameshot-0.5.1/src/capture/screenshot.cpp000066400000000000000000000070031324424505000206110ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "src/capture/screenshot.h" #include "src/capture/widgets/capturebutton.h" #include "capturemodification.h" #include "src/capture/tools/capturetool.h" #include "src/utils/filenamehandler.h" #include "src/utils/confighandler.h" #include #include #include #include #include #include #include #include // Screenshot is an extension of QPixmap which lets you manage specific tasks Screenshot::Screenshot(const QPixmap &p, QObject *parent) : QObject(parent), m_baseScreenshot(p), m_modifiedScreenshot(p) { } Screenshot::~Screenshot() { } void Screenshot::setScreenshot(const QPixmap &p) { m_baseScreenshot = p; m_modifiedScreenshot = p; } // getScreenshot returns the screenshot with no modifications QPixmap Screenshot::baseScreenshot() const { return m_baseScreenshot; } // getScreenshot returns the screenshot with all the modifications QPixmap Screenshot::screenshot() const { return m_modifiedScreenshot; } QPixmap Screenshot::croppedScreenshot(const QRect &selection) const { return m_modifiedScreenshot.copy(selection); } // paintModification adds a new modification to the screenshot QPixmap Screenshot::paintModification(const CaptureModification *modification) { QPainter painter(&m_modifiedScreenshot); painter.setRenderHint(QPainter::Antialiasing); paintInPainter(painter, modification); return m_modifiedScreenshot; } // paintTemporalModification paints a modification without updating the // member pixmap QPixmap Screenshot::paintTemporalModification( const CaptureModification *modification) { QPixmap tempPix(m_modifiedScreenshot); QPainter painter(&tempPix); if (modification->buttonType() != CaptureButton::TYPE_PENCIL) { painter.setRenderHint(QPainter::Antialiasing); } paintInPainter(painter, modification); return tempPix; } // paintBaseModifications overrides the modifications of the screenshot // with new ones. QPixmap Screenshot::overrideModifications( const QVector &m) { m_modifiedScreenshot = m_baseScreenshot; for (const CaptureModification *const modification: m) { paintModification(modification); } return m_modifiedScreenshot; } // paintInPainter is an aux method to prevent duplicated code, it draws the // passed modification to the painter. void Screenshot::paintInPainter(QPainter &painter, const CaptureModification *modification) { const QVector &points = modification->points(); QColor color = modification->color(); int thickness = modification->thickness(); modification->tool()->processImage(painter, points, color, thickness); } flameshot-0.5.1/src/capture/screenshot.h000066400000000000000000000030731324424505000202610ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include #include #include class QString; class CaptureModification; class QNetworkAccessManager; class Screenshot : public QObject { Q_OBJECT public: Screenshot(const QPixmap &, QObject *parent = nullptr); ~Screenshot(); void setScreenshot(const QPixmap &); QPixmap baseScreenshot() const; QPixmap screenshot() const; QPixmap croppedScreenshot(const QRect &selection) const; QPixmap paintModification(const CaptureModification*); QPixmap paintTemporalModification(const CaptureModification*); QPixmap overrideModifications(const QVector &); private: QPixmap m_baseScreenshot; QPixmap m_modifiedScreenshot; void paintInPainter(QPainter &, const CaptureModification *); }; flameshot-0.5.1/src/capture/tools/000077500000000000000000000000001324424505000170705ustar00rootroot00000000000000flameshot-0.5.1/src/capture/tools/applauncher.cpp000066400000000000000000000031441324424505000221000ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "applauncher.h" AppLauncher::AppLauncher(QObject *parent) : CaptureTool(parent) { } int AppLauncher::id() const { return 0; } bool AppLauncher::isSelectable() const { return false; } QString AppLauncher::iconName() const { return "open_with.png"; } QString AppLauncher::name() const { return tr("App Launcher"); } QString AppLauncher::description() const { return tr("Choose an app to open the capture"); } CaptureTool::ToolWorkType AppLauncher::toolType() const { return TYPE_WORKER; } void AppLauncher::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { Q_UNUSED(painter); Q_UNUSED(points); Q_UNUSED(color); Q_UNUSED(thickness); } void AppLauncher::onPressed() { Q_EMIT requestAction(REQ_OPEN_APP); } flameshot-0.5.1/src/capture/tools/applauncher.h000066400000000000000000000025401324424505000215440ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class AppLauncher : public CaptureTool { Q_OBJECT public: explicit AppLauncher(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/arrowtool.cpp000066400000000000000000000054121324424505000216260ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "arrowtool.h" #include namespace { const int ArrowWidth = 10; const int ArrowHeight = 18; QPainterPath getArrowHead(QPoint p1, QPoint p2, const int thickness) { QLineF body(p1, p2); int originalLength = body.length(); body.setLength(ArrowWidth + thickness*2); // move across the line up to the head QLineF temp(QPoint(0,0), p2-p1); temp.setLength(originalLength - ArrowHeight - thickness*2); QPointF bottonTranslation(temp.p2()); // generates the transformation to center of the arrowhead body.setAngle(body.angle()+90); QPointF temp2 = p1-body.p2(); QPointF centerTranslation((temp2.x()/2), (temp2.y()/2)); body.translate(bottonTranslation); body.translate(centerTranslation); QPainterPath path; path.moveTo(p2); path.lineTo(body.p1()); path.lineTo(body.p2()); path.lineTo(p2); return path; } // gets a shorter line to prevent overlap in the point of the arrow QLine getShorterLine(QPoint p1, QPoint p2, const int thickness) { QLineF l(p1, p2); l.setLength(l.length() - ArrowHeight - thickness*2); return l.toLine(); } } // unnamed namespace ArrowTool::ArrowTool(QObject *parent) : CaptureTool(parent) { } int ArrowTool::id() const { return 0; } bool ArrowTool::isSelectable() const { return true; } QString ArrowTool::iconName() const { return "arrow-bottom-left.png"; } QString ArrowTool::name() const { return tr("Arrow"); } QString ArrowTool::description() const { return tr("Sets the Arrow as the paint tool"); } CaptureTool::ToolWorkType ArrowTool::toolType() const { return TYPE_LINE_DRAWER; } void ArrowTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { painter.setPen(QPen(color, 2 + thickness)); painter.drawLine(getShorterLine(points[0], points[1], thickness)); painter.fillPath(getArrowHead(points[0], points[1], thickness), QBrush(color)); } void ArrowTool::onPressed() { } flameshot-0.5.1/src/capture/tools/arrowtool.h000066400000000000000000000025351324424505000212760ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class ArrowTool : public CaptureTool { Q_OBJECT public: explicit ArrowTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/blurtool.cpp000066400000000000000000000043301324424505000214360ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "blurtool.h" #include #include #include #include BlurTool::BlurTool(QObject *parent) : CaptureTool(parent) { } int BlurTool::id() const { return 0; } bool BlurTool::isSelectable() const { return true; } QString BlurTool::iconName() const { return "blur.png"; } QString BlurTool::name() const { return tr("Blur"); } QString BlurTool::description() const { return tr("Sets the Blur as the paint tool"); } CaptureTool::ToolWorkType BlurTool::toolType() const { return TYPE_LINE_DRAWER; } #include void BlurTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { Q_UNUSED(color); Q_UNUSED(thickness); QPoint p0 = points[0]; QPoint p1 = points[1]; QRect selection = QRect(p0, p1).normalized(); QPixmap *refPixmap = dynamic_cast(painter.device()); QGraphicsBlurEffect *blur = new QGraphicsBlurEffect; blur->setBlurRadius(10); QGraphicsPixmapItem *item = new QGraphicsPixmapItem ( refPixmap->copy(selection)); item->setGraphicsEffect(blur); QGraphicsScene scene; scene.addItem(item); scene.render(&painter, selection, QRectF()); blur->setBlurRadius(12); scene.render(&painter, selection, QRectF()); scene.render(&painter, selection, QRectF()); } void BlurTool::onPressed() { } flameshot-0.5.1/src/capture/tools/blurtool.h000066400000000000000000000026511324424505000211070ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class BlurTool : public CaptureTool { Q_OBJECT public: explicit BlurTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; private: bool needsAdjustment(const QPoint &p0, const QPoint &p1) const; }; flameshot-0.5.1/src/capture/tools/capturetool.cpp000066400000000000000000000015471324424505000221440ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "capturetool.h" CaptureTool::CaptureTool(QObject *parent) : QObject(parent) { } flameshot-0.5.1/src/capture/tools/capturetool.h000066400000000000000000000035641324424505000216120ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include class QPainter; class CaptureTool : public QObject { Q_OBJECT public: enum ToolWorkType { TYPE_WORKER, TYPE_PATH_DRAWER, TYPE_LINE_DRAWER }; enum Request { REQ_CLOSE_GUI, REQ_HIDE_GUI, REQ_HIDE_SELECTION, REQ_UNDO_MODIFICATION, REQ_CLEAR_MODIFICATIONS, REQ_SAVE_SCREENSHOT, REQ_SELECT_ALL, REQ_TO_CLIPBOARD, REQ_UPLOAD_TO_IMGUR, REQ_MOVE_MODE, REQ_OPEN_APP, }; explicit CaptureTool(QObject *parent = nullptr); virtual int id() const = 0; virtual bool isSelectable() const = 0; virtual ToolWorkType toolType() const = 0; virtual QString iconName() const = 0; virtual QString name() const = 0; virtual QString description() const = 0; virtual void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) = 0; signals: void requestAction(Request r); public slots: virtual void onPressed() = 0; }; flameshot-0.5.1/src/capture/tools/circletool.cpp000066400000000000000000000031231324424505000217320ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "circletool.h" #include CircleTool::CircleTool(QObject *parent) : CaptureTool(parent) { } int CircleTool::id() const { return 0; } bool CircleTool::isSelectable() const { return true; } QString CircleTool::iconName() const { return "circle-outline.png"; } QString CircleTool::name() const { return tr("Circle"); } QString CircleTool::description() const { return tr("Sets the Circle as the paint tool"); } CaptureTool::ToolWorkType CircleTool::toolType() const { return TYPE_LINE_DRAWER; } void CircleTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { painter.setPen(QPen(color, 2 + thickness)); painter.drawEllipse(QRect(points[0], points[1])); } void CircleTool::onPressed() { } flameshot-0.5.1/src/capture/tools/circletool.h000066400000000000000000000025371324424505000214070ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class CircleTool : public CaptureTool { Q_OBJECT public: explicit CircleTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/copytool.cpp000066400000000000000000000032041324424505000214430ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "copytool.h" #include CopyTool::CopyTool(QObject *parent) : CaptureTool(parent) { } int CopyTool::id() const { return 0; } bool CopyTool::isSelectable() const { return false; } QString CopyTool::iconName() const { return "content-copy.png"; } QString CopyTool::name() const { return tr("Copy"); } QString CopyTool::description() const { return tr("Copies the selecion into the clipboard"); } CaptureTool::ToolWorkType CopyTool::toolType() const { return TYPE_WORKER; } void CopyTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { Q_UNUSED(painter); Q_UNUSED(points); Q_UNUSED(color); Q_UNUSED(thickness); } void CopyTool::onPressed() { Q_EMIT requestAction(REQ_TO_CLIPBOARD); Q_EMIT requestAction(REQ_CLOSE_GUI); } flameshot-0.5.1/src/capture/tools/copytool.h000066400000000000000000000025331324424505000211140ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class CopyTool : public CaptureTool { Q_OBJECT public: explicit CopyTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/exittool.cpp000066400000000000000000000031031324424505000214400ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "exittool.h" #include ExitTool::ExitTool(QObject *parent) : CaptureTool(parent) { } int ExitTool::id() const { return 0; } bool ExitTool::isSelectable() const { return false; } QString ExitTool::iconName() const { return "close.png"; } QString ExitTool::name() const { return tr("Exit"); } QString ExitTool::description() const { return tr("Leave the capture screen"); } CaptureTool::ToolWorkType ExitTool::toolType() const { return TYPE_WORKER; } void ExitTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { Q_UNUSED(painter); Q_UNUSED(points); Q_UNUSED(color); Q_UNUSED(thickness); } void ExitTool::onPressed() { Q_EMIT requestAction(REQ_CLOSE_GUI); } flameshot-0.5.1/src/capture/tools/exittool.h000066400000000000000000000025331324424505000211130ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class ExitTool : public CaptureTool { Q_OBJECT public: explicit ExitTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/imguruploadertool.cpp000066400000000000000000000033031324424505000233500ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "imguruploadertool.h" #include ImgurUploaderTool::ImgurUploaderTool(QObject *parent) : CaptureTool(parent) { } int ImgurUploaderTool::id() const { return 0; } bool ImgurUploaderTool::isSelectable() const { return false; } QString ImgurUploaderTool::iconName() const { return "cloud-upload.png"; } QString ImgurUploaderTool::name() const { return tr("Image Uploader"); } QString ImgurUploaderTool::description() const { return tr("Uploads the selection to Imgur"); } CaptureTool::ToolWorkType ImgurUploaderTool::toolType() const { return TYPE_WORKER; } void ImgurUploaderTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { Q_UNUSED(painter); Q_UNUSED(points); Q_UNUSED(color); Q_UNUSED(thickness); } void ImgurUploaderTool::onPressed() { Q_EMIT requestAction(REQ_UPLOAD_TO_IMGUR); } flameshot-0.5.1/src/capture/tools/imguruploadertool.h000066400000000000000000000025551324424505000230250ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class ImgurUploaderTool : public CaptureTool { Q_OBJECT public: explicit ImgurUploaderTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/linetool.cpp000066400000000000000000000035451324424505000214300ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "linetool.h" #include #define ADJ_VALUE 13 LineTool::LineTool(QObject *parent) : CaptureTool(parent) { } int LineTool::id() const { return 0; } bool LineTool::isSelectable() const { return true; } QString LineTool::iconName() const { return "line.png"; } QString LineTool::name() const { return tr("Line"); } QString LineTool::description() const { return tr("Sets the Line as the paint tool"); } CaptureTool::ToolWorkType LineTool::toolType() const { return TYPE_LINE_DRAWER; } void LineTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { QPoint p0 = points[0]; QPoint p1 = points[1]; if (needsAdjustment(p0, p1)) { p1.setY(p0.y()); } painter.setPen(QPen(color, 2 + thickness)); painter.drawLine(p0, p1); } void LineTool::onPressed() { } // Have to force horizontal position bool LineTool::needsAdjustment(const QPoint &p0, const QPoint &p1) const { return (p1.y() >= p0.y() - ADJ_VALUE) && (p1.y() <= p0.y() + ADJ_VALUE); } flameshot-0.5.1/src/capture/tools/linetool.h000066400000000000000000000026511324424505000210720ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class LineTool : public CaptureTool { Q_OBJECT public: explicit LineTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; private: bool needsAdjustment(const QPoint &p0, const QPoint &p1) const; }; flameshot-0.5.1/src/capture/tools/markertool.cpp000066400000000000000000000036751324424505000217660ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "markertool.h" #include #define ADJ_VALUE 14 MarkerTool::MarkerTool(QObject *parent) : CaptureTool(parent) { } int MarkerTool::id() const { return 0; } bool MarkerTool::isSelectable() const { return true; } QString MarkerTool::iconName() const { return "marker.png"; } QString MarkerTool::name() const { return tr("Marker"); } QString MarkerTool::description() const { return tr("Sets the Marker as the paint tool"); } CaptureTool::ToolWorkType MarkerTool::toolType() const { return TYPE_LINE_DRAWER; } void MarkerTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { QPoint p0 = points[0]; QPoint p1 = points[1]; if (needsAdjustment(p0, p1)) { p1.setY(p0.y()); } painter.setOpacity(0.35); painter.setPen(QPen(color, 14 + thickness)); painter.drawLine(p0, p1); painter.setOpacity(1); } void MarkerTool::onPressed() { } // Have to force horizontal position bool MarkerTool::needsAdjustment(const QPoint &p0, const QPoint &p1) const { return (p1.y() >= p0.y() - ADJ_VALUE) && (p1.y() <= p0.y() + ADJ_VALUE); } flameshot-0.5.1/src/capture/tools/markertool.h000066400000000000000000000026551324424505000214300ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class MarkerTool : public CaptureTool { Q_OBJECT public: explicit MarkerTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; private: bool needsAdjustment(const QPoint &p0, const QPoint &p1) const; }; flameshot-0.5.1/src/capture/tools/movetool.cpp000066400000000000000000000031101324424505000214330ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "movetool.h" #include MoveTool::MoveTool(QObject *parent) : CaptureTool(parent) { } int MoveTool::id() const { return 0; } bool MoveTool::isSelectable() const { return false; } QString MoveTool::iconName() const { return "cursor-move.png"; } QString MoveTool::name() const { return tr("Move"); } QString MoveTool::description() const { return tr("Move the selection area"); } CaptureTool::ToolWorkType MoveTool::toolType() const { return TYPE_WORKER; } void MoveTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { Q_UNUSED(painter); Q_UNUSED(points); Q_UNUSED(color); Q_UNUSED(thickness); } void MoveTool::onPressed() { Q_EMIT requestAction(REQ_MOVE_MODE); } flameshot-0.5.1/src/capture/tools/movetool.h000066400000000000000000000025331324424505000211100ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class MoveTool : public CaptureTool { Q_OBJECT public: explicit MoveTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/penciltool.cpp000066400000000000000000000032641324424505000217510ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "penciltool.h" #include PencilTool::PencilTool(QObject *parent) : CaptureTool(parent) { } int PencilTool::id() const { return 0; } bool PencilTool::isSelectable() const { return true; } QString PencilTool::iconName() const { return "pencil.png"; } QString PencilTool::name() const { return tr("Pencil"); } QString PencilTool::description() const { return tr("Sets the Pencil as the paint tool"); } CaptureTool::ToolWorkType PencilTool::toolType() const { return TYPE_PATH_DRAWER; } void PencilTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { painter.setPen(QPen(color, 2 + thickness)); if (points.length() == 2) { painter.drawLine(points[0], points[1]); } else { painter.drawPolyline(points.data(), points.size()); } } void PencilTool::onPressed() { } flameshot-0.5.1/src/capture/tools/penciltool.h000066400000000000000000000025371324424505000214200ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class PencilTool : public CaptureTool { Q_OBJECT public: explicit PencilTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/rectangletool.cpp000066400000000000000000000032651324424505000224440ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "rectangletool.h" #include RectangleTool::RectangleTool(QObject *parent) : CaptureTool(parent) { } int RectangleTool::id() const { return 0; } bool RectangleTool::isSelectable() const { return true; } QString RectangleTool::iconName() const { return "square.png"; } QString RectangleTool::name() const { return tr("Rectangle"); } QString RectangleTool::description() const { return tr("Sets the Rectangle as the paint tool"); } CaptureTool::ToolWorkType RectangleTool::toolType() const { return TYPE_LINE_DRAWER; } void RectangleTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { painter.setPen(QPen(color, 2 + thickness)); painter.setBrush(QBrush(color)); painter.drawRect(QRect(points[0], points[1])); painter.setBrush(QBrush()); } void RectangleTool::onPressed() { } flameshot-0.5.1/src/capture/tools/rectangletool.h000066400000000000000000000025451324424505000221110ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class RectangleTool : public CaptureTool { Q_OBJECT public: explicit RectangleTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/savetool.cpp000066400000000000000000000031101324424505000214230ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "savetool.h" #include SaveTool::SaveTool(QObject *parent) : CaptureTool(parent) { } int SaveTool::id() const { return 0; } bool SaveTool::isSelectable() const { return false; } QString SaveTool::iconName() const { return "content-save.png"; } QString SaveTool::name() const { return tr("Save"); } QString SaveTool::description() const { return tr("Save the capture"); } CaptureTool::ToolWorkType SaveTool::toolType() const { return TYPE_WORKER; } void SaveTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { Q_UNUSED(painter); Q_UNUSED(points); Q_UNUSED(color); Q_UNUSED(thickness); } void SaveTool::onPressed() { Q_EMIT requestAction(REQ_SAVE_SCREENSHOT); } flameshot-0.5.1/src/capture/tools/savetool.h000066400000000000000000000025331324424505000211000ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class SaveTool : public CaptureTool { Q_OBJECT public: explicit SaveTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/selectiontool.cpp000066400000000000000000000032031324424505000224550ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "selectiontool.h" #include SelectionTool::SelectionTool(QObject *parent) : CaptureTool(parent) { } int SelectionTool::id() const { return 0; } bool SelectionTool::isSelectable() const { return true; } QString SelectionTool::iconName() const { return "square-outline.png"; } QString SelectionTool::name() const { return tr("Rectangular Selection"); } QString SelectionTool::description() const { return tr("Sets the Selection as the paint tool"); } CaptureTool::ToolWorkType SelectionTool::toolType() const { return TYPE_LINE_DRAWER; } void SelectionTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { painter.setPen(QPen(color, 2 + thickness)); painter.drawRect(QRect(points[0], points[1])); } void SelectionTool::onPressed() { } flameshot-0.5.1/src/capture/tools/selectiontool.h000066400000000000000000000025451324424505000221320ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class SelectionTool : public CaptureTool { Q_OBJECT public: explicit SelectionTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/sizeindicatortool.cpp000066400000000000000000000032421324424505000233420ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "sizeindicatortool.h" #include SizeIndicatorTool::SizeIndicatorTool(QObject *parent) : CaptureTool(parent) { } int SizeIndicatorTool::id() const { return 0; } bool SizeIndicatorTool::isSelectable() const { return false; } QString SizeIndicatorTool::iconName() const { return QString(); } QString SizeIndicatorTool::name() const { return tr("Selection Size Indicator"); } QString SizeIndicatorTool::description() const { return tr("Shows the dimensions of the selection (X Y)"); } CaptureTool::ToolWorkType SizeIndicatorTool::toolType() const { return TYPE_WORKER; } void SizeIndicatorTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { Q_UNUSED(painter); Q_UNUSED(points); Q_UNUSED(color); Q_UNUSED(thickness); } void SizeIndicatorTool::onPressed() { } flameshot-0.5.1/src/capture/tools/sizeindicatortool.h000066400000000000000000000025551324424505000230150ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class SizeIndicatorTool : public CaptureTool { Q_OBJECT public: explicit SizeIndicatorTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/tools/toolfactory.cpp000066400000000000000000000056251324424505000221510ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "toolfactory.h" #include "arrowtool.h" #include "circletool.h" #include "copytool.h" #include "exittool.h" #include "imguruploadertool.h" #include "linetool.h" #include "markertool.h" #include "movetool.h" #include "penciltool.h" #include "rectangletool.h" #include "savetool.h" #include "selectiontool.h" #include "sizeindicatortool.h" #include "undotool.h" #include "applauncher.h" #include "blurtool.h" ToolFactory::ToolFactory(QObject *parent) : QObject(parent) { } CaptureTool* ToolFactory::CreateTool( CaptureButton::ButtonType t, QObject *parent) { CaptureTool *tool; switch (t) { case CaptureButton::TYPE_ARROW: tool = new ArrowTool(parent); break; case CaptureButton::TYPE_CIRCLE: tool = new CircleTool(parent); break; case CaptureButton::TYPE_COPY: tool = new CopyTool(parent); break; case CaptureButton::TYPE_EXIT: tool = new ExitTool(parent); break; case CaptureButton::TYPE_IMAGEUPLOADER: tool = new ImgurUploaderTool(parent); break; case CaptureButton::TYPE_LINE: tool = new LineTool(parent); break; case CaptureButton::TYPE_MARKER: tool = new MarkerTool(parent); break; case CaptureButton::TYPE_MOVESELECTION: tool = new MoveTool(parent); break; case CaptureButton::TYPE_PENCIL: tool = new PencilTool(parent); break; case CaptureButton::TYPE_RECTANGLE: tool = new RectangleTool(parent); break; case CaptureButton::TYPE_SAVE: tool = new SaveTool(parent); break; case CaptureButton::TYPE_SELECTION: tool = new SelectionTool(parent); break; case CaptureButton::TYPE_SELECTIONINDICATOR: tool = new SizeIndicatorTool(parent); break; case CaptureButton::TYPE_UNDO: tool = new UndoTool(parent); break; case CaptureButton::TYPE_OPEN_APP: tool = new AppLauncher(parent); break; case CaptureButton::TYPE_BLUR: tool = new BlurTool(parent); break; default: tool = nullptr; break; } return tool; } flameshot-0.5.1/src/capture/tools/toolfactory.h000066400000000000000000000024101324424505000216030ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include "src/capture/widgets/capturebutton.h" #include "src/capture/tools/capturetool.h" class CaptureTool; class ToolFactory : public QObject { Q_OBJECT public: enum ToolType { }; explicit ToolFactory(QObject *parent = nullptr); ToolFactory(const ToolFactory &) = delete; ToolFactory & operator=(const ToolFactory &) = delete; CaptureTool* CreateTool( CaptureButton::ButtonType t, QObject *parent = nullptr); }; flameshot-0.5.1/src/capture/tools/undotool.cpp000066400000000000000000000031241324424505000214370ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "undotool.h" #include UndoTool::UndoTool(QObject *parent) : CaptureTool(parent) { } int UndoTool::id() const { return 0; } bool UndoTool::isSelectable() const { return false; } QString UndoTool::iconName() const { return "undo-variant.png"; } QString UndoTool::name() const { return tr("Undo"); } QString UndoTool::description() const { return tr("Undo the last modification"); } CaptureTool::ToolWorkType UndoTool::toolType() const { return TYPE_WORKER; } void UndoTool::processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) { Q_UNUSED(painter); Q_UNUSED(points); Q_UNUSED(color); Q_UNUSED(thickness); } void UndoTool::onPressed() { Q_EMIT requestAction(REQ_UNDO_MODIFICATION); } flameshot-0.5.1/src/capture/tools/undotool.h000066400000000000000000000025331324424505000211070ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturetool.h" class UndoTool : public CaptureTool { Q_OBJECT public: explicit UndoTool(QObject *parent = nullptr); int id() const override; bool isSelectable() const override; ToolWorkType toolType() const override; QString iconName() const override; QString name() const override; QString description() const override; void processImage( QPainter &painter, const QVector &points, const QColor &color, const int thickness) override; void onPressed() override; }; flameshot-0.5.1/src/capture/widgets/000077500000000000000000000000001324424505000173765ustar00rootroot00000000000000flameshot-0.5.1/src/capture/widgets/buttonhandler.cpp000066400000000000000000000333161324424505000227610ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "buttonhandler.h" #include #include #include // ButtonHandler is a habdler for every active button. It makes easier to // manipulate the buttons as a unit. ButtonHandler::ButtonHandler(const QVector &v, QObject *parent) : QObject(parent) { setButtons(v); init(); } ButtonHandler::ButtonHandler(QObject *parent) : QObject(parent) { init(); } void ButtonHandler::hide() { for (CaptureButton *b: m_vectorButtons) b->hide(); } void ButtonHandler::show() { if (m_vectorButtons.isEmpty() || m_vectorButtons.first()->isVisible()) { return; } for (CaptureButton *b: m_vectorButtons) b->animatedShow(); } bool ButtonHandler::isVisible() const { bool ret = true; for (const CaptureButton *b: m_vectorButtons) { if (!b->isVisible()) { ret = false; break; } } return ret; } bool ButtonHandler::buttonsAreInside() const { return m_buttonsAreInside; } size_t ButtonHandler::size() const { return m_vectorButtons.size(); } // updatePosition updates the position of the buttons around the // selection area. Ignores the sides blocked by the end of the screen. // When the selection is too small it works on a virtual selection with // the original in the center. void ButtonHandler::updatePosition(const QRect &selection) { resetRegionTrack(); const int vecLength = m_vectorButtons.size(); if (vecLength == 0) { return; } // Copy of the selection area for internal modifications m_selection = selection; updateBlockedSides(); ensureSelectionMinimunSize(); // Indicates the actual button to be moved int elemIndicator = 0; while (elemIndicator < vecLength) { // Add them inside the area when there is no more space if (m_allSidesBlocked) { positionButtonsInside(elemIndicator); break; // the while } // Number of buttons per row column int buttonsPerRow = (m_selection.width() + m_separator) / (m_buttonExtendedSize); int buttonsPerCol = (m_selection.height() + m_separator) / (m_buttonExtendedSize); // Buttons to be placed in the corners int extraButtons = (vecLength - elemIndicator) - (buttonsPerRow + buttonsPerCol) * 2; int elemsAtCorners = extraButtons > 4 ? 4 : extraButtons; int maxExtra = 2; if (m_oneHorizontalBlocked) { maxExtra = 1; } else if (m_horizontalyBlocked) { maxExtra = 0; } int elemCornersTop = qBound(0, elemsAtCorners, maxExtra); elemsAtCorners -= elemCornersTop; int elemCornersBotton = qBound(0, elemsAtCorners, maxExtra); // Add buttons at the botton of the seletion if (!m_blockedBotton) { int addCounter = buttonsPerRow + elemCornersBotton; // Don't add more than we have addCounter = qBound(0, addCounter, vecLength - elemIndicator); QPoint center = QPoint(m_selection.center().x(), m_selection.bottom() + m_separator); if (addCounter > buttonsPerRow) { adjustHorizontalCenter(center); } // ElemIndicator, elemsAtCorners QVector positions = horizontalPoints(center, addCounter, true); moveButtonsToPoints(positions, elemIndicator); } // Add buttons at the right side of the seletion if (!m_blockedRight && elemIndicator < vecLength) { int addCounter = buttonsPerCol; addCounter = qBound(0, addCounter, vecLength - elemIndicator); QPoint center = QPoint(m_selection.right() + m_separator, m_selection.center().y()); QVector positions = verticalPoints(center, addCounter, false); moveButtonsToPoints(positions, elemIndicator); } // Add buttons at the top of the seletion if (!m_blockedTop && elemIndicator < vecLength) { int addCounter = buttonsPerRow + elemCornersTop; addCounter = qBound(0, addCounter, vecLength - elemIndicator); QPoint center = QPoint(m_selection.center().x(), m_selection.top() - m_buttonExtendedSize); if (addCounter == 1 + buttonsPerRow) { adjustHorizontalCenter(center); } QVector positions = horizontalPoints(center, addCounter, false); moveButtonsToPoints(positions, elemIndicator); } // Add buttons at the left side of the seletion if (!m_blockedLeft && elemIndicator < vecLength) { int addCounter = buttonsPerCol; addCounter = qBound(0, addCounter, vecLength - elemIndicator); QPoint center = QPoint(m_selection.left() - m_buttonExtendedSize, m_selection.center().y()); QVector positions = verticalPoints(center, addCounter, true); moveButtonsToPoints(positions, elemIndicator); } // If there are elements for the next cycle, increase the size of the // base area if (elemIndicator < vecLength && !(m_allSidesBlocked)) { expandSelection(); } updateBlockedSides(); } } // horizontalPoints is an auxiliar method for the button position computation. // starts from a known center and keeps adding elements horizontally // and returns the computed positions. QVector ButtonHandler::horizontalPoints( const QPoint ¢er, const int elements, const bool leftToRight) const { QVector res; // Distance from the center to start adding buttons int shift = 0; if (elements % 2 == 0) { shift = m_buttonExtendedSize * (elements / 2) - (m_separator / 2); } else { shift = m_buttonExtendedSize * ((elements-1) / 2) + m_buttonBaseSize / 2; } if (!leftToRight) { shift -= m_buttonBaseSize; } int x = leftToRight ? center.x() - shift : center.x() + shift; QPoint i(x, center.y()); while (elements > res.length()) { res.append(i); leftToRight ? i.setX(i.x() + m_buttonExtendedSize) : i.setX(i.x() - m_buttonExtendedSize); } return res; } // verticalPoints is an auxiliar method for the button position computation. // starts from a known center and keeps adding elements vertically // and returns the computed positions. QVector ButtonHandler::verticalPoints( const QPoint ¢er, const int elements, const bool upToDown) const { QVector res; // Distance from the center to start adding buttons int shift = 0; if (elements % 2 == 0) { shift = m_buttonExtendedSize * (elements / 2) - (m_separator / 2); } else { shift = m_buttonExtendedSize * ((elements-1) / 2) + m_buttonBaseSize / 2; } if (!upToDown) { shift -= m_buttonBaseSize; } int y = upToDown ? center.y() - shift : center.y() + shift; QPoint i(center.x(), y); while (elements > res.length()) { res.append(i); upToDown ? i.setY(i.y() + m_buttonExtendedSize) : i.setY(i.y() - m_buttonExtendedSize); } return res; } void ButtonHandler::init() { m_separator = CaptureButton::buttonBaseSize() / 4; } void ButtonHandler::resetRegionTrack() { m_buttonsAreInside = false; } void ButtonHandler::updateBlockedSides() { const int EXTENSION = m_separator * 2 + m_buttonBaseSize; // Right QPoint pointA(m_selection.right() + EXTENSION, m_selection.bottom()); QPoint pointB(pointA.x(), m_selection.top()); m_blockedRight = !(m_screenRegions.contains(pointA) && m_screenRegions.contains(pointB)); // Left pointA.setX(m_selection.left() - EXTENSION); pointB.setX(pointA.x()); m_blockedLeft = !(m_screenRegions.contains(pointA) && m_screenRegions.contains(pointB)); // Botton pointA = QPoint(m_selection.left(), m_selection.bottom() + EXTENSION); pointB = QPoint(m_selection.right(), pointA.y()); m_blockedBotton = !(m_screenRegions.contains(pointA) && m_screenRegions.contains(pointB)); // Top pointA.setY(m_selection.top() - EXTENSION); pointB.setY(pointA.y()); m_blockedTop = !(m_screenRegions.contains(pointA) && m_screenRegions.contains(pointB)); // Auxiliar m_oneHorizontalBlocked = (!m_blockedRight && m_blockedLeft) || (m_blockedRight && !m_blockedLeft); m_horizontalyBlocked = (m_blockedRight && m_blockedLeft); m_allSidesBlocked = (m_blockedBotton && m_horizontalyBlocked && m_blockedTop); } void ButtonHandler::expandSelection() { if (m_blockedRight && !m_blockedLeft) { m_selection.setX(m_selection.x() - m_buttonExtendedSize); } else if (!m_blockedRight && !m_blockedLeft) { m_selection.setX(m_selection.x() - m_buttonExtendedSize); m_selection.setWidth(m_selection.width() + m_buttonExtendedSize); } else { m_selection.setWidth(m_selection.width() + m_buttonExtendedSize); } if (m_blockedBotton && !m_blockedTop) { m_selection.setY(m_selection.y() - m_buttonExtendedSize); } else if (!m_blockedTop && !m_blockedBotton) { m_selection.setY(m_selection.y() - m_buttonExtendedSize); m_selection.setHeight(m_selection.height() + m_buttonExtendedSize); } else { m_selection.setHeight(m_selection.height() + m_buttonExtendedSize); } } void ButtonHandler::positionButtonsInside(int index) { // Position the buttons from left to right starting at the botton // left of the selection. // The main screen has priority as the reference when its x,y botton // left corner values are lower than the ones of the selection. QRect mainArea = QGuiApplication::primaryScreen()->geometry(); int xPos = m_selection.left() + m_separator; int yPos = m_selection.bottom() - m_buttonExtendedSize; if (m_selection.left() < mainArea.left()) { xPos = mainArea.left() + m_separator; } if (m_selection.bottom() > mainArea.bottom()) { yPos = mainArea.bottom() - m_buttonExtendedSize; } CaptureButton *button = nullptr; for (; index < m_vectorButtons.size(); ++index) { button = m_vectorButtons[index]; button->move(xPos, yPos); if (button->pos().x() + m_buttonExtendedSize > mainArea.right()) { xPos = m_selection.left() + m_separator; yPos -= (m_buttonExtendedSize); } xPos += (m_buttonExtendedSize); } m_buttonsAreInside = true; } void ButtonHandler::ensureSelectionMinimunSize() { // Detect if a side is smaller than a button in order to prevent collision // and redimension the base area the the base size of a single button per side if (m_selection.width() < m_buttonBaseSize) { if (!m_blockedLeft) { m_selection.setX(m_selection.x() - (m_buttonBaseSize-m_selection.width()) / 2); } m_selection.setWidth(m_buttonBaseSize); } if (m_selection.height() < m_buttonBaseSize) { if (!m_blockedTop) { m_selection.setY(m_selection.y() - (m_buttonBaseSize-m_selection.height()) / 2); } m_selection.setHeight(m_buttonBaseSize); } } void ButtonHandler::moveButtonsToPoints( const QVector &points, int &index) { for (const QPoint &p: points) { auto button = m_vectorButtons[index]; button->move(p); ++index; } } void ButtonHandler::adjustHorizontalCenter(QPoint ¢er) { if (m_blockedLeft) { center.setX(center.x() + m_buttonExtendedSize/2); } else if (m_blockedRight) { center.setX(center.x() - m_buttonExtendedSize/2); } } // setButtons redefines the buttons of the button handler void ButtonHandler::setButtons(const QVector v) { if (v.isEmpty()) return; for (CaptureButton *b: m_vectorButtons) delete(b); m_vectorButtons = v; m_buttonBaseSize = CaptureButton::buttonBaseSize(); m_buttonExtendedSize = m_buttonBaseSize + m_separator; } bool ButtonHandler::contains(const QPoint &p) const { QPoint first(m_vectorButtons.first()->pos()); QPoint last(m_vectorButtons.last()->pos()); bool firstIsTopLeft = (first.x() <= last.x() && first.y() <= last.y()); QPoint topLeft = firstIsTopLeft ? first : last; QPoint bottonRight = firstIsTopLeft ? last : first; topLeft += QPoint(-m_separator, -m_separator); bottonRight += QPoint(m_buttonExtendedSize, m_buttonExtendedSize); QRegion r(QRect(topLeft, bottonRight).normalized()); return r.contains(p); } void ButtonHandler::updateScreenRegions(const QVector &rects) { m_screenRegions = QRegion(); for (const QRect &rect: rects) { m_screenRegions += rect; } } flameshot-0.5.1/src/capture/widgets/buttonhandler.h000066400000000000000000000047321324424505000224260ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "capturebutton.h" #include #include #include class CaptureButton; class QRect; class QPoint; class ButtonHandler : public QObject { Q_OBJECT public: ButtonHandler(const QVector&, QObject *parent = nullptr); ButtonHandler(QObject *parent = nullptr); void hideSectionUnderMouse(const QPoint &p); bool isVisible() const; bool buttonsAreInside() const; size_t size() const; void updatePosition(const QRect &selection); void setButtons(const QVector); bool contains(const QPoint &p) const; void updateScreenRegions(const QVector &rects); public slots: void hide(); void show(); private: QVector horizontalPoints(const QPoint ¢er, const int elements, const bool leftToRight) const; QVector verticalPoints(const QPoint ¢er, const int elements, const bool upToDown) const; QVector m_vectorButtons; QRegion m_screenRegions; QRect m_selection; int m_separator; int m_buttonExtendedSize; int m_buttonBaseSize; bool m_buttonsAreInside; bool m_blockedRight; bool m_blockedLeft; bool m_blockedBotton; bool m_blockedTop; bool m_oneHorizontalBlocked; bool m_horizontalyBlocked; bool m_allSidesBlocked; // aux methods void init(); void resetRegionTrack(); void updateBlockedSides(); void expandSelection(); void positionButtonsInside(int index); void ensureSelectionMinimunSize(); void moveButtonsToPoints(const QVector &points, int &index); void adjustHorizontalCenter(QPoint ¢er); }; flameshot-0.5.1/src/capture/widgets/capturebutton.cpp000066400000000000000000000165501324424505000230100ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "capturebutton.h" #include "src/capture/widgets/capturewidget.h" #include "src/utils/confighandler.h" #include "src/capture/tools/capturetool.h" #include "src/capture/tools/toolfactory.h" #include #include #include #include #include #include // Button represents a single button of the capture widget, it can enable // multiple functionality. namespace { qreal getColorLuma(const QColor &c) { return 0.30 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF(); } QColor getContrastColor(const QColor &c) { bool isWhite = CaptureButton::iconIsWhiteByColor(c); int change = isWhite ? 30 : -45; return QColor(qBound(0, c.red() + change, 255), qBound(0, c.green() + change, 255), qBound(0, c.blue() + change, 255)); } } // unnamed namespace CaptureButton::CaptureButton(const ButtonType t, QWidget *parent) : QPushButton(parent), m_buttonType(t) { initButton(); if (t == TYPE_SELECTIONINDICATOR) { QFont f = this->font(); setFont(QFont(f.family(), 7, QFont::Bold)); } else { updateIcon(); } setCursor(Qt::ArrowCursor); } void CaptureButton::initButton() { m_tool = ToolFactory().CreateTool(m_buttonType, this); connect(this, &CaptureButton::pressed, m_tool, &CaptureTool::onPressed); setFocusPolicy(Qt::NoFocus); resize(buttonBaseSize(), buttonBaseSize()); setMask(QRegion(QRect(-1,-1, buttonBaseSize()+2, buttonBaseSize()+2), QRegion::Ellipse)); setToolTip(m_tool->description()); m_emergeAnimation = new QPropertyAnimation(this, "size", this); m_emergeAnimation->setEasingCurve(QEasingCurve::InOutQuad); m_emergeAnimation->setDuration(80); m_emergeAnimation->setStartValue(QSize(0, 0)); m_emergeAnimation->setEndValue(QSize(buttonBaseSize(), buttonBaseSize())); auto dsEffect = new QGraphicsDropShadowEffect(this); dsEffect->setBlurRadius(5); dsEffect->setOffset(0); dsEffect->setColor(QColor(Qt::black)); setGraphicsEffect(dsEffect); } void CaptureButton::updateIcon() { setIcon(icon()); setIconSize(size()*0.6); } QVector CaptureButton::getIterableButtonTypes() { return iterableButtonTypes; } QString CaptureButton::globalStyleSheet() { QColor mainColor = ConfigHandler().uiMainColorValue(); QString baseSheet = "CaptureButton { border-radius: %3;" "background-color: %1; color: %4 }" "CaptureButton:hover { background-color: %2; }" "CaptureButton:pressed:!hover { " "background-color: %1; }"; // define color when mouse is hovering QColor contrast = getContrastColor(m_mainColor); // foreground color QString color = iconIsWhiteByColor(mainColor) ? "white" : "black"; return baseSheet.arg(mainColor.name()).arg(contrast.name()) .arg(buttonBaseSize()/2).arg(color); } QString CaptureButton::styleSheet() const { QString baseSheet = "CaptureButton { border-radius: %3;" "background-color: %1; color: %4 }" "CaptureButton:hover { background-color: %2; }" "CaptureButton:pressed:!hover { " "background-color: %1; }"; // define color when mouse is hovering QColor contrast = getContrastColor(m_mainColor); // foreground color QString color = iconIsWhiteByColor(m_mainColor) ? "white" : "black"; return baseSheet.arg(m_mainColor.name()).arg(contrast.name()) .arg(buttonBaseSize()/2).arg(color); } // get icon returns the icon for the type of button QIcon CaptureButton::icon() const { QString color(iconIsWhiteByColor(m_mainColor) ? "White" : "Black"); QString iconPath = QStringLiteral(":/img/buttonIcons%1/%2") .arg(color).arg(m_tool->iconName()); return QIcon(iconPath); } void CaptureButton::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { Q_EMIT pressedButton(this); Q_EMIT pressed(); } } void CaptureButton::animatedShow() { if(!isVisible()) { show(); m_emergeAnimation->start(); connect(m_emergeAnimation, &QPropertyAnimation::finished, this, [this](){ }); } } CaptureButton::ButtonType CaptureButton::buttonType() const { return m_buttonType; } CaptureTool *CaptureButton::tool() const { return m_tool; } void CaptureButton::setColor(const QColor &c) { m_mainColor = c; setStyleSheet(styleSheet()); updateIcon(); } // getButtonBaseSize returns the base size of the buttons int CaptureButton::buttonBaseSize() { return QApplication::fontMetrics().lineSpacing() * 2.2; } bool CaptureButton::iconIsWhiteByColor(const QColor &c) { bool isWhite = false; if (getColorLuma(c) <= 0.60) { isWhite = true; } return isWhite; } QColor CaptureButton::m_mainColor = ConfigHandler().uiMainColorValue(); static std::map buttonTypeOrder { { CaptureButton::TYPE_PENCIL, 0 }, { CaptureButton::TYPE_LINE, 1 }, { CaptureButton::TYPE_ARROW, 2 }, { CaptureButton::TYPE_SELECTION, 3 }, { CaptureButton::TYPE_RECTANGLE, 4 }, { CaptureButton::TYPE_CIRCLE, 5 }, { CaptureButton::TYPE_MARKER, 6 }, { CaptureButton::TYPE_SELECTIONINDICATOR, 8 }, { CaptureButton::TYPE_MOVESELECTION, 9 }, { CaptureButton::TYPE_UNDO, 10 }, { CaptureButton::TYPE_COPY, 11 }, { CaptureButton::TYPE_SAVE, 12 }, { CaptureButton::TYPE_EXIT, 13 }, { CaptureButton::TYPE_IMAGEUPLOADER, 14 }, { CaptureButton::TYPE_OPEN_APP, 15 }, { CaptureButton::TYPE_BLUR, 7 }, }; int CaptureButton::getPriorityByButton(CaptureButton::ButtonType b) { auto it = buttonTypeOrder.find(b); return it == buttonTypeOrder.cend() ? (int)buttonTypeOrder.size() : it->second; } QVector CaptureButton::iterableButtonTypes = { CaptureButton::TYPE_PENCIL, CaptureButton::TYPE_LINE, CaptureButton::TYPE_ARROW, CaptureButton::TYPE_SELECTION, CaptureButton::TYPE_RECTANGLE, CaptureButton::TYPE_CIRCLE, CaptureButton::TYPE_MARKER, CaptureButton::TYPE_BLUR, CaptureButton::TYPE_SELECTIONINDICATOR, CaptureButton::TYPE_MOVESELECTION, CaptureButton::TYPE_UNDO, CaptureButton::TYPE_COPY, CaptureButton::TYPE_SAVE, CaptureButton::TYPE_EXIT, CaptureButton::TYPE_IMAGEUPLOADER, CaptureButton::TYPE_OPEN_APP, }; flameshot-0.5.1/src/capture/widgets/capturebutton.h000066400000000000000000000050731324424505000224530ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include #include class QWidget; class QPropertyAnimation; class CaptureTool; class CaptureButton : public QPushButton { Q_OBJECT Q_ENUMS(ButtonType) public: // Don't forget to add the new types to CaptureButton::iterableButtonTypes // in the .cpp and the order value in the private array buttonTypeOrder enum ButtonType { TYPE_PENCIL = 0, TYPE_LINE = 1, TYPE_ARROW = 2, TYPE_SELECTION = 3, TYPE_RECTANGLE = 4, TYPE_CIRCLE = 5, TYPE_MARKER = 6, TYPE_SELECTIONINDICATOR = 7, TYPE_MOVESELECTION = 8, TYPE_UNDO = 9, TYPE_COPY = 10, TYPE_SAVE = 11, TYPE_EXIT = 12, TYPE_IMAGEUPLOADER = 13, TYPE_OPEN_APP = 14, TYPE_BLUR = 15, }; CaptureButton() = delete; explicit CaptureButton(const ButtonType, QWidget *parent = nullptr); static int buttonBaseSize(); static bool iconIsWhiteByColor(const QColor &); static QString globalStyleSheet(); static QVector getIterableButtonTypes(); static int getPriorityByButton(CaptureButton::ButtonType); QString name() const; QString description() const; QIcon icon() const; QString styleSheet() const; ButtonType buttonType() const; CaptureTool* tool() const; void setColor(const QColor &c); void animatedShow(); protected: virtual void mousePressEvent(QMouseEvent *); static QVector iterableButtonTypes; CaptureTool *m_tool; signals: void pressedButton(CaptureButton *); private: CaptureButton(QWidget *parent = 0); ButtonType m_buttonType; QPropertyAnimation *m_emergeAnimation; static QColor m_mainColor; void initButton(); void updateIcon(); }; flameshot-0.5.1/src/capture/widgets/capturewidget.cpp000066400000000000000000000615241324424505000227610ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . // Based on Lightscreen areadialog.cpp, Copyright 2017 Christian Kaiser // released under the GNU GPL2 // Based on KDE's KSnapshot regiongrabber.cpp, revision 796531, Copyright 2007 Luca Gugelmann // released under the GNU LGPL #include "src/capture/screenshot.h" #include "src/capture/capturemodification.h" #include "capturewidget.h" #include "capturebutton.h" #include "src/capture/widgets/notifierbox.h" #include "src/capture/widgets/colorpicker.h" #include "src/utils/screengrabber.h" #include "src/utils/systemnotification.h" #include "src/core/resourceexporter.h" #include #include #include #include #include #include #include #include #include // CaptureWidget is the main component used to capture the screen. It contains an // are of selection with its respective buttons. // enableSaveWIndow CaptureWidget::CaptureWidget(const uint id, const QString &forcedSavePath, CaptureWidget::LaunchMode mode, QWidget *parent) : QWidget(parent), m_screenshot(nullptr), m_mouseOverHandle(0), m_mouseIsClicked(false), m_rightClick(false), m_newSelection(false), m_grabbing(false), m_captureDone(false), m_toolIsForDrawing(false), m_forcedSavePath(forcedSavePath), m_id(id), m_state(CaptureButton::TYPE_MOVESELECTION) { m_showInitialMsg = m_config.showHelpValue(); m_thickness = m_config.drawThicknessValue(); m_opacity = m_config.contrastOpacityValue(); setAttribute(Qt::WA_DeleteOnClose); // create selection handlers QRect baseRect(0, 0, handleSize(), handleSize()); m_TLHandle = baseRect; m_TRHandle = baseRect; m_BLHandle = baseRect; m_BRHandle = baseRect; m_LHandle = baseRect; m_THandle = baseRect; m_RHandle = baseRect; m_BHandle = baseRect; m_handles << &m_TLHandle << &m_TRHandle << &m_BLHandle << &m_BRHandle << &m_LHandle << &m_THandle << &m_RHandle << &m_BHandle; m_sides << &m_TLHandle << &m_TRHandle << &m_BLHandle << &m_BRHandle << &m_LSide << &m_TSide << &m_RSide << &m_BSide; // set base config of the widget setMouseTracking(true); updateCursor(); initShortcuts(); #ifdef Q_OS_WIN QPoint topLeft(0,0); #endif if (mode == FULLSCREEN) { // init content bool ok = true; QPixmap fullScreenshot(ScreenGrabber().grabEntireDesktop(ok)); if(!ok) { SystemNotification().sendMessage(tr("Unable to capture screen")); this->close(); } m_screenshot = new Screenshot(fullScreenshot, this); #ifdef Q_OS_WIN setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Popup); for (QScreen *const screen : QGuiApplication::screens()) { QPoint topLeftScreen = screen->geometry().topLeft(); if (topLeft.x() > topLeftScreen.x() || topLeft.y() > topLeftScreen.y()) { topLeft = topLeftScreen; } } move(topLeft); #else setWindowFlags(Qt::BypassWindowManagerHint | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Tool); #endif resize(pixmap().size()); } // create buttons m_buttonHandler = new ButtonHandler(this); updateButtons(); QVector areas; if (mode == FULLSCREEN) { for (QScreen *const screen : QGuiApplication::screens()) { QRect r = screen->geometry(); #ifdef Q_OS_WIN r.moveTo(r.topLeft() - topLeft); #endif areas.append(r); } } else { areas.append(rect()); } m_buttonHandler->updateScreenRegions(areas); m_buttonHandler->hide(); // init interface color m_colorPicker = new ColorPicker(this); m_colorPicker->hide(); m_notifierBox = new NotifierBox(this); m_notifierBox->hide(); } CaptureWidget::~CaptureWidget() { if (m_captureDone) { QByteArray byteArray; QBuffer buffer(&byteArray); this->pixmap().save(&buffer, "PNG"); Q_EMIT captureTaken(m_id, byteArray); } else { Q_EMIT captureFailed(m_id); } m_config.setdrawThickness(m_thickness); } // redefineButtons retrieves the buttons configured to be shown with the // selection in the capture void CaptureWidget::updateButtons() { m_uiColor = m_config.uiMainColorValue(); m_contrastUiColor = m_config.uiContrastColorValue(); auto buttons = m_config.getButtons(); QVector vectorButtons; for (const CaptureButton::ButtonType &t: buttons) { CaptureButton *b = new CaptureButton(t, this); if (t == CaptureButton::TYPE_SELECTIONINDICATOR) { m_sizeIndButton = b; } b->setColor(m_uiColor); connect(b, &CaptureButton::pressedButton, this, &CaptureWidget::setState); connect(b->tool(), &CaptureTool::requestAction, this, &CaptureWidget::handleButtonSignal); vectorButtons << b; } m_buttonHandler->setButtons(vectorButtons); } QPixmap CaptureWidget::pixmap() { if (m_selection.isNull()) { // copy full screen when no selection return m_screenshot->screenshot(); } else { return m_screenshot->screenshot().copy(extendedSelection()); } } void CaptureWidget::paintEvent(QPaintEvent *) { QPainter painter(this); // If we are creating a new modification to the screenshot we just draw // a temporal modification without antialiasing in the pencil tool for // performance. When we are not drawing we just shot the modified screenshot bool stateIsSelection = m_state == CaptureButton::TYPE_MOVESELECTION; if (m_mouseIsClicked && !stateIsSelection) { painter.drawPixmap(0, 0, m_screenshot->paintTemporalModification( m_modifications.last())); } else if (m_toolIsForDrawing && !stateIsSelection) { CaptureButton::ButtonType type = CaptureButton::ButtonType::TYPE_LINE; if (m_state == CaptureButton::ButtonType::TYPE_MARKER) { type = CaptureButton::ButtonType::TYPE_MARKER; } CaptureModification tempMod(type, m_mousePos, m_colorPicker->drawColor(), m_thickness); tempMod.addPoint(m_mousePos); painter.drawPixmap(0, 0, m_screenshot->paintTemporalModification( &tempMod)); } else { painter.drawPixmap(0, 0, m_screenshot->screenshot()); } QColor overlayColor(0, 0, 0, m_opacity); painter.setBrush(overlayColor); QRect r = m_selection.normalized().adjusted(0, 0, -1, -1); QRegion grey(rect()); grey = grey.subtracted(r); painter.setClipRegion(grey); painter.drawRect(-1, -1, rect().width() + 1, rect().height() + 1); painter.setClipRect(rect()); if (m_showInitialMsg) { QRect helpRect = QGuiApplication::primaryScreen()->geometry(); helpRect.moveTo(mapFromGlobal(helpRect.topLeft())); QString helpTxt = tr("Select an area with the mouse, or press Esc to exit." "\nPress Enter to capture the screen." "\nPress Right Click to show the color picker." "\nUse the Mouse Wheel to change the thickness of your tool."); // We draw the white contrasting background for the text, using the //same text and options to get the boundingRect that the text will have. QRectF bRect = painter.boundingRect(helpRect, Qt::AlignCenter, helpTxt); // These four calls provide padding for the rect const int margin = QApplication::fontMetrics().height() / 2; bRect.setWidth(bRect.width() + margin); bRect.setHeight(bRect.height() + margin); bRect.setX(bRect.x() - margin); bRect.setY(bRect.y() - margin); QColor rectColor(m_uiColor); rectColor.setAlpha(180); QColor textColor((CaptureButton::iconIsWhiteByColor(rectColor) ? Qt::white : Qt::black)); painter.setBrush(QBrush(rectColor, Qt::SolidPattern)); painter.setPen(QPen(textColor)); painter.drawRect(bRect); painter.drawText(helpRect, Qt::AlignCenter, helpTxt); } if (!m_selection.isNull()) { // paint selection rect painter.setPen(m_uiColor); painter.setBrush(Qt::NoBrush); painter.drawRect(r); // paint handlers painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(m_uiColor); for(auto r: m_handles) { painter.drawRoundRect(*r, 100, 100); } } } void CaptureWidget::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) { m_rightClick = true; m_colorPicker->move(e->pos().x()-m_colorPicker->width()/2, e->pos().y()-m_colorPicker->height()/2); m_colorPicker->show(); } else if (e->button() == Qt::LeftButton) { m_showInitialMsg = false; m_mouseIsClicked = true; if (m_state != CaptureButton::TYPE_MOVESELECTION) { auto mod = new CaptureModification(m_state, e->pos(), m_colorPicker->drawColor(), m_thickness, this); m_modifications.append(mod); return; } m_dragStartPoint = e->pos(); m_selectionBeforeDrag = m_selection; if (!m_selection.contains(e->pos()) && !m_mouseOverHandle) { m_newSelection = true; m_selection = QRect(); m_buttonHandler->hide(); update(); } else { m_grabbing = true; } } updateCursor(); } void CaptureWidget::mouseMoveEvent(QMouseEvent *e) { m_mousePos = e->pos(); if (m_mouseIsClicked && m_state == CaptureButton::TYPE_MOVESELECTION) { if (m_buttonHandler->isVisible()) { m_buttonHandler->hide(); } if (m_newSelection) { m_selection = QRect(m_dragStartPoint, m_mousePos).normalized(); updateHandles(); update(); } else if (!m_mouseOverHandle) { // Moving the whole selection QRect r = rect().normalized(); QRect initialRect = m_selection.normalized(); // new top left QPoint p = initialRect.topLeft() + (e->pos() - m_dragStartPoint); m_dragStartPoint += e->pos() - m_dragStartPoint; m_selection.moveTo(p); if (!r.contains(QPoint(r.center().x(), m_selection.top()))) { m_selection.setTop(r.top()); } if (!r.contains(QPoint(m_selection.left(), r.center().y()))) { m_selection.setLeft(r.left()); } if (!r.contains(QPoint(m_selection.right(), r.center().y()))) { m_selection.setRight(r.right()); } if (!r.contains(QPoint(r.center().x(), m_selection.bottom()))) { m_selection.setBottom(r.bottom()); } updateHandles(); update(); } else { // Dragging a handle QRect r = m_selectionBeforeDrag; QPoint offset = e->pos() - m_dragStartPoint; bool symmetryMod = qApp->keyboardModifiers() & Qt::ShiftModifier; if (m_mouseOverHandle == &m_TLHandle || m_mouseOverHandle == &m_TSide || m_mouseOverHandle == &m_TRHandle) { // dragging one of the top handles r.setTop(r.top() + offset.y()); if (symmetryMod) { r.setBottom(r.bottom() - offset.y()); } } if (m_mouseOverHandle == &m_TLHandle || m_mouseOverHandle == &m_LSide || m_mouseOverHandle == &m_BLHandle) { // dragging one of the left handles r.setLeft(r.left() + offset.x()); if (symmetryMod) { r.setRight(r.right() - offset.x()); } } if (m_mouseOverHandle == &m_BLHandle || m_mouseOverHandle == &m_BSide || m_mouseOverHandle == &m_BRHandle) { // dragging one of the bottom handles r.setBottom(r.bottom() + offset.y()); if (symmetryMod) { r.setTop(r.top() - offset.y()); } } if (m_mouseOverHandle == &m_TRHandle || m_mouseOverHandle == &m_RSide || m_mouseOverHandle == &m_BRHandle) { // dragging one of the right handles r.setRight(r.right() + offset.x()); if (symmetryMod) { r.setLeft(r.left() - offset.x()); } } m_selection = r.normalized(); updateHandles(); update(); } } else if (m_mouseIsClicked && m_state != CaptureButton::TYPE_MOVESELECTION) { // drawing with a tool m_modifications.last()->addPoint(e->pos()); update(); // Hides the buttons under the mouse. If the mouse leaves, it shows them. if (m_buttonHandler->buttonsAreInside()) { const bool containsMouse = m_buttonHandler->contains(m_mousePos); if (containsMouse) { m_buttonHandler->hide(); } else { m_buttonHandler->show(); } } } else if (m_toolIsForDrawing) { update(); } else { if (m_selection.isNull()) { return; } bool found = false; for (QRect *const r: m_sides) { if (r->contains(e->pos())) { m_mouseOverHandle = r; found = true; break; } } if (!found) { m_mouseOverHandle = nullptr; } updateCursor(); } } void CaptureWidget::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) { m_colorPicker->hide(); m_rightClick = false; // when we end the drawing of a modification in the capture we have to // register the last point and add the whole modification to the screenshot } else if (m_mouseIsClicked && m_state != CaptureButton::TYPE_MOVESELECTION) { m_screenshot->paintModification(m_modifications.last()); update(); } if (!m_buttonHandler->isVisible() && !m_selection.isNull()) { updateSizeIndicator(); m_buttonHandler->updatePosition(m_selection); m_buttonHandler->show(); } m_mouseIsClicked = false; m_newSelection = false; m_grabbing = false; updateCursor(); } void CaptureWidget::keyPressEvent(QKeyEvent *e) { if (m_selection.isNull()) { return; } else if (e->key() == Qt::Key_Up && m_selection.top() > rect().top()) { m_selection.moveTop(m_selection.top()-1); m_buttonHandler->updatePosition(m_selection); updateHandles(); update(); } else if (e->key() == Qt::Key_Down && m_selection.bottom() < rect().bottom()) { m_selection.moveBottom(m_selection.bottom()+1); m_buttonHandler->updatePosition(m_selection); updateHandles(); update(); } else if (e->key() == Qt::Key_Left && m_selection.left() > rect().left()) { m_selection.moveLeft(m_selection.left()-1); m_buttonHandler->updatePosition(m_selection); updateHandles(); update(); } else if (e->key() == Qt::Key_Right && m_selection.right() < rect().right()) { m_selection.moveRight(m_selection.right()+1); m_buttonHandler->updatePosition(m_selection); updateHandles(); update(); } } void CaptureWidget::wheelEvent(QWheelEvent *e) { m_thickness += e->delta() / 120; m_thickness = qBound(0, m_thickness, 100); QPoint topLeft = qApp->desktop()->screenGeometry( qApp->desktop()->screenNumber(QCursor::pos())).topLeft(); int offset = m_notifierBox->width() / 4; m_notifierBox->move(mapFromGlobal(topLeft) + QPoint(offset, offset)); m_notifierBox->showMessage(QString::number(m_thickness)); if (m_toolIsForDrawing) { update(); } } bool CaptureWidget::undo() { bool itemRemoved = false; if (!m_modifications.isEmpty()) { m_modifications.last()->deleteLater(); m_modifications.pop_back(); m_screenshot->overrideModifications(m_modifications); update(); itemRemoved = true; } return itemRemoved; } void CaptureWidget::setState(CaptureButton *b) { CaptureButton::ButtonType t = b->buttonType(); if (b->tool()->isSelectable()) { if (t != m_state) { m_state = t; m_toolIsForDrawing = (b->tool()->toolType() != CaptureTool::ToolWorkType::TYPE_WORKER) && b->buttonType() != CaptureButton::TYPE_BLUR; if (m_lastPressedButton) { m_lastPressedButton->setColor(m_uiColor); } m_lastPressedButton = b; m_lastPressedButton->setColor(m_contrastUiColor); } else { handleButtonSignal(CaptureTool::REQ_MOVE_MODE); } update(); // clear mouse preview } } void CaptureWidget::handleButtonSignal(CaptureTool::Request r) { switch (r) { case CaptureTool::REQ_CLEAR_MODIFICATIONS: while(undo()); break; case CaptureTool::REQ_CLOSE_GUI: close(); break; case CaptureTool::REQ_HIDE_GUI: hide(); break; case CaptureTool::REQ_HIDE_SELECTION: m_newSelection = true; m_selection = QRect(); updateCursor(); break; case CaptureTool::REQ_SAVE_SCREENSHOT: saveScreenshot(); break; case CaptureTool::REQ_SELECT_ALL: m_selection = rect(); break; case CaptureTool::REQ_TO_CLIPBOARD: copyScreenshot(); break; case CaptureTool::REQ_UNDO_MODIFICATION: undo(); break; case CaptureTool::REQ_UPLOAD_TO_IMGUR: uploadToImgur(); break; case CaptureTool::REQ_OPEN_APP: openWithProgram(); break; case CaptureTool::REQ_MOVE_MODE: m_state = CaptureButton::TYPE_MOVESELECTION; m_toolIsForDrawing = false; if (m_lastPressedButton) { m_lastPressedButton->setColor(m_uiColor); m_lastPressedButton = nullptr; } break; default: break; } } void CaptureWidget::leftResize() { if (!m_selection.isNull() && m_selection.right() > m_selection.left()) { m_selection.setRight(m_selection.right()-1); m_buttonHandler->updatePosition(m_selection); updateSizeIndicator(); updateHandles(); update(); } } void CaptureWidget::rightResize() { if (!m_selection.isNull() && m_selection.right() < rect().right()) { m_selection.setRight(m_selection.right()+1); m_buttonHandler->updatePosition(m_selection); updateSizeIndicator(); updateHandles(); update(); } } void CaptureWidget::upResize() { if (!m_selection.isNull() && m_selection.bottom() > m_selection.top()) { m_selection.setBottom(m_selection.bottom()-1); m_buttonHandler->updatePosition(m_selection); updateSizeIndicator(); updateHandles(); update(); } } void CaptureWidget::downResize() { if (!m_selection.isNull() && m_selection.bottom() < rect().bottom()) { m_selection.setBottom(m_selection.bottom()+1); m_buttonHandler->updatePosition(m_selection); updateSizeIndicator(); updateHandles(); update(); } } void CaptureWidget::initShortcuts() { new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this, SLOT(close())); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_S), this, SLOT(saveScreenshot())); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), this, SLOT(copyScreenshot())); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Z), this, SLOT(undo())); new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Right), this, SLOT(rightResize())); new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Left), this, SLOT(leftResize())); new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Up), this, SLOT(upResize())); new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Down), this, SLOT(downResize())); new QShortcut(Qt::Key_Escape, this, SLOT(close())); new QShortcut(Qt::Key_Return, this, SLOT(copyScreenshot())); } void CaptureWidget::updateHandles() { QRect r = m_selection.normalized().adjusted(0, 0, -1, -1); int s2 = handleSize() / 2; m_TLHandle.moveTopLeft(QPoint(r.x() - s2, r.y() - s2)); m_TRHandle.moveTopRight(QPoint(r.right() + s2, r.y() - s2)); m_BRHandle.moveBottomRight(QPoint(r.x() + r.width() + s2, r.bottom() + s2)); m_BLHandle.moveBottomLeft(QPoint(QPoint(r.x() - s2, r.bottom() + s2))); m_LHandle.moveTopLeft(QPoint(r.x() - s2, r.y() + r.height() / 2 - s2)); m_THandle.moveTopLeft(QPoint(r.x() + r.width() / 2 - s2, r.y() - s2)); m_RHandle.moveTopRight(QPoint(r.right() + s2, r.y() + r.height() / 2 - s2)); m_BHandle.moveBottomLeft(QPoint(r.x() + r.width() / 2 - s2, r.bottom() + s2)); m_LSide = QRect(m_TLHandle.bottomLeft(), m_BLHandle.topRight()); m_RSide = QRect(m_TRHandle.bottomLeft(), m_BRHandle.topRight()); m_BSide = QRect(m_BLHandle.topRight(), m_BRHandle.bottomLeft()); m_TSide = QRect(m_TLHandle.topRight(), m_TRHandle.bottomLeft()); } void CaptureWidget::updateSizeIndicator() { if (m_sizeIndButton){ const QRect &selection = extendedSelection(); m_sizeIndButton->setText(QStringLiteral("%1\n%2") .arg(selection.width()) .arg(selection.height())); } } void CaptureWidget::updateCursor() { if (m_rightClick) { setCursor(Qt::ArrowCursor); } else if (m_grabbing) { setCursor(Qt::ClosedHandCursor); } else if (m_state == CaptureButton::TYPE_MOVESELECTION) { if (m_mouseOverHandle){ // cursor on the handlers if (m_mouseOverHandle == &m_TLHandle || m_mouseOverHandle == &m_BRHandle) { setCursor(Qt::SizeFDiagCursor); } else if (m_mouseOverHandle == &m_TRHandle || m_mouseOverHandle == &m_BLHandle) { setCursor(Qt::SizeBDiagCursor); } else if (m_mouseOverHandle == &m_LSide || m_mouseOverHandle == &m_RSide) { setCursor(Qt::SizeHorCursor); } else if (m_mouseOverHandle == &m_TSide || m_mouseOverHandle == &m_BSide) { setCursor(Qt::SizeVerCursor); } } else if (m_selection.contains(m_mousePos)) { setCursor(Qt::OpenHandCursor); } else { setCursor(Qt::CrossCursor); } } else { setCursor(Qt::CrossCursor); } } int CaptureWidget::handleSize() { return (QApplication::fontMetrics().height() * 0.7); } void CaptureWidget::copyScreenshot() { m_captureDone = true; hide(); ResourceExporter().captureToClipboard(pixmap()); close(); } void CaptureWidget::saveScreenshot() { m_captureDone = true; hide(); if (m_forcedSavePath.isEmpty()) { ResourceExporter().captureToFileUi(pixmap()); } else { ResourceExporter().captureToFile(pixmap(), m_forcedSavePath); } close(); } void CaptureWidget::uploadToImgur() { m_captureDone = true; hide(); ResourceExporter().captureToImgur(pixmap()); close(); } void CaptureWidget::openWithProgram() { m_captureDone = true; hide(); ResourceExporter().captureToProgram(pixmap()); close(); } QRect CaptureWidget::extendedSelection() const { if (m_selection.isNull()) return QRect(); auto devicePixelRatio = m_screenshot->screenshot().devicePixelRatio(); return QRect(m_selection.left() * devicePixelRatio, m_selection.top() * devicePixelRatio, m_selection.width() * devicePixelRatio, m_selection.height() * devicePixelRatio); } flameshot-0.5.1/src/capture/widgets/capturewidget.h000066400000000000000000000102371324424505000224210ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . // Based on Lightscreen areadialog.h, Copyright 2017 Christian Kaiser // released under the GNU GPL2 // Based on KDE's KSnapshot regiongrabber.cpp, revision 796531, Copyright 2007 Luca Gugelmann // released under the GNU LGPL #pragma once #include "capturebutton.h" #include "src/capture/tools/capturetool.h" #include "src/utils/confighandler.h" #include "buttonhandler.h" #include #include class QPaintEvent; class QResizeEvent; class QMouseEvent; class CaptureModification; class QNetworkAccessManager; class QNetworkReply; class ColorPicker; class Screenshot; class NotifierBox; class CaptureWidget : public QWidget { Q_OBJECT public: enum LaunchMode { WINDOW_MODE, FULLSCREEN, }; explicit CaptureWidget(const uint id = 0, const QString &forcedSavePath = QString(), CaptureWidget::LaunchMode mode = LaunchMode::FULLSCREEN, QWidget *parent = nullptr); ~CaptureWidget(); void updateButtons(); QPixmap pixmap(); signals: void captureTaken(uint id, QByteArray p); void captureFailed(uint id); private slots: void copyScreenshot(); void saveScreenshot(); void uploadToImgur(); void openWithProgram(); bool undo(); void leftResize(); void rightResize(); void upResize(); void downResize(); void setState(CaptureButton *); void handleButtonSignal(CaptureTool::Request r); protected: void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void keyPressEvent(QKeyEvent *); void wheelEvent(QWheelEvent *); // pixel map of the screen Screenshot* m_screenshot; QPoint m_dragStartPoint; QPoint m_mousePos; // pointer to the handlers under the mouse QRect *m_mouseOverHandle; QRect m_selection; QRect m_selectionBeforeDrag; // utility flags bool m_mouseIsClicked; bool m_rightClick; bool m_newSelection; bool m_grabbing; bool m_showInitialMsg; bool m_captureDone; bool m_toolIsForDrawing; const QString m_forcedSavePath; int m_thickness; int m_opacity; uint m_id; NotifierBox *m_notifierBox; // naming convention for handles // T top, B bottom, R Right, L left // 2 letters: a corner // 1 letter: the handle on the middle of the corresponding side QRect m_TLHandle, m_TRHandle, m_BLHandle, m_BRHandle; QRect m_LHandle, m_THandle, m_RHandle, m_BHandle; // Side Rects QRect m_LSide, m_TSide, m_RSide, m_BSide; // list containing the active habdlers QVector m_handles; QVector m_sides; private: void initShortcuts(); void updateHandles(); void updateSizeIndicator(); void updateCursor(); // size of the handlers at the corners of the selection int handleSize(); QRect extendedSelection() const; QVector m_modifications; QPointer m_sizeIndButton; QPointer m_lastPressedButton; CaptureButton::ButtonType m_state; ButtonHandler *m_buttonHandler; QColor m_uiColor; QColor m_contrastUiColor; ColorPicker *m_colorPicker; ConfigHandler m_config; }; flameshot-0.5.1/src/capture/widgets/colorpicker.cpp000066400000000000000000000075001324424505000224200ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "colorpicker.h" #include "src/utils/confighandler.h" #include "src/capture/widgets/capturebutton.h" #include #include ColorPicker::ColorPicker(QWidget *parent) : QWidget(parent) { ConfigHandler config; m_colorList = config.getUserColors(); m_colorAreaSize = CaptureButton::buttonBaseSize() * 0.6; setMouseTracking(true); // save the color values in member variables for faster access m_uiColor = config.uiMainColorValue(); m_drawColor = config.drawColorValue(); // extraSize represents the extra space needed for the highlight of the // selected color. const int extraSize = 6; double radius = (m_colorList.size()*m_colorAreaSize/1.3)/(3.141592); resize(radius*2 + m_colorAreaSize + extraSize, radius*2 + m_colorAreaSize+ extraSize); double degree = 360 / (m_colorList.size()); double degreeAcum = degree; // this line is the radius of the circle which will be rotated to add // the color components. QLineF baseLine = QLineF(QPoint(radius+extraSize/2, radius+extraSize/2), QPoint(radius*2, radius)); for (int i = 0; i rects = handleMask(); painter.setPen(QColor(Qt::black)); for (int i = 0; i < rects.size(); ++i) { // draw the highlight when we have to draw the selected color if (m_drawColor == QColor(m_colorList.at(i))) { QColor c = QColor(m_uiColor); c.setAlpha(155); painter.setBrush(c); c.setAlpha(100); painter.setPen(c); QRect highlight = rects.at(i); highlight.moveTo(highlight.x() - 3, highlight.y() - 3); highlight.setHeight(highlight.height() + 6); highlight.setWidth(highlight.width() + 6); painter.drawRoundRect(highlight, 100, 100); painter.setPen(QColor(Qt::black)); } painter.setBrush(QColor(m_colorList.at(i))); painter.drawRoundRect(rects.at(i), 100, 100); } } void ColorPicker::mouseMoveEvent(QMouseEvent *e) { for (int i = 0; i < m_colorList.size(); ++i) { if (m_colorAreaList.at(i).contains(e->pos())) { m_drawColor = m_colorList.at(i); update(); break; } } } QVector ColorPicker::handleMask() const { QVector areas; for (const QRect &rect: m_colorAreaList) { areas.append(rect); } return areas; } flameshot-0.5.1/src/capture/widgets/colorpicker.h000066400000000000000000000023761324424505000220730ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class ColorPicker : public QWidget { Q_OBJECT public: explicit ColorPicker(QWidget *parent = nullptr); ~ColorPicker(); QColor drawColor(); void show(); void hide(); protected: void paintEvent(QPaintEvent *); void mouseMoveEvent(QMouseEvent *); QVector handleMask() const; private: int m_colorAreaSize; QVector m_colorAreaList; QVector m_colorList; QColor m_uiColor, m_drawColor; }; flameshot-0.5.1/src/capture/widgets/notifierbox.cpp000066400000000000000000000041641324424505000224370ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "notifierbox.h" #include "src/utils/confighandler.h" #include "src/capture/widgets/capturebutton.h" #include #include #include NotifierBox::NotifierBox(QWidget *parent) : QWidget(parent) { m_timer = new QTimer(this); m_timer->setSingleShot(true); m_timer->setInterval(1200); connect(m_timer, &QTimer::timeout, this, &NotifierBox::hide); m_bgColor = ConfigHandler().uiMainColorValue(); m_foregroundColor = (CaptureButton::iconIsWhiteByColor(m_bgColor) ? Qt::white : Qt::black); m_bgColor.setAlpha(180); const int size = (CaptureButton::buttonBaseSize() + CaptureButton::buttonBaseSize()/2) * qApp->devicePixelRatio(); setFixedSize(QSize(size, size)); } void NotifierBox::enterEvent(QEvent *) { hide(); } void NotifierBox::paintEvent(QPaintEvent *) { QPainter painter(this); // draw Elipse painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(QBrush(m_bgColor, Qt::SolidPattern)); painter.setPen(QPen(Qt::transparent)); painter.drawEllipse(rect()); // Draw the text: painter.setPen(QPen(m_foregroundColor)); painter.drawText(rect(), Qt::AlignCenter, m_message); } void NotifierBox::showMessage(const QString &msg) { m_message = msg; update(); show(); m_timer->start(); } flameshot-0.5.1/src/capture/widgets/notifierbox.h000066400000000000000000000022621324424505000221010ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class QTimer; class NotifierBox : public QWidget { Q_OBJECT public: explicit NotifierBox(QWidget *parent = nullptr); protected: virtual void enterEvent(QEvent *); virtual void paintEvent(QPaintEvent *); public slots: void showMessage(const QString &msg); private: QTimer *m_timer; QString m_message; QColor m_bgColor; QColor m_foregroundColor; }; flameshot-0.5.1/src/capture/workers/000077500000000000000000000000001324424505000174245ustar00rootroot00000000000000flameshot-0.5.1/src/capture/workers/imgur/000077500000000000000000000000001324424505000205475ustar00rootroot00000000000000flameshot-0.5.1/src/capture/workers/imgur/imguruploader.cpp000066400000000000000000000125441324424505000241400ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "imguruploader.h" #include "src/utils/filenamehandler.h" #include "src/utils/systemnotification.h" #include "src/widgets/loadspinner.h" #include "src/widgets/imagelabel.h" #include "src/widgets/notificationwidget.h" #include "src/utils/confighandler.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ImgurUploader::ImgurUploader(const QPixmap &capture, QWidget *parent) : QWidget(parent), m_pixmap(capture) { setWindowTitle(tr("Upload to Imgur")); m_spinner = new LoadSpinner(this); m_spinner->setColor(ConfigHandler().uiMainColorValue()); m_spinner->start(); m_infoLabel = new QLabel(tr("Uploading Image")); m_vLayout = new QVBoxLayout(); setLayout(m_vLayout); m_vLayout->addWidget(m_spinner, 0, Qt::AlignHCenter); m_vLayout->addWidget(m_infoLabel); m_NetworkAM = new QNetworkAccessManager(this); connect(m_NetworkAM, &QNetworkAccessManager::finished, this, &ImgurUploader::handleReply); setAttribute(Qt::WA_DeleteOnClose); upload(); // QTimer::singleShot(2000, this, &ImgurUploader::onUploadOk); // testing } void ImgurUploader::handleReply(QNetworkReply *reply) { m_spinner->deleteLater(); if (reply->error() == QNetworkReply::NoError) { QString data = QString::fromUtf8(reply->readAll()); QString imageID = data.split("\"").at(5); QString url = QStringLiteral("http://i.imgur.com/%1.png").arg(imageID); m_imageURL.setUrl(url); onUploadOk(); } else { m_infoLabel->setText(reply->errorString()); } new QShortcut(Qt::Key_Escape, this, SLOT(close())); } void ImgurUploader::startDrag() { QMimeData *mimeData = new QMimeData; mimeData->setUrls(QList { m_imageURL }); mimeData->setImageData(m_pixmap); QDrag *dragHandler = new QDrag(this); dragHandler->setMimeData(mimeData); dragHandler->setPixmap(m_pixmap.scaled(256, 256, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); dragHandler->exec(); } void ImgurUploader::upload() { QByteArray byteArray; QBuffer buffer(&byteArray); m_pixmap.save(&buffer, "PNG"); QUrlQuery urlQuery; urlQuery.addQueryItem("title", "flameshot_screenshot"); QString description = FileNameHandler().parsedPattern(); urlQuery.addQueryItem("description", description); QUrl url("https://api.imgur.com/3/image"); url.setQuery(urlQuery); QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/application/x-www-form-urlencoded"); request.setRawHeader("Authorization", "Client-ID 313baf0c7b4d3ff"); m_NetworkAM->post(request, byteArray); } void ImgurUploader::onUploadOk() { m_infoLabel->deleteLater(); m_notification = new NotificationWidget(); m_vLayout->addWidget(m_notification); ImageLabel *imageLabel = new ImageLabel(); imageLabel->setScreenshot(m_pixmap); imageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); connect(imageLabel, &ImageLabel::dragInitiated, this, &ImgurUploader::startDrag); m_vLayout->addWidget(imageLabel); m_hLayout = new QHBoxLayout(); m_vLayout->addLayout(m_hLayout); m_copyUrlButton = new QPushButton(tr("Copy URL")); m_openUrlButton = new QPushButton(tr("Open URL")); m_toClipboardButton = new QPushButton(tr("Image to Clipboard.")); m_hLayout->addWidget(m_copyUrlButton); m_hLayout->addWidget(m_openUrlButton); m_hLayout->addWidget(m_toClipboardButton); connect(m_copyUrlButton, &QPushButton::clicked, this, &ImgurUploader::copyURL); connect(m_openUrlButton, &QPushButton::clicked, this, &ImgurUploader::openURL); connect(m_toClipboardButton, &QPushButton::clicked, this, &ImgurUploader::copyImage); } void ImgurUploader::openURL() { bool successful = QDesktopServices::openUrl(m_imageURL); if (!successful) { m_notification->showMessage(tr("Unable to open the URL.")); } } void ImgurUploader::copyURL() { QApplication::clipboard()->setText(m_imageURL.toString()); m_notification->showMessage(tr("URL copied to clipboard.")); } void ImgurUploader::copyImage() { QApplication::clipboard()->setPixmap(m_pixmap); m_notification->showMessage(tr("Screenshot copied to clipboard.")); } flameshot-0.5.1/src/capture/workers/imgur/imguruploader.h000066400000000000000000000032621324424505000236020ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include class QNetworkReply; class QNetworkAccessManager; class QHBoxLayout; class QVBoxLayout; class QLabel; class LoadSpinner; class QPushButton; class QUrl; class NotificationWidget; class ImgurUploader : public QWidget { Q_OBJECT public: explicit ImgurUploader(const QPixmap &p, QWidget *parent = nullptr); private slots: void handleReply(QNetworkReply *reply); void startDrag(); void openURL(); void copyURL(); void copyImage(); private: QPixmap m_pixmap; QNetworkAccessManager *m_NetworkAM; QVBoxLayout *m_vLayout; QHBoxLayout *m_hLayout; // loading QLabel *m_infoLabel; LoadSpinner *m_spinner; // uploaded QPushButton *m_openUrlButton; QPushButton *m_copyUrlButton; QPushButton *m_toClipboardButton; QUrl m_imageURL; NotificationWidget *m_notification; void upload(); void onUploadOk(); }; flameshot-0.5.1/src/capture/workers/launcher/000077500000000000000000000000001324424505000212255ustar00rootroot00000000000000flameshot-0.5.1/src/capture/workers/launcher/applauncherwidget.cpp000066400000000000000000000207561324424505000254510ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "applauncherwidget.h" #include "src/utils/filenamehandler.h" #include "src/capture/workers/launcher/launcheritemdelegate.h" #include "src/capture/widgets/capturebutton.h" #include "src/utils/confighandler.h" #include "terminallauncher.h" #include #include #include #include #include #include #include #include #include #include #include namespace { QMap catIconNames({ { "Multimedia", "applications-multimedia" }, { "Development","applications-development" }, { "Graphics", "applications-graphics" }, { "Network", "preferences-system-network" }, { "Office", "applications-office" }, { "Science", "applications-science" }, { "Settings", "preferences-desktop" }, { "System", "preferences-system" }, { "Utility", "applications-utilities" } }); } AppLauncherWidget::AppLauncherWidget(const QPixmap &p, QWidget *parent): QWidget(parent), m_pixmap(p) { setAttribute(Qt::WA_DeleteOnClose); setWindowIcon(QIcon(":img/flameshot.png")); setWindowTitle(tr("Open With")); m_keepOpen = ConfigHandler().keepOpenAppLauncherValue(); QString dirLocal = QDir::homePath() + "/.local/share/applications/"; QDir appsDirLocal(dirLocal); m_parser.processDirectory(appsDirLocal); QString dir = "/usr/share/applications/"; QDir appsDir(dir); m_parser.processDirectory(appsDir); initAppMap(); initListWidget(); m_terminalCheckbox = new QCheckBox(tr("Launch in terminal"), this); m_keepOpenCheckbox = new QCheckBox(tr("Keep open after selection"), this); m_keepOpenCheckbox->setChecked(ConfigHandler().keepOpenAppLauncherValue()); connect(m_keepOpenCheckbox, &QCheckBox::clicked, this, &AppLauncherWidget::checkboxClicked); // search items m_lineEdit = new QLineEdit; connect(m_lineEdit, &QLineEdit::textChanged, this, &AppLauncherWidget::searchChanged); m_filterList = new QListWidget; m_filterList->hide(); configureListView(m_filterList); connect(m_filterList, &QListWidget::clicked, this, &AppLauncherWidget::launch); m_layout = new QVBoxLayout(this); m_layout->addWidget(m_filterList); m_layout->addWidget(m_tabWidget); m_layout->addWidget(m_lineEdit); m_layout->addWidget(m_keepOpenCheckbox); m_layout->addWidget(m_terminalCheckbox); m_lineEdit->setFocus(); } void AppLauncherWidget::launch(const QModelIndex &index) { if (!QFileInfo(m_tempFile).isReadable()) { m_tempFile = FileNameHandler().generateAbsolutePath(QDir::tempPath()) + ".png"; bool ok = m_pixmap.save(m_tempFile); if (!ok) { QMessageBox::about(this, tr("Error"), tr("Unable to write in") + QDir::tempPath()); return; } } QString command = index.data(Qt::UserRole).toString().replace( QRegExp("(\\%.)"), '"' + m_tempFile + '"'); bool inTerminal = index.data(Qt::UserRole+1).toBool() || m_terminalCheckbox->isChecked(); if (inTerminal) { bool ok = TerminalLauncher::launchDetached(command); if (!ok) { QMessageBox::about(this, tr("Error"), tr("Unable to launch in terminal.")); } } else { QProcess::startDetached(command); } if (!m_keepOpen) { close(); } } void AppLauncherWidget::checkboxClicked(const bool enabled) { m_keepOpen = enabled; ConfigHandler().setKeepOpenAppLauncher(enabled); m_keepOpenCheckbox->setChecked(enabled); } void AppLauncherWidget::searchChanged(const QString &text) { if (text.isEmpty()) { m_filterList->hide(); m_tabWidget->show(); } else { m_tabWidget->hide(); m_filterList->show(); m_filterList->clear(); QRegExp regexp(text, Qt::CaseInsensitive, QRegExp::Wildcard); QVector apps; for (auto const& i : catIconNames.toStdMap()) { const QString &cat = i.first; if (!m_appsMap.contains(cat)) { continue; } const QVector &appList = m_appsMap[cat]; for (const DesktopAppData &app: appList) { if (!apps.contains(app) && (app.name.contains(regexp) || app.description.contains(regexp) )) { apps.append(app); } } } addAppsToListWidget(m_filterList, apps); } } void AppLauncherWidget::initListWidget() { m_tabWidget = new QTabWidget; const int size = CaptureButton::buttonBaseSize(); m_tabWidget->setIconSize(QSize(size, size)); for (auto const& i : catIconNames.toStdMap()) { const QString &cat = i.first; const QString &iconName = i.second; if (!m_appsMap.contains(cat)) { continue; } QListWidget *itemsWidget = new QListWidget(); configureListView(itemsWidget); const QVector &appList = m_appsMap[cat]; addAppsToListWidget(itemsWidget, appList); m_tabWidget->addTab(itemsWidget, QIcon::fromTheme(iconName), ""); m_tabWidget->setTabToolTip(m_tabWidget->count(), cat); if (cat == "Graphics") { m_tabWidget->setCurrentIndex(m_tabWidget->count() -1); } } } void AppLauncherWidget::initAppMap() { QStringList categories({"AudioVideo", "Audio", "Video", "Development", "Graphics", "Network", "Office", "Science", "Settings", "System", "Utility"}); m_appsMap = m_parser.getAppsByCategory(categories); // Unify multimedia. QVector multimediaList; QStringList multimediaNames; multimediaNames << "AudioVideo" << "Audio" << "Video"; for (const QString &name : multimediaNames) { if(!m_appsMap.contains(name)) { continue; } for (auto i : m_appsMap[name]) { if (!multimediaList.contains(i)) { multimediaList.append(i); } } m_appsMap.remove(name); } m_appsMap.insert("Multimedia", multimediaList); } void AppLauncherWidget::configureListView(QListWidget *widget) { widget->setItemDelegate(new LauncherItemDelegate()); widget->setViewMode(QListWidget::IconMode); widget->setResizeMode(QListView::Adjust); widget->setSpacing(4); widget->setFlow(QListView::LeftToRight); widget->setDragEnabled(false); widget->setMinimumWidth(CaptureButton::buttonBaseSize() * 11); connect(widget, &QListWidget::clicked, this, &AppLauncherWidget::launch); } void AppLauncherWidget::addAppsToListWidget( QListWidget *widget, const QVector &appList) { for (const DesktopAppData &app: appList) { QListWidgetItem *buttonItem = new QListWidgetItem(widget); buttonItem->setData(Qt::DecorationRole, app.icon); buttonItem->setData(Qt::DisplayRole, app.name); buttonItem->setData(Qt::UserRole, app.exec); buttonItem->setData(Qt::UserRole+1, app.showInTerminal); QColor foregroundColor = this->palette().color(QWidget::foregroundRole()); buttonItem->setForeground(foregroundColor); buttonItem->setIcon(app.icon); buttonItem->setText(app.name); buttonItem->setToolTip(app.description); } } flameshot-0.5.1/src/capture/workers/launcher/applauncherwidget.h000066400000000000000000000034361324424505000251120ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "src/utils/desktopfileparse.h" #include #include class QTabWidget; class QCheckBox; class QVBoxLayout; class QLineEdit; class QListWidget; class AppLauncherWidget: public QWidget { Q_OBJECT public: explicit AppLauncherWidget(const QPixmap &p, QWidget *parent = nullptr); private slots: void launch(const QModelIndex &index); void checkboxClicked(const bool enabled); void searchChanged(const QString &text); private: void initListWidget(); void initAppMap(); void configureListView(QListWidget *widget); void addAppsToListWidget(QListWidget *widget, const QVector &appList); DesktopFileParser m_parser; QPixmap m_pixmap; QString m_tempFile; bool m_keepOpen; QMap> m_appsMap; QCheckBox *m_keepOpenCheckbox; QCheckBox *m_terminalCheckbox; QVBoxLayout *m_layout; QLineEdit *m_lineEdit; QListWidget *m_filterList; QTabWidget *m_tabWidget; }; flameshot-0.5.1/src/capture/workers/launcher/launcheritemdelegate.cpp000066400000000000000000000047661324424505000261210ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "launcheritemdelegate.h" #include "src/capture/widgets/capturebutton.h" #include LauncherItemDelegate::LauncherItemDelegate(QObject *parent) : QStyledItemDelegate(parent) { } void LauncherItemDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { const QRect &rect = option.rect; if (option.state & (QStyle::State_Selected | QStyle::State_MouseOver)) { painter->save(); painter->setPen(Qt::transparent); painter->setBrush(QPalette().highlight()); painter->drawRect(rect.x(), rect.y(), rect.width() -1, rect.height() -1); painter->restore(); } QIcon icon = index.data(Qt::DecorationRole).value(); const int iconSide = CaptureButton::buttonBaseSize() * 1.3; const int halfIcon = iconSide/2; const int halfWidth = rect.width()/2; const int halfHeight = rect.height()/2; QSize size(iconSide, iconSide); QPixmap pixIcon = icon.pixmap(size).scaled(size, Qt::KeepAspectRatio); painter->drawPixmap(rect.x() + (halfWidth - halfIcon), rect.y()+ (halfHeight/2 - halfIcon), iconSide, iconSide, pixIcon); const QRect textRect(rect.x(), rect.y() + halfHeight, rect.width(), halfHeight); painter->drawText(textRect, Qt::TextWordWrap | Qt::AlignHCenter, index.data(Qt::DisplayRole).toString()); } QSize LauncherItemDelegate::sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(option); Q_UNUSED(index); const int size = CaptureButton::buttonBaseSize(); return QSize(size * 3.2, size * 3.7); } flameshot-0.5.1/src/capture/workers/launcher/launcheritemdelegate.h000066400000000000000000000023351324424505000255540ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "src/utils/desktopfileparse.h" #include class LauncherItemDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit LauncherItemDelegate(QObject *parent = nullptr); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; private: }; flameshot-0.5.1/src/capture/workers/launcher/openwithprogram.cpp000066400000000000000000000033701324424505000251610ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "openwithprogram.h" #if defined(Q_OS_WIN) #include "src/utils/filenamehandler.h" #include #include #include #include #pragma comment(lib, "Shell32.lib") #else #include "src/capture/workers/launcher/applauncherwidget.h" #endif void showOpenWithMenu(const QPixmap &capture) { #if defined(Q_OS_WIN) QString tempFile = FileNameHandler().generateAbsolutePath(QDir::tempPath()) + ".png"; bool ok = capture.save(tempFile); if (!ok) { QMessageBox::about(nullptr, QObject::tr("Error"), QObject::tr("Unable to write in") + QDir::tempPath()); return; } OPENASINFO info; auto wStringFile = tempFile.replace("/", "\\").toStdWString(); info.pcszFile = wStringFile.c_str(); info.pcszClass = nullptr; info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC; SHOpenWithDialog(nullptr, &info); #else auto w = new AppLauncherWidget(capture); w->show(); #endif } flameshot-0.5.1/src/capture/workers/launcher/openwithprogram.h000066400000000000000000000015361324424505000246300ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include void showOpenWithMenu(const QPixmap &capture); flameshot-0.5.1/src/capture/workers/launcher/terminallauncher.cpp000066400000000000000000000040241324424505000252660ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "terminallauncher.h" #include #include #include #include namespace { static const TerminalApp terminalApps[] = { { "x-terminal-emulator", "-e" }, { "xfce4-terminal", "-x" }, { "konsole", "-e" }, { "gnome-terminal", "--" }, { "terminator", "-e" }, { "terminology", "-e" }, { "tilix", "-e" }, { "xterm", "-e" }, { "aterm", "-e" }, { "Eterm", "-e" }, { "rxvt", "-e" }, { "urxvt", "-e" }, }; } TerminalLauncher::TerminalLauncher(QObject *parent) : QObject(parent) { } TerminalApp TerminalLauncher::getPreferedTerminal() { TerminalApp res; for (const TerminalApp &app : terminalApps) { QString path = QStandardPaths::findExecutable(app.name); if (!path.isEmpty()) { res = app; break; } } return res; } bool TerminalLauncher::launchDetached(const QString &command) { TerminalApp app = getPreferedTerminal(); QString s = app.name + " " + app.arg + " " + command; return QProcess::startDetached(s); } flameshot-0.5.1/src/capture/workers/launcher/terminallauncher.h000066400000000000000000000021271324424505000247350ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include struct TerminalApp { QString name; QString arg; }; class TerminalLauncher : public QObject { Q_OBJECT public: explicit TerminalLauncher(QObject *parent = nullptr); static bool launchDetached(const QString &command); private: static TerminalApp getPreferedTerminal(); }; flameshot-0.5.1/src/capture/workers/screenshotsaver.cpp000066400000000000000000000053741324424505000233570ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "screenshotsaver.h" #include "src/utils/systemnotification.h" #include "src/utils/filenamehandler.h" #include "src/utils/confighandler.h" #include #include #include #include #include ScreenshotSaver::ScreenshotSaver() { } void ScreenshotSaver::saveToClipboard(const QPixmap &capture) { QApplication::clipboard()->setPixmap(capture); } void ScreenshotSaver::saveToFilesystem(const QPixmap &capture, const QString &path) { QString completePath = FileNameHandler().generateAbsolutePath(path); completePath += ".png"; bool ok = capture.save(completePath); QString saveMessage; if (ok) { ConfigHandler().setSavePath(path); saveMessage = QObject::tr("Capture saved as ") + completePath; } else { saveMessage = QObject::tr("Error trying to save as ") + completePath; } SystemNotification().sendMessage(saveMessage); } void ScreenshotSaver::saveToFilesystemGUI(const QPixmap &capture) { bool ok = false; while (!ok) { QString savePath = QFileDialog::getSaveFileName( nullptr, QString(), FileNameHandler().absoluteSavePath() + ".png"); if (savePath.isNull()) { return; } ok = capture.save(savePath); if (ok) { QString pathNoFile = savePath.left(savePath.lastIndexOf("/")); ConfigHandler().setSavePath(pathNoFile); QString msg = QObject::tr("Capture saved as ") + savePath; SystemNotification().sendMessage(msg); } else { QString msg = QObject::tr("Error trying to save as ") + savePath; QMessageBox saveErrBox( QMessageBox::Warning, QObject::tr("Save Error"), msg); saveErrBox.setWindowIcon(QIcon(":img/flameshot.png")); saveErrBox.exec(); } } } flameshot-0.5.1/src/capture/workers/screenshotsaver.h000066400000000000000000000020461324424505000230150ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once class QPixmap; class QString; class ScreenshotSaver { public: ScreenshotSaver(); void saveToClipboard(const QPixmap &capture); void saveToFilesystem(const QPixmap &capture, const QString &path); void saveToFilesystemGUI(const QPixmap &capture); }; flameshot-0.5.1/src/cli/000077500000000000000000000000001324424505000150345ustar00rootroot00000000000000flameshot-0.5.1/src/cli/commandargument.cpp000066400000000000000000000030651324424505000207250ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "commandargument.h" CommandArgument::CommandArgument() { } CommandArgument::CommandArgument(const QString &name, const QString &description) : m_name(name), m_description(description) { } void CommandArgument::setName(const QString &name) { m_name = name; } QString CommandArgument::name() const { return m_name; } void CommandArgument::setDescription(const QString &description) { m_description = description; } QString CommandArgument::description() const { return m_description; } bool CommandArgument::isRoot() const { return m_name.isEmpty() && m_description.isEmpty(); } bool CommandArgument::operator ==(const CommandArgument &arg) const { return m_description == arg.m_description && m_name == arg.m_name; } flameshot-0.5.1/src/cli/commandargument.h000066400000000000000000000023361324424505000203720ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class CommandArgument { public: CommandArgument(); explicit CommandArgument(const QString &name, const QString &description); void setName(const QString &name); QString name() const; void setDescription(const QString &description); QString description() const; bool isRoot() const; bool operator ==(const CommandArgument &arg) const; private: QString m_name; QString m_description; }; flameshot-0.5.1/src/cli/commandlineparser.cpp000066400000000000000000000305161324424505000212500ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "commandlineparser.h" #include #include CommandLineParser::CommandLineParser() : m_description(qApp->applicationName()) { } namespace { QTextStream out(stdout); QTextStream err(stderr); auto versionOption = CommandOption({"v", "version"}, "Displays version information"); auto helpOption = CommandOption({"h", "help"}, "Displays this help"); QStringList addDashToOptionNames(const QStringList &names) { QStringList dashedNames; for (const QString &name: names) { // prepend "-" to single character options, and "--" to the others QString dashedName = (name.length() == 1) ? QStringLiteral("-%1").arg(name) : QStringLiteral("--%1").arg(name); dashedNames << dashedName; } return dashedNames; } QString optionsToString(const QList &options, const QList &arguments) { int size = 0; // track the largest size QStringList dashedOptionList; // save the dashed options and its size in order to print the description // of every option at the same horizontal character position. for (auto const &option: options) { QStringList dashedOptions = addDashToOptionNames(option.names()); QString joinedDashedOptions = dashedOptions.join(", "); if (!option.valueName().isEmpty()) { joinedDashedOptions += QStringLiteral(" <%1>") .arg(option.valueName()); } if (joinedDashedOptions.length() > size) { size = joinedDashedOptions.length(); } dashedOptionList << joinedDashedOptions; } // check the length of the arguments for (auto const &arg: arguments) { if(arg.name().length() > size) size = arg.name().length(); } // generate the text QString result; if(!dashedOptionList.isEmpty()) { result += "Options:\n"; for (int i = 0; i < options.length(); ++i) { result += QStringLiteral(" %1 %2\n") .arg(dashedOptionList.at(i).leftJustified(size, ' ')) .arg(options.at(i).description()); } if (!arguments.isEmpty()) { result += "\n"; } } if (!arguments.isEmpty()) { result += "Arguments:\n"; } for (int i = 0; i < arguments.length(); ++i) { result += QStringLiteral(" %1 %2\n") .arg(arguments.at(i).name().leftJustified(size, ' ')) .arg(arguments.at(i).description()); } return result; } } // unnamed namespace bool CommandLineParser::processArgs(const QStringList &args, QStringList::const_iterator &actualIt, Node * &actualNode) { QString argument = *actualIt; bool ok = true; bool isValidArg = false; for (Node &n: actualNode->subNodes) { if (n.argument.name() == argument) { actualNode = &n; isValidArg = true; break; } } if (isValidArg) { auto nextArg = actualNode->argument; m_foundArgs.append(nextArg); // check next is help ++actualIt; ok = processIfOptionIsHelp(args, actualIt, actualNode); --actualIt; } else { ok = false; out << QStringLiteral("'%1' is not a valid argument.").arg(argument); } return ok; } bool CommandLineParser::processOptions(const QStringList &args, QStringList::const_iterator &actualIt, Node *const actualNode) { QString arg = *actualIt; bool ok = true; // track values int equalsPos = arg.indexOf("="); QString valueStr; if (equalsPos != -1) { valueStr = arg.mid(equalsPos +1); // right arg = arg.mid(0, equalsPos); // left } // check format -x --xx... bool isDoubleDashed = arg.startsWith("--"); ok = isDoubleDashed ? arg.length() > 3 : arg.length() == 2; if (!ok) { out << QStringLiteral("the option %1 has a wrong format.").arg(arg); return ok; } arg = isDoubleDashed ? arg.remove(0, 2) : arg.remove(0, 1); // get option auto endIt = actualNode->options.cend(); auto optionIt = endIt; for (auto i = actualNode->options.cbegin(); i != endIt; ++i) { if ((*i).names().contains(arg)) { optionIt = i; break; } } if (optionIt == endIt) { QString argName = actualNode->argument.name(); if (argName.isEmpty()) { argName = qApp->applicationName(); } out << QStringLiteral("the option '%1' is not a valid option " "for the argument '%2'.").arg(arg) .arg(argName); ok = false; return ok; } // check presence of values CommandOption option = *optionIt; bool requiresValue = !(option.valueName().isEmpty()); if (!requiresValue && equalsPos != -1) { out << QStringLiteral("the option '%1' contains a '=' and it doesn't " "require a value.").arg(arg); ok = false; return ok; } else if (requiresValue && valueStr.isEmpty()) { // find in the next if (actualIt+1 != args.cend()) { ++actualIt; } else { out << QStringLiteral("Expected value after the option '%1'.").arg(arg); ok = false; return ok; } valueStr = *actualIt; } // check the value correctness if (requiresValue) { ok = option.checkValue(valueStr); if (!ok) { QString err = option.errorMsg(); if (!err.endsWith(".")) err += "."; out << err; return ok; } option.setValue(valueStr); } m_foundOptions.append(option); return ok; } bool CommandLineParser::parse(const QStringList &args) { m_foundArgs.clear(); m_foundOptions.clear(); bool ok = true; Node *actualNode = &m_parseTree; auto it = ++args.cbegin(); // check version option QStringList dashedVersion = addDashToOptionNames(versionOption.names()); if (m_withVersion && args.length() > 1 && dashedVersion.contains(args.at(1))) { if (args.length() == 2) { printVersion(); m_foundOptions << versionOption; } else { out << "Invalid arguments after the version option."; ok = false; } return ok; } // check help option ok = processIfOptionIsHelp(args, it, actualNode); // process the other args for (; it != args.cend() && ok; ++it) { const QString &value = *it; if (value.startsWith("-")) { ok = processOptions(args, it, actualNode); } else { ok = processArgs(args, it, actualNode); } } if (!ok && !m_generalErrorMessage.isEmpty()) { out << QStringLiteral(" %1\n").arg(m_generalErrorMessage); } return ok; } CommandOption CommandLineParser::addVersionOption() { m_withVersion = true; return versionOption; } CommandOption CommandLineParser::addHelpOption() { m_withHelp = true; return helpOption; } bool CommandLineParser::AddArgument(const CommandArgument &arg, const CommandArgument &parent) { bool res = true; Node *n = findParent(parent); if (n == nullptr) { res = false; } else { Node child; child.argument = arg; n->subNodes.append(child); } return res; } bool CommandLineParser::AddOption(const CommandOption &option, const CommandArgument &parent) { bool res = true; Node *n = findParent(parent); if (n == nullptr) { res = false; } else { n->options.append(option); } return res; } bool CommandLineParser::AddOptions(const QList &options, const CommandArgument &parent) { bool res = true; for (auto const &option: options) { if (!AddOption(option, parent)) { res = false; break; } } return res; } void CommandLineParser::setGeneralErrorMessage(const QString &msg) { m_generalErrorMessage = msg; } void CommandLineParser::setDescription(const QString &description) { m_description = description; } bool CommandLineParser::isSet(const CommandArgument &arg) const { return m_foundArgs.contains(arg); } bool CommandLineParser::isSet(const CommandOption &option) const { return m_foundOptions.contains(option); } QString CommandLineParser::value(const CommandOption &option) const { QString value; for (const CommandOption &fOption: m_foundOptions) { if (option == fOption) { value = fOption.value(); break; } } return value; } void CommandLineParser::printVersion() { out << "Flameshot " << qApp->applicationVersion() << "\nCompiled with QT " << static_cast(QT_VERSION_STR) << "\n"; } void CommandLineParser::printHelp(QStringList args, const Node *node) { args.removeLast(); // remove the help, it's always the last QString helpText; // add usage info QString argName = node->argument.name(); if (argName.isEmpty()) { argName = qApp->applicationName(); } QString argText = node->subNodes.isEmpty() ? "" : "[arguments]"; helpText += QStringLiteral("Usage: %1 [%2-options] %3\n\n") .arg(args.join(" ")) .arg(argName).arg(argText); // add command options and subarguments QList subArgs; for (const Node &n: node->subNodes) subArgs.append(n.argument); auto modifiedOptions = node->options; if (m_withHelp) modifiedOptions << helpOption; if (m_withVersion && node == &m_parseTree) { modifiedOptions << versionOption; } helpText += optionsToString(modifiedOptions, subArgs); // print it out << helpText; } CommandLineParser::Node* CommandLineParser::findParent( const CommandArgument &parent) { if (parent == CommandArgument()) { return &m_parseTree; } //find the parent in the subNodes recursively Node *res = nullptr; for (auto i = m_parseTree.subNodes.begin(); i != m_parseTree.subNodes.end(); ++i) { res = recursiveParentSearch(parent, *i); if (res != nullptr) { break; } } return res; } CommandLineParser::Node* CommandLineParser::recursiveParentSearch( const CommandArgument &parent, Node &node) const { Node * res = nullptr; if (node.argument == parent) { res = &node; } else { for (auto i = node.subNodes.begin(); i != node.subNodes.end(); ++i){ res = recursiveParentSearch(parent, *i); if (res != nullptr) { break; } } } return res; } bool CommandLineParser::processIfOptionIsHelp( const QStringList &args, QStringList::const_iterator &actualIt, Node * &actualNode) { bool ok = true; auto dashedHelpNames = addDashToOptionNames(helpOption.names()); if (m_withHelp && actualIt != args.cend() && dashedHelpNames.contains(*actualIt)) { if (actualIt+1 == args.cend()) { m_foundOptions << helpOption; printHelp(args, actualNode); actualIt++; } else { out << "Invalid arguments after the help option."; ok = false; } } return ok; } flameshot-0.5.1/src/cli/commandlineparser.h000066400000000000000000000061601324424505000207130ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "src/cli/commandargument.h" #include "src/cli/commandoption.h" #include class CommandLineParser { public: CommandLineParser(); bool parse(const QStringList &args); CommandArgument rootArgument() const { return CommandArgument(); } CommandOption addVersionOption(); CommandOption addHelpOption(); bool AddArgument(const CommandArgument &arg, const CommandArgument &parent = CommandArgument()); bool AddOption(const CommandOption &option, const CommandArgument &parent = CommandArgument()); bool AddOptions(const QList &options, const CommandArgument &parent = CommandArgument()); void setGeneralErrorMessage(const QString &msg); void setDescription(const QString &description); bool isSet(const CommandArgument &arg) const; bool isSet(const CommandOption &option) const; QString value(const CommandOption &option) const; private: bool m_withHelp = false; bool m_withVersion = false; QString m_description; QString m_generalErrorMessage; struct Node { Node(const CommandArgument &arg) : argument(arg) {} Node() {} bool operator==(const Node &n) const { return argument == n.argument && options == n.options && subNodes == n.subNodes; } CommandArgument argument; QList options; QList subNodes; }; Node m_parseTree; QList m_foundOptions; QList m_foundArgs; // helper functions void printVersion(); void printHelp(QStringList args, const Node *node); Node* findParent(const CommandArgument &parent); Node* recursiveParentSearch(const CommandArgument &parent, Node &node) const; bool processIfOptionIsHelp(const QStringList &args, QStringList::const_iterator &actualIt, Node * &actualNode); bool processArgs(const QStringList &args, QStringList::const_iterator &actualIt, Node * &actualNode); bool processOptions(const QStringList &args, QStringList::const_iterator &actualIt, Node *const actualNode); }; flameshot-0.5.1/src/cli/commandoption.cpp000066400000000000000000000055021324424505000204110ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "commandoption.h" CommandOption::CommandOption(const QString &name, const QString &description, const QString &valueName, const QString &defaultValue) : m_names(name), m_description(description), m_valueName(valueName), m_value(defaultValue) { m_checker = [](QString const&){ return true; }; } CommandOption::CommandOption(const QStringList &names, const QString &description, const QString &valueName, const QString &defaultValue) : m_names(names), m_description(description), m_valueName(valueName), m_value(defaultValue) { m_checker = [](QString const&) -> bool { return true; }; } void CommandOption::setName(const QString &name) { m_names = QStringList() << name; } void CommandOption::setNames(const QStringList &names) { m_names = names; } QStringList CommandOption::names() const { return m_names; } void CommandOption::setValueName(const QString &name) { m_valueName = name; } QString CommandOption::valueName() const { return m_valueName; } void CommandOption::setValue(const QString &value) { if (m_valueName.isEmpty()) { m_valueName = "value"; } m_value = value; } QString CommandOption::value() const { return m_value; } void CommandOption::addChecker(const function checker, const QString &errMsg) { m_checker = checker; m_errorMsg = errMsg; } bool CommandOption::checkValue(const QString &value) const { return m_checker(value); } QString CommandOption::description() const { return m_description; } void CommandOption::setDescription(const QString &description) { m_description = description; } QString CommandOption::errorMsg() const { return m_errorMsg; } bool CommandOption::operator ==(const CommandOption &option) const { return m_description == option.m_description && m_names == option.m_names && m_valueName == option.m_valueName; } flameshot-0.5.1/src/cli/commandoption.h000066400000000000000000000037501324424505000200610ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include using std::function; class CommandOption { public: CommandOption(const QString &name, const QString &description, const QString &valueName = QString(), const QString &defaultValue = QString()); CommandOption(const QStringList &names, const QString &description, const QString &valueName = QString(), const QString &defaultValue = QString()); void setName(const QString &name); void setNames(const QStringList &names); QStringList names() const; void setValueName(const QString &name); QString valueName() const; void setValue(const QString &value); QString value() const; void addChecker(const function checker, const QString &errMsg); bool checkValue(const QString &value) const; QString description() const; void setDescription(const QString &description); QString errorMsg() const; bool operator==(const CommandOption &option) const; private: QStringList m_names; QString m_description; QString m_valueName; QString m_value; function m_checker; QString m_errorMsg; }; flameshot-0.5.1/src/config/000077500000000000000000000000001324424505000155325ustar00rootroot00000000000000flameshot-0.5.1/src/config/buttonlistview.cpp000066400000000000000000000075321324424505000213470ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "buttonlistview.h" #include "src/capture/tools/toolfactory.h" #include "src/utils/confighandler.h" #include #include ButtonListView::ButtonListView(QWidget *parent) : QListWidget(parent) { setMouseTracking(true); setFlow(QListWidget::TopToBottom); initButtonList(); updateComponents(); connect(this, &QListWidget::itemClicked, this, &ButtonListView::reverseItemCheck); } void ButtonListView::initButtonList() { ToolFactory factory; auto listTypes = CaptureButton::getIterableButtonTypes(); for (const CaptureButton::ButtonType t: listTypes) { CaptureTool *tool = factory.CreateTool(t); // add element to the local map m_buttonTypeByName.insert(tool->name(), t); // init the menu option QListWidgetItem *m_buttonItem = new QListWidgetItem(this); // when the background is lighter than gray, it uses the white icons QColor bgColor = this->palette().color(QWidget::backgroundRole()); QString color = bgColor.valueF() < 0.6 ? "White" : "Black"; QString iconPath = QStringLiteral(":/img/buttonIcons%1/%2") .arg(color).arg(tool->iconName()); if (t == CaptureButton::TYPE_SELECTIONINDICATOR) { iconPath = QStringLiteral(":/img/buttonIcons%1/size_indicator.png") .arg(color); } m_buttonItem->setIcon(QIcon(iconPath)); m_buttonItem->setFlags(Qt::ItemIsUserCheckable); QColor foregroundColor = this->palette().color(QWidget::foregroundRole()); m_buttonItem->setForeground(foregroundColor); m_buttonItem->setText(tool->name()); m_buttonItem->setToolTip(tool->description()); tool->deleteLater(); } } void ButtonListView::updateActiveButtons(QListWidgetItem *item) { CaptureButton::ButtonType bType = m_buttonTypeByName[item->text()]; if (item->checkState() == Qt::Checked) { m_listButtons.append(bType); std::sort(m_listButtons.begin(), m_listButtons.end()); } else { m_listButtons.remove(m_listButtons.indexOf(bType)); } ConfigHandler().setButtons(m_listButtons); } void ButtonListView::reverseItemCheck(QListWidgetItem *item){ if (item->checkState() == Qt::Checked) { item->setCheckState(Qt::Unchecked); } else { item->setCheckState(Qt::Checked); } updateActiveButtons(item); } void ButtonListView::selectAll() { ConfigHandler().setAllTheButtons(); for(int i = 0; i < this->count(); ++i) { QListWidgetItem* item = this->item(i); item->setCheckState(Qt::Checked); } } void ButtonListView::updateComponents() { m_listButtons = ConfigHandler().getButtons(); auto listTypes = CaptureButton::getIterableButtonTypes(); for(int i = 0; i < this->count(); ++i) { QListWidgetItem* item = this->item(i); auto elem = static_cast(listTypes.at(i)); if (m_listButtons.contains(elem)) { item->setCheckState(Qt::Checked); } else { item->setCheckState(Qt::Unchecked); } } } flameshot-0.5.1/src/config/buttonlistview.h000066400000000000000000000024421324424505000210070ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "src/capture/widgets/capturebutton.h" #include class ButtonListView : public QListWidget { public: ButtonListView(QWidget *parent= nullptr); public slots: void selectAll(); void updateComponents(); private slots: void reverseItemCheck(QListWidgetItem *); protected: void initButtonList(); private: QVector m_listButtons; QMap m_buttonTypeByName; void updateActiveButtons(QListWidgetItem *); }; flameshot-0.5.1/src/config/clickablelabel.cpp000066400000000000000000000020401324424505000211430ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "clickablelabel.h" ClickableLabel::ClickableLabel(QWidget *parent) : QLabel(parent) { } ClickableLabel::ClickableLabel(QString s, QWidget *parent) : QLabel(parent) { setText(s); } void ClickableLabel::mousePressEvent(QMouseEvent *) { Q_EMIT clicked(); } flameshot-0.5.1/src/config/clickablelabel.h000066400000000000000000000020621324424505000206140ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class ClickableLabel : public QLabel { Q_OBJECT public: explicit ClickableLabel(QWidget *parent = nullptr); ClickableLabel(QString s, QWidget *parent = nullptr); signals: void clicked(); private: void mousePressEvent (QMouseEvent *); }; flameshot-0.5.1/src/config/configwindow.cpp000066400000000000000000000060371324424505000207410ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "configwindow.h" #include "src/capture/widgets/capturebutton.h" #include "src/config/geneneralconf.h" #include "src/config/filenameeditor.h" #include "src/config/strftimechooserwidget.h" #include "src/utils/confighandler.h" #include "src/config/visualseditor.h" #include #include #include #include #include // ConfigWindow contains the menus where you can configure the application ConfigWindow::ConfigWindow(QWidget *parent) : QTabWidget(parent) { setAttribute(Qt::WA_DeleteOnClose); const int size = CaptureButton::buttonBaseSize() * 12; setMinimumSize(size, size); setWindowIcon(QIcon(":img/flameshot.png")); setWindowTitle(tr("Configuration")); auto changedSlot = [this](QString s){ QStringList files = m_configWatcher->files(); if (!files.contains(s)) { this->m_configWatcher->addPath(s); } Q_EMIT updateChildren(); }; m_configWatcher = new QFileSystemWatcher(this); m_configWatcher->addPath(ConfigHandler().configFilePath()); connect(m_configWatcher, &QFileSystemWatcher::fileChanged, this, changedSlot); QColor background = this->palette().background().color(); bool isWhite = CaptureButton::iconIsWhiteByColor(background); QString modifier = isWhite ? ":img/configWhite/" : ":img/configBlack/"; // visuals m_visuals = new VisualsEditor(); addTab(m_visuals, QIcon(modifier + "graphics.png"), tr("Interface")); // filename m_filenameEditor = new FileNameEditor(); addTab(m_filenameEditor, QIcon(modifier + "name_edition.png"), tr("Filename Editor")); // general m_generalConfig = new GeneneralConf(); addTab(m_generalConfig, QIcon(modifier + "config.png"), tr("General")); // connect update sigslots connect(this, &ConfigWindow::updateChildren, m_filenameEditor, &FileNameEditor::updateComponents); connect(this, &ConfigWindow::updateChildren, m_visuals, &VisualsEditor::updateComponents); connect(this, &ConfigWindow::updateChildren, m_generalConfig, &GeneneralConf::updateComponents); } void ConfigWindow::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape) { close(); } } flameshot-0.5.1/src/config/configwindow.h000066400000000000000000000023661324424505000204070ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class FileNameEditor; class GeneneralConf; class QFileSystemWatcher; class VisualsEditor; class ConfigWindow : public QTabWidget { Q_OBJECT public: explicit ConfigWindow(QWidget *parent = nullptr); signals: void updateChildren(); protected: void keyPressEvent(QKeyEvent *); private: FileNameEditor *m_filenameEditor; GeneneralConf *m_generalConfig; VisualsEditor *m_visuals; QFileSystemWatcher *m_configWatcher; }; flameshot-0.5.1/src/config/extendedslider.cpp000066400000000000000000000033641324424505000212470ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "extendedslider.h" ExtendedSlider::ExtendedSlider(QWidget *parent) : QSlider(parent) { connect(this, &ExtendedSlider::valueChanged, this, &ExtendedSlider::updateTooltip); connect(this, &ExtendedSlider::sliderMoved, this, &ExtendedSlider::fireTimer); m_timer.setSingleShot(true); connect(&m_timer, &QTimer::timeout, this, &ExtendedSlider::modificationsEnded); } int ExtendedSlider::mappedValue(int min, int max) { qreal progress = ((value() - minimum())) / static_cast(maximum() - minimum()); return min + (max - min) * progress; } void ExtendedSlider::setMapedValue(int min, int val, int max) { qreal progress = ((val - min) + 1) / static_cast(max - min); int value = minimum() + (maximum() - minimum()) * progress; setValue(value); } void ExtendedSlider::updateTooltip() { setToolTip(QString::number(value())+"%"); } void ExtendedSlider::fireTimer() { m_timer.start(500); } flameshot-0.5.1/src/config/extendedslider.h000066400000000000000000000022341324424505000207070ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include class ExtendedSlider : public QSlider { Q_OBJECT public: explicit ExtendedSlider(QWidget *parent = nullptr); int mappedValue(int min, int max); void setMapedValue(int min, int val, int max); signals: void modificationsEnded(); private slots: void updateTooltip(); void fireTimer(); private: QTimer m_timer; }; flameshot-0.5.1/src/config/filenameeditor.cpp000066400000000000000000000101641324424505000212270ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "filenameeditor.h" #include "src/utils/filenamehandler.h" #include "src/utils/confighandler.h" #include "src/config/strftimechooserwidget.h" #include #include #include #include #include FileNameEditor::FileNameEditor(QWidget *parent) : QWidget(parent) { initWidgets(); initLayout(); } void FileNameEditor::initLayout() { m_layout = new QVBoxLayout(this); auto infoLabel = new QLabel(tr("Edit the name of your captures:"), this); infoLabel->setFixedHeight(20); m_layout->addWidget(infoLabel); m_layout->addWidget(m_helperButtons); m_layout->addWidget(new QLabel(tr("Edit:"))); m_layout->addWidget(m_nameEditor); m_layout->addWidget(new QLabel(tr("Preview:"))); m_layout->addWidget(m_outputLabel); QHBoxLayout *horizLayout = new QHBoxLayout(); horizLayout->addWidget(m_saveButton); horizLayout->addWidget(m_resetButton); horizLayout->addWidget(m_clearButton); m_layout->addLayout(horizLayout); } void FileNameEditor::initWidgets() { m_nameHandler = new FileNameHandler(this); // editor m_nameEditor = new QLineEdit(this); m_nameEditor->setMaxLength(FileNameHandler::MAX_CHARACTERS); // preview m_outputLabel = new QLineEdit(this); m_outputLabel->setDisabled(true); QString foreground = this->palette().foreground().color().name(); m_outputLabel->setStyleSheet(QStringLiteral("color: %1").arg(foreground)); QPalette pal = m_outputLabel->palette(); QColor color = pal.color(QPalette::Disabled, m_outputLabel->backgroundRole()); pal.setColor(QPalette::Active, m_outputLabel->backgroundRole(), color); m_outputLabel->setPalette(pal); connect(m_nameEditor, &QLineEdit::textChanged, this, &FileNameEditor::showParsedPattern); updateComponents(); // helper buttons m_helperButtons = new StrftimeChooserWidget(this); connect(m_helperButtons, &StrftimeChooserWidget::variableEmitted, this, &FileNameEditor::addToNameEditor); // save m_saveButton = new QPushButton(tr("Save"), this); connect(m_saveButton, &QPushButton::clicked, this, &FileNameEditor::savePattern); m_saveButton->setToolTip(tr("Saves the pattern")); // reset m_resetButton = new QPushButton(tr("Reset"), this); connect(m_resetButton, &QPushButton::clicked, this, &FileNameEditor::resetName); m_resetButton->setToolTip(tr("Restores the saved pattern")); // clear m_clearButton = new QPushButton(tr("Clear"), this); connect(m_clearButton, &QPushButton::clicked, this, [this](){ m_nameEditor->setText(QString()); }); m_clearButton->setToolTip(tr("Deletes the name"));} void FileNameEditor::savePattern() { QString pattern = m_nameEditor->text(); m_nameHandler->setPattern(pattern); } void FileNameEditor::showParsedPattern(const QString &p) { QString output = m_nameHandler->parseFilename(p); m_outputLabel->setText(output); } void FileNameEditor::resetName() { m_nameEditor->setText(ConfigHandler().filenamePatternValue()); } void FileNameEditor::addToNameEditor(QString s) { m_nameEditor->setText(m_nameEditor->text() + s); m_nameEditor->setFocus(); } void FileNameEditor::updateComponents() { m_nameEditor->setText(ConfigHandler().filenamePatternValue()); m_outputLabel->setText(m_nameHandler->parsedPattern()); } flameshot-0.5.1/src/config/filenameeditor.h000066400000000000000000000030431324424505000206720ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include class QVBoxLayout; class QLineEdit; class FileNameHandler; class QPushButton; class StrftimeChooserWidget; class FileNameEditor : public QWidget { Q_OBJECT public: explicit FileNameEditor(QWidget *parent = nullptr); private: QVBoxLayout *m_layout; QLineEdit *m_outputLabel; QLineEdit *m_nameEditor; FileNameHandler *m_nameHandler; StrftimeChooserWidget *m_helperButtons; QPushButton *m_saveButton; QPushButton *m_resetButton; QPushButton *m_clearButton; void initLayout(); void initWidgets(); public slots: void addToNameEditor(QString s); void updateComponents(); private slots: void savePattern(); void showParsedPattern(const QString &); void resetName(); }; flameshot-0.5.1/src/config/geneneralconf.cpp000066400000000000000000000145401324424505000210500ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "geneneralconf.h" #include "src/utils/confighandler.h" #include "src/utils/confighandler.h" #include "src/core/controller.h" #include #include #include #include #include #include #include #include #include GeneneralConf::GeneneralConf(QWidget *parent) : QWidget(parent) { m_layout = new QVBoxLayout(this); m_layout->setAlignment(Qt::AlignTop); initShowHelp(); initShowDesktopNotification(); initShowTrayIcon(); initAutostart(); // this has to be at the end initConfingButtons(); updateComponents(); } void GeneneralConf::updateComponents() { ConfigHandler config; m_helpMessage->setChecked(config.showHelpValue()); m_sysNotifications->setChecked(config.desktopNotificationValue()); m_autostart->setChecked(config.startupLaunchValue()); #ifdef Q_OS_LINUX m_showTray->setChecked(!config.disabledTrayIconValue()); #endif } void GeneneralConf::showHelpChanged(bool checked) { ConfigHandler().setShowHelp(checked); } void GeneneralConf::showDesktopNotificationChanged(bool checked) { ConfigHandler().setDesktopNotification(checked); } void GeneneralConf::showTrayIconChanged(bool checked) { auto controller = Controller::getInstance(); if (checked) { controller->enableTrayIcon(); } else { controller->disableTrayIcon(); } } void GeneneralConf::autostartChanged(bool checked) { ConfigHandler().setStartupLaunch(checked); } void GeneneralConf::importConfiguration() { QString fileName = QFileDialog::getOpenFileName(this, tr("Import")); if (fileName.isEmpty()) { return; } QFile file(fileName); QTextCodec *codec = QTextCodec::codecForLocale(); if (!file.open(QFile::ReadOnly)) { QMessageBox::about(this, tr("Error"), tr("Unable to read file.")); return; } QString text = codec->toUnicode(file.readAll()); file.close(); QFile config(ConfigHandler().configFilePath()); if (!config.open(QFile::WriteOnly)) { QMessageBox::about(this, tr("Error"), tr("Unable to write file.")); return; } config.write(codec->fromUnicode(text)); config.close(); } void GeneneralConf::exportFileConfiguration() { QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "flameshot.conf"); bool ok = QFile::copy(ConfigHandler().configFilePath(), fileName); if (!ok) { QMessageBox::about(this, tr("Error"), tr("Unable to write file.")); } } void GeneneralConf::resetConfiguration() { QMessageBox::StandardButton reply; reply = QMessageBox::question( this, tr("Confirm Reset"), tr("Are you sure you want to reset the configuration?"), QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) { ConfigHandler().setDefaults(); } } void GeneneralConf::initShowHelp() { m_helpMessage = new QCheckBox(tr("Show help message"), this); ConfigHandler config; bool checked = config.showHelpValue(); m_helpMessage->setChecked(checked); m_helpMessage->setToolTip(tr("Show the help message at the beginning " "in the capture mode.")); m_layout->addWidget(m_helpMessage); connect(m_helpMessage, &QCheckBox::clicked, this, &GeneneralConf::showHelpChanged); } void GeneneralConf::initShowDesktopNotification() { m_sysNotifications = new QCheckBox(tr("Show desktop notifications"), this); ConfigHandler config; bool checked = config.desktopNotificationValue(); m_sysNotifications->setChecked(checked); m_sysNotifications->setToolTip(tr("Show desktop notifications")); m_layout->addWidget(m_sysNotifications); connect(m_sysNotifications, &QCheckBox::clicked, this, &GeneneralConf::showDesktopNotificationChanged); } void GeneneralConf::initShowTrayIcon() { #ifdef Q_OS_LINUX m_showTray = new QCheckBox(tr("Show tray icon"), this); ConfigHandler config; bool checked = !config.disabledTrayIconValue(); m_showTray->setChecked(checked); m_showTray->setToolTip(tr("Show the systemtray icon")); m_layout->addWidget(m_showTray); connect(m_showTray, &QCheckBox::clicked, this, &GeneneralConf::showTrayIconChanged); #endif } void GeneneralConf::initConfingButtons() { QHBoxLayout *buttonLayout = new QHBoxLayout(); m_layout->addStretch(); QGroupBox *box = new QGroupBox(tr("Configuration File")); box->setFlat(true); box->setLayout(buttonLayout); m_layout->addWidget(box); m_exportButton = new QPushButton(tr("Export")); buttonLayout->addWidget(m_exportButton); connect(m_exportButton, &QPushButton::clicked, this, &GeneneralConf::exportFileConfiguration); m_importButton = new QPushButton(tr("Import")); buttonLayout->addWidget(m_importButton); connect(m_importButton, &QPushButton::clicked, this, &GeneneralConf::importConfiguration); m_resetButton = new QPushButton(tr("Reset")); buttonLayout->addWidget(m_resetButton); connect(m_resetButton, &QPushButton::clicked, this, &GeneneralConf::resetConfiguration); } void GeneneralConf::initAutostart() { m_autostart = new QCheckBox(tr("Launch at startup"), this); ConfigHandler config; bool checked = config.startupLaunchValue(); m_autostart->setChecked(checked); m_autostart->setToolTip(tr("Launch Flameshot ")); m_layout->addWidget(m_autostart); connect(m_autostart, &QCheckBox::clicked, this, &GeneneralConf::autostartChanged); } flameshot-0.5.1/src/config/geneneralconf.h000066400000000000000000000032701324424505000205130ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class QVBoxLayout; class QCheckBox; class QPushButton; class GeneneralConf : public QWidget { Q_OBJECT public: GeneneralConf(QWidget *parent = nullptr); public slots: void updateComponents(); private slots: void showHelpChanged(bool checked); void showDesktopNotificationChanged(bool checked); void showTrayIconChanged(bool checked); void autostartChanged(bool checked); void importConfiguration(); void exportFileConfiguration(); void resetConfiguration(); private: QVBoxLayout *m_layout; QCheckBox *m_sysNotifications; QCheckBox *m_showTray; QCheckBox *m_helpMessage; QCheckBox *m_autostart; QPushButton *m_importButton; QPushButton *m_exportButton; QPushButton *m_resetButton; void initShowHelp(); void initShowDesktopNotification(); void initShowTrayIcon(); void initConfingButtons(); void initAutostart(); }; flameshot-0.5.1/src/config/strftimechooserwidget.cpp000066400000000000000000000056271324424505000226740ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "strftimechooserwidget.h" #include #include #include StrftimeChooserWidget::StrftimeChooserWidget(QWidget *parent) : QWidget(parent) { QGridLayout *layout = new QGridLayout(this); auto k = m_buttonData.keys(); int middle = k.length()/2; // add the buttons in 2 columns (they need to be even) for (int i = 0; i < 2; i++) { for (int j = 0; j < middle; j++) { QString key = k.last(); k.pop_back(); QString variable = m_buttonData.value(key); QPushButton *button = new QPushButton(this); button->setText(tr(key.toStdString().data())); button->setToolTip(variable); button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); button->setMinimumHeight(25); layout->addWidget(button, j, i); connect(button, &QPushButton::clicked, this, [variable, this](){Q_EMIT variableEmitted(variable);}); } } setLayout(layout); } QMap StrftimeChooserWidget::m_buttonData { { QT_TR_NOOP("Century (00-99)"), "%C"}, { QT_TR_NOOP("Year (00-99)"), "%y"}, { QT_TR_NOOP("Year (2000)"), "%Y"}, { QT_TR_NOOP("Month Name (jan)"), "%b"}, { QT_TR_NOOP("Month Name (january)"), "%B"}, { QT_TR_NOOP("Month (01-12)"), "%m"}, { QT_TR_NOOP("Week Day (1-7)"), "%u"}, { QT_TR_NOOP("Week (01-53)"), "%V"}, { QT_TR_NOOP("Day Name (mon)"), "%a"}, { QT_TR_NOOP("Day Name (monday)"), "%A"}, { QT_TR_NOOP("Day (01-31)"), "%d"}, { QT_TR_NOOP("Day of Month (1-31)"), "%e"}, { QT_TR_NOOP("Day (001-366)"), "%j"}, { QT_TR_NOOP("Time (%H:%M:%S)"), "%T"}, { QT_TR_NOOP("Time (%H:%M)"), "%R"}, { QT_TR_NOOP("Hour (00-23)"), "%H"}, { QT_TR_NOOP("Hour (01-12)"), "%I"}, { QT_TR_NOOP("Minute (00-59)"), "%M"}, { QT_TR_NOOP("Second (00-59)"), "%S"}, { QT_TR_NOOP("Full Date (%m/%d/%y)"), "%D"}, { QT_TR_NOOP("Full Date (%Y-%m-%d)"), "%F"}, }; flameshot-0.5.1/src/config/strftimechooserwidget.h000066400000000000000000000020451324424505000223300ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class StrftimeChooserWidget : public QWidget { Q_OBJECT public: explicit StrftimeChooserWidget(QWidget *parent = nullptr); signals: void variableEmitted(const QString &); private: static QMap m_buttonData; }; flameshot-0.5.1/src/config/uicoloreditor.cpp000066400000000000000000000140431324424505000211230ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "src/utils/confighandler.h" #include "uicoloreditor.h" #include "clickablelabel.h" #include #include #include #include #include #include UIcolorEditor::UIcolorEditor(QWidget *parent) : QGroupBox(parent) { setTitle(tr("UI Color Editor")); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_hLayout = new QHBoxLayout; m_vLayout = new QVBoxLayout; const int space = QApplication::fontMetrics().lineSpacing(); m_hLayout->addItem(new QSpacerItem(space, space, QSizePolicy::Expanding)); m_vLayout->setAlignment(Qt::AlignVCenter); initButtons(); initColorWheel(); m_vLayout->addSpacing(space); m_hLayout->addLayout(m_vLayout); m_hLayout->addItem(new QSpacerItem(space, space, QSizePolicy::Expanding)); setLayout(m_hLayout); updateComponents(); } void UIcolorEditor::updateComponents() { ConfigHandler config; m_uiColor = config.uiMainColorValue(); m_contrastColor = config.uiContrastColorValue(); m_buttonContrast->setColor(m_contrastColor); m_buttonMainColor->setColor(m_uiColor); if (m_lastButtonPressed == m_buttonMainColor) { m_colorWheel->setColor(m_uiColor); } else { m_colorWheel->setColor(m_contrastColor); } } // updateUIcolor updates the appearance of the buttons void UIcolorEditor::updateUIcolor() { ConfigHandler config; if (m_lastButtonPressed == m_buttonMainColor) { config.setUIMainColor(m_uiColor); } else { config.setUIContrastColor(m_contrastColor); } } // updateLocalColor updates the local button void UIcolorEditor::updateLocalColor(const QColor c) { if (m_lastButtonPressed == m_buttonMainColor) { m_uiColor = c; } else { m_contrastColor = c; } m_lastButtonPressed->setColor(c); } void UIcolorEditor::initColorWheel() { m_colorWheel = new color_widgets::ColorWheel(this); connect(m_colorWheel, &color_widgets::ColorWheel::mouseReleaseOnColor, this, &UIcolorEditor::updateUIcolor); connect(m_colorWheel, &color_widgets::ColorWheel::colorChanged, this, &UIcolorEditor::updateLocalColor); const int size = CaptureButton::buttonBaseSize() * 3; m_colorWheel->setMinimumSize(size, size); m_colorWheel->setMaximumSize(size*2, size*2); m_colorWheel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_colorWheel->setToolTip(tr("Change the color moving the selectors and see" " the changes in the preview buttons.")); m_hLayout->addWidget(m_colorWheel); } void UIcolorEditor::initButtons() { const int extraSize = CaptureButton::buttonBaseSize() / 3; int frameSize = CaptureButton::buttonBaseSize() + extraSize; m_vLayout->addWidget(new QLabel(tr("Select a Button to modify it"), this)); QGroupBox *frame = new QGroupBox(); frame->setFixedSize(frameSize, frameSize); m_buttonMainColor = new CaptureButton(m_buttonIconType, frame); m_buttonMainColor->move(m_buttonMainColor->x() + extraSize/2, m_buttonMainColor->y() + extraSize/2); QHBoxLayout *h1 = new QHBoxLayout(); h1->addWidget(frame); m_labelMain = new ClickableLabel(tr("Main Color"), this); h1->addWidget(m_labelMain); m_vLayout->addLayout(h1); m_buttonMainColor->setToolTip(tr("Click on this button to set the edition" " mode of the main color.")); QGroupBox *frame2 = new QGroupBox(); m_buttonContrast = new CaptureButton(m_buttonIconType, frame2); m_buttonContrast->move(m_buttonContrast->x() + extraSize/2, m_buttonContrast->y() + extraSize/2); QHBoxLayout *h2 = new QHBoxLayout(); h2->addWidget(frame2); frame2->setFixedSize(frameSize, frameSize); m_labelContrast = new ClickableLabel(tr("Contrast Color"), this); m_labelContrast->setStyleSheet("color : gray"); h2->addWidget(m_labelContrast); m_vLayout->addLayout(h2); m_buttonContrast->setToolTip(tr("Click on this button to set the edition" " mode of the contrast color.")); connect(m_buttonMainColor, &CaptureButton::pressedButton, this, &UIcolorEditor::changeLastButton); connect(m_buttonContrast, &CaptureButton::pressedButton, this, &UIcolorEditor::changeLastButton); // clicking the labels chages the button too connect(m_labelMain, &ClickableLabel::clicked, this, [this]{ changeLastButton(m_buttonMainColor); }); connect(m_labelContrast, &ClickableLabel::clicked, this, [this]{ changeLastButton(m_buttonContrast); }); m_lastButtonPressed = m_buttonMainColor; } // visual update for the selected button void UIcolorEditor::changeLastButton(CaptureButton *b) { if (m_lastButtonPressed != b) { m_lastButtonPressed = b; QString offStyle("QLabel { color : gray; }"); if (b == m_buttonMainColor) { m_colorWheel->setColor(m_uiColor); m_labelContrast->setStyleSheet(offStyle); m_labelMain->setStyleSheet(styleSheet()); } else { m_colorWheel->setColor(m_contrastColor); m_labelContrast->setStyleSheet(styleSheet()); m_labelMain->setStyleSheet(offStyle); } b->setIcon(b->icon()); } } flameshot-0.5.1/src/config/uicoloreditor.h000066400000000000000000000033201324424505000205640ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "color_wheel.hpp" #include "src/capture/widgets/capturebutton.h" #include class QVBoxLayout; class QHBoxLayout; class CaptureButton; class ClickableLabel; class UIcolorEditor : public QGroupBox { Q_OBJECT public: explicit UIcolorEditor(QWidget *parent = nullptr); public slots: void updateComponents(); private slots: void updateUIcolor(); void updateLocalColor(const QColor); void changeLastButton(CaptureButton *); private: QColor m_uiColor, m_contrastColor; CaptureButton *m_buttonMainColor; ClickableLabel *m_labelMain; CaptureButton *m_buttonContrast; ClickableLabel *m_labelContrast; CaptureButton *m_lastButtonPressed; color_widgets::ColorWheel *m_colorWheel; static const CaptureButton::ButtonType m_buttonIconType = CaptureButton::TYPE_CIRCLE; QHBoxLayout *m_hLayout; QVBoxLayout *m_vLayout; void initColorWheel(); void initButtons(); }; flameshot-0.5.1/src/config/visualseditor.cpp000066400000000000000000000060311324424505000211330ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "visualseditor.h" #include "src/config/buttonlistview.h" #include "src/config/uicoloreditor.h" #include "src/utils/confighandler.h" #include "src/config/extendedslider.h" #include #include #include VisualsEditor::VisualsEditor(QWidget *parent) : QWidget(parent) { m_layout= new QVBoxLayout(); setLayout(m_layout); initWidgets(); } void VisualsEditor::updateComponents() { m_buttonList->updateComponents(); m_colorEditor->updateComponents(); int opacity = ConfigHandler().contrastOpacityValue(); m_opacitySlider->setMapedValue(0, opacity, 255); } void VisualsEditor::initOpacitySlider() { m_opacitySlider = new ExtendedSlider(); m_opacitySlider->setOrientation(Qt::Horizontal); m_opacitySlider->setRange(0, 100); connect(m_opacitySlider, &ExtendedSlider::modificationsEnded, this, &VisualsEditor::saveOpacity); QHBoxLayout *localLayout = new QHBoxLayout(); localLayout->addWidget(new QLabel("0%")); localLayout->addWidget(m_opacitySlider); localLayout->addWidget(new QLabel("100%")); QLabel *label = new QLabel(); QString labelMsg = tr("Opacity of area outside selection:") + " %1%"; connect(m_opacitySlider, &ExtendedSlider::valueChanged, this, [labelMsg, label](int val){ label->setText(labelMsg.arg(val)); }); m_layout->addWidget(label); m_layout->addLayout(localLayout); int opacity = ConfigHandler().contrastOpacityValue(); m_opacitySlider->setMapedValue(0, opacity, 255); } void VisualsEditor::saveOpacity() { int value = m_opacitySlider->mappedValue(0, 255); ConfigHandler().setContrastOpacity(value); } void VisualsEditor::initWidgets() { m_colorEditor = new UIcolorEditor(); m_layout->addWidget(m_colorEditor); initOpacitySlider(); auto boxButtons = new QGroupBox(); boxButtons->setTitle(tr("Button Selection")); auto listLayout = new QVBoxLayout(boxButtons); m_buttonList = new ButtonListView(); m_layout->addWidget(boxButtons); listLayout->addWidget(m_buttonList); QPushButton* setAllButtons = new QPushButton(tr("Select All")); connect(setAllButtons, &QPushButton::clicked, m_buttonList, &ButtonListView::selectAll); listLayout->addWidget(setAllButtons); } flameshot-0.5.1/src/config/visualseditor.h000066400000000000000000000024231324424505000206010ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class ExtendedSlider; class QVBoxLayout; class ButtonListView; class UIcolorEditor; class VisualsEditor : public QWidget { Q_OBJECT public: explicit VisualsEditor(QWidget *parent = nullptr); public slots: void updateComponents(); private slots: void saveOpacity(); private: QVBoxLayout *m_layout; ButtonListView *m_buttonList; UIcolorEditor *m_colorEditor; ExtendedSlider *m_opacitySlider; void initWidgets(); void initOpacitySlider(); }; flameshot-0.5.1/src/core/000077500000000000000000000000001324424505000152155ustar00rootroot00000000000000flameshot-0.5.1/src/core/controller.cpp000066400000000000000000000115371324424505000201130ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "controller.h" #include "src/capture/widgets/capturewidget.h" #include "src/utils/confighandler.h" #include "src/infowindow.h" #include "src/config/configwindow.h" #include "src/capture/widgets/capturebutton.h" #include #include #include #include #include #ifdef Q_OS_WIN #include "src/core/globalshortcutfilter.h" #endif // Controller is the core component of Flameshot, creates the trayIcon and // launches the capture widget Controller::Controller() : m_captureWindow(nullptr) { qApp->setQuitOnLastWindowClosed(false); // init tray icon #if defined(Q_OS_LINUX) if (!ConfigHandler().disabledTrayIconValue()) { enableTrayIcon(); } #elif defined(Q_OS_WIN) enableTrayIcon(); GlobalShortcutFilter *nativeFilter = new GlobalShortcutFilter(this); qApp->installNativeEventFilter(nativeFilter); connect(nativeFilter, &GlobalShortcutFilter::printPressed, this, [this](){ this->createVisualCapture(); }); #endif QString StyleSheet = CaptureButton::globalStyleSheet(); qApp->setStyleSheet(StyleSheet); } Controller *Controller::getInstance() { static Controller c; return &c; } // creation of a new capture in GUI mode void Controller::createVisualCapture(const uint id, const QString &forcedSavePath) { if (!m_captureWindow) { QWidget *modalWidget = nullptr; do { modalWidget = qApp->activeModalWidget(); if (modalWidget) { modalWidget->close(); modalWidget->deleteLater(); } } while (modalWidget); m_captureWindow = new CaptureWidget(id, forcedSavePath); connect(m_captureWindow, &CaptureWidget::captureFailed, this, &Controller::captureFailed); connect(m_captureWindow, &CaptureWidget::captureTaken, this, &Controller::captureTaken); #ifdef Q_OS_WIN m_captureWindow->show(); #else m_captureWindow->showFullScreen(); #endif } } // creation of the configuration window void Controller::openConfigWindow() { if (!m_configWindow) { m_configWindow = new ConfigWindow(); m_configWindow->show(); } } // creation of the window of information void Controller::openInfoWindow() { if (!m_infoWindow) { m_infoWindow = new InfoWindow(); } } void Controller::enableTrayIcon() { if (m_trayIcon) { return; } ConfigHandler().setDisabledTrayIcon(false); QAction *configAction = new QAction(tr("&Configuration"), this); connect(configAction, &QAction::triggered, this, &Controller::openConfigWindow); QAction *infoAction = new QAction(tr("&Information"), this); connect(infoAction, &QAction::triggered, this, &Controller::openInfoWindow); QAction *quitAction = new QAction(tr("&Quit"), this); connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit); QMenu *trayIconMenu = new QMenu(); trayIconMenu->addAction(configAction); trayIconMenu->addAction(infoAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(quitAction); m_trayIcon = new QSystemTrayIcon(); m_trayIcon->setToolTip("Flameshot"); m_trayIcon->setContextMenu(trayIconMenu); m_trayIcon->setIcon(QIcon(":img/flameshot.png")); auto trayIconActivated = [this](QSystemTrayIcon::ActivationReason r){ if (r == QSystemTrayIcon::Trigger) { createVisualCapture(); } }; connect(m_trayIcon, &QSystemTrayIcon::activated, this, trayIconActivated); m_trayIcon->show(); } void Controller::disableTrayIcon() { #ifdef Q_OS_LINUX if (m_trayIcon) { m_trayIcon->deleteLater(); } ConfigHandler().setDisabledTrayIcon(true); #endif } void Controller::sendTrayNotification( const QString &text, const QString &title, const int timeout) { if (m_trayIcon) { m_trayIcon->showMessage(title, text, QSystemTrayIcon::Information, timeout); } } void Controller::updateConfigComponents() { if (m_configWindow) { m_configWindow->updateChildren(); } } flameshot-0.5.1/src/core/controller.h000066400000000000000000000035521324424505000175560ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include #include class CaptureWidget; class ConfigWindow; class InfoWindow; class QSystemTrayIcon; class Controller : public QObject { Q_OBJECT public: static Controller* getInstance(); Controller(const Controller&) = delete; void operator =(const Controller&) = delete; signals: void captureTaken(uint id, QByteArray p); void captureFailed(uint id); public slots: void createVisualCapture(const uint id = 0, const QString &forcedSavePath = QString()); void openConfigWindow(); void openInfoWindow(); void enableTrayIcon(); void disableTrayIcon(); void sendTrayNotification(const QString &text, const QString &title = "Flameshot Info", const int timeout = 5000); void updateConfigComponents(); private slots: private: Controller(); QPointer m_captureWindow; QPointer m_infoWindow; QPointer m_configWindow; QPointer m_trayIcon; }; flameshot-0.5.1/src/core/flameshotdbusadapter.cpp000066400000000000000000000066001324424505000221240ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "flameshotdbusadapter.h" #include "src/utils/confighandler.h" #include "src/utils/screengrabber.h" #include "src/core/controller.h" #include "src/core/resourceexporter.h" #include "src/utils/systemnotification.h" #include #include #include namespace { using std::function; using lambda = function; // replace QTimer::singleShot introduced in QT 5.4 // the actual target QT version is QT 5.3 void doLater(int msec, QObject *receiver, lambda func) { QTimer *timer = new QTimer(receiver); QObject::connect(timer, &QTimer::timeout, receiver, [timer, func](){ func(); timer->deleteLater(); }); timer->setInterval(msec); timer->start(); } } FlameshotDBusAdapter::FlameshotDBusAdapter(QObject *parent) : QDBusAbstractAdaptor(parent) { auto controller = Controller::getInstance(); connect(controller, &Controller::captureFailed, this, &FlameshotDBusAdapter::captureFailed); connect(controller, &Controller::captureTaken, this, &FlameshotDBusAdapter::captureTaken); } FlameshotDBusAdapter::~FlameshotDBusAdapter() { } void FlameshotDBusAdapter::graphicCapture(QString path, int delay, uint id) { auto controller = Controller::getInstance(); auto f = [controller, id, path, this]() { controller->createVisualCapture(id, path); }; // QTimer::singleShot(delay, controller, f); // requires Qt 5.4 doLater(delay, controller, f); } void FlameshotDBusAdapter::fullScreen( QString path, bool toClipboard, int delay, uint id) { auto f = [id, path, toClipboard, this]() { bool ok = true; QPixmap p(ScreenGrabber().grabEntireDesktop(ok)); if (!ok) { SystemNotification().sendMessage(tr("Unable to capture screen")); Q_EMIT captureFailed(id); return; } if(toClipboard) { ResourceExporter().captureToClipboard(p); } if(!path.isEmpty()) { ResourceExporter().captureToFile(p, path); } QByteArray byteArray; QBuffer buffer(&byteArray); p.save(&buffer, "PNG"); Q_EMIT captureTaken(id, byteArray); }; //QTimer::singleShot(delay, this, f); // // requires Qt 5.4 doLater(delay, this, f); } void FlameshotDBusAdapter::openConfig() { Controller::getInstance()->openConfigWindow(); } void FlameshotDBusAdapter::trayIconEnabled(bool enabled) { auto controller = Controller::getInstance(); if (enabled) { controller->enableTrayIcon(); } else { controller->disableTrayIcon(); } } flameshot-0.5.1/src/core/flameshotdbusadapter.h000066400000000000000000000026521324424505000215740ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include "src/core/controller.h" class FlameshotDBusAdapter : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.dharkael.Flameshot") public: FlameshotDBusAdapter(QObject *parent = nullptr); virtual ~FlameshotDBusAdapter(); signals: void captureTaken(uint id, QByteArray rawImage); void captureFailed(uint id); public slots: Q_NOREPLY void graphicCapture(QString path, int delay, uint id); Q_NOREPLY void fullScreen(QString path, bool toClipboard, int delay, uint id); Q_NOREPLY void openConfig(); Q_NOREPLY void trayIconEnabled(bool enabled); }; flameshot-0.5.1/src/core/globalshortcutfilter.cpp000066400000000000000000000032061324424505000221640ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "globalshortcutfilter.h" #include "src/core/controller.h" #include GlobalShortcutFilter::GlobalShortcutFilter(QObject *parent) : QObject(parent) { // Forced Print Screen if (RegisterHotKey(NULL, 1, 0, VK_SNAPSHOT)) { // ok } } bool GlobalShortcutFilter::nativeEventFilter( const QByteArray &eventType, void *message, long *result) { Q_UNUSED(eventType); Q_UNUSED(result); MSG* msg = static_cast(message); if (msg->message == WM_HOTKEY) { //const quint32 keycode = HIWORD(msg->lParam); //const quint32 modifiers = LOWORD(msg->lParam); // TODO: this is just a temporal workwrround, proper global // support would need custom shortcuts defined by the user. Controller::getInstance()->createVisualCapture(); return true; } return false; } flameshot-0.5.1/src/core/globalshortcutfilter.h000066400000000000000000000025511324424505000216330ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include class GlobalShortcutFilter : public QObject, public QAbstractNativeEventFilter { Q_OBJECT public: explicit GlobalShortcutFilter(QObject *parent = 0); bool nativeEventFilter(const QByteArray &eventType, void *message, long *result); signals: void printPressed(); private: quint32 getNativeModifier(Qt::KeyboardModifiers modifiers); quint32 nativeKeycode(Qt::Key key); bool registerShortcut(quint32 nativeKey, quint32 nativeMods); bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods); }; flameshot-0.5.1/src/core/resourceexporter.cpp000066400000000000000000000030261324424505000213420ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "resourceexporter.h" #include "src/capture/workers/imgur/imguruploader.h" #include "src/capture/workers/screenshotsaver.h" #include "src/capture/workers/launcher/openwithprogram.h" ResourceExporter::ResourceExporter() { } void ResourceExporter::captureToClipboard(const QPixmap &p) { ScreenshotSaver().saveToClipboard(p); } void ResourceExporter::captureToFile(const QPixmap &p, const QString &path) { ScreenshotSaver().saveToFilesystem(p, path); } void ResourceExporter::captureToFileUi(const QPixmap &p) { ScreenshotSaver().saveToFilesystemGUI(p); } void ResourceExporter::captureToImgur(const QPixmap &p) { auto w = new ImgurUploader(p); w->show(); } void ResourceExporter::captureToProgram(const QPixmap &p) { showOpenWithMenu(p); } flameshot-0.5.1/src/core/resourceexporter.h000066400000000000000000000021361324424505000210100ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class ResourceExporter { public: ResourceExporter(); void captureToClipboard(const QPixmap &p); void captureToFile(const QPixmap &p, const QString &path); void captureToFileUi(const QPixmap &p); void captureToImgur(const QPixmap &p); void captureToProgram(const QPixmap &p); }; flameshot-0.5.1/src/infowindow.cpp000066400000000000000000000103001324424505000171460ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "infowindow.h" #include #include #include #include #include #include // InfoWindow show basic information about the usage of Flameshot InfoWindow::InfoWindow(QWidget *parent) : QWidget(parent) { setAttribute(Qt::WA_DeleteOnClose); setWindowIcon(QIcon(":img/flameshot.png")); setWindowTitle(tr("About")); m_layout = new QVBoxLayout(this); m_layout->setAlignment(Qt::AlignHCenter); initLabels(); initInfoTable(); show(); } QVector InfoWindow::m_keys = { "←↓↑→", "SHIFT + ←↓↑→", "ESC", "CTRL + C", "CTRL + S", "CTRL + Z", QT_TR_NOOP("Right Click"), QT_TR_NOOP("Mouse Wheel") }; QVector InfoWindow::m_description = { QT_TR_NOOP("Move selection 1px"), QT_TR_NOOP("Resize selection 1px"), QT_TR_NOOP("Quit capture"), QT_TR_NOOP("Copy to clipboard"), QT_TR_NOOP("Save selection as a file"), QT_TR_NOOP("Undo the last modification"), QT_TR_NOOP("Show color picker"), QT_TR_NOOP("Change the tool's thickness") }; void InfoWindow::initInfoTable() { QTableWidget *table = new QTableWidget(this); table->setToolTip(tr("Available shortcuts in the screen capture mode.")); m_layout->addWidget(table); table->setColumnCount(2); table->setRowCount(m_keys.size()); table->setSelectionMode(QAbstractItemView::NoSelection); table->setFocusPolicy(Qt::NoFocus); table->verticalHeader()->hide(); // header creation QStringList names; names << tr("Key") << tr("Description"); table->setHorizontalHeaderLabels(names); //add content for (int i= 0; i < m_keys.size(); ++i){ table->setItem(i, 0, new QTableWidgetItem(tr(m_keys.at(i)))); table->setItem(i, 1, new QTableWidgetItem(tr(m_description.at(i)))); } // adjust size table->resizeColumnsToContents(); table->resizeRowsToContents(); table->setMinimumWidth(400); table->setMaximumWidth(600); table->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); table->horizontalHeader()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_layout->addStretch(); } void InfoWindow::initLabels() { m_layout->addStretch(); QLabel *licenseTitleLabel = new QLabel(tr("License"), this); licenseTitleLabel->setAlignment(Qt::AlignHCenter); m_layout->addWidget(licenseTitleLabel); QLabel *licenseLabel = new QLabel("GPLv3+", this); licenseLabel->setAlignment(Qt::AlignHCenter); m_layout->addWidget(licenseLabel); m_layout->addStretch(); QLabel *versionTitleLabel = new QLabel(tr("Version"), this); versionTitleLabel->setAlignment(Qt::AlignHCenter); m_layout->addWidget(versionTitleLabel); QString versionMsg = "Flameshot " + QString(APP_VERSION) + "\nCompiled with QT " + QT_VERSION_STR; QLabel *versionLabel = new QLabel(versionMsg, this); versionLabel->setAlignment(Qt::AlignHCenter); m_layout->addWidget(versionLabel); m_layout->addStretch(); m_layout->addSpacing(10); QLabel *shortcutsTitleLabel = new QLabel(tr("Shortcuts"), this); shortcutsTitleLabel->setAlignment(Qt::AlignHCenter);; m_layout->addWidget(shortcutsTitleLabel); } void InfoWindow::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape) { close(); } } flameshot-0.5.1/src/infowindow.h000066400000000000000000000022251324424505000166220ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class QVBoxLayout; class InfoWindow : public QWidget { Q_OBJECT public: explicit InfoWindow(QWidget *parent = nullptr); protected: void keyPressEvent(QKeyEvent *); private: void initInfoTable(); void initLabels(); QVBoxLayout *m_layout; static QVector m_keys; static QVector m_description; }; flameshot-0.5.1/src/main.cpp000066400000000000000000000317571324424505000157320ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "src/core/controller.h" #include "singleapplication.h" #include "src/utils/filenamehandler.h" #include "src/utils/confighandler.h" #include "src/cli/commandlineparser.h" #include "src/utils/systemnotification.h" #include "src/utils/pathinfo.h" #include #include #include #include #include #ifdef Q_OS_LINUX #include "src/core/flameshotdbusadapter.h" #include "src/utils/dbusutils.h" #include #include #endif int main(int argc, char *argv[]) { // required for the button serialization // TODO: change to QVector in v1.0 qRegisterMetaTypeStreamOperators >("QList"); qApp->setApplicationVersion(static_cast(APP_VERSION)); // no arguments, just launch Flameshot if (argc == 1) { SingleApplication app(argc, argv); QTranslator translator; QStringList trPaths = PathInfo::translations(); bool match = false; for (const QString &path: trPaths) { match = translator.load(QLocale::system().language(), "Internationalization", "_", path); if (match) { break; } } app.installTranslator(&translator); app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); app.setApplicationName("flameshot"); app.setOrganizationName("Dharkael"); #ifdef Q_OS_LINUX auto c = Controller::getInstance(); new FlameshotDBusAdapter(c); QDBusConnection dbus = QDBusConnection::sessionBus(); if (!dbus.isConnected()) { SystemNotification().sendMessage( QObject::tr("Unable to connect via DBus")); } dbus.registerObject("/", c); dbus.registerService("org.dharkael.Flameshot"); #else // Create inicial static instance Controller::getInstance(); #endif return app.exec(); } #ifndef Q_OS_WIN /*--------------| * CLI parsing | * ------------*/ QCoreApplication app(argc, argv); app.setApplicationName("flameshot"); app.setOrganizationName("Dharkael"); app.setApplicationVersion(qApp->applicationVersion()); CommandLineParser parser; // Add description parser.setDescription( "Powerful yet simple to use screenshot software."); parser.setGeneralErrorMessage("See 'flameshot --help'."); // Arguments CommandArgument fullArgument("full", "Capture the entire desktop."); CommandArgument guiArgument("gui", "Start a manual capture in GUI mode."); CommandArgument configArgument("config", "Configure flameshot."); // Options CommandOption pathOption( {"p", "path"}, "Path where the capture will be saved", "path"); CommandOption clipboardOption( {"c", "clipboard"}, "Save the capture to the clipboard"); CommandOption delayOption( {"d", "delay"}, "Delay time in milliseconds", "milliseconds"); CommandOption filenameOption( {"f", "filename"}, "Set the filename pattern", "pattern"); CommandOption trayOption( {"t", "trayicon"}, "Enable or disable the trayicon", "bool"); CommandOption showHelpOption( {"s", "showhelp"}, "Show the help message in the capture mode", "bool"); CommandOption mainColorOption( {"m", "maincolor"}, "Define the main UI color", "color-code"); CommandOption contrastColorOption( {"k", "contrastcolor"}, "Define the contrast UI color", "color-code"); CommandOption rawImageOption( {"r", "raw"}, "Print raw PNG capture"); // Add checkers auto colorChecker = [&parser](const QString &colorCode) -> bool { QColor parsedColor(colorCode); return parsedColor.isValid() && parsedColor.alphaF() == 1.0; }; QString colorErr = "Invalid color, " "this flag supports the following formats:\n" "- #RGB (each of R, G, and B is a single hex digit)\n" "- #RRGGBB\n- #RRRGGGBBB\n" "- #RRRRGGGGBBBB\n" "- Named colors like 'blue' or 'red'\n" "You may need to escape the '#' sign as in '\\#FFF'"; const QString delayErr = "Invalid delay, it must be higher than 0"; auto delayChecker = [&parser](const QString &delayValue) -> bool { int value = delayValue.toInt(); return value >= 0; }; const QString pathErr = "Invalid path, it must be a real path in the system"; auto pathChecker = [&parser, pathErr](const QString &pathValue) -> bool { bool res = QDir(pathValue).exists(); if (!res) { SystemNotification().sendMessage(QObject::tr(pathErr.toLatin1().data())); } return res; }; const QString booleanErr = "Invalid value, it must be defined as 'true' or 'false'"; auto booleanChecker = [&parser](const QString &value) -> bool { return value == "true" || value == "false"; }; contrastColorOption.addChecker(colorChecker, colorErr); mainColorOption.addChecker(colorChecker, colorErr); delayOption.addChecker(delayChecker, delayErr); pathOption.addChecker(pathChecker, pathErr); trayOption.addChecker(booleanChecker, booleanErr); showHelpOption.addChecker(booleanChecker, booleanErr); // Relationships parser.AddArgument(guiArgument); parser.AddArgument(fullArgument); parser.AddArgument(configArgument); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); parser.AddOptions({ pathOption, delayOption, rawImageOption }, guiArgument); parser.AddOptions({ pathOption, clipboardOption, delayOption, rawImageOption }, fullArgument); parser.AddOptions({ filenameOption, trayOption, showHelpOption, mainColorOption, contrastColorOption }, configArgument); // Parse if (!parser.parse(app.arguments())) { goto finish; } // PROCESS DATA //-------------- if (parser.isSet(helpOption) || parser.isSet(versionOption)) { } else if (parser.isSet(guiArgument)) { // GUI QString pathValue = parser.value(pathOption); int delay = parser.value(delayOption).toInt(); bool isRaw = parser.isSet(rawImageOption); uint id = qHash(app.arguments().join(" ")); DBusUtils utils(id); // Send message QDBusMessage m = QDBusMessage::createMethodCall("org.dharkael.Flameshot", "/", "", "graphicCapture"); m << pathValue << delay << id; QDBusConnection sessionBus = QDBusConnection::sessionBus(); utils.checkDBusConnection(sessionBus); sessionBus.call(m); if (isRaw) { // captureTaken sessionBus.connect("org.dharkael.Flameshot", "/", "", "captureTaken", &utils, SLOT(captureTaken(uint, QByteArray))); // captureFailed sessionBus.connect("org.dharkael.Flameshot", "/", "", "captureFailed", &utils, SLOT(captureFailed(uint))); QTimer t; t.setInterval(1000 * 60 * 15); // 15 minutes timeout QObject::connect(&t, &QTimer::timeout, qApp, &QCoreApplication::quit); t.start(); // wait app.exec(); } } else if (parser.isSet(fullArgument)) { // FULL QString pathValue = parser.value(pathOption); int delay = parser.value(delayOption).toInt(); bool toClipboard = parser.isSet(clipboardOption); bool isRaw = parser.isSet(rawImageOption); // Not a valid command if (!isRaw && !toClipboard && pathValue.isEmpty()) { QTextStream(stdout) << "you have to set a valid flag:\n\n"; parser.parse(QStringList() << argv[0] << "full" << "-h"); goto finish; } uint id = qHash(app.arguments().join(" ")); DBusUtils utils(id); // Send message QDBusMessage m = QDBusMessage::createMethodCall("org.dharkael.Flameshot", "/", "", "fullScreen"); m << pathValue << toClipboard << delay << id; QDBusConnection sessionBus = QDBusConnection::sessionBus(); utils.checkDBusConnection(sessionBus); sessionBus.call(m); if (isRaw) { // captureTaken sessionBus.connect("org.dharkael.Flameshot", "/", "", "captureTaken", &utils, SLOT(captureTaken(uint, QByteArray))); // captureFailed sessionBus.connect("org.dharkael.Flameshot", "/", "", "captureFailed", &utils, SLOT(captureFailed(uint))); // timeout just in case QTimer t; t.setInterval(2000); QObject::connect(&t, &QTimer::timeout, qApp, &QCoreApplication::quit); t.start(); // wait app.exec(); } } else if (parser.isSet(configArgument)) { // CONFIG bool filename = parser.isSet(filenameOption); bool tray = parser.isSet(trayOption); bool help = parser.isSet(showHelpOption); bool mainColor = parser.isSet(mainColorOption); bool contrastColor = parser.isSet(contrastColorOption); bool someFlagSet = (filename || tray || help || mainColor || contrastColor); ConfigHandler config; if (filename) { QString newFilename(parser.value(filenameOption)); config.setFilenamePattern(newFilename); FileNameHandler fh; QTextStream(stdout) << QStringLiteral("The new pattern is '%1'\n" "Parsed pattern example: %2\n").arg(newFilename) .arg(fh.parsedPattern()); } if (tray) { QDBusMessage m = QDBusMessage::createMethodCall("org.dharkael.Flameshot", "/", "", "trayIconEnabled"); if (parser.value(trayOption) == "false") { m << false; } else if (parser.value(trayOption) == "true") { m << true; } QDBusConnection sessionBus = QDBusConnection::sessionBus(); if (!sessionBus.isConnected()) { SystemNotification().sendMessage( QObject::tr("Unable to connect via DBus")); } sessionBus.call(m); } if (help) { if (parser.value(showHelpOption) == "false") { config.setShowHelp(false); } else if (parser.value(showHelpOption) == "true") { config.setShowHelp(true); } } if (mainColor) { QString colorCode = parser.value(mainColorOption); QColor parsedColor(colorCode); config.setUIMainColor(parsedColor); } if (contrastColor) { QString colorCode = parser.value(contrastColorOption); QColor parsedColor(colorCode); config.setUIContrastColor(parsedColor); } // Open gui when no options if (!someFlagSet) { QDBusMessage m = QDBusMessage::createMethodCall("org.dharkael.Flameshot", "/", "", "openConfig"); QDBusConnection sessionBus = QDBusConnection::sessionBus(); if (!sessionBus.isConnected()) { SystemNotification().sendMessage( QObject::tr("Unable to connect via DBus")); } sessionBus.call(m); } } finish: #endif return 0; } flameshot-0.5.1/src/third-party/000077500000000000000000000000001324424505000165345ustar00rootroot00000000000000flameshot-0.5.1/src/third-party/Qt-Color-Widgets/000077500000000000000000000000001324424505000216005ustar00rootroot00000000000000flameshot-0.5.1/src/third-party/Qt-Color-Widgets/COPYING000066400000000000000000000167431324424505000226460ustar00rootroot00000000000000 GNU LESSER 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. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser 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 Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. flameshot-0.5.1/src/third-party/Qt-Color-Widgets/LICENSE-EXCEPTION000066400000000000000000000016641324424505000241500ustar00rootroot00000000000000Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU Lesser General Public License version 3 cover the whole combination. As a special exception, the copyright holders of this library give you permission to combine this library with independent modules to produce an executable, and to copy and distribute the resulting executable under terms of any of the GNU General Public licenses, as published by the Free Software Foundation, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this library. If you modify this library, you may extend this exception to your version of the library, but you are not obliged to do so. If you do not wish to do so, delete this exception statement from your version. flameshot-0.5.1/src/third-party/Qt-Color-Widgets/README.md000066400000000000000000000043521324424505000230630ustar00rootroot00000000000000Color Widgets ============= Here is a color dialog that is more user-friendly than the default QColorDialog and several other color-related widgets The provided widgets are: * ColorWheel, An analog widget used to select a color * ColorPreview, A simple widget that displays a color * GradientSlider, A slider that has a gradient background * HueSlider, A variant of GradientSlider that has a rainbow background * ColorSelector, A ColorPreview that shows a ColorDialog when clicked * ColorDialog, A dialog that uses the above widgets to provide a better user experience than QColorDialog * ColorListWidget, A widget to edit a list of colors * Swatch, A widget to display a color palette * ColorPaletteWidget, A widget to use and manage a list of palettes * Color2DSlider, An analog widget used to select 2 color components * ColorLineEdit, A widget to manipulate a string representing a color they are all in the color_widgets namespace. See [the gallery](gallery/README.md) for more information and screenshots. Using it in a project --------------------- For QMake-based projects, include color_widgets.pri in the QMake project file. For CMake-based projects, add this as subdirectory, it will be compiled as a library and you can link the required targets to ColorWidgets-qt5. All the required files are in ./src and ./include. Installing as a Qt Designer/Creator Plugin ------------------------------------------ The sources for the designer plugin are in ./color_widgets_designer_plugin Compile the library and install in (Qt SDK)/Tools/QtCreator/bin/designer/ (Qt SDK)/(Qt Version)/(Toolchain)/plugins/designer cd build && cmake .. && make ColorWidgetsPlugin && make install Latest Version -------------- The latest version of the sources can be found at the following locations: * https://github.com/mbasaglia/Qt-Color-Widgets * git://github.com/mbasaglia/Qt-Color-Widgets.git License ------- LGPLv3+, See COPYING. As a special exception, this library can be included in any project under the terms of any of the GNU liceses, distributing the whole project under a different GNU license, see LICENSE-EXCEPTION for details. Copyright (C) 2013-2017 Mattia Basaglia flameshot-0.5.1/src/third-party/Qt-Color-Widgets/color_widgets.pri000066400000000000000000000017061324424505000251640ustar00rootroot00000000000000# Copyright (C) 2013-2017 Mattia Basaglia # # # This software 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 3 of the License, or # (at your option) any later version. # # This software is distributed in the hope that 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 Color Widgets. If not, see . CONFIG += c++11 INCLUDEPATH += $$PWD/src $$PWD/include SOURCES += \ $$PWD/src/color_wheel.cpp \ $$PWD/src/color_utils.cpp HEADERS += \ $$PWD/include/color_wheel.hpp \ $$PWD/src/color_utils.hpp RESOURCES += \ $$PWD/src/color_widgets.qrc flameshot-0.5.1/src/third-party/Qt-Color-Widgets/color_widgets.pro000066400000000000000000000023741324424505000251740ustar00rootroot00000000000000# # Copyright (C) 2013-2017 Mattia Basaglia # # This program 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 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that 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 program. If not, see . # TEMPLATE=lib CONFIG += dll QT += core gui widgets DEFINES += QTCOLORWIDGETS_LIBRARY TARGET=ColorWidgets-qt5 VERSION=1.0.0 OBJECTS_DIR = out/obj MOC_DIR = out/generated UI_DIR = out/generated RCC_DIR = out/generated include(color_widgets.pri) build_all:!build_pass { CONFIG -= build_all CONFIG += release } unix { LIB_TARGET = lib$${TARGET}.so } win32 { LIB_TARGET = $${TARGET}.dll } isEmpty(PREFIX) { PREFIX = /usr/local } target.path = $$PREFIX/lib headers.path = $$PREFIX/include/QtColorWidgets headers.files = $$HEADERS INSTALLS += target headers flameshot-0.5.1/src/third-party/Qt-Color-Widgets/include/000077500000000000000000000000001324424505000232235ustar00rootroot00000000000000flameshot-0.5.1/src/third-party/Qt-Color-Widgets/include/ColorWheel000066400000000000000000000000331324424505000252050ustar00rootroot00000000000000#include "color_wheel.hpp" flameshot-0.5.1/src/third-party/Qt-Color-Widgets/include/color_wheel.hpp000066400000000000000000000120361324424505000262400ustar00rootroot00000000000000/** * \file * * \author Mattia Basaglia * * \copyright Copyright (C) 2013-2017 Mattia Basaglia * * This program 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that 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 program. If not, see . * */ #ifndef COLOR_WHEEL_HPP #define COLOR_WHEEL_HPP #include namespace color_widgets { /** * \brief Display an analog widget that allows the selection of a HSV color * * It has an outer wheel to select the Hue and an intenal square to select * Saturation and Lightness. */ class ColorWheel : public QWidget { Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged DESIGNABLE true STORED false ) Q_PROPERTY(qreal hue READ hue WRITE setHue DESIGNABLE false ) Q_PROPERTY(qreal saturation READ saturation WRITE setSaturation DESIGNABLE false ) Q_PROPERTY(qreal value READ value WRITE setValue DESIGNABLE false ) Q_PROPERTY(unsigned wheelWidth READ wheelWidth WRITE setWheelWidth DESIGNABLE true ) Q_PROPERTY(DisplayFlags displayFlags READ displayFlags WRITE setDisplayFlags NOTIFY displayFlagsChanged DESIGNABLE true ) public: enum DisplayEnum { SHAPE_DEFAULT = 0x000, ///< Use the default shape SHAPE_TRIANGLE = 0x001, ///< A triangle SHAPE_SQUARE = 0x002, ///< A square SHAPE_FLAGS = 0x00f, ///< Mask for the shape flags ANGLE_DEFAULT = 0x000, ///< Use the default rotation style ANGLE_FIXED = 0x010, ///< The inner part doesn't rotate ANGLE_ROTATING = 0x020, ///< The inner part follows the hue selector ANGLE_FLAGS = 0x0f0, ///< Mask for the angle flags COLOR_DEFAULT = 0x000, ///< Use the default colorspace COLOR_HSV = 0x100, ///< Use the HSV color space COLOR_HSL = 0x200, ///< Use the HSL color space COLOR_LCH = 0x400, ///< Use Luma Chroma Hue (Y_601') COLOR_FLAGS = 0xf00, ///< Mask for the color space flags FLAGS_DEFAULT = 0x000, ///< Use all defaults FLAGS_ALL = 0xfff ///< Mask matching all flags }; Q_DECLARE_FLAGS(DisplayFlags, DisplayEnum) Q_FLAGS(DisplayFlags) explicit ColorWheel(QWidget *parent = 0); ~ColorWheel(); /// Get current color QColor color() const; virtual QSize sizeHint() const Q_DECL_OVERRIDE; /// Get current hue in the range [0-1] qreal hue() const; /// Get current saturation in the range [0-1] qreal saturation() const; /// Get current value in the range [0-1] qreal value() const; /// Get the width in pixels of the outer wheel unsigned int wheelWidth() const; /// Set the width in pixels of the outer wheel void setWheelWidth(unsigned int w); /// Get display flags DisplayFlags displayFlags(DisplayFlags mask = FLAGS_ALL) const; /// Set the default display flags static void setDefaultDisplayFlags(DisplayFlags flags); /// Get default display flags static DisplayFlags defaultDisplayFlags(DisplayFlags mask = FLAGS_ALL); /** * @brief Set a specific display flag * @param flag Flag replacing the mask * @param mask Mask to be cleared */ void setDisplayFlag(DisplayFlags flag, DisplayFlags mask); public Q_SLOTS: /// Set current color void setColor(QColor c); /** * @param h Hue [0-1] */ void setHue(qreal h); /** * @param s Saturation [0-1] */ void setSaturation(qreal s); /** * @param v Value [0-1] */ void setValue(qreal v); /** * @brief Set the display flags * @param flags which will replace the current ones */ void setDisplayFlags(ColorWheel::DisplayFlags flags); Q_SIGNALS: /** * Emitted when the user selects a color or setColor is called */ void colorChanged(QColor); /** * Emitted when the user selects a color */ void colorSelected(QColor); void displayFlagsChanged(ColorWheel::DisplayFlags flags); void mouseReleaseOnColor(QColor); protected: void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE; void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE; void dragEnterEvent(QDragEnterEvent* event) Q_DECL_OVERRIDE; void dropEvent(QDropEvent* event) Q_DECL_OVERRIDE; private: class Private; Private * const p; }; Q_DECLARE_OPERATORS_FOR_FLAGS(ColorWheel::DisplayFlags) } // namespace color_widgets #endif // COLOR_WHEEL_HPP flameshot-0.5.1/src/third-party/Qt-Color-Widgets/src/000077500000000000000000000000001324424505000223675ustar00rootroot00000000000000flameshot-0.5.1/src/third-party/Qt-Color-Widgets/src/alphaback.png000066400000000000000000000003201324424505000247760ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME**`RtEXtCommentCreated with GIMPW+IDAT8cLKKgI301PF  gώ7CldPEIENDB`flameshot-0.5.1/src/third-party/Qt-Color-Widgets/src/color_utils.cpp000066400000000000000000000046651324424505000254440ustar00rootroot00000000000000/** * \file * * \author Mattia Basaglia * * \copyright Copyright (C) 2013-2017 Mattia Basaglia * * This program 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that 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 program. If not, see . * */ #include "color_utils.hpp" namespace color_widgets { namespace detail { QColor color_from_lch(qreal hue, qreal chroma, qreal luma, qreal alpha ) { qreal h1 = hue*6; qreal x = chroma*(1-qAbs(std::fmod(h1,2)-1)); QColor col; if ( h1 >= 0 && h1 < 1 ) col = QColor::fromRgbF(chroma,x,0); else if ( h1 < 2 ) col = QColor::fromRgbF(x,chroma,0); else if ( h1 < 3 ) col = QColor::fromRgbF(0,chroma,x); else if ( h1 < 4 ) col = QColor::fromRgbF(0,x,chroma); else if ( h1 < 5 ) col = QColor::fromRgbF(x,0,chroma); else if ( h1 < 6 ) col = QColor::fromRgbF(chroma,0,x); qreal m = luma - color_lumaF(col); return QColor::fromRgbF( qBound(0.0,col.redF()+m,1.0), qBound(0.0,col.greenF()+m,1.0), qBound(0.0,col.blueF()+m,1.0), alpha); } QColor color_from_hsl(qreal hue, qreal sat, qreal lig, qreal alpha ) { qreal chroma = (1 - qAbs(2*lig-1))*sat; qreal h1 = hue*6; qreal x = chroma*(1-qAbs(std::fmod(h1,2)-1)); QColor col; if ( h1 >= 0 && h1 < 1 ) col = QColor::fromRgbF(chroma,x,0); else if ( h1 < 2 ) col = QColor::fromRgbF(x,chroma,0); else if ( h1 < 3 ) col = QColor::fromRgbF(0,chroma,x); else if ( h1 < 4 ) col = QColor::fromRgbF(0,x,chroma); else if ( h1 < 5 ) col = QColor::fromRgbF(x,0,chroma); else if ( h1 < 6 ) col = QColor::fromRgbF(chroma,0,x); qreal m = lig-chroma/2; return QColor::fromRgbF( qBound(0.0,col.redF()+m,1.0), qBound(0.0,col.greenF()+m,1.0), qBound(0.0,col.blueF()+m,1.0), alpha); } } // namespace detail } // namespace color_widgets flameshot-0.5.1/src/third-party/Qt-Color-Widgets/src/color_utils.hpp000066400000000000000000000036221324424505000254410ustar00rootroot00000000000000/** * \file * * \author Mattia Basaglia * * \copyright Copyright (C) 2013-2017 Mattia Basaglia * * This program 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that 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 program. If not, see . * */ #include #include namespace color_widgets { namespace detail { inline qreal color_chromaF(const QColor& c) { qreal max = qMax(c.redF(), qMax(c.greenF(), c.blueF())); qreal min = qMin(c.redF(), qMin(c.greenF(), c.blueF())); return max - min; } inline qreal color_lumaF(const QColor& c) { return 0.30 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF(); } QColor color_from_lch(qreal hue, qreal chroma, qreal luma, qreal alpha = 1 ); inline QColor rainbow_lch(qreal hue) { return color_from_lch(hue,1,1); } inline QColor rainbow_hsv(qreal hue) { return QColor::fromHsvF(hue,1,1); } inline qreal color_lightnessF(const QColor& c) { return ( qMax(c.redF(),qMax(c.greenF(),c.blueF())) + qMin(c.redF(),qMin(c.greenF(),c.blueF())) ) / 2; } inline qreal color_HSL_saturationF(const QColor& col) { qreal c = color_chromaF(col); qreal l = color_lightnessF(col); if ( qFuzzyCompare(l+1,1) || qFuzzyCompare(l+1,2) ) return 0; return c / (1-qAbs(2*l-1)); } QColor color_from_hsl(qreal hue, qreal sat, qreal lig, qreal alpha = 1 ); } // namespace detail } // namespace color_widgets flameshot-0.5.1/src/third-party/Qt-Color-Widgets/src/color_wheel.cpp000066400000000000000000000373661324424505000254140ustar00rootroot00000000000000/** * \file * * \author Mattia Basaglia * * \copyright Copyright (C) 2013-2017 Mattia Basaglia * * This program 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that 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 program. If not, see . * */ #include "color_wheel.hpp" #include #include #include #include #include #include #include "color_utils.hpp" namespace color_widgets { enum MouseStatus { Nothing, DragCircle, DragSquare }; static const ColorWheel::DisplayFlags hard_default_flags = ColorWheel::SHAPE_TRIANGLE|ColorWheel::ANGLE_ROTATING|ColorWheel::COLOR_HSV; static ColorWheel::DisplayFlags default_flags = hard_default_flags; static const double selector_radius = 6; class ColorWheel::Private { private: ColorWheel * const w; public: qreal hue, sat, val; qreal bgBrightness; unsigned int wheel_width; MouseStatus mouse_status; QPixmap hue_ring; QImage inner_selector; DisplayFlags display_flags; QColor (*color_from)(qreal,qreal,qreal,qreal); QColor (*rainbow_from_hue)(qreal); int max_size = 128; Private(ColorWheel *widget) : w(widget), hue(0), sat(0), val(0), wheel_width(20), mouse_status(Nothing), display_flags(FLAGS_DEFAULT), color_from(&QColor::fromHsvF), rainbow_from_hue(&detail::rainbow_hsv) { QColor bgColor = widget->palette().background().color(); bgBrightness = color_widgets::detail::color_lumaF(bgColor); } /// Calculate outer wheel radius from idget center qreal outer_radius() const { return qMin(w->geometry().width(), w->geometry().height())/2; } /// Calculate inner wheel radius from idget center qreal inner_radius() const { return outer_radius()-wheel_width; } /// Calculate the edge length of the inner square qreal square_size() const { return inner_radius()*qSqrt(2); } /// Calculate the height of the inner triangle qreal triangle_height() const { return inner_radius()*3/2; } /// Calculate the side of the inner triangle qreal triangle_side() const { return inner_radius()*qSqrt(3); } /// return line from center to given point QLineF line_to_point(const QPoint &p) const { return QLineF (w->geometry().width()/2, w->geometry().height()/2, p.x(), p.y()); } void render_square() { int width = qMin(square_size(), max_size); QSize size(width, width); inner_selector = QImage(size, QImage::Format_RGB32); for ( int y = 0; y < width; ++y ) { for ( int x = 0; x < width; ++x ) { inner_selector.setPixel( x, y, color_from(hue,double(x)/width,double(y)/width,1).rgb()); } } } /** * \brief renders the selector as a triangle * \note It's the same as a square with the edge with value=0 collapsed to a single point */ void render_triangle() { QSizeF size = selector_size(); if ( size.height() > max_size ) size *= max_size / size.height(); qreal ycenter = size.height()/2; inner_selector = QImage(size.toSize(), QImage::Format_RGB32); for (int x = 0; x < inner_selector.width(); x++ ) { qreal pval = x / size.height(); qreal slice_h = size.height() * pval; for (int y = 0; y < inner_selector.height(); y++ ) { qreal ymin = ycenter-slice_h/2; qreal psat = qBound(0.0,(y-ymin)/slice_h,1.0); inner_selector.setPixel(x,y,color_from(hue,psat,pval,1).rgb()); } } } /// Updates the inner image that displays the saturation-value selector void render_inner_selector() { if ( display_flags & ColorWheel::SHAPE_TRIANGLE ) render_triangle(); else render_square(); } /// Offset of the selector image QPointF selector_image_offset() { if ( display_flags & SHAPE_TRIANGLE ) return QPointF(-inner_radius(),-triangle_side()/2); return QPointF(-square_size()/2,-square_size()/2); } /** * \brief Size of the selector when rendered to the screen */ QSizeF selector_size() { if ( display_flags & SHAPE_TRIANGLE ) return QSizeF(triangle_height(), triangle_side()); return QSizeF(square_size(), square_size()); } /// Rotation of the selector image qreal selector_image_angle() { if ( display_flags & SHAPE_TRIANGLE ) { if ( display_flags & ANGLE_ROTATING ) return -hue*360-60; return -150; } else { if ( display_flags & ANGLE_ROTATING ) return -hue*360-45; else return 180; } } /// Updates the outer ring that displays the hue selector void render_ring() { hue_ring = QPixmap(outer_radius()*2,outer_radius()*2); hue_ring.fill(Qt::transparent); QPainter painter(&hue_ring); painter.setRenderHint(QPainter::Antialiasing); painter.setCompositionMode(QPainter::CompositionMode_Source); const int hue_stops = 24; QConicalGradient gradient_hue(0, 0, 0); if ( gradient_hue.stops().size() < hue_stops ) { for ( double a = 0; a < 1.0; a+=1.0/(hue_stops-1) ) { gradient_hue.setColorAt(a,rainbow_from_hue(a)); } gradient_hue.setColorAt(1,rainbow_from_hue(0)); } painter.translate(outer_radius(),outer_radius()); painter.setPen(Qt::NoPen); painter.setBrush(QBrush(gradient_hue)); painter.drawEllipse(QPointF(0,0),outer_radius(),outer_radius()); painter.setBrush(Qt::transparent);//palette().background()); painter.drawEllipse(QPointF(0,0),inner_radius(),inner_radius()); } void set_color(const QColor& c) { if ( display_flags & ColorWheel::COLOR_HSV ) { hue = qMax(0.0, c.hsvHueF()); sat = c.hsvSaturationF(); val = c.valueF(); } else if ( display_flags & ColorWheel::COLOR_HSL ) { hue = qMax(0.0, c.hueF()); sat = detail::color_HSL_saturationF(c); val = detail::color_lightnessF(c); } else if ( display_flags & ColorWheel::COLOR_LCH ) { hue = qMax(0.0, c.hsvHueF()); sat = detail::color_chromaF(c); val = detail::color_lumaF(c); } } }; ColorWheel::ColorWheel(QWidget *parent) : QWidget(parent), p(new Private(this)) { setDisplayFlags(FLAGS_DEFAULT); setAcceptDrops(true); } ColorWheel::~ColorWheel() { delete p; } QColor ColorWheel::color() const { return p->color_from(p->hue, p->sat, p->val, 1); } QSize ColorWheel::sizeHint() const { return QSize(p->wheel_width*5, p->wheel_width*5); } qreal ColorWheel::hue() const { if ( (p->display_flags & COLOR_LCH) && p->sat > 0.01 ) return color().hueF(); return p->hue; } qreal ColorWheel::saturation() const { return color().hsvSaturationF(); } qreal ColorWheel::value() const { return color().valueF(); } unsigned int ColorWheel::wheelWidth() const { return p->wheel_width; } void ColorWheel::setWheelWidth(unsigned int w) { p->wheel_width = w; p->render_inner_selector(); update(); } void ColorWheel::paintEvent(QPaintEvent * ) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.translate(geometry().width()/2,geometry().height()/2); // hue wheel if(p->hue_ring.isNull()) p->render_ring(); painter.drawPixmap(-p->outer_radius(), -p->outer_radius(), p->hue_ring); // hue selector QColor penColor = p->bgBrightness < 0.6 ? Qt::white : Qt::black; painter.setPen(QPen(penColor,3)); painter.setBrush(Qt::NoBrush); QLineF ray(0, 0, p->outer_radius(), 0); ray.setAngle(p->hue*360); QPointF h1 = ray.p2(); ray.setLength(p->inner_radius()); QPointF h2 = ray.p2(); painter.drawLine(h1,h2); // lum-sat square if(p->inner_selector.isNull()) p->render_inner_selector(); painter.rotate(p->selector_image_angle()); painter.translate(p->selector_image_offset()); QPointF selector_position; if ( p->display_flags & SHAPE_SQUARE ) { qreal side = p->square_size(); selector_position = QPointF(p->sat*side, p->val*side); } else if ( p->display_flags & SHAPE_TRIANGLE ) { qreal side = p->triangle_side(); qreal height = p->triangle_height(); qreal slice_h = side * p->val; qreal ymin = side/2-slice_h/2; selector_position = QPointF(p->val*height, ymin + p->sat*slice_h); QPolygonF triangle; triangle.append(QPointF(0,side/2)); triangle.append(QPointF(height,0)); triangle.append(QPointF(height,side)); QPainterPath clip; clip.addPolygon(triangle); painter.setClipPath(clip); } painter.drawImage(QRectF(QPointF(0, 0), p->selector_size()), p->inner_selector); painter.setClipping(false); // lum-sat selector // we define the color of the selecto based on the background color of the widget // in order to improve the contrast qreal colorBrightness = color_widgets::detail::color_lumaF(color()); if (p->bgBrightness < 0.6) // dark theme { bool isWhite = (colorBrightness < 0.7); painter.setPen(QPen(isWhite ? Qt::white : Qt::black, 3)); } else // light theme { bool isWhite = (colorBrightness < 0.4 && p->val < 0.3); painter.setPen(QPen(isWhite ? Qt::white : Qt::black, 3)); } painter.setBrush(Qt::NoBrush); painter.drawEllipse(selector_position, selector_radius, selector_radius); } void ColorWheel::mouseMoveEvent(QMouseEvent *ev) { if (p->mouse_status == DragCircle ) { p->hue = p->line_to_point(ev->pos()).angle()/360.0; p->render_inner_selector(); Q_EMIT colorSelected(color()); Q_EMIT colorChanged(color()); update(); } else if(p->mouse_status == DragSquare) { QLineF glob_mouse_ln = p->line_to_point(ev->pos()); QLineF center_mouse_ln ( QPointF(0,0), glob_mouse_ln.p2() - glob_mouse_ln.p1() ); center_mouse_ln.setAngle(center_mouse_ln.angle()+p->selector_image_angle()); center_mouse_ln.setP2(center_mouse_ln.p2()-p->selector_image_offset()); if ( p->display_flags & SHAPE_SQUARE ) { p->sat = qBound(0.0, center_mouse_ln.x2()/p->square_size(), 1.0); p->val = qBound(0.0, center_mouse_ln.y2()/p->square_size(), 1.0); } else if ( p->display_flags & SHAPE_TRIANGLE ) { QPointF pt = center_mouse_ln.p2(); qreal side = p->triangle_side(); p->val = qBound(0.0, pt.x() / p->triangle_height(), 1.0); qreal slice_h = side * p->val; qreal ycenter = side/2; qreal ymin = ycenter-slice_h/2; if ( slice_h > 0 ) p->sat = qBound(0.0, (pt.y()-ymin)/slice_h, 1.0); } Q_EMIT colorSelected(color()); Q_EMIT colorChanged(color()); update(); } } void ColorWheel::mousePressEvent(QMouseEvent *ev) { if ( ev->buttons() & Qt::LeftButton ) { setFocus(); QLineF ray = p->line_to_point(ev->pos()); if ( ray.length() <= p->inner_radius() ) p->mouse_status = DragSquare; else if ( ray.length() <= p->outer_radius() ) p->mouse_status = DragCircle; // Update the color mouseMoveEvent(ev); } } void ColorWheel::mouseReleaseEvent(QMouseEvent *ev) { mouseMoveEvent(ev); p->mouse_status = Nothing; Q_EMIT mouseReleaseOnColor(color()); } void ColorWheel::resizeEvent(QResizeEvent *) { p->render_ring(); p->render_inner_selector(); } void ColorWheel::setColor(QColor c) { qreal oldh = p->hue; p->set_color(c); if (!qFuzzyCompare(oldh+1, p->hue+1)) p->render_inner_selector(); update(); Q_EMIT colorChanged(c); } void ColorWheel::setHue(qreal h) { p->hue = qBound(0.0, h, 1.0); p->render_inner_selector(); update(); } void ColorWheel::setSaturation(qreal s) { p->sat = qBound(0.0, s, 1.0); update(); } void ColorWheel::setValue(qreal v) { p->val = qBound(0.0, v, 1.0); update(); } void ColorWheel::setDisplayFlags(DisplayFlags flags) { if ( ! (flags & COLOR_FLAGS) ) flags |= default_flags & COLOR_FLAGS; if ( ! (flags & ANGLE_FLAGS) ) flags |= default_flags & ANGLE_FLAGS; if ( ! (flags & SHAPE_FLAGS) ) flags |= default_flags & SHAPE_FLAGS; if ( (flags & COLOR_FLAGS) != (p->display_flags & COLOR_FLAGS) ) { QColor old_col = color(); if ( flags & ColorWheel::COLOR_HSL ) { p->hue = old_col.hueF(); p->sat = detail::color_HSL_saturationF(old_col); p->val = detail::color_lightnessF(old_col); p->color_from = &detail::color_from_hsl; p->rainbow_from_hue = &detail::rainbow_hsv; } else if ( flags & ColorWheel::COLOR_LCH ) { p->hue = old_col.hueF(); p->sat = detail::color_chromaF(old_col); p->val = detail::color_lumaF(old_col); p->color_from = &detail::color_from_lch; p->rainbow_from_hue = &detail::rainbow_lch; } else { p->hue = old_col.hsvHueF(); p->sat = old_col.hsvSaturationF(); p->val = old_col.valueF(); p->color_from = &QColor::fromHsvF; p->rainbow_from_hue = &detail::rainbow_hsv; } p->render_ring(); } p->display_flags = flags; p->render_inner_selector(); update(); Q_EMIT displayFlagsChanged(flags); } ColorWheel::DisplayFlags ColorWheel::displayFlags(DisplayFlags mask) const { return p->display_flags & mask; } void ColorWheel::setDefaultDisplayFlags(DisplayFlags flags) { if ( !(flags & COLOR_FLAGS) ) flags |= hard_default_flags & COLOR_FLAGS; if ( !(flags & ANGLE_FLAGS) ) flags |= hard_default_flags & ANGLE_FLAGS; if ( !(flags & SHAPE_FLAGS) ) flags |= hard_default_flags & SHAPE_FLAGS; default_flags = flags; } ColorWheel::DisplayFlags ColorWheel::defaultDisplayFlags(DisplayFlags mask) { return default_flags & mask; } void ColorWheel::setDisplayFlag(DisplayFlags flag, DisplayFlags mask) { setDisplayFlags((p->display_flags&~mask)|flag); } void ColorWheel::dragEnterEvent(QDragEnterEvent* event) { if ( event->mimeData()->hasColor() || ( event->mimeData()->hasText() && QColor(event->mimeData()->text()).isValid() ) ) event->acceptProposedAction(); } void ColorWheel::dropEvent(QDropEvent* event) { if ( event->mimeData()->hasColor() ) { setColor(event->mimeData()->colorData().value()); event->accept(); } else if ( event->mimeData()->hasText() ) { QColor col(event->mimeData()->text()); if ( col.isValid() ) { setColor(col); event->accept(); } } } } // namespace color_widgets flameshot-0.5.1/src/third-party/Qt-Color-Widgets/src/color_widgets.qrc000066400000000000000000000001511324424505000257370ustar00rootroot00000000000000 alphaback.png flameshot-0.5.1/src/third-party/singleapplication/000077500000000000000000000000001324424505000222415ustar00rootroot00000000000000flameshot-0.5.1/src/third-party/singleapplication/CHANGELOG.md000066400000000000000000000117011324424505000240520ustar00rootroot00000000000000Changelog ========= __3.0.10__ ---------- * Removed C style casts and eliminated all clang warnings. Fixed `instanceId` reading from only one byte in the message deserialization. Cleaned up serialization code using `QDataStream`. Changed connection type to use `quint8 enum` rather than `char`. * Renamed `SingleAppConnectionType` to `ConnectionType`. Added initialization values to all `ConnectionType` enum cases. _Jedidiah Buck McCready_ __3.0.9__ --------- * Added SingleApplicationPrivate::primaryPid() as a solution to allow bringing the primary window of an application to the foreground on Windows. _Eelco van Dam from Peacs BV_ __3.0.8__ --------- * Bug fix - changed QApplication::instance() to QCoreApplication::instance() _Evgeniy Bazhenov_ __3.0.7a__ ---------- * Fixed compilation error with Mingw32 in MXE thanks to Vitaly Tonkacheyev. * Removed QMutex used for thread safe behaviour. The implementation now uses QCoreApplication::instance() to get an instance to SingleApplication for memory deallocation. __3.0.6a__ ---------- * Reverted GetUserName API usage on Windows. Fixed bug with missing library. * Fixed bug in the Calculator example, preventing it's window to be raised on Windows. Special thanks to Charles Gunawan. __3.0.5a__ ---------- * Fixed a memory leak in the SingleApplicationPrivate destructor. _Sergei Moiseev_ __3.0.4a__ ---------- * Fixed shadow and uninitialised variable warnings. _Paul Walmsley_ __3.0.3a__ ---------- * Removed Microsoft Windows specific code for getting username due to multiple problems and compiler differences on Windows platforms. On Windows the shared memory block in User mode now includes the user's home path (which contains the user's username). * Explicitly getting absolute path of the user's home directory as on Unix a relative path (`~`) may be returned. __3.0.2a__ ---------- * Fixed bug on Windows when username containing wide characters causes the library to crash. _Le Liu_ __3.0.1a__ ---------- * Allows the application path and version to be excluded from the server name hash. The following flags were added for this purpose: * `SingleApplication::Mode::ExcludeAppVersion` * `SingleApplication::Mode::ExcludeAppPath` * Allow a non elevated process to connect to a local server created by an elevated process run by the same user on Windows * Fixes a problem with upper case letters in paths on Windows _Le Liu_ __v3.0a__ --------- * Depricated secondary instances count. * Added a sendMessage() method to send a message to the primary instance. * Added a receivedMessage() signal, emitted when a message is received from a secondary instance. * The SingleApplication constructor's third parameter is now a bool specifying if the current instance should be allowed to run as a secondary instance if there is already a primary instance. * The SingleApplication constructor accept a fourth parameter specifying if the SingleApplication block should be User-wide or System-wide. * SingleApplication no longer relies on `applicationName` and `organizationName` to be set. It instead concatenates all of the following data and computes a `SHA256` hash which is used as the key of the `QSharedMemory` block and the `QLocalServer`. Since at least `applicationFilePath` is always present there is no need to explicitly set any of the following prior to initialising `SingleApplication`. * `QCoreApplication::applicationName` * `QCoreApplication::applicationVersion` * `QCoreApplication::applicationFilePath` * `QCoreApplication::organizationName` * `QCoreApplication::organizationDomain` * User name or home directory path if in User mode * The primary instance is no longer notified when a secondary instance had been started by default. A `Mode` flag for this feature exists. * Added `instanceNumber()` which represents a unique identifier for each secondary instance started. When called from the primary instance will return `0`. __v2.4__ -------- * Stability improvements * Support for secondary instances. * The library now recovers safely after the primary process has crashed and the shared memory had not been deleted. __v2.3__ -------- * Improved pimpl design and inheritance safety. _Vladislav Pyatnichenko_ __v2.2__ -------- * The `QAPPLICATION_CLASS` macro can now be defined in the file including the Single Application header or with a `DEFINES+=` statement in the project file. __v2.1__ -------- * A race condition can no longer occur when starting two processes nearly simultaneously. Fix issue [#3](https://github.com/itay-grudev/SingleApplication/issues/3) __v2.0__ -------- * SingleApplication is now being passed a reference to `argc` instead of a copy. Fix issue [#1](https://github.com/itay-grudev/SingleApplication/issues/1) * Improved documentation. flameshot-0.5.1/src/third-party/singleapplication/LICENSE000066400000000000000000000022321324424505000232450ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) Itay Grudev 2015 - 2016 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Note: Some of the examples include code not distributed under the terms of the MIT License. flameshot-0.5.1/src/third-party/singleapplication/README.md000066400000000000000000000217441324424505000235300ustar00rootroot00000000000000SingleApplication ================= This is a replacement of the QtSingleApplication for `Qt5`. Keeps the Primary Instance of your Application and kills each subsequent instances. It can (if enabled) spawn secondary (non-related to the primary) instances and can send data to the primary instance from secondary instances. Usage ----- The `SingleApplication` class inherits from whatever `Q[Core|Gui]Application` class you specify via the `QAPPLICATION_CLASS` macro (`QCoreApplication` is the default). Further usage is similar to the use of the `Q[Core|Gui]Application` classes. The library sets up a `QLocalServer` and a `QSharedMemory` block. The first instance of your Application is your Primary Instance. It would check if the shared memory block exists and if not it will start a `QLocalServer` and listen for connections. Each subsequent instance of your application would check if the shared memory block exists and if it does, it will connect to the QLocalServer to notify the primary instance that a new instance had been started, after which it would terminate with status code `0`. In the Primary Instance `SingleApplication` would emit the `instanceStarted()` signal upon detecting that a new instance had been started. The library uses `stdlib` to terminate the program with the `exit()` function. You can use the library as if you use any other `QCoreApplication` derived class: ```cpp #include #include int main( int argc, char* argv[] ) { SingleApplication app( argc, argv ); return app.exec(); } ``` To include the library files I would recommend that you add it as a git submodule to your project and include it's contents with a `.pri` file. Here is how: ```bash git submodule add git@github.com:itay-grudev/SingleApplication.git singleapplication ``` Then include the `singleapplication.pri` file in your `.pro` project file. Also don't forget to specify which `QCoreApplication` class your app is using if it is not `QCoreApplication`. ```qmake include(singleapplication/singleapplication.pri) DEFINES += QAPPLICATION_CLASS=QApplication ``` The `Instance Started` signal ------------------------ The SingleApplication class implements a `instanceStarted()` signal. You can bind to that signal to raise your application's window when a new instance had been started, for example. ```cpp // window is a QWindow instance QObject::connect( &app, &SingleApplication::instanceStarted, &window, &QWindow::raise ); ``` Using `SingleApplication::instance()` is a neat way to get the `SingleApplication` instance for binding to it's signals anywhere in your program. __Note:__ On Windows the ability to bring the application windows to the foreground is restricted. See [Windows specific implementations](Windows.md) for a workaround and an example implementation. Secondary Instances ------------------- If you want to be able to launch additional Secondary Instances (not related to your Primary Instance) you have to enable that with the third parameter of the `SingleApplication` constructor. The default is `false` meaning no Secondary Instances. Here is an example of how you would start a Secondary Instance send a message with the command line arguments to the primary instance and then shut down. ```cpp int main(int argc, char *argv[]) { SingleApplication app( argc, argv, true ); if( app.isSecondary() ) { app.sendMessage( app.arguments().join(' ')).toUtf8() ); app.exit( 0 ); } return app.exec(); } ``` *__Note:__ A secondary instance won't cause the emission of the `instanceStarted()` signal by default. See `SingleApplication::Mode` for more details.* You can check whether your instance is a primary or secondary with the following methods: ```cpp app.isPrimary(); // or app.isSecondary(); ``` *__Note:__ If your Primary Instance is terminated a newly launched instance will replace the Primary one even if the Secondary flag has been set.* API --- ### Members ```cpp SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100 ) ``` Depending on whether `allowSecondary` is set, this constructor may terminate your app if there is already a primary instance running. Additional `Options` can be specified to set whether the SingleApplication block should work user-wide or system-wide. Additionally the `Mode::SecondaryNotification` may be used to notify the primary instance whenever a secondary instance had been started (disabled by default). `timeout` specifies the maximum time in milliseconds to wait for blocking operations. *__Note:__ `argc` and `argv` may be changed as Qt removes arguments that it recognizes.* *__Note:__ `Mode::SecondaryNotification` only works if set on both the primary and the secondary instance.* *__Note:__ Operating system can restrict the shared memory blocks to the same user, in which case the User/System modes will have no effect and the block will be user wide.* --- ```cpp bool SingleApplication::sendMessage( QByteArray message, int timeout = 100 ) ``` Sends `message` to the Primary Instance. Uses `timeout` as a the maximum timeout in milliseconds for blocking functions --- ```cpp bool SingleApplication::isPrimary() ``` Returns if the instance is the primary instance. --- ```cpp bool SingleApplication::isSecondary() ``` Returns if the instance is a secondary instance. --- ```cpp quint32 SingleApplication::instanceId() ``` Returns a unique identifier for the current instance. --- ```cpp qint64 SingleApplication::primaryPid() ``` Returns the process ID (PID) of the primary instance. ### Signals ```cpp void SingleApplication::instanceStarted() ``` Triggered whenever a new instance had been started, except for secondary instances if the `Mode::SecondaryNotification` flag is not specified. --- ```cpp void SingleApplication::receivedMessage( quint32 instanceId, QByteArray message ) ``` Triggered whenever there is a message received from a secondary instance. --- ### Flags ```cpp enum SingleApplication::Mode ``` * `Mode::User` - The SingleApplication block should apply user wide. This adds user specific data to the key used for the shared memory and server name. This is the default functionality. * `Mode::System` – The SingleApplication block applies system-wide. * `Mode::SecondaryNotification` – Whether to trigger `instanceStarted()` even whenever secondary instances are started. * `Mode::ExcludeAppPath` – Excludes the application path from the server name (and memory block) hash. * `Mode::ExcludeAppVersion` – Excludes the application version from the server name (and memory block) hash. *__Note:__ `Mode::SecondaryNotification` only works if set on both the primary and the secondary instance.* *__Note:__ Operating system can restrict the shared memory blocks to the same user, in which case the User/System modes will have no effect and the block will be user wide.* --- Versioning ---------- Each major version introduces either very significant changes or is not backwards compatible with the previous version. Minor versions only add additional features, bug fixes or performance improvements and are backwards compatible with the previous release. See [`CHANGELOG.md`](CHANGELOG.md) for more details. Implementation -------------- The library is implemented with a QSharedMemory block which is thread safe and guarantees a race condition will not occur. It also uses a QLocalSocket to notify the main process that a new instance had been spawned and thus invoke the `instanceStarted()` signal. To handle an issue on `*nix` systems, where the operating system owns the shared memory block and if the program crashes the memory remains untouched, the library binds to the following signals and closes the program with `error code = 128 + signum` where signum is the number representation of the signal listed below. Handling the signal is required in order to safely delete the `QSharedMemory` block. Each of these signals are potentially lethal and will results in process termination. * `SIGHUP` - `1`, Hangup. * `SIGINT` - `2`, Terminal interrupt signal * `SIGQUIT` - `3`, Terminal quit signal. * `SIGILL` - `4`, Illegal instruction. * `SIGABRT` - `6`, Process abort signal. * `SIGBUS` - `7`, Access to an undefined portion of a memory object. * `SIGFPE` - `8`, Erroneous arithmetic operation (such as division by zero). * `SIGSEGV` - `11`, Invalid memory reference. * `SIGSYS` - `12`, Bad system call. * `SIGPIPE` - `13`, Write on a pipe with no one to read it. * `SIGALRM` - `14`, Alarm clock. * `SIGTERM` - `15`, Termination signal. * `SIGXCPU` - `24`, CPU time limit exceeded. * `SIGXFSZ` - `25`, File size limit exceeded. Additionally the library can recover from being killed with uncatchable signals and will reset the memory block given that there are no other instances running. License ------- This library and it's supporting documentation are released under `The MIT License (MIT)` with the exception of some of the examples distributed under the BSD license. flameshot-0.5.1/src/third-party/singleapplication/Windows.md000066400000000000000000000026411324424505000242200ustar00rootroot00000000000000Windows Specific Implementations ================================ Setting the foreground window ----------------------------- In the `instanceStarted()` example in the `README` we demonstrated how an application can bring it's primary instance window whenever a second copy of the application is started. On Windows the ability to bring the application windows to the foreground is restricted, see [`AllowSetForegroundWindow()`][AllowSetForegroundWindow] for more details. The background process (the primary instance) can bring its windows to the foreground if it is allowed by the current foreground process (the secondary instance). To bypass this `SingleApplication` must be initialized with the `allowSecondary` parameter set to `true` and the `options` parameter must include `Mode::SecondaryNotification`, See `SingleApplication::Mode` for more details. Here is an example: ```cpp if( app.isSecondary() ) { // This API requires LIBS += User32.lib to be added to the project AllowSetForegroundWindow( DWORD( app.getPrimaryPid() ) ); } if( app.isPrimary() ) { QObject::connect( &app, &SingleApplication::instanceStarted, this, &App::instanceStarted ); } ``` ```cpp void App::instanceStarted() { QApplication::setActiveWindow( [window/widget to set to the foreground] ); } ``` [AllowSetForegroundWindow]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms632668.aspx flameshot-0.5.1/src/third-party/singleapplication/singleapplication.cpp000066400000000000000000000353411324424505000264600ustar00rootroot00000000000000// The MIT License (MIT) // // Copyright (c) Itay Grudev 2015 - 2016 // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #include #endif #ifdef Q_OS_WIN #include #include #endif #include "singleapplication.h" #include "singleapplication_p.h" SingleApplicationPrivate::SingleApplicationPrivate( SingleApplication *q_ptr ) : q_ptr( q_ptr ) { server = nullptr; socket = nullptr; } SingleApplicationPrivate::~SingleApplicationPrivate() { if( socket != nullptr ) { socket->close(); delete socket; } memory->lock(); InstancesInfo* inst = static_cast(memory->data()); if( server != nullptr ) { server->close(); delete server; inst->primary = false; inst->primaryPid = -1; } memory->unlock(); delete memory; } void SingleApplicationPrivate::genBlockServerName( int timeout ) { QCryptographicHash appData( QCryptographicHash::Sha256 ); appData.addData( "SingleApplication", 17 ); appData.addData( SingleApplication::app_t::applicationName().toUtf8() ); appData.addData( SingleApplication::app_t::organizationName().toUtf8() ); appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() ); if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ) { appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() ); } if( ! (options & SingleApplication::Mode::ExcludeAppPath) ) { #ifdef Q_OS_WIN appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() ); #else appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() ); #endif } // User level block requires a user specific data in the hash if( options & SingleApplication::Mode::User ) { #ifdef Q_OS_WIN Q_UNUSED(timeout); wchar_t username [ UNLEN + 1 ]; // Specifies size of the buffer on input DWORD usernameLength = UNLEN + 1; if( GetUserNameW( username, &usernameLength ) ) { appData.addData( QString::fromWCharArray(username).toUtf8() ); } else { appData.addData( QStandardPaths::standardLocations( QStandardPaths::HomeLocation ).join("").toUtf8() ); } #endif #ifdef Q_OS_UNIX QProcess process; process.start( "whoami" ); if( process.waitForFinished( timeout ) && process.exitCode() == QProcess::NormalExit) { appData.addData( process.readLine() ); } else { appData.addData( QDir( QStandardPaths::standardLocations( QStandardPaths::HomeLocation ).first() ).absolutePath().toUtf8() ); } #endif } // Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with // server naming requirements. blockServerName = appData.result().toBase64().replace("/", "_"); } void SingleApplicationPrivate::startPrimary( bool resetMemory ) { Q_Q(SingleApplication); #ifdef Q_OS_UNIX // Handle any further termination signals to ensure the // QSharedMemory block is deleted even if the process crashes crashHandler(); #endif // Successful creation means that no main process exists // So we start a QLocalServer to listen for connections QLocalServer::removeServer( blockServerName ); server = new QLocalServer(); // Restrict access to the socket according to the // SingleApplication::Mode::User flag on User level or no restrictions if( options & SingleApplication::Mode::User ) { server->setSocketOptions( QLocalServer::UserAccessOption ); } else { server->setSocketOptions( QLocalServer::WorldAccessOption ); } server->listen( blockServerName ); QObject::connect( server, &QLocalServer::newConnection, this, &SingleApplicationPrivate::slotConnectionEstablished ); // Reset the number of connections memory->lock(); InstancesInfo* inst = static_cast(memory->data()); if( resetMemory ) { inst->secondary = 0; } inst->primary = true; inst->primaryPid = q->applicationPid(); memory->unlock(); instanceNumber = 0; } void SingleApplicationPrivate::startSecondary() { #ifdef Q_OS_UNIX // Handle any further termination signals to ensure the // QSharedMemory block is deleted even if the process crashes crashHandler(); #endif } void SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType connectionType ) { // Connect to the Local Server of the Primary Instance if not already // connected. if( socket == nullptr ) { socket = new QLocalSocket(); } // If already connected - we are done; if( socket->state() == QLocalSocket::ConnectedState ) return; // If not connect if( socket->state() == QLocalSocket::UnconnectedState || socket->state() == QLocalSocket::ClosingState ) { socket->connectToServer( blockServerName ); } // Wait for being connected if( socket->state() == QLocalSocket::ConnectingState ) { socket->waitForConnected( msecs ); } // Initialisation message according to the SingleApplication protocol if( socket->state() == QLocalSocket::ConnectedState ) { // Notify the parent that a new instance had been started; QByteArray initMsg; QDataStream writeStream(&initMsg, QIODevice::WriteOnly); writeStream.setVersion(QDataStream::Qt_5_2); writeStream << blockServerName.toLatin1(); writeStream << static_cast(connectionType); writeStream << instanceNumber; quint16 checksum = qChecksum(initMsg.constData(), static_cast(initMsg.length())); writeStream << checksum; socket->write( initMsg ); socket->flush(); socket->waitForBytesWritten( msecs ); } } qint64 SingleApplicationPrivate::primaryPid() { qint64 pid; memory->lock(); InstancesInfo* inst = static_cast(memory->data()); pid = inst->primaryPid; memory->unlock(); return pid; } #ifdef Q_OS_UNIX void SingleApplicationPrivate::crashHandler() { // Handle any further termination signals to ensure the // QSharedMemory block is deleted even if the process crashes signal( SIGHUP, SingleApplicationPrivate::terminate ); // 1 signal( SIGINT, SingleApplicationPrivate::terminate ); // 2 signal( SIGQUIT, SingleApplicationPrivate::terminate ); // 3 signal( SIGILL, SingleApplicationPrivate::terminate ); // 4 signal( SIGABRT, SingleApplicationPrivate::terminate ); // 6 signal( SIGFPE, SingleApplicationPrivate::terminate ); // 8 signal( SIGBUS, SingleApplicationPrivate::terminate ); // 10 signal( SIGSEGV, SingleApplicationPrivate::terminate ); // 11 signal( SIGSYS, SingleApplicationPrivate::terminate ); // 12 signal( SIGPIPE, SingleApplicationPrivate::terminate ); // 13 signal( SIGALRM, SingleApplicationPrivate::terminate ); // 14 signal( SIGTERM, SingleApplicationPrivate::terminate ); // 15 signal( SIGXCPU, SingleApplicationPrivate::terminate ); // 24 signal( SIGXFSZ, SingleApplicationPrivate::terminate ); // 25 } void SingleApplicationPrivate::terminate( int signum ) { delete ((SingleApplication*)QCoreApplication::instance())->d_ptr; ::exit( 128 + signum ); } #endif /** * @brief Executed when a connection has been made to the LocalServer */ void SingleApplicationPrivate::slotConnectionEstablished() { Q_Q(SingleApplication); QLocalSocket *nextConnSocket = server->nextPendingConnection(); quint32 instanceId = 0; ConnectionType connectionType = InvalidConnection; if( nextConnSocket->waitForReadyRead( 100 ) ) { // read all data from message in same order/format as written QByteArray msgBytes = nextConnSocket->read(nextConnSocket->bytesAvailable() - static_cast(sizeof(quint16))); QByteArray checksumBytes = nextConnSocket->read(sizeof(quint16)); QDataStream readStream(msgBytes); readStream.setVersion(QDataStream::Qt_5_2); // server name QByteArray latin1Name; readStream >> latin1Name; // connectioon type quint8 connType = InvalidConnection; readStream >> connType; connectionType = static_cast(connType); // instance id readStream >> instanceId; // checksum quint16 msgChecksum = 0; QDataStream checksumStream(checksumBytes); checksumStream.setVersion(QDataStream::Qt_5_2); checksumStream >> msgChecksum; const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast(msgBytes.length())); if (readStream.status() != QDataStream::Ok || QLatin1String(latin1Name) != blockServerName || msgChecksum != actualChecksum) { connectionType = InvalidConnection; } } if( connectionType == InvalidConnection ) { nextConnSocket->close(); delete nextConnSocket; return; } QObject::connect( nextConnSocket, &QLocalSocket::aboutToClose, this, [nextConnSocket, instanceId, this]() { Q_EMIT this->slotClientConnectionClosed( nextConnSocket, instanceId ); } ); QObject::connect( nextConnSocket, &QLocalSocket::readyRead, this, [nextConnSocket, instanceId, this]() { Q_EMIT this->slotDataAvailable( nextConnSocket, instanceId ); } ); if( connectionType == NewInstance || ( connectionType == SecondaryInstance && options & SingleApplication::Mode::SecondaryNotification ) ) { Q_EMIT q->instanceStarted(); } if( nextConnSocket->bytesAvailable() > 0 ) { Q_EMIT this->slotDataAvailable( nextConnSocket, instanceId ); } } void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId ) { Q_Q(SingleApplication); Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() ); } void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId ) { if( closedSocket->bytesAvailable() > 0 ) Q_EMIT slotDataAvailable( closedSocket, instanceId ); closedSocket->deleteLater(); } /** * @brief Constructor. Checks and fires up LocalServer or closes the program * if another instance already exists * @param argc * @param argv * @param {bool} allowSecondaryInstances */ SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout ) : app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) ) { Q_D(SingleApplication); // Store the current mode of the program d->options = options; // Generating an application ID used for identifying the shared memory // block and QLocalServer d->genBlockServerName( timeout ); // Guarantee thread safe behaviour with a shared memory block. Also by // explicitly attaching it and then deleting it we make sure that the // memory is deleted even if the process had crashed on Unix. #ifdef Q_OS_UNIX d->memory = new QSharedMemory( d->blockServerName ); d->memory->attach(); delete d->memory; #endif d->memory = new QSharedMemory( d->blockServerName ); // Create a shared memory block if( d->memory->create( sizeof( InstancesInfo ) ) ) { d->startPrimary( true ); return; } else { // Attempt to attach to the memory segment if( d->memory->attach() ) { d->memory->lock(); InstancesInfo* inst = static_cast(d->memory->data()); if( ! inst->primary ) { d->startPrimary( false ); d->memory->unlock(); return; } // Check if another instance can be started if( allowSecondary ) { inst->secondary += 1; d->instanceNumber = inst->secondary; d->startSecondary(); if( d->options & Mode::SecondaryNotification ) { d->connectToPrimary( timeout, SingleApplicationPrivate::SecondaryInstance ); } d->memory->unlock(); return; } d->memory->unlock(); } } d->connectToPrimary( timeout, SingleApplicationPrivate::NewInstance ); delete d; ::exit( EXIT_SUCCESS ); } /** * @brief Destructor */ SingleApplication::~SingleApplication() { Q_D(SingleApplication); delete d; } bool SingleApplication::isPrimary() { Q_D(SingleApplication); return d->server != nullptr; } bool SingleApplication::isSecondary() { Q_D(SingleApplication); return d->server == nullptr; } quint32 SingleApplication::instanceId() { Q_D(SingleApplication); return d->instanceNumber; } qint64 SingleApplication::primaryPid() { Q_D(SingleApplication); return d->primaryPid(); } bool SingleApplication::sendMessage( QByteArray message, int timeout ) { Q_D(SingleApplication); // Nobody to connect to if( isPrimary() ) return false; // Make sure the socket is connected d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect ); d->socket->write( message ); bool dataWritten = d->socket->flush(); d->socket->waitForBytesWritten( timeout ); return dataWritten; } flameshot-0.5.1/src/third-party/singleapplication/singleapplication.h000066400000000000000000000112671324424505000261260ustar00rootroot00000000000000// The MIT License (MIT) // // Copyright (c) Itay Grudev 2015 - 2016 // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef SINGLE_APPLICATION_H #define SINGLE_APPLICATION_H #include #include #ifndef QAPPLICATION_CLASS #define QAPPLICATION_CLASS QCoreApplication #endif #include QT_STRINGIFY(QAPPLICATION_CLASS) class SingleApplicationPrivate; /** * @brief The SingleApplication class handles multipe instances of the same * Application * @see QCoreApplication */ class SingleApplication : public QAPPLICATION_CLASS { Q_OBJECT typedef QAPPLICATION_CLASS app_t; public: /** * @brief Mode of operation of SingleApplication. * Whether the block should be user-wide or system-wide and whether the * primary instance should be notified when a secondary instance had been * started. * @note Operating system can restrict the shared memory blocks to the same * user, in which case the User/System modes will have no effect and the * block will be user wide. * @enum */ enum Mode { User = 1 << 0, System = 1 << 1, SecondaryNotification = 1 << 2, ExcludeAppVersion = 1 << 3, ExcludeAppPath = 1 << 4 }; Q_DECLARE_FLAGS(Options, Mode) /** * @brief Intitializes a SingleApplication instance with argc command line * arguments in argv * @arg {int &} argc - Number of arguments in argv * @arg {const char *[]} argv - Supplied command line arguments * @arg {bool} allowSecondary - Whether to start the instance as secondary * if there is already a primary instance. * @arg {Mode} mode - Whether for the SingleApplication block to be applied * User wide or System wide. * @arg {int} timeout - Timeout to wait in miliseconds. * @note argc and argv may be changed as Qt removes arguments that it * recognizes * @note Mode::SecondaryNotification only works if set on both the primary * instance and the secondary instance. * @note The timeout is just a hint for the maximum time of blocking * operations. It does not guarantee that the SingleApplication * initialisation will be completed in given time, though is a good hint. * Usually 4*timeout would be the worst case (fail) scenario. * @see See the corresponding QAPPLICATION_CLASS constructor for reference */ explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100 ); ~SingleApplication(); /** * @brief Returns if the instance is the primary instance * @returns {bool} */ bool isPrimary(); /** * @brief Returns if the instance is a secondary instance * @returns {bool} */ bool isSecondary(); /** * @brief Returns a unique identifier for the current instance * @returns {qint32} */ quint32 instanceId(); /** * @brief Returns the process ID (PID) of the primary instance * @returns {qint64} */ qint64 primaryPid(); /** * @brief Sends a message to the primary instance. Returns true on success. * @param {int} timeout - Timeout for connecting * @returns {bool} * @note sendMessage() will return false if invoked from the primary * instance. */ bool sendMessage( QByteArray message, int timeout = 100 ); Q_SIGNALS: void instanceStarted(); void receivedMessage( quint32 instanceId, QByteArray message ); private: SingleApplicationPrivate *d_ptr; Q_DECLARE_PRIVATE(SingleApplication) }; Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options) #endif // SINGLE_APPLICATION_H flameshot-0.5.1/src/third-party/singleapplication/singleapplication.pri000066400000000000000000000005001324424505000264550ustar00rootroot00000000000000QT += core network CONFIG += c++11 HEADERS += $$PWD/singleapplication.h \ $$PWD/singleapplication_p.h SOURCES += $$PWD/singleapplication.cpp INCLUDEPATH += $$PWD win32 { msvc:LIBS += Advapi32.lib gcc:LIBS += -lAdvapi32 } DISTFILES += \ $$PWD/README.md \ $$PWD/CHANGELOG.md \ $$PWD/Windows.md flameshot-0.5.1/src/third-party/singleapplication/singleapplication_p.h000066400000000000000000000052741324424505000264460ustar00rootroot00000000000000// The MIT License (MIT) // // Copyright (c) Itay Grudev 2015 - 2016 // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // W A R N I N G !!! // ----------------- // // This file is not part of the SingleApplication API. It is used purely as an // implementation detail. This header file may change from version to // version without notice, or may even be removed. // #ifndef SINGLEAPPLICATION_P_H #define SINGLEAPPLICATION_P_H #include #include #include #include "singleapplication.h" struct InstancesInfo { bool primary; quint32 secondary; qint64 primaryPid; }; class SingleApplicationPrivate : public QObject { Q_OBJECT public: enum ConnectionType : quint8 { InvalidConnection = 0, NewInstance = 1, SecondaryInstance = 2, Reconnect = 3 }; Q_DECLARE_PUBLIC(SingleApplication) SingleApplicationPrivate( SingleApplication *q_ptr ); ~SingleApplicationPrivate(); void genBlockServerName( int msecs ); void startPrimary( bool resetMemory ); void startSecondary(); void connectToPrimary(int msecs, ConnectionType connectionType ); qint64 primaryPid(); #ifdef Q_OS_UNIX void crashHandler(); static void terminate( int signum ); #endif QSharedMemory *memory; SingleApplication *q_ptr; QLocalSocket *socket; QLocalServer *server; quint32 instanceNumber; QString blockServerName; SingleApplication::Options options; public Q_SLOTS: void slotConnectionEstablished(); void slotDataAvailable( QLocalSocket*, quint32 ); void slotClientConnectionClosed( QLocalSocket*, quint32 ); }; #endif // SINGLEAPPLICATION_P_H flameshot-0.5.1/src/utils/000077500000000000000000000000001324424505000154255ustar00rootroot00000000000000flameshot-0.5.1/src/utils/confighandler.cpp000066400000000000000000000214341324424505000207400ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "confighandler.h" #include #include #include #include ConfigHandler::ConfigHandler(){ m_settings.setDefaultFormat(QSettings::IniFormat); } QVector ConfigHandler::getButtons() { QVector buttons; if (m_settings.contains("buttons")) { // TODO: remove toList in v1.0 QVector buttonsInt = m_settings.value("buttons").value >().toVector(); bool modified = normalizeButtons(buttonsInt); if (modified) { m_settings.setValue("buttons", QVariant::fromValue(buttonsInt.toList())); } buttons = fromIntToButton(buttonsInt); } else { buttons = CaptureButton::getIterableButtonTypes(); } return buttons; } void ConfigHandler::setButtons(const QVector &buttons) { QVector l = fromButtonToInt(buttons); normalizeButtons(l); // TODO: remove toList in v1.0 m_settings.setValue("buttons", QVariant::fromValue(l.toList())); } QVector ConfigHandler::getUserColors() { QVector colors; if (m_settings.contains("userColors")) { colors = m_settings.value("userColors").value >(); } else { colors = { Qt::darkRed, Qt::red, Qt::yellow, Qt::green, Qt::darkGreen, Qt::cyan, Qt::blue, Qt::magenta, Qt::darkMagenta, }; } return colors; } void ConfigHandler::setUserColors(const QVector &l) { m_settings.setValue("userColors", QVariant::fromValue(l)); } QString ConfigHandler::savePathValue() { return m_settings.value("savePath").toString(); } void ConfigHandler::setSavePath(const QString &savePath) { m_settings.setValue("savePath", savePath); } QColor ConfigHandler::uiMainColorValue() { QColor res = QColor(116, 0, 150); if (m_settings.contains("uiColor")) { res = m_settings.value("uiColor").value(); } return res; } void ConfigHandler::setUIMainColor(const QColor &c) { m_settings.setValue("uiColor", c); } QColor ConfigHandler::uiContrastColorValue() { QColor res = QColor(86, 0, 120); if (m_settings.contains("contastUiColor")) { res = m_settings.value("contastUiColor").value(); } return res; } void ConfigHandler::setUIContrastColor(const QColor &c) { m_settings.setValue("contastUiColor", c); } QColor ConfigHandler::drawColorValue() { QColor res(Qt::red); if (m_settings.contains("drawColor")) { res = m_settings.value("drawColor").value(); } return res; } void ConfigHandler::setDrawColor(const QColor &c) { m_settings.setValue("drawColor", c); } bool ConfigHandler::showHelpValue() { bool res = true; if (m_settings.contains("showHelp")) { res = m_settings.value("showHelp").toBool(); } return res; } void ConfigHandler::setShowHelp(const bool showHelp) { m_settings.setValue("showHelp", showHelp); } bool ConfigHandler::desktopNotificationValue() { bool res = true; if (m_settings.contains("showDesktopNotification")) { res = m_settings.value("showDesktopNotification").toBool(); } return res; } void ConfigHandler::setDesktopNotification(const bool showDesktopNotification) { m_settings.setValue("showDesktopNotification", showDesktopNotification); } QString ConfigHandler::filenamePatternValue() { return m_settings.value("filenamePattern").toString(); } void ConfigHandler::setFilenamePattern(const QString &pattern) { return m_settings.setValue("filenamePattern", pattern); } bool ConfigHandler::disabledTrayIconValue() { bool res = false; if (m_settings.contains("disabledTrayIcon")) { res = m_settings.value("disabledTrayIcon").toBool(); } return res; } void ConfigHandler::setDisabledTrayIcon(const bool disabledTrayIcon) { m_settings.setValue("disabledTrayIcon", disabledTrayIcon); } int ConfigHandler::drawThicknessValue() { int res = 0; if (m_settings.contains("drawThickness")) { res = m_settings.value("drawThickness").toInt(); } return res; } void ConfigHandler::setdrawThickness(const int thickness) { m_settings.setValue("drawThickness", thickness); } bool ConfigHandler::keepOpenAppLauncherValue() { return m_settings.value("keepOpenAppLauncher").toBool(); } void ConfigHandler::setKeepOpenAppLauncher(const bool keepOpen) { m_settings.setValue("keepOpenAppLauncher", keepOpen); } bool ConfigHandler::startupLaunchValue() { bool res = false; #if defined(Q_OS_LINUX) QString path = QDir::homePath() + "/.config/autostart/Flameshot.desktop"; res = QFile(path).exists(); #elif defined(Q_OS_WIN) QSettings bootUpSettings( "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); res = bootUpSettings.value("Flameshot").toString() == QDir::toNativeSeparators(QCoreApplication::applicationFilePath()); #endif return res; } void ConfigHandler::setStartupLaunch(const bool start) { #if defined(Q_OS_LINUX) QString path = QDir::homePath() + "/.config/autostart/Flameshot.desktop"; QFile file(path); if (start) { if (file.open(QIODevice::WriteOnly)) { QByteArray data("[Desktop Entry]\nName=flameshot\nIcon=flameshot" "\nExec=flameshot\nTerminal=false\nType=Application" "\nX-GNOME-Autostart-enabled=true\n"); file.write(data); } } else { file.remove(); } #elif defined(Q_OS_WIN) QSettings bootUpSettings( "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); if (start) { QString app_path = QDir::toNativeSeparators(QCoreApplication::applicationFilePath()); bootUpSettings.setValue("Flameshot", app_path); } else { bootUpSettings.remove("Flameshot"); } #endif } int ConfigHandler::contrastOpacityValue() { int opacity = 190; if (m_settings.contains("contrastOpacity")) { opacity = m_settings.value("contrastOpacity").toInt(); opacity = qBound(0, opacity, 255); } return opacity; } void ConfigHandler::setContrastOpacity(const int transparency) { m_settings.setValue("contrastOpacity", transparency); } void ConfigHandler::setDefaults() { m_settings.clear(); } void ConfigHandler::setAllTheButtons() { QVector buttons; auto listTypes = CaptureButton::getIterableButtonTypes(); for (const CaptureButton::ButtonType t: listTypes) { buttons << static_cast(t); } // TODO: remove toList in v1.0 m_settings.setValue("buttons", QVariant::fromValue(buttons.toList())); } QString ConfigHandler::configFilePath() const { return m_settings.fileName(); } bool ConfigHandler::normalizeButtons(QVector &buttons) { auto listTypes = CaptureButton::getIterableButtonTypes(); QVector listTypesInt; for(auto i: listTypes) listTypesInt << static_cast(i); bool hasChanged = false; for (int i = 0; i < buttons.size(); i++) { if (!listTypesInt.contains(buttons.at(i))) { buttons.remove(i); hasChanged = true; } } std::sort(buttons.begin(), buttons.end(), [](int a, int b){ return CaptureButton::getPriorityByButton((CaptureButton::ButtonType)a) < CaptureButton::getPriorityByButton((CaptureButton::ButtonType)b); }); return hasChanged; } QVector ConfigHandler::fromIntToButton( const QVector &l) { QVector buttons; for (auto const i: l) buttons << static_cast(i); return buttons; } QVector ConfigHandler::fromButtonToInt( const QVector &l) { QVector buttons; for (auto const i: l) buttons << static_cast(i); return buttons; } flameshot-0.5.1/src/utils/confighandler.h000066400000000000000000000045071324424505000204070ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "src/capture/widgets/capturebutton.h" #include #include class ConfigHandler { public: explicit ConfigHandler(); QVector getButtons(); void setButtons(const QVector &); QVector getUserColors(); void setUserColors(const QVector &); QString savePathValue(); void setSavePath(const QString &); QColor uiMainColorValue(); void setUIMainColor(const QColor &); QColor uiContrastColorValue(); void setUIContrastColor(const QColor &); QColor drawColorValue(); void setDrawColor(const QColor &); bool showHelpValue(); void setShowHelp(const bool); bool desktopNotificationValue(); void setDesktopNotification(const bool); QString filenamePatternValue(); void setFilenamePattern(const QString &); bool disabledTrayIconValue(); void setDisabledTrayIcon(const bool); int drawThicknessValue(); void setdrawThickness(const int); bool keepOpenAppLauncherValue(); void setKeepOpenAppLauncher(const bool); bool startupLaunchValue(); void setStartupLaunch(const bool); int contrastOpacityValue(); void setContrastOpacity(const int); void setDefaults(); void setAllTheButtons(); QString configFilePath() const; private: QSettings m_settings; bool normalizeButtons(QVector &); QVector fromIntToButton(const QVector &l); QVector fromButtonToInt(const QVector &l); }; flameshot-0.5.1/src/utils/dbusutils.cpp000066400000000000000000000032221324424505000201460ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "dbusutils.h" #include "src/utils/systemnotification.h" #include #include #include DBusUtils::DBusUtils(QObject *parent) : QObject(parent) { m_id = qHash(qApp->arguments().join(" ")); } DBusUtils::DBusUtils(uint id, QObject *parent) : QObject(parent), m_id(id) { } void DBusUtils::checkDBusConnection(const QDBusConnection &c) { if (!c.isConnected()) { SystemNotification().sendMessage(tr("Unable to connect via DBus")); qApp->exit(); } } void DBusUtils::captureTaken(uint id, QByteArray rawImage) { if (m_id == id) { QFile file; file.open(stdout, QIODevice::WriteOnly); file.write(rawImage); file.close(); qApp->exit(); } } void DBusUtils::captureFailed(uint id) { if (m_id == id) { QTextStream(stdout) << "screenshot failed"; qApp->exit(); } } flameshot-0.5.1/src/utils/dbusutils.h000066400000000000000000000023331324424505000176150ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "src/cli/commandlineparser.h" #include #include class DBusUtils : public QObject { Q_OBJECT public: explicit DBusUtils(QObject *parent = nullptr); explicit DBusUtils(uint id, QObject *parent = nullptr); void checkDBusConnection(const QDBusConnection &connection); public slots: void captureTaken(uint id, QByteArray rawImage); void captureFailed(uint id); private: uint m_id; }; flameshot-0.5.1/src/utils/desktopfileparse.cpp000066400000000000000000000121151324424505000214750ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "desktopfileparse.h" #include #include #include #include #include DesktopFileParser::DesktopFileParser() { QString locale = QLocale().name(); QString localeShort = QLocale().name().left(2); m_localeName = QStringLiteral("Name[%1]").arg(locale); m_localeDescription = QStringLiteral("Comment[%1]").arg(locale); m_localeNameShort = QStringLiteral("Name[%1]").arg(localeShort); m_localeDescriptionShort = QStringLiteral("Comment[%1]") .arg(localeShort); m_defaultIcon = QIcon::fromTheme("application-x-executable"); } DesktopAppData DesktopFileParser::parseDesktopFile( const QString &fileName, bool &ok) const { DesktopAppData res; ok = true; QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { ok = false; return res; } bool nameLocaleSet = false; bool descriptionLocaleSet = false; bool isApplication = false; QTextStream in(&file); // enter the desktop entry definition while (!in.atEnd() && in.readLine() != "[Desktop Entry]") { } // start parsing while (!in.atEnd()) { QString line = in.readLine(); if (line.startsWith("Icon")) { res.icon = QIcon::fromTheme( line.mid(line.indexOf("=")+1).trimmed(), m_defaultIcon); } else if (!nameLocaleSet && line.startsWith("Name")) { if (line.startsWith(m_localeName) || line.startsWith(m_localeNameShort)) { res.name = line.mid(line.indexOf("=")+1).trimmed(); nameLocaleSet = true; } else if (line.startsWith("Name=")) { res.name = line.mid(line.indexOf("=")+1).trimmed(); } } else if (!descriptionLocaleSet && line.startsWith("Comment")) { if (line.startsWith(m_localeDescription) || line.startsWith(m_localeDescriptionShort)) { res.description = line.mid(line.indexOf("=")+1).trimmed(); descriptionLocaleSet = true; } else if (line.startsWith("Comment=")) { res.description = line.mid(line.indexOf("=")+1).trimmed(); } } else if (line.startsWith("Exec")) { if (line.contains("%")) { res.exec = line.mid(line.indexOf("=")+1) .trimmed(); } else { ok = false; break; } } else if (line.startsWith("Type")) { if (line.contains("Application")) { isApplication = true; } } else if (line.startsWith("Categories")) { res.categories = line.mid(line.indexOf("=")+1).split(";"); } else if (line == "NoDisplay=true") { ok = false; break; } else if (line == "Terminal=true") { res.showInTerminal = true; } // ignore the other entries else if (line.startsWith("[")) { break; } } file.close(); if (res.exec.isEmpty() || res.name.isEmpty() || !isApplication) { ok = false; } return res; } int DesktopFileParser::processDirectory(const QDir &dir) { QStringList entries = dir.entryList(QDir::NoDotAndDotDot | QDir::Files); bool ok; int length = m_appList.length(); for (QString file: entries){ DesktopAppData app = parseDesktopFile(dir.absoluteFilePath(file), ok); if (ok) { m_appList.append(app); } } return m_appList.length() - length; } QVector DesktopFileParser::getAppsByCategory(const QString &category) { QVector res; for (const DesktopAppData &app : m_appList) { if (app.categories.contains(category)) { res.append(app); } } return res; } QMap> DesktopFileParser::getAppsByCategory( const QStringList &categories) { QMap> res; for (const DesktopAppData &app : m_appList) { for (const QString &category: categories) { if (app.categories.contains(category)) { res[category].append(app); } } } return res; } flameshot-0.5.1/src/utils/desktopfileparse.h000066400000000000000000000037451324424505000211530ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include #include #include class QDir; class QString; class QTextStream; struct DesktopAppData { DesktopAppData() : showInTerminal() {} DesktopAppData( QString name, QString description, QString exec, QIcon icon) : name(name), description(description), exec(exec), icon(icon), showInTerminal(false) {} bool operator==(const DesktopAppData &other) const { return name == other.name; } QString name; QString description; QString exec; QStringList categories; QIcon icon; bool showInTerminal; }; struct DesktopFileParser { DesktopFileParser(); DesktopAppData parseDesktopFile(const QString &fileName, bool &ok) const; int processDirectory(const QDir &dir); QVector getAppsByCategory(const QString &category); QMap> getAppsByCategory( const QStringList &categories); private: QString m_localeName; QString m_localeDescription; QString m_localeNameShort; QString m_localeDescriptionShort; QIcon m_defaultIcon; QVector m_appList; }; flameshot-0.5.1/src/utils/desktopinfo.cpp000066400000000000000000000034101324424505000204540ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "desktopinfo.h" #include DesktopInfo::DesktopInfo() { auto e = QProcessEnvironment::systemEnvironment(); XDG_CURRENT_DESKTOP = e.value("XDG_CURRENT_DESKTOP"); XDG_SESSION_TYPE = e.value("XDG_SESSION_TYPE"); WAYLAND_DISPLAY = e.value("WAYLAND_DISPLAY"); KDE_FULL_SESSION = e.value("KDE_FULL_SESSION"); GNOME_DESKTOP_SESSION_ID = e.value("GNOME_DESKTOP_SESSION_ID"); DESKTOP_SESSION = e.value("DESKTOP_SESSION"); } bool DesktopInfo::waylandDectected() { return XDG_SESSION_TYPE == "wayland" || WAYLAND_DISPLAY.contains("wayland", Qt::CaseInsensitive); } DesktopInfo::WM DesktopInfo::windowManager() { DesktopInfo::WM res = DesktopInfo::OTHER; if (XDG_CURRENT_DESKTOP.contains("GNOME", Qt::CaseInsensitive) || !GNOME_DESKTOP_SESSION_ID.isEmpty()) { res = DesktopInfo::GNOME; } else if (!KDE_FULL_SESSION.isEmpty() || DESKTOP_SESSION == "kde-plasma") { res = DesktopInfo::KDE; } return res; } flameshot-0.5.1/src/utils/desktopinfo.h000066400000000000000000000022671324424505000201320ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class DesktopInfo { public: DesktopInfo(); enum WM { GNOME, KDE, OTHER }; bool waylandDectected(); WM windowManager(); private: QString XDG_CURRENT_DESKTOP; QString XDG_SESSION_TYPE; QString WAYLAND_DISPLAY; QString KDE_FULL_SESSION; QString GNOME_DESKTOP_SESSION_ID; QString GDMSESSION; QString DESKTOP_SESSION; }; flameshot-0.5.1/src/utils/filenamehandler.cpp000066400000000000000000000071151324424505000212530ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "filenamehandler.h" #include "src/utils/confighandler.h" #include #include #include #include FileNameHandler::FileNameHandler(QObject *parent) : QObject(parent) { std::locale::global(std::locale("")); } QString FileNameHandler::parsedPattern() { return parseFilename(ConfigHandler().filenamePatternValue()); } QString FileNameHandler::parseFilename(const QString &name) { QString res; if (name.isEmpty()) { res = tr("screenshot"); } else { std::time_t t = std::time(NULL); char *tempData = QStringTocharArr(name); char data[MAX_CHARACTERS] = {0}; std::strftime(data, sizeof(data), tempData, std::localtime(&t)); res = QString::fromLocal8Bit(data, (int)strlen(data)); free(tempData); } // add the parsed pattern in a correct format for the filesystem res = res.replace("/", "⁄"); return res; } QString FileNameHandler::generateAbsolutePath(const QString &path) { QString directory = path; QString filename = parsedPattern(); fixPath(directory, filename); return directory + filename; } // path a images si no existe, add numeration void FileNameHandler::setPattern(const QString &pattern) { ConfigHandler().setFilenamePattern(pattern); } QString FileNameHandler::absoluteSavePath(QString &directory, QString &filename) { ConfigHandler config; directory = config.savePathValue(); if (directory.isEmpty() || !QDir(directory).exists() || !QFileInfo(directory).isWritable()) { directory = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); } filename = parsedPattern(); fixPath(directory, filename); return directory + filename; } QString FileNameHandler::absoluteSavePath() { QString dir, file; return absoluteSavePath(dir, file); } QString FileNameHandler::charArrToQString(const char *c) { return QString::fromLocal8Bit(c, MAX_CHARACTERS); } char * FileNameHandler::QStringTocharArr(const QString &s) { QByteArray ba = s.toLocal8Bit(); return const_cast(strdup(ba.constData())); } void FileNameHandler::fixPath(QString &directory, QString &filename) { // add '/' at the end of the directory if (!directory.endsWith("/")) { directory += "/"; } // add numeration in case of repeated filename in the directory // find unused name adding _n where n is a number QFileInfo checkFile(directory + filename + ".png"); if (checkFile.exists()) { filename += "_"; int i = 1; while (true) { checkFile.setFile( directory + filename + QString::number(i) + ".png"); if (!checkFile.exists()) { filename += QString::number(i); break; } ++i; } } } flameshot-0.5.1/src/utils/filenamehandler.h000066400000000000000000000027101324424505000207140ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class FileNameHandler : public QObject { Q_OBJECT public: explicit FileNameHandler(QObject *parent = nullptr); QString parsedPattern(); QString parseFilename(const QString &name); QString generateAbsolutePath(const QString &path); QString absoluteSavePath(QString &directory, QString &filename); QString absoluteSavePath(); static const int MAX_CHARACTERS = 70; public slots: void setPattern(const QString &pattern); private: //using charArr = char[MAX_CHARACTERS]; QString charArrToQString(const char *c); char * QStringTocharArr(const QString &s); void fixPath(QString &directory, QString &filename); }; flameshot-0.5.1/src/utils/pathinfo.cpp000066400000000000000000000025771324424505000177540ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "pathinfo.h" #include #include #include QStringList PathInfo::translations() { QString binaryPath = QFileInfo(qApp->applicationFilePath()) .absoluteFilePath(); QString trPath = QDir::toNativeSeparators(binaryPath) + "translations"; #if defined(Q_OS_LINUX) return QStringList() << QString(APP_PREFIX) + "/share/flameshot/translations" << trPath << "/usr/share/flameshot/translations" << "/usr/local/share/flameshot/translations"; #elif defined(Q_OS_WIN) return QStringList() << trPath; #endif } flameshot-0.5.1/src/utils/pathinfo.h000066400000000000000000000015661324424505000174160ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class PathInfo { public: static QStringList translations(); }; flameshot-0.5.1/src/utils/screengrabber.cpp000066400000000000000000000063101324424505000207350ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "screengrabber.h" #include "src/utils/filenamehandler.h" #include #include #include #include #include #ifdef Q_OS_LINUX #include #include #include #endif ScreenGrabber::ScreenGrabber(QObject *parent) : QObject(parent) { } QPixmap ScreenGrabber::grabEntireDesktop(bool &ok) { ok = true; #ifdef Q_OS_LINUX if(m_info.waylandDectected()) { QPixmap res; // handle screenshot based on DE switch (m_info.windowManager()) { case DesktopInfo::GNOME: { // https://github.com/GNOME/gnome-shell/blob/695bfb96160033be55cfb5ac41c121998f98c328/data/org.gnome.Shell.Screenshot.xml QString path = FileNameHandler().generateAbsolutePath(QDir::tempPath()) + ".png"; QDBusInterface gnomeInterface(QStringLiteral("org.gnome.Shell"), QStringLiteral("/org/gnome/Shell/Screenshot"), QStringLiteral("org.gnome.Shell.Screenshot")); QDBusReply reply = gnomeInterface.call("Screenshot", false, false, path); if (reply.value()) { res = QPixmap(path); } else { ok = false; } break; } case DesktopInfo::KDE: { // https://github.com/KDE/spectacle/blob/517a7baf46a4ca0a45f32fd3f2b1b7210b180134/src/PlatformBackends/KWinWaylandImageGrabber.cpp#L145 QDBusInterface kwinInterface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot")); QDBusReply reply = kwinInterface.call("screenshotFullscreen"); res = QPixmap(reply.value()); break; } default: ok = false; break; } return res; } #endif QRect geometry; for (QScreen *const screen : QGuiApplication::screens()) { geometry = geometry.united(screen->geometry()); } QPixmap p(QApplication::primaryScreen()->grabWindow( QApplication::desktop()->winId(), geometry.x(), geometry.y(), geometry.width(), geometry.height()) ); p.setDevicePixelRatio(QApplication::desktop()->devicePixelRatio()); return p; } flameshot-0.5.1/src/utils/screengrabber.h000066400000000000000000000020231324424505000203770ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include "src/utils/desktopinfo.h" #include class ScreenGrabber : public QObject { Q_OBJECT public: explicit ScreenGrabber(QObject *parent = nullptr); QPixmap grabEntireDesktop(bool &ok); private: DesktopInfo m_info; }; flameshot-0.5.1/src/utils/systemnotification.cpp000066400000000000000000000031201324424505000220600ustar00rootroot00000000000000#include "systemnotification.h" #include "src/utils/confighandler.h" #include #ifndef Q_OS_WIN #include #include #include #else #endif #include "src/core/controller.h" #ifdef Q_OS_LINUX SystemNotification::SystemNotification(QObject *parent) : QObject(parent) { m_interface = new QDBusInterface(QStringLiteral("org.freedesktop.Notifications"), QStringLiteral("/org/freedesktop/Notifications"), QStringLiteral("org.freedesktop.Notifications"), QDBusConnection::sessionBus(), this); } #else SystemNotification::SystemNotification(QObject *parent) : QObject(parent) { } #endif void SystemNotification::sendMessage( const QString &text, const QString &title, const int timeout) { if(!ConfigHandler().desktopNotificationValue()) { return; } #ifndef Q_OS_WIN QList args; args << (qAppName()) //appname << static_cast(0) //id << "flameshot.png" //icon << title //summary << text //body << QStringList() //actions << QVariantMap() //hints << timeout; //timeout m_interface->callWithArgumentList(QDBus::AutoDetect, "Notify", args); #else auto c = Controller::getInstance(); c->sendTrayNotification(text, title, timeout); #endif } flameshot-0.5.1/src/utils/systemnotification.h000066400000000000000000000022131324424505000215270ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class QDBusInterface; class SystemNotification : public QObject { Q_OBJECT public: explicit SystemNotification(QObject *parent = nullptr); void sendMessage(const QString &text, const QString &title = "Flameshot Info", const int timeout = 5000); private: QDBusInterface *m_interface; }; flameshot-0.5.1/src/utils/waylandutils.cpp000066400000000000000000000001501324424505000206450ustar00rootroot00000000000000#include "waylandutils.h" WaylandUtils::WaylandUtils() { } bool WaylandUtils::waylandDetected() { } flameshot-0.5.1/src/utils/waylandutils.h000066400000000000000000000002551324424505000203200ustar00rootroot00000000000000#ifndef WAYLANDUTILS_H #define WAYLANDUTILS_H class WaylandUtils { public: WaylandUtils(); static bool waylandDetected(); private: }; #endif // WAYLANDUTILS_H flameshot-0.5.1/src/widgets/000077500000000000000000000000001324424505000157335ustar00rootroot00000000000000flameshot-0.5.1/src/widgets/imagelabel.cpp000066400000000000000000000052331324424505000205240ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . // This code is a modified version of the KDE software Spectacle // /src/Gui/KSImageWidget.cpp commit cbbd6d45f6426ccbf1a82b15fdf98613ccccbbe9 #include "imagelabel.h" ImageLabel::ImageLabel(QWidget *parent): QLabel(parent), m_pixmap(QPixmap()) { m_DSEffect = new QGraphicsDropShadowEffect(this); m_DSEffect->setBlurRadius(5); m_DSEffect->setOffset(0); m_DSEffect->setColor(QColor(Qt::black)); setGraphicsEffect(m_DSEffect); setCursor(Qt::OpenHandCursor); setAlignment(Qt::AlignCenter); setMinimumSize(size()); } void ImageLabel::setScreenshot(const QPixmap &pixmap) { m_pixmap = pixmap; const QString tooltip = QStringLiteral("%1x%2 px").arg(m_pixmap.width()) .arg(m_pixmap.height()); setToolTip(tooltip); setScaledPixmap(); } void ImageLabel::setScaledPixmap() { const qreal scale = qApp->devicePixelRatio(); QPixmap scaledPixmap = m_pixmap.scaled(size() * scale, Qt::KeepAspectRatio, Qt::SmoothTransformation); scaledPixmap.setDevicePixelRatio(scale); setPixmap(scaledPixmap); } // drag handlers void ImageLabel::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_dragStartPosition = event->pos(); setCursor(Qt::ClosedHandCursor); } } void ImageLabel::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { setCursor(Qt::OpenHandCursor); } } void ImageLabel::mouseMoveEvent(QMouseEvent *event) { if (!(event->buttons() & Qt::LeftButton)) { return; } if ((event->pos() - m_dragStartPosition).manhattanLength() < QGuiApplication::styleHints()->startDragDistance()) { return; } setCursor(Qt::OpenHandCursor); emit dragInitiated(); } // resize handler void ImageLabel::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); setScaledPixmap(); } flameshot-0.5.1/src/widgets/imagelabel.h000066400000000000000000000033321324424505000201670ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . // This code is a modified version of the KDE software Spectacle // /src/Gui/KSImageWidget.h commit cbbd6d45f6426ccbf1a82b15fdf98613ccccbbe9 #pragma once #include #include #include #include #include #include #include #include class ImageLabel : public QLabel { Q_OBJECT public: explicit ImageLabel(QWidget *parent = 0); void setScreenshot(const QPixmap &pixmap); signals: void dragInitiated(); protected: void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; private: void setScaledPixmap(); QGraphicsDropShadowEffect *m_DSEffect; QPixmap m_pixmap; QPoint m_dragStartPosition; }; flameshot-0.5.1/src/widgets/loadspinner.cpp000066400000000000000000000050601324424505000207560ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "loadspinner.h" #include #include #include #include #define OFFSET 5 LoadSpinner::LoadSpinner(QWidget *parent) : QWidget(parent), m_startAngle(0), m_span(0), m_growing(true) { setAttribute(Qt::WA_TranslucentBackground); const int size = QApplication::fontMetrics().height() * 8; setFixedSize(size, size); updateFrame(); // init timer m_timer = new QTimer(this); connect(m_timer, SIGNAL(timeout()), this, SLOT(rotate())); m_timer->setInterval(30); } void LoadSpinner::setColor(const QColor &c) { m_color = c; } void LoadSpinner::setWidth(int w) { setFixedSize(w, w); updateFrame(); } void LoadSpinner::setHeight(int h) { setFixedSize(h, h); updateFrame(); } void LoadSpinner::start() { m_timer->start(); } void LoadSpinner::stop() { m_timer->stop(); } void LoadSpinner::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); auto pen = QPen(m_color); pen.setWidth(height()/10); painter.setPen(pen); painter.setOpacity(0.2); painter.drawArc(m_frame, 0, 5760); painter.setOpacity(1.0); painter.drawArc(m_frame, (m_startAngle * 16), (m_span * 16)); } void LoadSpinner::rotate() { const int advance = 3; const int grow = 8; if (m_growing) { m_startAngle = (m_startAngle + advance) % 360; m_span += grow; if(m_span > 260) { m_growing = false; } } else { m_startAngle = (m_startAngle + grow) % 360; m_span = m_span + advance - grow; if(m_span < 10) { m_growing = true; } } update(); } void LoadSpinner::updateFrame() { m_frame = QRect(OFFSET, OFFSET, width() - OFFSET*2, height() - OFFSET*2); } flameshot-0.5.1/src/widgets/loadspinner.h000066400000000000000000000024251324424505000204250ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class LoadSpinner : public QWidget { Q_OBJECT public: explicit LoadSpinner(QWidget *parent = nullptr); void setColor(const QColor &c); void setWidth(int w); void setHeight(int h); void start(); void stop(); protected: void paintEvent(QPaintEvent *); private slots: void rotate(); private: QColor m_color; QTimer *m_timer; int m_startAngle = 0; int m_span =180; bool m_growing; QRect m_frame; void updateFrame(); }; flameshot-0.5.1/src/widgets/notificationwidget.cpp000066400000000000000000000045771324424505000223460ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #include "notificationwidget.h" #include #include #include #include #include #include #include NotificationWidget::NotificationWidget(QWidget *parent) : QWidget(parent) { m_timer = new QTimer(this); m_timer->setSingleShot(true); m_timer->setInterval(7000); connect(m_timer, &QTimer::timeout, this, &NotificationWidget::animatedHide); m_content = new QFrame(); m_layout = new QVBoxLayout(); m_label = new QLabel(m_content); m_label->hide(); m_showAnimation = new QPropertyAnimation(m_content, "geometry", this); m_showAnimation->setDuration(300); m_hideAnimation = new QPropertyAnimation(m_content, "geometry", this); m_hideAnimation->setDuration(300); connect(m_hideAnimation, &QPropertyAnimation::finished, m_label, &QLabel::hide); auto mainLayout = new QVBoxLayout(); setLayout(mainLayout); mainLayout->addWidget(m_content); m_layout->addWidget(m_label, 0, Qt::AlignHCenter); m_content->setLayout(m_layout); setFixedHeight(40); } void NotificationWidget::showMessage(const QString &msg) { m_label->setText(msg); m_label->show(); animatedShow(); } void NotificationWidget::animatedShow() { m_showAnimation->setStartValue(QRect(0, 0, width(), 0)); m_showAnimation->setEndValue(QRect(0, 0, width(), height())); m_showAnimation->start(); m_timer->start(); } void NotificationWidget::animatedHide() { m_hideAnimation->setStartValue(QRect(0, 0, width(), height())); m_hideAnimation->setEndValue(QRect(0, 0, width(), 0)); m_hideAnimation->start(); } flameshot-0.5.1/src/widgets/notificationwidget.h000066400000000000000000000024361324424505000220030ustar00rootroot00000000000000// Copyright(c) 2017-2018 Alejandro Sirgo Rica & Contributors // // This file is part of Flameshot. // // Flameshot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Flameshot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Flameshot. If not, see . #pragma once #include class QLabel; class QTimer; class QPropertyAnimation; class QVBoxLayout; class QFrame; class NotificationWidget : public QWidget { Q_OBJECT public: explicit NotificationWidget(QWidget *parent = nullptr); void showMessage(const QString &msg); private: QLabel *m_label; QPropertyAnimation *m_showAnimation; QPropertyAnimation *m_hideAnimation; QVBoxLayout *m_layout; QFrame *m_content; QTimer *m_timer; void animatedShow(); void animatedHide(); }; flameshot-0.5.1/translations/000077500000000000000000000000001324424505000162175ustar00rootroot00000000000000flameshot-0.5.1/translations/Internationalization_ca.ts000066400000000000000000000514141324424505000234440ustar00rootroot00000000000000 AppLauncher App Launcher Llançador d'aplicacions Choose an app to open the capture Trieu una aplicació per obrir la captura AppLauncherWidget Open With Obrir Amb Launch in terminal Llançament a la terminal Keep open after selection Segueix obert després de la selecció Error Error Unable to launch in terminal. No es pot iniciar a la terminal. Unable to write in No es pot escriure a ArrowTool Arrow Fletxa Sets the Arrow as the paint tool Estableix la fletxa com a eina de dibuix BlurTool Blur Desenfocament Sets the Blur as the paint tool Estableix el desenfocament com a eina de dibuix CaptureWidget Select an area with the mouse, or press Esc to exit. Press Enter to capture the screen. Press Right Click to show the color picker. Use the Mouse Wheel to change the thickness of your tool. Seleccioneu una àrea amb el ratolí, o premeu Esc per a eixir. Premeu Retorn per a capturar la pantalla. Feu clic amb el botó dret per a mostrar el selector de color. Utilitzeu la roda del ratolí per a canviar el gruix de l'eina. Unable to capture screen Impossible capturar la pantalla Imposible capturar la pantalla CircleTool Circle Cercle Sets the Circle as the paint tool Estableix el cercle com a eina de dibuix ConfigWindow Configuration Configuració Button Selection Selecció de botó Select All Selecciona-ho tot Interface Interfície Filename Editor Editor de noms General General Controller &Configuration &Configuració &Information &Informació &Quit &Ix CopyTool Copy Copia Copies the selecion into the clipboard Copia la selecció al porta-retalls DBusUtils Unable to connect via DBus Impossible connectar mitjançant DBus ExitTool Exit Ix Leave the capture screen Ix de la pantalla de captura FileNameEditor Edit the name of your captures: Editeu el nom de les vostres captures: Edit: Edita: Preview: Previsualització: Save Guarda Saves the pattern Guarda el patró Reset Reinicialitza Restores the saved pattern Restaura el patró guardat Clear Neteja Deletes the name Elimina el patró FileNameHandler screenshot captura FlameshotDBusAdapter Unable to capture screen Imposible capturar la pantalla GeneneralConf Show help message Mostra el missatge d'ajuda Show the help message at the beginning in the capture mode. Mostra el missatge d'ajuda en iniciar el mode de captura. Show desktop notifications Mostra les notificacions d'escriptori Show tray icon Mostra la icona en la barra de tasques Show the systemtray icon Mostra la icona en la barra de tasques Import Importar Error Error Unable to read file. Impossible llegir el fitxer. Unable to write file. Impossible escriure al fitxer. Save File Guardar Arxiu Confirm Reset Confirmar Reset Are you sure you want to reset the configuration? Esteu segur que voleu reiniciar la configuració? Configuration File Fitxer de Configuració Export Exportar Reset Reset Launch at startup Llançament a l'inici Launch Flameshot Llançament de Flameshot ImgurUploader Upload to Imgur Puja a Imgur Uploading Image S'està pujant la imatge Copy URL Copia l'URL Open URL Obri l'URL Image to Clipboard. Imatge al porta-retalls. Unable to open the URL. No es pot obrir l'URL. URL copied to clipboard. L'URL s'ha copiat al porta-retalls. Screenshot copied to clipboard. La captura s'ha copiat al porta-retalls. ImgurUploaderTool Image Uploader Puja la imatge Uploads the selection to Imgur Puja la selecció a Imgur InfoWindow About Quant a Right Click Clic dret Mouse Wheel Roda del ratolí Move selection 1px Mou la selecció 1 px Resize selection 1px Redimensiona la selecció 1 px Quit capture Ix de la captura Copy to clipboard Copia al porta-retalls Save selection as a file Guarda la selecció com a fitxer Undo the last modification Desfés l'última modificació Show color picker Mostra el selector de color Change the tool's thickness Canvia el gruix de l'eina Available shorcuts in the screen capture mode. Dreceres disponibles en el mode de captura de pantalla. Key Tecla Description Descripció <u><b>License</b></u> <u><b>Llicència</b></u> <u><b>Version</b></u> <u><b>Versió</b></u> <u><b>Shortcuts</b></u> <u><b>Dreceres</b></u> Available shortcuts in the screen capture mode. Dreceres disponibles en el mode de captura de pantalla. LineTool Line Línia Sets the Line as the paint tool Estableix la línia com a eina de dibuix MarkerTool Marker Marcador Sets the Marker as the paint tool Estableix el marcador com a eina de dibuix MoveTool Move Mou Move the selection area Mou la selecció PencilTool Pencil Llapis Sets the Pencil as the paint tool Estableix el llapis com a eina de dibuix QObject Save As Anomena i guarda Save Error S'ha produït un error en guardar Capture saved as Anomena i guarda la captura Error trying to save as S'ha produït un error en anomenar i guardar Unable to connect via DBus No es pot connectar mitjançant DBus Error Error Unable to write in No es pot escriure a RectangleTool Rectangle Rectangle Sets the Rectangle as the paint tool Estableix el rectangle com a eina de dibuix SaveTool Save Guarda Save the capture Guarda la captura SelectionTool Rectangular Selection Selecció rectangular Sets the Selection as the paint tool Estableix la selecció com a eina de dibuix SizeIndicatorTool Selection Size Indicator Indicador de mida de selecció Shows the dimensions of the selection (X Y) Mostra les mides de la selecció (X Y) StrftimeChooserWidget Century (00-99) Segle (00-99) Year (00-99) Any (00-99) Year (2000) Any (2000) Month Name (jan) Nom del mes (jul) Month Name (january) Nom del mes (juliol) Month (01-12) Mes (01-12) Week Day (1-7) Dia de la setmana (1-7) Week (01-53) Setmana (01-53) Day Name (mon) Nom del dia (dg) Day Name (monday) Nom del dia (diumenge) Day (01-31) Dia (01-31) Day of Month (1-31) Dia del mes (1-31) Day (001-366) Dia (001-366) Time (%H:%M:%S) Temps (%H:%M:%S) Time (%H:%M) Temps (%H:%M) Hour (00-23) Hora (00-23) Hour (01-12) Hora (01-12) Minute (00-59) Minut (00-59) Second (00-59) Segon (00-59) Full Date (%m/%d/%y) Data (%m/%d/%y) Full Date (%Y-%m-%d) Data (%Y-%m-%d) UIcolorEditor UI Color Editor Editor de color de la interfície Change the color moving the selectors and see the changes in the preview buttons. Canvieu el color movent els selectors i observeu els canvis en els botons de previsualització. Select a Button to modify it Seleccioneu un botó per a modificar-lo Main Color Color principal Click on this button to set the edition mode of the main color. Feu clic en aquest botó per a aplicar el mode d'edició per al color principal. Contrast Color Color de contrast Click on this button to set the edition mode of the contrast color. Feu clic en aquest botó per a aplicar el mode d'edició per al color de contrast. UndoTool Undo Desfés Undo the last modification Desfés l'última modificació VisualsEditor Opacity of area outside selection: Opacitat de la zona fora de la selecció: Button Selection Selecció de botó Select All Selecciona-ho tot flameshot-0.5.1/translations/Internationalization_es.ts000066400000000000000000000770251324424505000234760ustar00rootroot00000000000000 AppLauncher App Launcher Lanzador de Aplicaciones Choose an app to open the capture Elije una aplicación con la que abrir la captura AppLauncherWidget Open With Abrir Con Launch in terminal Lanzar en terminal Keep open after selection Mantener abierto tras la selección Error Error Unable to write in Imposible escribir en Unable to launch in terminal. Imposible lanzar en terminal. ArrowTool Arrow Flecha Sets the Arrow as the paint tool Establece la Flecha como herramienta de dibujo BlurTool Blur Desenfoque Sets the Blur as the paint tool Establece el Desenfoque como herramienta de dibujo CaptureWidget Unable to capture screen Imposible capturar la pantalla Select an area with the mouse, or press Esc to exit. Press Enter to capture the screen. Press Right Click to show the color picker. Use the Mouse Wheel to change the thickness of your tool. Selecciona un área con el ratón. o presiona Esc para salir. Presiona Enter para capturar la pantalla. Presion Click Derecho para mostrar el selector de color. Usa la rueda del ratón para cambiar el grosor de la herramienta. CircleTool Circle Círculo Sets the Circle as the paint tool Establece el Círculo como herramienta de dibujo ConfigWindow Configuration Configuración Button Selection Selección de Botón Select All Seleccionar Todos Interface Interfaz Filename Editor Editor de Nombre General General Controller &Configuration &Configuración &Information &Información &Quit &Salir CopyTool Copy Copiar Copies the selecion into the clipboard Copia la selección al portapapeles DBusUtils Unable to connect via DBus Imposible conectarse mediante DBus ExitTool Exit Salir Leave the capture screen Salir de la pantalla de captura FileNameEditor Edit the name of your captures: Edita el nombre de tus capturas: Edit: Editar: Preview: Previsualización: Save Guardar Saves the pattern Guarda el patrón Reset Reiniciar Restores the saved pattern Restaura el patrón guardado Clear Limpiar Deletes the name Borra el patrón FileNameHandler screenshot captura FlameshotDBusAdapter Unable to capture screen Imposible capturar la pantalla GeneneralConf Import Importar Error Error Unable to read file. Imposible leer el archivo. Unable to write file. Imposible escribir el archivo. Save File Guardar Archivo Confirm Reset Confirmar Reset Are you sure you want to reset the configuration? ¿Estás seguro de que quieres reiniciar la configuración? Show help message Mostrar mensaje de ayuda Show the help message at the beginning in the capture mode. Muestra el mensaje de ayuda al iniciar el modo de captura. Show desktop notifications Mostrar notificaciones del escritorio Show tray icon Mostrar icono en la barra de tareas Show the systemtray icon Mostrar el icono en la barra de tareas Configuration File Archivo de Configuración Export Exportar Reset Reset Launch at startup Lanzar en el arranque Launch Flameshot Lanzar Flameshot ImgurUploader Upload to Imgur Subir a Imgur Uploading Image Subiendo Imagen Copy URL Copiar URL Open URL Abrir URL Image to Clipboard. Imagen al Portapapeles. Unable to open the URL. No puede abrir la URL. URL copied to clipboard. URL copiada al portapapeles. Screenshot copied to clipboard. Captura copiada al portapapeles. ImgurUploaderTool Image Uploader Subir Imagen Uploads the selection to Imgur Sube la selección a Imgur InfoWindow About Información Right Click Click Derecho Mouse Wheel Rueda del Ratón Move selection 1px Mueve la selección 1px Resize selection 1px Redimensiona la selección 1px Quit capture Salir de la captura Copy to clipboard Copiar al portapapeles Save selection as a file Guarda la selección como un archivo Undo the last modification Deshacer la última modificación Show color picker Muestra el selector de color Change the tool's thickness Cambiar el grosor de la herramienta Available shortcuts in the screen capture mode. Atajos disponibles en el modo captura de pantalla. Available shorcuts in the screen capture mode. Atajos disponibles en el modo de captura de pantalla. Key Tecla Description Descripción <u><b>License</b></u> <u><b>Licencia</b></u> <u><b>Version</b></u> <u><b>Versión</b></u> <u><b>Shortcuts</b></u> <u><b>Atajos</b></u> LineTool Line Línea Sets the Line as the paint tool Establece la Línea como herramienta de dibujo MarkerTool Marker Marcador Sets the Marker as the paint tool Establece el Marcador como herramienta de dibujo MoveTool Move Mover Selección Move the selection area Mueve la selección PencilTool Pencil Lápiz Sets the Pencil as the paint tool Establece el Lápiz como herramienta de dibujo QObject Save As Guardar Como Save Error Error al Guardar Capture saved as Captura guardada como Error trying to save as Error intentando guardar como Unable to connect via DBus Imposible conectar mediante DBus Error Error Unable to write in Imposible escribir en RectangleTool Rectangle Rectángulo Sets the Rectangle as the paint tool Establece el Rectángulo como herramienta de dibujo SaveTool Save Guardar Save the capture Guarda la captura SelectionTool Rectangular Selection Selección Rectangular Sets the Selection as the paint tool Establece la Selección como herramienta de dibujo SizeIndicatorTool Selection Size Indicator Indicador de Tamaño de Selección Shows the dimensions of the selection (X Y) Muestra la dimensión de la selección (X Y) StrftimeChooserWidget Century (00-99) Siglo (00-99) Year (00-99) Año (00-99) Year (2000) Año (2000) Month Name (jan) Nombre del Mes (jul) Month Name (january) Nombre del Mes (julio) Month (01-12) Mes (01-12) Week Day (1-7) Día de la Semana (1-7) Week (01-53) Semana (01-53) Day Name (mon) Nombre del Día (dom) Day Name (monday) Nombre del Día (domingo) Day (01-31) Día (01-31) Day of Month (1-31) Día del Mes (1-31) Day (001-366) Día (001-366) Time (%H:%M:%S) Tiempo (%H:%M:%S) Time (%H:%M) Tiempo (%H:%M) Hour (00-23) Hora (00-23) Hour (01-12) Hora (01-12) Minute (00-59) Minuto (00-59) Second (00-59) Segundo (00-59) Full Date (%m/%d/%y) Fecha (%m/%d/%y) Full Date (%Y-%m-%d) Fecha (%Y-%m-%d) UIcolorEditor UI Color Editor Editor de Color de Interfaz Change the color moving the selectors and see the changes in the preview buttons. Cambia el color moviendo los selectores y observa los cambios en los botones de previsualización. Select a Button to modify it Selecciona un Botón para modificarlo Main Color Color Principal Click on this button to set the edition mode of the main color. Clica en este botón para aplicar el modo edición para el color primario. Contrast Color Color de Contraste Click on this button to set the edition mode of the contrast color. Clica en este botón para aplicar el modo edición para el color de contraste. UndoTool Undo Deshacer Undo the last modification Borra la última modificación VisualsEditor Opacity of area outside selection: Opacidad del area fuera de la selección: Button Selection Selección de Botón Select All Seleccionar Todos flameshot-0.5.1/translations/Internationalization_fr.ts000066400000000000000000000767661324424505000235110ustar00rootroot00000000000000 AppLauncher App Launcher Lanceur d'applications Choose an app to open the capture Sélectionner une application pour ouvrir la capture AppLauncherWidget Open With Ouvrir Avec Launch in terminal Lancer dans le terminal Keep open after selection Maintenir ouvert après la sélection Error Erreur Unable to write in Imposible d'écrire dessus Unable to launch in terminal. Imposible de lancer dans le terminal. ArrowTool Arrow Flèche Sets the Arrow as the paint tool Sélectionner l'outil Flèche BlurTool Blur Flou Sets the Blur as the paint tool Sélectionner l'outil Flou CaptureWidget Unable to capture screen Imposible de capturer l'écran Select an area with the mouse, or press Esc to exit. Press Enter to capture the screen. Press Right Click to show the color picker. Use the Mouse Wheel to change the thickness of your tool. Sélectionner une zone avec la souris, ou taper sur Echap pour quitter. Taper sur Entrée pour capturer l'écran. Clic droit pour afficher la palette de couleurs. Utiliser la molette pour changer l'épaisseur de l'outil. CircleTool Circle Ellipse Sets the Circle as the paint tool Sélectionner l'outil Ellipse ConfigWindow Configuration Configuration Button Selection Boutton Sélection Select All Sélectionner Tout Interface Interface Filename Editor Editeur de Noms General Général Controller &Configuration &Configuration &Information &Information &Quit &Quitter CopyTool Copy Copier Copies the selecion into the clipboard Copie la sélection dans le Presse-papier DBusUtils Unable to connect via DBus Imposible de se connecter via DBus ExitTool Exit Sortir Leave the capture screen Quitter l'écran de capture FileNameEditor Edit the name of your captures: Editer le nom des captures: Edit: Editer: Preview: Prévisualisation: Save Sauvegarder Saves the pattern Sauvegarder le modèle Reset Réinitialiser Restores the saved pattern Réstaurer le modèle sauvegardé Clear Purger Deletes the name Supprime le nom FileNameHandler screenshot capture d'écran FlameshotDBusAdapter Unable to capture screen Impossible de capturer l'écran GeneneralConf Import Importer Error Erreur Unable to read file. Impossible de lire le fichier. Unable to write file. Impossible d'écrire le fichier. Save File Sauvegarder le fichier Confirm Reset Confirmer la Réinitialisation Are you sure you want to reset the configuration? Êtes-vous sûr de vouloir réinitialiser la configuration ? Show help message Montrer le message d'aide Show the help message at the beginning in the capture mode. Afficher ce message au lancement du mode capture. Show desktop notifications Afficher les notifications du bureau Show tray icon Afficher les icones de la barre d'état Show the systemtray icon Afficher l'icône dans la barre de tâches Configuration File Fichier de Configuration Export Exporter Reset Réinitialiser Launch at startup Lancer au démarrage Launch Flameshot Lancer Flameshot ImgurUploader Upload to Imgur Mettre en ligne vers Imgur Uploading Image Mise en ligne de l'image Copy URL Copier l'URL Open URL Ouvrir l'URL Image to Clipboard. Image dans le Presse-papier. Unable to open the URL. Impossible d'ouvrir l'URL. URL copied to clipboard. URL copiée dans le Presse-papier. Screenshot copied to clipboard. Capture d'écran copiée dans le Presse-papier. ImgurUploaderTool Image Uploader Mise en ligne d'images Uploads the selection to Imgur Mettre en ligne la sélection vers Imgur InfoWindow About À propos Right Click Clic Droit Mouse Wheel Molette de la Souris Move selection 1px Déplacer la sélection 1px Resize selection 1px Redimensionner la sélection 1px Quit capture Quitter la capture d'écran Copy to clipboard Copier vers le Presse-papier Save selection as a file Sauvegarder la sélection vers un fichier Undo the last modification Annuler la dernière modification Show color picker Afficher la palette de couleurs Change the tool's thickness Changer l'épaisseur des outils Available shortcuts in the screen capture mode. Raccourcis disponibles en mode capture d'écran. Available shorcuts in the screen capture mode. Raccourcis disponibles en mode capture d'écran. Key Clé Description Description <u><b>License</b></u> <u><b>Licences</b></u> <u><b>Version</b></u> <u><b>Version</b></u> <u><b>Shortcuts</b></u> <u><b>Raccourci</b></u> LineTool Line Ligne Sets the Line as the paint tool Sélectionner l'outil Ligne MarkerTool Marker Surligneur Sets the Marker as the paint tool Sélectionner l'outil Surligneur MoveTool Move Déplacer Move the selection area Déplacer la sélection PencilTool Pencil Crayon Sets the Pencil as the paint tool Sélectionner l'outil Crayon QObject Save As Sauvegarder sous Save Error Erreur lors de la sauvegarde Capture saved as Capture d'écran sauvegardée sous Error trying to save as Erreur lors de la sauvegarde sous Unable to connect via DBus Impossible de se connecter via DBus RectangleTool Rectangle Rectangle plein Sets the Rectangle as the paint tool Sélectionner l'outil Rectangle plein SaveTool Save Sauvegarder Save the capture Sauvegarder la capture d'écran SelectionTool Rectangular Selection Rectangle Sets the Selection as the paint tool Sélectionner l'outil Rectangle SizeIndicatorTool Selection Size Indicator Indicateur de la taille de la sélection Shows the dimensions of the selection (X Y) Montre les dimmensions de la sélection (X Y) StrftimeChooserWidget Century (00-99) Siècle (00-99) Year (00-99) Année (00-99) Year (2000) Année (2000) Month Name (jan) Nom des Mois (jan) Month Name (january) nom des Mois (janvier) Month (01-12) Mois (01-12) Week Day (1-7) Jour de la Semaine (1-7) Week (01-53) Semaine (01-53) Day Name (mon) Nom du Jour (lun) Day Name (monday) Nom du Jour (lundi) Day (01-31) Jour (01-31) Day of Month (1-31) Jour du Mois (1-31) Day (001-366) Jour de l'année (001-366) Time (%H:%M:%S) Temps (%H:%M:%S) Time (%H:%M) Temps (%H:%M) Hour (00-23) Heure (00-23) Hour (01-12) Heure (01-12) Minute (00-59) Minute (00-59) Second (00-59) Seconde (00-59) Full Date (%m/%d/%y) Date (%m/%d/%y) Full Date (%Y-%m-%d) Date Complête (%Y-%m-%d) UIcolorEditor UI Color Editor Editeur de la Couleur de l'interface Change the color moving the selectors and see the changes in the preview buttons. Modifiez la couleur en déplaçant les sélecteur et voir les changements dans les boutons de prévisualisation. Select a Button to modify it Sélectionner un bouton pour le modifier Main Color Couleur Principale Click on this button to set the edition mode of the main color. Cliquer sur ce boutton pour définir le mode édition de la couleur principale. Contrast Color Couleur de Contraste Click on this button to set the edition mode of the contrast color. Cliquer sur ce boutton pour définir le mode édition de la couleur de contraste. UndoTool Undo Annuler Undo the last modification Annuler la dernière modification VisualsEditor Opacity of area outside selection: Opacité de la zone en dehors de la sélection: Button Selection Boutton de sélection Select All Sélectionner Tout flameshot-0.5.1/translations/Internationalization_ka.ts000066400000000000000000001105721324424505000234550ustar00rootroot00000000000000 AppLauncher App Launcher აპლიკაციის გამშვები Choose an app to open the capture აირჩიეთ აპლიკაცია სურათის გასახსნელად AppLauncherWidget Open With გახსნა პროგრამით Launch in terminal ტერმინალში გაშვება Keep open after selection არ დახურო დიალოგი არჩევის შემდეგ Error შეცდომა Unable to write in შემდეგ მისამართზე ჩაწერა ვერ მოხერხდა: Unable to launch in terminal. ტერმინალში გაშვება ვერ მოხერხდა. ArrowTool Arrow ისარი Sets the Arrow as the paint tool ისრის ხელსაწყოს არჩევა სახატავად BlurTool Blur გაბუნდოვნება Sets the Blur as the paint tool გაბუნდოვნების ხელსაწყოს არჩევა სახატავად CaptureWidget Unable to capture screen ეკრანის გადაღება ვერ მოხერხდა Select an area with the mouse, or press Esc to exit. Press Enter to capture the screen. Press Right Click to show the color picker. Use the Mouse Wheel to change the thickness of your tool. შეარჩიეთ ეკრანის არე მაუსით, ან დააწექით Esc-ს გამოსასვლელად. დააწექით Enter-ს ეკრანის გადასაღებად. წააწექით და დაიჭირეთ მაუსის მარჯვენა ღილაკი ფერის ასარჩევად. გამოიყენეთ მაუსის გორგოლაჭი ხელსაწყოს სისქის შესარევად. CircleTool Circle წრე Sets the Circle as the paint tool წრის ხელსაწყოს არჩევა სახატავად ConfigWindow Configuration პარამეტრები Button Selection ღილაკის არჩევა Select All ყველაფრის შერჩევა Interface ინტერფეისი Filename Editor ფაილის სახელის რედაქტორი General ზოგადი Controller &Configuration &პარამეტრები &Information &ინფორმაცია &Quit &გამოსვლა CopyTool Copy კოპირება Copies the selecion into the clipboard შერჩეულის გაცვლის ბუფერში კოპირება DBusUtils Unable to connect via DBus DBus-ით დაკავშირება ვერ მოხერხდა ExitTool Exit გამოსვლა Leave the capture screen ეკრანის გადაღების დატოვება FileNameEditor Edit the name of your captures: შეცვალეთ თქვენი სურათების სახელი: Edit: თარგი: Preview: გადახედვა: Save შენახვა Saves the pattern თარგის შენახვა Reset განულება Restores the saved pattern შენახული შაბლონის განულება Clear გაწმენდა Deletes the name სახელის წაშლა FileNameHandler screenshot სურათი FlameshotDBusAdapter Unable to capture screen ეკრანის გადაღება ვერ მოხერხდა GeneneralConf Import იმპორტირება Error შეცდომა Unable to read file. ფაილის წაკითხვა ვერ მოხერხდა. Unable to write file. ფაილის ჩაწერა ვერ მოხერხდა. Save File ფაილის შენახვა Confirm Reset განულების დადასტურება Are you sure you want to reset the configuration? დარწმუნებული ხართ, რომ გსურთ პარამეტრების განულება? Show help message დახმარების შეტყობინების ნახვა Show the help message at the beginning in the capture mode. დახმარების შეტყობინების ნახვა გადაღების რეჟიმის დაწყებისას. Show desktop notifications ცნობების ჩვენება სამუშაო მაგიდაზე Show tray icon ხატულის ჩვენება სისტემურ პანელზე Show the systemtray icon ხატულის ჩვენება სისტემურ პანელზე Configuration File პარამეტრების ფაილი Export ექსპორტირება Reset განულება Launch at startup გაშვება სისტემის ჩატვირთვისას Launch Flameshot Flameshot-ის გაშვება ImgurUploader Upload to Imgur Imgur-ზე ატვირთვა Uploading Image სურათის ატვირთვა Copy URL URL-ის კოპირება Open URL URL-ის გახსნა Image to Clipboard. სურათის გაცვლის ბუფერში გაგზავნა Unable to open the URL. URL-ის გახსნა ვერ მოხერხდა. URL copied to clipboard. URL დაკოპირდა გაცვლის ბუფერში. Screenshot copied to clipboard. სურათი დაკოპირდა გაცვლის ბუფერში. ImgurUploaderTool Image Uploader სურათის ამტვირთველი Uploads the selection to Imgur შერჩეულის Imgur-ზე ატვირთვა InfoWindow About პროგრამის შესახებ Right Click მაუსის მარჯვენა ღილაკი Mouse Wheel მაუსის გორგოლაჭი Move selection 1px შერჩეულის გადაადგილება 1px-ით Resize selection 1px შერჩეულის ზომის შეცვლა 1px-ით Quit capture გადაღებიდან გამოსვლა Copy to clipboard გაცვლის ბუფერში კოპირება Save selection as a file შერჩეულის ფაილად შენახვა Undo the last modification ბოლო ცვლილების გაუქმება Show color picker ფერის შესარჩევის ჩვენება Change the tool's thickness ხელსაწყოს სისქის შეცვლა Available shortcuts in the screen capture mode. გადაღების რეჟიმში ხელმისაწვდომი მალსახმობები. Key კლავიში Description აღწერა <u><b>License</b></u> <u><b>ლიცენზია</b></u> <u><b>Version</b></u> <u><b>ვერსია</b></u> <u><b>Shortcuts</b></u> <u><b>მალსახმობები</b></u> LineTool Line ხაზი Sets the Line as the paint tool ხაზის ხელსაწყოს არჩევა სახატავად MarkerTool Marker მარკერი Sets the Marker as the paint tool მარკერის ხელსაწყოს არჩევა სახატავად MoveTool Move გადაადგილება Move the selection area შერჩეული არის გადაადგილება PencilTool Pencil ფანქარი Sets the Pencil as the paint tool ფანქრის ხელსაწყოს არჩევა სახატავად QObject Save As შენახვა როგორც Save Error შეცდომა შენახვისას Capture saved as სურათი შენახულია როგორც: Error trying to save as შეცდომა მცდელობისას შენახულიყო როგორც: Unable to connect via DBus DBus-ით დაკავშირება ვერ მოხერხდა Error შეცდომა Unable to write in შემდეგ მისამართზე ჩაწერა ვერ მოხერხდა: RectangleTool Rectangle მართკუთხედი Sets the Rectangle as the paint tool მართკუთხედის ხელსაწყოს არჩევა სახატავად SaveTool Save შენახვა Save the capture სურათის შენახვა SelectionTool Rectangular Selection მართკუთხა შერჩევა Sets the Selection as the paint tool შერჩევის ხელსაწყოს არჩევა სახატავად SizeIndicatorTool Selection Size Indicator შერჩეულის ზომის მაჩვენებელი Shows the dimensions of the selection (X Y) აჩვენებს შერჩეული არის განზომილებებს (X Y) StrftimeChooserWidget Century (00-99) საუკუნე (00-99) Year (00-99) წელი (00-99) Year (2000) წელი (2000) Month Name (jan) თვის სახელი (იან) Month Name (january) თვის სახელი (იანვარი) Month (01-12) თვე (01-12) Week Day (1-7) კვირის დღე (1-7) Week (01-53) კვირა (01-53) Day Name (mon) დღის სახელი (ორშ) Day Name (monday) დღის სახელი (ორშაბათი) Day (01-31) დღე (01-31) Day of Month (1-31) თვის დღე (1-31) Day (001-366) დღე (001-366) Time (%H:%M:%S) დრო (%H:%M:%S) Time (%H:%M) დრო (%H:%M) Hour (00-23) საათი (00-23) Hour (01-12) საათი (01-12) Minute (00-59) წუთი (00-59) Second (00-59) წამი (00-59) Full Date (%m/%d/%y) სრული თარიღი (%m/%d/%y) Full Date (%Y-%m-%d) სრული თარიღი (%Y-%m-%d) UIcolorEditor UI Color Editor ინტერფეისის ფერის რედაქტორი Change the color moving the selectors and see the changes in the preview buttons. შეცვალეთ ფერი ნიშნულის გადაადგილებით და შეხედეთ ცვლილებებს გადასახედ ღილაკებზე. Select a Button to modify it აირჩიეთ ღილაკი მის შესაცვლელად Main Color ძირითადი ფერი Click on this button to set the edition mode of the main color. დააწექით ამ ღილაკს ძირითადი ფერის არჩევის რეჟიმის ჩასართავად. Contrast Color კონტრასტული ფერი Click on this button to set the edition mode of the contrast color. დააწექით ამ ღილაკს კონტრასტული ფერის არჩევის რეჟიმის ჩასართავად. UndoTool Undo უკუქმნა Undo the last modification ბოლო ცვლილების გაუქმება VisualsEditor Opacity of area outside selection: შერჩეულის გარე არეს გაუმჭვირვალობა Button Selection ღილაკის არჩევა Select All ყველაფრის შერჩევა flameshot-0.5.1/translations/Internationalization_pl.ts000066400000000000000000000762711324424505000235040ustar00rootroot00000000000000 AppLauncher App Launcher Uruchamianie aplikacji Choose an app to open the capture Wybierz aplikację do otwierania zrzutu AppLauncherWidget Open With Otwórz w Launch in terminal Otwórz w terminalu Keep open after selection Pozostaw otwarte po zaznaczeniu Error Błąd Unable to write in Nie można zapisać Unable to launch in terminal. Nie można uruchomić w terminalu. ArrowTool Arrow Strzałka Sets the Arrow as the paint tool Rysowanie strzałek BlurTool Blur Rozmycie Sets the Blur as the paint tool Rozmywanie obszarów CaptureWidget Unable to capture screen Nie można przechwycić ekranu Select an area with the mouse, or press Esc to exit. Press Enter to capture the screen. Press Right Click to show the color picker. Use the Mouse Wheel to change the thickness of your tool. Zaznacz obszar za pomocą myszy lub wciśnij Esc aby wyjść. Wciśnij Enter aby wykonać zrzut ekranu. Kliknij prawym przyciskiem myszy, aby pokazać próbnik kolorów. Użyj kółka myszy, aby zmienić grubość narzędzia do rysowania. CircleTool Circle Okręgi Sets the Circle as the paint tool Rysowanie okręgów i elips ConfigWindow Configuration Konfiguracja Button Selection Wybór przycisków Select All Zaznacz wszystkie Interface Interfejs Filename Editor Edytor nazw plików General Ogólne Controller &Configuration &Konfiguracja &Information &Informacje &Quit &Wyjdź CopyTool Copy Kopiuj Copies the selecion into the clipboard Kopiuje zaznaczenie do schowka DBusUtils Unable to connect via DBus Nie można się połączyć za pomocą DBus ExitTool Exit Wyjdź Leave the capture screen Opuść ekran przechwytywania FileNameEditor Edit the name of your captures: Edycja wzorca nazwy plików: Edit: Edytuj: Preview: Podgląd: Save Zapisz Saves the pattern Zapisuje wzorzec Reset Reset Restores the saved pattern Resetuje wzorzec Clear Wyczyść Deletes the name Czyści wzorzec FileNameHandler screenshot screenshot FlameshotDBusAdapter Unable to capture screen Nie można przechwycić ekranu GeneneralConf Import Import Error Błąd Unable to read file. Nie można odczytać pliku. Unable to write file. Nie można zapisać pliku. Save File Zapisz plik Confirm Reset Potwierdź Reset Are you sure you want to reset the configuration? Czy na pewno chcesz zresetować konfigurację? Show help message Pokaż podpowiedzi Show the help message at the beginning in the capture mode. Pokaż podpowiedzi na początku trybu przechwytywania. Show desktop notifications Pokaż powiadomienia ekranowe Show tray icon Pokaż ikonę w trayu Show the systemtray icon Pokaż ikonę w zasobniku systemowym Configuration File Plik konfiguracyjny Export Export Reset Reset Launch at startup Uruchom podczas startu Launch Flameshot Uruchom Flameshot ImgurUploader Upload to Imgur Wyślij do Imgur Uploading Image Wysyłanie obrazka Copy URL Kopiuj URL Open URL Otwórz URL Image to Clipboard. Obrazek do schowka. Unable to open the URL. Nie można otworzyć adresu URL. URL copied to clipboard. URL skopiowany do schowka. Screenshot copied to clipboard. Zrzut ekranu skopiowany do schowka. ImgurUploaderTool Image Uploader Uploader obrazów Uploads the selection to Imgur Wyślij zaznaczenie do Imgur InfoWindow About O programie Right Click Prawy klik Mouse Wheel Kółko myszy Move selection 1px Przesuń zaznaczenie o 1px Resize selection 1px Zmień rozmiar zaznaczenia o 1px Quit capture Zakończ przechwytywanie Copy to clipboard Kopiuj do schowka Save selection as a file Zapisz zaznaczenie jako plik Undo the last modification Cofnij ostatnią modyfikację Show color picker Pokaż próbnik kolorów Change the tool's thickness Zmień grubość narzędzia Available shortcuts in the screen capture mode. Dostępne skróty w trybie przechwytywania obrazu. Available shorcuts in the screen capture mode. Dostępne skróty w trybie przechwytywania obrazu. Key Klawisz Description Działanie <u><b>License</b></u> <u><b>Licencja</b></u> <u><b>Version</b></u> <u><b>Wersja</b></u> <u><b>Shortcuts</b></u> <u><b>Skróty klawiszowe</b></u> LineTool Line Linia Sets the Line as the paint tool Ustawia linię jako narzędzie do rysowania MarkerTool Marker Marker Sets the Marker as the paint tool Ustawia Marker jako narzędzie rysowania MoveTool Move Przesuwanie Move the selection area Przesuwa zaznaczenie PencilTool Pencil Ołówek Sets the Pencil as the paint tool Ustawia ołówek jako narzędzie do rysowania QObject Save As Zapisz jako Save Error Błąd zapisu Capture saved as Zaznaczenie zapisano jako Error trying to save as Błąd przy próbie zapisu jako Unable to connect via DBus Nie udało się połączyć za pomocą DBus Error Błąd Unable to write in Nie można zapisać w RectangleTool Rectangle Prostokąt Sets the Rectangle as the paint tool Ustawia prostokąt jako narzędzie do rysowania SaveTool Save Zapisz Save the capture Zapisz zaznaczenie SelectionTool Rectangular Selection Zaznaczenie prostokątne Sets the Selection as the paint tool Ustawia zaznaczenie prostokątne jako narzędzie do rysowania SizeIndicatorTool Selection Size Indicator Miernik zaznaczenia Shows the dimensions of the selection (X Y) Pokazuje wymiary zaznaczenia (X Y) StrftimeChooserWidget Century (00-99) Wiek (00-99) Year (00-99) Rok (00-99) Year (2000) Rok (2000) Month Name (jan) Nazwa miesiąca (cze) Month Name (january) Nazwa miesiąca (czerwiec) Month (01-12) Miesiąc (01-12) Week Day (1-7) Dzień tygodnia (1-7) Week (01-53) Tydzień (01-53) Day Name (mon) Nazwa dniaa (pią) Day Name (monday) Nazwa dnia (piątek) Day (01-31) Dzień (01-31) Day of Month (1-31) Dzień miesiąca (1-31) Day (001-366) Dzień (001-366) Time (%H:%M:%S) Czas (%H:%M:%S) Time (%H:%M) Czas (%H:%M) Hour (00-23) Godzina (00-23) Hour (01-12) Godzina (01-12) Minute (00-59) Minuta (00-59) Second (00-59) Sekunda (00-59) Full Date (%m/%d/%y) Data (%m/%d/%y) Full Date (%Y-%m-%d) Data (%Y-%m-%d) UIcolorEditor UI Color Editor Edytor kolorów interfejsu Change the color moving the selectors and see the changes in the preview buttons. Zmień kolor przesuwając selektory i obserwując podgląd przycisków. Select a Button to modify it Wybierz przycisk do zmodyfikowania Main Color Kolor główny Click on this button to set the edition mode of the main color. Kliknij na przycisk aby móc modyfikować kolor główny. Contrast Color Kolor kontrastowy Click on this button to set the edition mode of the contrast color. Kliknij na przycisk aby móc modyfikować kolor kontrastowy. UndoTool Undo Cofnij Undo the last modification Cofnij ostatnią zmianę VisualsEditor Opacity of area outside selection: Przezroczystość obszaru poza zaznaczeniem: Button Selection Wybór przycisków Select All Wybierz wszystkie flameshot-0.5.1/translations/Internationalization_ru.ts000066400000000000000000001101341324424505000235020ustar00rootroot00000000000000 AppLauncher App Launcher Запуск приложения Choose an app to open the capture Выберите приложение, чтобы открыть снимок AppLauncherWidget Open With Открыть с помощью Launch in terminal Запустить в терминале Keep open after selection Оставить запущенным после выделения Error Ошибка Unable to write in Не удалось сохранить Unable to launch in terminal. Не удалось запустить в терминале. ArrowTool Arrow Стрелка Sets the Arrow as the paint tool Выбрать Стрелку инструментом для рисования BlurTool Blur Размытие Sets the Blur as the paint tool Выбрать Размытие инструментом для рисования CaptureWidget Unable to capture screen Не удалось захватить экран Select an area with the mouse, or press Esc to exit. Press Enter to capture the screen. Press Right Click to show the color picker. Use the Mouse Wheel to change the thickness of your tool. Выберите область с помощью мыши или нажмите Esc для выхода. Нажмите Enter, чтобы сделать снимок. Нажмите ПКМ, чтобы отобразить панель выбора цвета. Используйте колесико мыши, чтобы изменить толщину вашего инструмента. CircleTool Circle Окружность Sets the Circle as the paint tool Выбрать Окружность инструментом для рисования ConfigWindow Configuration Настройка Button Selection Выбор кнопок Select All Выбрать все Interface Интерфейс Filename Editor Редактор имен файлов General Общее Controller &Configuration &Настройка &Information &Информация &Quit &Выход CopyTool Copy Скопировать Copies the selecion into the clipboard Скопировать выделение в буфер обмена DBusUtils Unable to connect via DBus Не удалось подключится через DBus ExitTool Exit Выход Leave the capture screen Покинуть захват экрана FileNameEditor Edit the name of your captures: Отредактируйте имя ваших снимков: Edit: Шаблон: Preview: Предпросмотр: Save Сохранить Saves the pattern Сохранить шаблон Reset Сбросить Restores the saved pattern Восстанавливает сохраненный шаблон Clear Очистить Deletes the name Удаляет имя FileNameHandler screenshot снимок FlameshotDBusAdapter Unable to capture screen Не удается захватить экран GeneneralConf Import Импорт Error Ошибка Unable to read file. Не удалось прочитать файл. Unable to write file. Не удалось записать файл. Save File Сохранить файл Confirm Reset Подтвердить сброс Are you sure you want to reset the configuration? Вы действительно хотите сбросить настройки? Show help message Показывать справочное сообщение Show the help message at the beginning in the capture mode. Показать справочное сообщение перед началом захвата экрана. Show desktop notifications Показывать уведомления Show tray icon Показывать значок в трее Show the systemtray icon Показать значок в системном трее Configuration File Файл конфигурации Export Экспорт Reset Сброс Launch at startup Launch Flameshot ImgurUploader Upload to Imgur Загрузить в Imgur Uploading Image Загрузка изображения Copy URL Скопировать URL Open URL Открыть URL Image to Clipboard. Изображение в буфер обмена. Unable to open the URL. Не удалось открыть URL. URL copied to clipboard. URL скопирован в буфер обмена. Screenshot copied to clipboard. Снимок скопирован в буфер обмена. ImgurUploaderTool Image Uploader Отправка изображений Uploads the selection to Imgur Загрузить выделение на Imgur InfoWindow About Информация Right Click ПКМ Mouse Wheel Колесико мыши Move selection 1px Переместить выделение на 1px Resize selection 1px Изменить размер выделения на 1px Quit capture Выйти из захвата экрана Copy to clipboard Скопировать в буфер обмена Save selection as a file Сохранить выделение в файл Undo the last modification Отменить последнее изменение Show color picker Показать выбор цвета Change the tool's thickness Изменить толщину инструмента Available shortcuts in the screen capture mode. Доступные горячие клавиши в режиме захвата экрана. Key Клавиша Description Описание <u><b>License</b></u> <u><b>Лицензия</b></u> <u><b>Version</b></u> <u><b>Версия</b></u> <u><b>Shortcuts</b></u> <u><b>Горячие клавиши</b></u> LineTool Line Линия Sets the Line as the paint tool Выбрать Линию инструментом для рисования MarkerTool Marker Маркер Sets the Marker as the paint tool Выбрать Маркер инструментом для рисования MoveTool Move Перемещение Move the selection area Выбрать Перемещение инструментом для рисования PencilTool Pencil Карандаш Sets the Pencil as the paint tool Выбрать Карандаш инструментом для рисования QObject Save As Сохранить как Save Error Ошибка сохранения Capture saved as Сохранить снимок как Error trying to save as Ошибка при попытке сохранить как Unable to connect via DBus Не удалось подключиться через DBus Error Ошибка Unable to write in Не удалось сохранить RectangleTool Rectangle Прямоугольник Sets the Rectangle as the paint tool Выбрать Прямоугольник инструментом для рисования SaveTool Save Сохранить Save the capture Сохранить снимок SelectionTool Rectangular Selection Прямоугольное выделение Sets the Selection as the paint tool Выбрать Прямоугольное выделение инструментом для рисования SizeIndicatorTool Selection Size Indicator Индикатор размера выделения Shows the dimensions of the selection (X Y) Показывает размер выделения (X Y) StrftimeChooserWidget Century (00-99) Век (00-99) Year (00-99) Год (00-99) Year (2000) Год (2000) Month Name (jan) Название месяца (янв) Month Name (january) Название месяца (январь) Month (01-12) Месяц (01-12) Week Day (1-7) День недели (1-7) Week (01-53) Неделя (01-53) Day Name (mon) День недели (пн) Day Name (monday) День недели (понедельник) Day (01-31) День (01-31) Day of Month (1-31) День месяца (1-31) Day (001-366) День (001-366) Time (%H:%M:%S) Время (%H:%M:%S) Time (%H:%M) Время (%H:%M) Hour (00-23) Час (00-23) Hour (01-12) Час (01-12) Minute (00-59) Минута (00-59) Second (00-59) Секунда (00-59) Full Date (%m/%d/%y) Полная дата (%m/%d/%y) Full Date (%Y-%m-%d) Полная дата (%Y-%m-%d) UIcolorEditor UI Color Editor Редактор цвета интерфейса Change the color moving the selectors and see the changes in the preview buttons. Измените цвет, перемещая выделение, и посмотрите изменения в кнопках предварительного просмотра. Select a Button to modify it Выберите кнопку, чтобы изменить ее Main Color Основной цвет Click on this button to set the edition mode of the main color. Нажмите на эту кнопку, чтобы перейти в режим редактирования основного цвета. Contrast Color Контрастный цвет Click on this button to set the edition mode of the contrast color. Нажмите на эту кнопку, чтобы перейти в режим редактирования контрастного цвета. UndoTool Undo Отменить Undo the last modification Отменить последнее изменение VisualsEditor Opacity of area outside selection: Button Selection Выбор кнопок Select All Выбрать все flameshot-0.5.1/translations/Internationalization_tr.ts000066400000000000000000000764311324424505000235140ustar00rootroot00000000000000 AppLauncher App Launcher Uygulama Başlatıcı Choose an app to open the capture Yakalamayı açmak için bir uygulama seçin AppLauncherWidget Open With ile Aç Launch in terminal Terminalde aç Keep open after selection Seçimden sonra açık tutun Error Hata Unable to write in Yazmak mümkün değil Unable to launch in terminal. Terminalde başlatılamadı. ArrowTool Arrow Ok Sets the Arrow as the paint tool Oku boya aracı olarak ayarlar BlurTool Blur Bulanıklık Sets the Blur as the paint tool Bulnıklığı boya aracı olarak ayarlar CaptureWidget Unable to capture screen Ekran yakalanamadı Select an area with the mouse, or press Esc to exit. Press Enter to capture the screen. Press Right Click to show the color picker. Use the Mouse Wheel to change the thickness of your tool. Fareyle bir alan seçin veya çıkmak için Esc tuşuna basın. Ekranı yakalamak için Enter tuşuna basın. Renk seçicisini göstermek için sağdaki Basın düğmesine basın. Araç boyutunu değiştirmek için Fare tekerleğini kullanın. CircleTool Circle Çember Sets the Circle as the paint tool Çemberi boya aracı olarak ayarlar ConfigWindow Configuration Ayarlar Button Selection Selección de Botón Select All Seleccionar Todos Interface Arayüz Filename Editor Dosyaadı Düzenleyici General Genel Controller &Configuration &Ayarlar &Information &Bilgi &Quit &Çıkış CopyTool Copy Kopyala Copies the selecion into the clipboard Seçimi panoya kopyalar DBusUtils Unable to connect via DBus DBus ile bağlanılamadı ExitTool Exit Çıkış Leave the capture screen Yakalama ekranından ayrıl FileNameEditor Edit the name of your captures: Çekimlerinizin adını düzenleyin: Edit: Düzenle: Preview: Önizleme: Save Kaydet Saves the pattern Desenini kaydeder Reset Sıfırla Restores the saved pattern Kaydedilen deseni geri yükler Clear Temizle Deletes the name İsmi siler FileNameHandler screenshot Ekran yakala FlameshotDBusAdapter Unable to capture screen Ekran yakalanamadı GeneneralConf Import Dışa aktar Error Hata Unable to read file. Dosya okunamıyor. Unable to write file. Dosya yazılamıyor. Save File Dosyayı Kaydet Confirm Reset Sıfırlamayı Onayla Are you sure you want to reset the configuration? Konfigürasyonu sıfırlamak istediğinizden emin misiniz? Show help message Yardım mesajını göster Show the help message at the beginning in the capture mode. Yakalama modunda başında yardım mesajını gösterin. Show desktop notifications Masaüstü bildirimlerini göster Show tray icon Tepsi simgesini göster Show the systemtray icon Sistem tepsisi simgesini göster Configuration File Yapılandırma Dosyası Export Dışa aktar Reset Sıfırla Launch at startup Başlangıçta başlatın Launch Flameshot Flameshot'u başlatın ImgurUploader Upload to Imgur Imgur'a yükle Uploading Image Resim Yükleniyor Copy URL URL Kopyala Open URL URL Aç Image to Clipboard. Resim Pano'ya. Unable to open the URL. URL açılamıyor. URL copied to clipboard. URL panoya kopyalandı. Screenshot copied to clipboard. Ekran görüntüsü panoya kopyalandı. ImgurUploaderTool Image Uploader Resim Yükleme Aracı Uploads the selection to Imgur Seçimi Imgur'a yükler InfoWindow About Hakkında Right Click Sağ Tık Mouse Wheel Fare Tekerleği Move selection 1px Move selection 1px Resize selection 1px 1px seçimini yeniden boyutlandır Quit capture Yakala'dan çık Copy to clipboard Panoya kopyala Save selection as a file Seçimi dosya olarak kaydet Undo the last modification Son değişikliği geri al Show color picker Renk seçici göster Change the tool's thickness Araç kalınlığını değiştirin Available shortcuts in the screen capture mode. Ekran yakalama modunda kullanılabilir kısayollar. Available shorcuts in the screen capture mode. Atajos disponibles en el modo de captura de pantalla. Key Anahtar Description Tanım <u><b>License</b></u> <u><b>Lisans</b></u> <u><b>Version</b></u> <u><b>Sürüm</b></u> <u><b>Shortcuts</b></u> <u><b>Kısayollar</b></u> LineTool Line Çizgi Sets the Line as the paint tool Çizgi boya aracı olarak ayarlar MarkerTool Marker İşaretleyici Sets the Marker as the paint tool İşaretleyiciyi boya aracı olarak ayarlar MoveTool Move Oynat Move the selection area Seçim alanını hareket ettir PencilTool Pencil Kurşun Kalem Sets the Pencil as the paint tool Kurşun Kalemi boya aracı olarak ayarlar QObject Save As Farklı Kaydet Save Error Hata Kaydet Capture saved as Yakalanma şu şekilde kaydedildi Error trying to save as Olarak kaydedilmeye çalışılırken hata oluştu Unable to connect via DBus DBus ile bağlanılamadı Error Hata Unable to write in Yazmak mümkün değil RectangleTool Rectangle Dikdörtgen Sets the Rectangle as the paint tool Dikdörtgeni boya aracı olarak ayarlar SaveTool Save Kaydet Save the capture Yakalamayı kaydet SelectionTool Rectangular Selection Dikdörtgen Seçim Sets the Selection as the paint tool Seçimi boya aracı olarak ayarlar SizeIndicatorTool Selection Size Indicator Seçim Boyutu Göstergesi Shows the dimensions of the selection (X Y) Seçimin boyutlarını gösterir (X Y) StrftimeChooserWidget Century (00-99) Ülke (00-99) Year (00-99) Yıl (00-99) Year (2000) Yıl (2000) Month Name (jan) Ay Adı (Oca) Month Name (january) Ay Adı (Ocak) Month (01-12) Ay (01-12) Week Day (1-7) Haftanın Günü (1-7) Week (01-53) Hafta (01-53) Day Name (mon) Gün Adı (pzt) Day Name (monday) Gün Adı (pazartesi) Day (01-31) Gün (01-31) Day of Month (1-31) Ayın Günü (1-31) Day (001-366) Gün (001-366) Time (%H:%M:%S) Zaman (%H:%M:%S) Time (%H:%M) Zaman (%H:%M) Hour (00-23) Saat (00-23) Hour (01-12) Saat (01-12) Minute (00-59) Dakika (00-59) Second (00-59) Saniye (00-59) Full Date (%m/%d/%y) Tam Tarih (%d/%m/%y) Full Date (%Y-%m-%d) Tam Tarih (%d-%m-%Y) UIcolorEditor UI Color Editor UI Renk Editörü Change the color moving the selectors and see the changes in the preview buttons. Seçicileri hareket ettiren rengi değiştirin ve önizleme düğmelerindeki değişiklikleri görün. Select a Button to modify it Değiştirmek için bir Düğme seçin Main Color Ana Renk Click on this button to set the edition mode of the main color. Ana rengin baskı modunu ayarlamak için bu düğmeyi tıklayın. Contrast Color Kontrast Renk Click on this button to set the edition mode of the contrast color. Kontrast renginin baskı modunu ayarlamak için bu düğmeyi tıklayın. UndoTool Undo Geri Undo the last modification Son değişikliği geri al VisualsEditor Opacity of area outside selection: Seçim dışı alanın opaklığı: Button Selection Düğme Seçimi Select All Tümünü Seç flameshot-0.5.1/translations/Internationalization_zh_CN.ts000066400000000000000000000751351324424505000240700ustar00rootroot00000000000000 AppLauncher App Launcher 应用启动器 Choose an app to open the capture 选择一个应用打开此截图 AppLauncherWidget Open With 打开 Launch in terminal 在终端中启动 Keep open after selection 选择后保持此窗口打开 Error 错误 Unable to launch in terminal. 无法在终端中启动。 Unable to write in 无法写入 ArrowTool Arrow 箭头 Sets the Arrow as the paint tool 选择箭头作为油漆工具 BlurTool Blur 模糊 Sets the Blur as the paint tool 选择模糊作为绘画工具 CaptureWidget Select an area with the mouse, or press Esc to exit. Press Enter to capture the screen. Press Right Click to show the color picker. Use the Mouse Wheel to change the thickness of your tool. 用鼠标选择一个区域,或按Esc退出。 按Enter键捕捉屏幕。 按鼠标右键显示颜色选择器。 使用鼠标滚轮来改变油漆工具的厚度。 Unable to capture screen 无法捕获屏幕 无法捕获屏幕 CircleTool Circle 圆环 Sets the Circle as the paint tool 选择圆环作为绘画工具 ConfigWindow Configuration 配置 Button Selection 按钮选择 Select All 全选 Interface 界面 Filename Editor 文件名编辑器 General 常规 Controller &Configuration &配置 &Information &信息 &Quit &退出 CopyTool Copy 复制 Copies the selecion into the clipboard 复制选择到剪贴板 DBusUtils Unable to connect via DBus 无法通过Dbus进行连接 ExitTool Exit 退出 Leave the capture screen 离开屏幕捕获 FileNameEditor Edit the name of your captures: 编辑您的截图名称: Edit: 编辑器: Preview: 预览: Save 保存 Saves the pattern 保存样式 Reset 恢复 Restores the saved pattern 恢复保存的样式 Clear 清空 Deletes the name 删除这个名字 FileNameHandler screenshot 屏幕截图 FlameshotDBusAdapter Unable to capture screen 无法捕获屏幕 GeneneralConf Show help message 显示帮助文档 Show the help message at the beginning in the capture mode. 在捕获之前显示帮助信息。 Show desktop notifications 显示桌面通知 Show tray icon 显示托盘图标 Show the systemtray icon 显示任务栏图标 Import 导入 Error 错误 Unable to read file. 无法读取文件. Unable to write file. 无法写入文件. Save File 保存到文件 Confirm Reset 确定重置 Are you sure you want to reset the configuration? 你确定你想要重置配置? Configuration File 配置文件 Export 导出 Reset 重置 Launch at startup 开机时启动 Launch Flameshot 启动 Flameshot ImgurUploader Upload to Imgur 上传到Imgur Uploading Image 正在上传 Copy URL 复制链接 Open URL 打开链接 Image to Clipboard. 保存文件到剪贴板。 Unable to open the URL. 无法打开此链接。 URL copied to clipboard. 复制链接到剪贴板。 Screenshot copied to clipboard. 截图复制到剪贴板。 ImgurUploaderTool Image Uploader 上传图片 Uploads the selection to Imgur 上传选择到 Imgur InfoWindow About 关于 Right Click 右键 Mouse Wheel 鼠标滑轮 Move selection 1px 移动选择 1 px Resize selection 1px 调整选择大小 1 px Quit capture 退出捕获 Copy to clipboard 复制到剪贴板 Save selection as a file 将选择保存为文件 Undo the last modification 撤消上次修改 Show color picker 显示颜色选择器 Change the tool's thickness 改变工具的厚度 Available shorcuts in the screen capture mode. 屏幕捕捉模式中的可用快捷键。 Key Description 描述 <u><b>License</b></u> <u><b>License</b></u> <u><b>Version</b></u> <u><b>Version</b></u> <u><b>Shortcuts</b></u> <u><b>快捷键</b></u> Available shortcuts in the screen capture mode. 屏幕捕捉模式中的可用快捷键。 LineTool Line 直线 Sets the Line as the paint tool 将直线线设置为绘画工具 MarkerTool Marker 标记 Sets the Marker as the paint tool 将标记设置为绘画工具 MoveTool Move 移动 Move the selection area 移动选择区域 PencilTool Pencil 铅笔 Sets the Pencil as the paint tool 将铅笔设置为绘画工具 QObject Save As 另存为 Save Error 保存错误 Capture saved as 捕获保存为 Error trying to save as 尝试另存为时出错 Unable to connect via DBus 无法通过DBus进行连接 Error 错误 Unable to write in 无法写入 RectangleTool Rectangle 实心矩形 Sets the Rectangle as the paint tool 将实心矩形设置为绘画工具 SaveTool Save 保存 Save the capture 保存捕获 SelectionTool Rectangular Selection 矩形选择 Sets the Selection as the paint tool 将矩形选择设置为绘画工具 SizeIndicatorTool Selection Size Indicator 选择尺寸指示 Shows the dimensions of the selection (X Y) 显示选择的尺寸 (X Y) StrftimeChooserWidget Century (00-99) 世纪 (00-99) Year (00-99) 年 (00-99) Year (2000) 年 (2000) Month Name (jan) 月 (jul) Month Name (january) 月 (juliol) Month (01-12) 月 (01-12) Week Day (1-7) 平常日 (1-7) Week (01-53) 周 (01-53) Day Name (mon) 星期 (dg) Day Name (monday) 星期 (diumenge) Day (01-31) 天 (01-31) Day of Month (1-31) 一月中的某天 (1-31) Day (001-366) 天 (001-366) Time (%H:%M:%S) 时间 (%H:%M:%S) Time (%H:%M) 时间 (%H:%M) Hour (00-23) 小时 (00-23) Hour (01-12) 小时 (01-12) Minute (00-59) 分钟 (00-59) Second (00-59) 秒 (00-59) Full Date (%m/%d/%y) 日期 (%m/%d/%y) Full Date (%Y-%m-%d) 日期 (%Y-%m-%d) UIcolorEditor UI Color Editor UI颜色编辑器 Change the color moving the selectors and see the changes in the preview buttons. 移动颜色选择并在预览按钮查看。 Select a Button to modify it 选择一个按钮来修改它 Main Color 主色 Click on this button to set the edition mode of the main color. 点击按钮设置主色。 Contrast Color 对比色 Click on this button to set the edition mode of the contrast color. 点击按钮设置对比色。 UndoTool Undo 撤消 Undo the last modification 撤消上次修改 VisualsEditor Opacity of area outside selection: 选中区域之外的不透明度: Button Selection 按钮选择 Select All 全选 flameshot-0.5.1/translations/Internationalization_zh_TW.ts000066400000000000000000000750221324424505000241150ustar00rootroot00000000000000 AppLauncher App Launcher 應用程式啟動器 Choose an app to open the capture 選擇一個程式打開此截圖 AppLauncherWidget Open With 打開 Launch in terminal 在終端機中啟動 Keep open after selection 選擇後維持此視窗開啟 Error 錯誤 Unable to launch in terminal. 無法在終端機中啟動 Unable to write in 無法寫入 ArrowTool Arrow 箭頭 Sets the Arrow as the paint tool 選擇箭頭作為繪製工具 BlurTool Blur 模糊 Sets the Blur as the paint tool 選擇模糊作為繪製工具 CaptureWidget Select an area with the mouse, or press Esc to exit. Press Enter to capture the screen. Press Right Click to show the color picker. Use the Mouse Wheel to change the thickness of your tool. 用滑鼠選擇一個區域,或按 Esc 退出 按 Enter 鍵擷取螢幕 按滑鼠右鍵顯示顏色選擇器 使用滑鼠滾輪來改變繪製工具的寬度 Unable to capture screen 無法擷取螢幕 CircleTool Circle 圈型 Sets the Circle as the paint tool 選擇圈型作為繪畫工具 ConfigWindow Configuration 設定 Button Selection 按鈕選擇 Select All 全選 Interface 介面 Filename Editor 檔案名稱編輯器 General 一般 Controller &Configuration &設定 &Information &資訊 &Quit &結束 CopyTool Copy 複製 Copies the selecion into the clipboard 複製到剪貼簿 DBusUtils Unable to connect via DBus 無法透過 DBus 進行連接 ExitTool Exit 離開 Leave the capture screen 離開螢幕擷取 FileNameEditor Edit the name of your captures: 編輯您的截圖名稱: Edit: 編輯器: Preview: 預覽: Save 存檔 Saves the pattern 儲存樣式 Reset 重設 Restores the saved pattern 恢復儲存的樣式 Clear 清空 Deletes the name 刪除這個名稱 FileNameHandler screenshot 螢幕截圖 FlameshotDBusAdapter Unable to capture screen 無法擷取螢幕 GeneneralConf Show help message 顯示説明資訊 Show the help message at the beginning in the capture mode. 在擷取之前顯示説明資訊 Show desktop notifications 顯示桌面通知 Show tray icon 顯示託盤圖示 Show the systemtray icon 顯示工作列圖示 Import 匯入 Error 錯誤 Unable to read file. 無法讀取檔案 Unable to write file. 無法寫入檔案 Save File 存檔 Confirm Reset 確認重設 Are you sure you want to reset the configuration? 你確定你想要重設? Configuration File 設定檔 Export 匯出 Reset 重設 Launch at startup 自動啟動 Launch Flameshot 啟動 Flameshot ImgurUploader Upload to Imgur 上傳到 Imgur Uploading Image 正在上傳 Copy URL 複製連結 Open URL 打開連結 Image to Clipboard. 將檔案複製到剪貼簿 Unable to open the URL. 無法打開此連結 URL copied to clipboard. 連結已複製到剪貼簿 Screenshot copied to clipboard. 截圖已複製到剪貼簿 ImgurUploaderTool Image Uploader 上傳圖片 Uploads the selection to Imgur 上傳到 Imgur InfoWindow About 關於 Right Click 右鍵 Mouse Wheel 滑鼠滑輪 Move selection 1px 移動 1px Resize selection 1px 調整大小 1px Quit capture 結束擷取 Copy to clipboard 複製到剪貼簿 Save selection as a file 將選擇範圍另存新檔 Undo the last modification 復原上次修改 Show color picker 顯示顏色選擇器 Change the tool's thickness 改變工具的寬度 Available shorcuts in the screen capture mode. 螢幕截取模式中的可用快速鍵 Key Description 描述 <u><b>License</b></u> <u><b>授權條款</b></u> <u><b>Version</b></u> <u><b>版本</b></u> <u><b>Shortcuts</b></u> <u><b>快速鍵</b></u> Available shortcuts in the screen capture mode. 螢幕擷取模式中的可用快速鍵 LineTool Line 直線 Sets the Line as the paint tool 將直線線設定為繪畫工具 MarkerTool Marker 標記 Sets the Marker as the paint tool 將標記設定為繪畫工具 MoveTool Move 移動 Move the selection area 移動選擇區域 PencilTool Pencil 鉛筆 Sets the Pencil as the paint tool 將鉛筆設定為繪畫工具 QObject Save As 另存為 Save Error 存檔錯誤 Capture saved as 截圖已另存為 Error trying to save as 嘗試另存新檔時發生錯誤 Unable to connect via DBus 無法透過 DBus 進行連接 Error 錯誤 Unable to write in 無法寫入 RectangleTool Rectangle 實心矩形 Sets the Rectangle as the paint tool 將實心矩形設定為繪畫工具 SaveTool Save 儲存 Save the capture 儲存擷取 SelectionTool Rectangular Selection 矩形選擇 Sets the Selection as the paint tool 將矩形選擇設定為繪畫工具 SizeIndicatorTool Selection Size Indicator 選擇尺寸指示 Shows the dimensions of the selection (X Y) 顯示選擇的尺寸 (X Y) StrftimeChooserWidget Century (00-99) 世紀 (00-99) Year (00-99) 年 (00-99) Year (2000) 年 (2000) Month Name (jan) 月 (jul) Month Name (january) 月 (juliol) Month (01-12) 月 (01-12) Week Day (1-7) 平常日 (1-7) Week (01-53) 周 (01-53) Day Name (mon) 星期 (dg) Day Name (monday) 星期 (diumenge) Day (01-31) 天 (01-31) Day of Month (1-31) 一月中的某天 (1-31) Day (001-366) 天 (001-366) Time (%H:%M:%S) 時間 (%H:%M:%S) Time (%H:%M) 時間 (%H:%M) Hour (00-23) 小時 (00-23) Hour (01-12) 小時 (01-12) Minute (00-59) 分鐘 (00-59) Second (00-59) 秒 (00-59) Full Date (%m/%d/%y) 日期 (%m/%d/%y) Full Date (%Y-%m-%d) 日期 (%Y-%m-%d) UIcolorEditor UI Color Editor UI 顏色編輯器 Change the color moving the selectors and see the changes in the preview buttons. 移動顏色選擇並在預覽按鈕檢視 Select a Button to modify it 選擇一個按鈕來修改它 Main Color 主色 Click on this button to set the edition mode of the main color. 點選按鈕設定主色 Contrast Color 對比色 Click on this button to set the edition mode of the contrast color. 點選按鈕設定對比色 UndoTool Undo 復原 Undo the last modification 復原上次修改 VisualsEditor Opacity of area outside selection: 選擇區域以外的不透明度 Button Selection 按鈕選擇 Select All 全選