pax_global_header00006660000000000000000000000064135447150010014512gustar00rootroot0000000000000052 comment=91ba28c3ded7ca3314f02418761c982069cf8b33 flameshot-0.6.0+git20191001/000077500000000000000000000000001354471500100150745ustar00rootroot00000000000000flameshot-0.6.0+git20191001/.github/000077500000000000000000000000001354471500100164345ustar00rootroot00000000000000flameshot-0.6.0+git20191001/.github/ISSUE_TEMPLATE/000077500000000000000000000000001354471500100206175ustar00rootroot00000000000000flameshot-0.6.0+git20191001/.github/ISSUE_TEMPLATE/Bug_report.md000066400000000000000000000006401354471500100232510ustar00rootroot00000000000000--- name: bug report about: Create a report to help us improve --- **Flameshot version** **Describe the bug** **To Reproduce** **Expected behavior** **System Information** flameshot-0.6.0+git20191001/.github/ISSUE_TEMPLATE/Feature_request.md000066400000000000000000000003731354471500100243070ustar00rootroot00000000000000--- name: feature request about: Suggest an idea for this project --- **Is your feature request related to a problem?** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] Please, a single feature per issue. flameshot-0.6.0+git20191001/.gitignore000066400000000000000000000010231354471500100170600ustar00rootroot00000000000000# 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 # Created by https://www.gitignore.io/api/snapcraft ### Snapcraft ### # Snapcraft parts/ prime/ stage/ *.snap .snapcraft/ flameshot*.tar.bz2 # End of https://www.gitignore.io/api/snapcraft flameshot-0.6.0+git20191001/.travis.yml000066400000000000000000000052031354471500100172050ustar00rootroot00000000000000dist: xenial sudo: required language: cpp branches: only: - master cache: directories: - $HOME/.cache env: global: # Environment variables for packaging - PRODUCT=flameshot - VERSION=0.6.0 - RELEASE=1 - ARCH=x86_64 # Dockerfile from https://github.com/flameshotapp/flameshot-docker-images - DOCKER_REPO=vitzy/flameshot # Option: wetransfer.com, file.io, 0x0.st, transfer.sh - UPLOAD_SERVICE=wetransfer.com # The actual list of distribution is available on # https://hub.docker.com/r/vitzy/flameshot/tags/ matrix: include: - os: linux # 28 env: OS=fedora DIST=28 EXTEN=rpm services: docker - os: linux # 29 env: OS=fedora DIST=29 EXTEN=rpm services: docker - os: linux # 30 env: OS=fedora DIST=30 EXTEN=rpm services: docker - os: linux # 16.04 LTS env: OS=ubuntu DIST=xenial EXTEN=deb services: docker - os: linux # 18.04 LTS env: OS=ubuntu DIST=bionic EXTEN=deb services: docker - os: linux # 19.04 env: OS=ubuntu DIST=disco EXTEN=deb services: docker - os: linux # 8 env: OS=debian DIST=jessie EXTEN=deb services: docker - os: linux # 9 env: OS=debian DIST=stretch EXTEN=deb services: docker - os: linux # No docker environment, just for CI build & test # ubuntu xenial; default Qt version is 5.6.1 env: OS=ubuntu DIST=xenial EXTEN=other # - os: osx # compiler: clang # osx_image: xcode9.2 before_install: - export ROOT_PATH="$(pwd)" - chmod +x .travis/*.sh - chmod +x .travis/services/*.sh - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then source .travis/linux_before_install.sh; fi install: - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then source .travis/linux_install.sh; fi script: # - git submodule update --init --recursive # - git describe --long - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then source .travis/linux_script.sh; fi # - if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then source .travis/osx_script.sh; fi after_success: - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then source .travis/linux_after_success.sh; fi - echo "Download URL is $TEMP_DOWNLOAD_URL ." # 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.6.0+git20191001/.travis/000077500000000000000000000000001354471500100164625ustar00rootroot00000000000000flameshot-0.6.0+git20191001/.travis/linux_after_success.sh000066400000000000000000000021301354471500100230620ustar00rootroot00000000000000#!/bin/bash -- set -e DIST_PATH=dist if [[ "${EXTEN}" == "other" ]]; then cp "${BUILD_DST_PATH}/flameshot" "${ROOT_PATH}/.travis/services/flameshot_${VERSION}_${ARCH}" cd "${ROOT_PATH}/.travis/services" TEMP_DOWNLOAD_URL=$(travis_retry bash \ "${ROOT_PATH}/.travis/services/${UPLOAD_SERVICE}.sh" \ flameshot_"${VERSION}_${ARCH}") else case "${OS}" in "ubuntu"|"debian") cp "${DIST_PATH}/flameshot_${VERSION}_${DIST}_${ARCH}.${EXTEN}" "${ROOT_PATH}/.travis/services/flameshot_${VERSION}_${DIST}_${ARCH}.${EXTEN}" cd "${ROOT_PATH}/.travis/services" TEMP_DOWNLOAD_URL=$(travis_retry bash \ "${ROOT_PATH}/.travis/services/${UPLOAD_SERVICE}.sh" \ "flameshot_${VERSION}_${DIST}_${ARCH}.${EXTEN}") ;; "fedora") cp "${DIST_PATH}/flameshot_${VERSION}_fedora${DIST}_${ARCH}.${EXTEN}" "${ROOT_PATH}/.travis/services/flameshot_${VERSION}_fedora${DIST}_${ARCH}.${EXTEN}" cd "${ROOT_PATH}/.travis/services" TEMP_DOWNLOAD_URL=$(travis_retry bash \ "${ROOT_PATH}/.travis/services/${UPLOAD_SERVICE}.sh" \ "flameshot_${VERSION}_fedora${DIST}_${ARCH}.${EXTEN}") ;; esac fi flameshot-0.6.0+git20191001/.travis/linux_before_install.sh000066400000000000000000000001361354471500100232250ustar00rootroot00000000000000#!/bin/bash -- set -e if [[ "${EXTEN}" == "other" ]]; then travis_retry sudo apt update fi flameshot-0.6.0+git20191001/.travis/linux_install.sh000066400000000000000000000007141354471500100217050ustar00rootroot00000000000000#!/bin/bash -- set -e if [[ "${EXTEN}" == "other" ]]; then # Compile-time travis_retry sudo apt install -y gcc g++ build-essential qt5-default qt5-qmake qttools5-dev-tools # Run-time travis_retry sudo apt install -y libqt5dbus5 libqt5network5 libqt5core5a libqt5widgets5 libqt5gui5 libqt5svg5-dev # Optional travis_retry sudo apt install -y openssl ca-certificates # Install fcitx-frontend-qt5 travis_retry sudo apt install -y fcitx-frontend-qt5 fi flameshot-0.6.0+git20191001/.travis/linux_script.sh000066400000000000000000000015611354471500100215440ustar00rootroot00000000000000#!/bin/bash -- set -e DIST_PATH=dist if [[ ! -d "${DIST_PATH}" ]]; then mkdir "${DIST_PATH}" fi if [[ "${EXTEN}" == "other" ]]; then project_dir="$(pwd)" BUILD_DST_PATH=build-test qmake --version mkdir "${BUILD_DST_PATH}" qmake -makefile DESTDIR="${BUILD_DST_PATH}" "${project_dir}"/flameshot.pro # Building flameshot make -j$(nproc) # Running flameshot tests make check -j$(nproc) ls -alhR else travis_retry git clone https://github.com/flameshotapp/packpack.git travis_retry packpack/packpack pwd && ls case "${OS}" in "ubuntu"|"debian") # copy deb to dist path for distribution cp \ build/flameshot_*_*.deb \ "${DIST_PATH}"/flameshot_${VERSION}_${DIST}_${ARCH}.${EXTEN} ;; "fedora") cp \ build/flameshot-${VERSION}-${RELEASE}.*.${ARCH}.rpm \ "${DIST_PATH}"/flameshot_${VERSION}_fedora${DIST}_${ARCH}.${EXTEN} ;; esac fi flameshot-0.6.0+git20191001/.travis/osx_script.sh000066400000000000000000000025201354471500100212120ustar00rootroot00000000000000#!/bin/bash -- set -e 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 TEMP_DOWNLOAD_URL=$(curl \ --upload-file \ flameshot_X64_$VERSION.dmg \ "https://transfer.sh/flameshot_X64_$VERSION.dmg") cd .. flameshot-0.6.0+git20191001/.travis/services/000077500000000000000000000000001354471500100203055ustar00rootroot00000000000000flameshot-0.6.0+git20191001/.travis/services/0x0.st.sh000066400000000000000000000011351354471500100216750ustar00rootroot00000000000000#!/bin/sh #=============================================================== # File URLs are valid for at least 30 days and up to a year (see below). # Shortened URLs do not expire. # Maximum file size: 512.0 MiB # Blocked file types: application/x-dosexec, application/x-executable #=============================================================== URL="https://0x0.st" if [ $# -eq 0 ]; then echo "Usage: 0x0.st FILE\n" exit 1 fi FILE=$1 if [ ! -f "$FILE" ]; then echo "File ${FILE} not found" exit 1 fi RESPONSE=$(curl -# -F "file=@${FILE}" "${URL}") echo "${RESPONSE}" # to terminal flameshot-0.6.0+git20191001/.travis/services/file.io.sh000066400000000000000000000010671354471500100221720ustar00rootroot00000000000000#!/bin/sh #========================================== # 100 uploads per day, 5GB file size limit for FREE plan. #========================================== URL="https://file.io" DEFAULT_EXPIRE="14d" # Default to 14 days if [ $# -eq 0 ]; then echo "Usage: file.io FILE [DURATION]\n" echo "Example: file.io path/to/my/file 1w\n" exit 1 fi FILE=$1 EXPIRE=${2:-$DEFAULT_EXPIRE} if [ ! -f "$FILE" ]; then echo "File ${FILE} not found" exit 1 fi RESPONSE=$(curl -# -F "file=@${FILE}" "${URL}/?expires=${EXPIRE}") echo "${RESPONSE}" # to terminal flameshot-0.6.0+git20191001/.travis/services/transfer.sh.sh000066400000000000000000000004261354471500100231000ustar00rootroot00000000000000#!/bin/sh URL="https://transfer.sh" if [ $# -eq 0 ]; then echo "Usage: transfer.sh FILE\n" exit 1 fi FILE=$1 if [ ! -f "$FILE" ]; then echo "File ${FILE} not found" exit 1 fi RESPONSE=$(curl -# -F "file=@${FILE}" "${URL}") echo "${RESPONSE}" # to terminalflameshot-0.6.0+git20191001/.travis/services/transferwee.py000077500000000000000000000253721354471500100232200ustar00rootroot00000000000000#!/usr/bin/env python3.7 # # Copyright (c) 2018-2019 Leonardo Taccari # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # """ Download/upload files via wetransfer.com transferwee is a script/module to download/upload files via wetransfer.com. It exposes `download' and `upload' subcommands, respectively used to download files from a `we.tl' or `wetransfer.com/downloads' URLs and upload files that will be shared via emails or link. """ from typing import List import os.path import urllib.parse import zlib import requests WETRANSFER_API_URL = 'https://wetransfer.com/api/v4/transfers' WETRANSFER_DOWNLOAD_URL = WETRANSFER_API_URL + '/{transfer_id}/download' WETRANSFER_UPLOAD_EMAIL_URL = WETRANSFER_API_URL + '/email' WETRANSFER_UPLOAD_LINK_URL = WETRANSFER_API_URL + '/link' WETRANSFER_FILES_URL = WETRANSFER_API_URL + '/{transfer_id}/files' WETRANSFER_PART_PUT_URL = WETRANSFER_FILES_URL + '/{file_id}/part-put-url' WETRANSFER_FINALIZE_MPP_URL = WETRANSFER_FILES_URL + '/{file_id}/finalize-mpp' WETRANSFER_FINALIZE_URL = WETRANSFER_API_URL + '/{transfer_id}/finalize' WETRANSFER_DEFAULT_CHUNK_SIZE = 5242880 def download_url(url: str) -> str: """Given a wetransfer.com download URL download return the downloadable URL. The URL should be of the form `https://we.tl/' or `https://wetransfer.com/downloads/'. If it is a short URL (i.e. `we.tl') the redirect is followed in order to retrieve the corresponding `wetransfer.com/downloads/' URL. The following type of URLs are supported: - `https://we.tl/`: received via link upload, via email to the sender and printed by `upload` action - `https://wetransfer.com//`: directly not shared in any ways but the short URLs actually redirect to them - `https://wetransfer.com///`: received via email by recipients when the files are shared via email upload Return the download URL (AKA `direct_link') as a str or None if the URL could not be parsed. """ # Follow the redirect if we have a short URL if url.startswith('https://we.tl/'): r = requests.head(url, allow_redirects=True) url = r.url recipient_id = None params = url.replace('https://wetransfer.com/downloads/', '').split('/') if len(params) == 2: transfer_id, security_hash = params elif len(params) == 3: transfer_id, recipient_id, security_hash = params else: return None j = { "security_hash": security_hash, } if recipient_id: j["recipient_id"] = recipient_id r = requests.post(WETRANSFER_DOWNLOAD_URL.format(transfer_id=transfer_id), json=j) j = r.json() return j.get('direct_link') def download(url: str) -> None: """Given a `we.tl/' or `wetransfer.com/downloads/' download it. First a direct link is retrieved (via download_url()), the filename will be extracted to it and it will be fetched and stored on the current working directory. """ dl_url = download_url(url) file = urllib.parse.urlparse(dl_url).path.split('/')[-1] r = requests.get(dl_url, stream=True) with open(file, 'wb') as f: for chunk in r.iter_content(chunk_size=1024): f.write(chunk) def _file_name_and_size(file: str) -> dict: """Given a file, prepare the "name" and "size" dictionary. Return a dictionary with "name" and "size" keys. """ filename = os.path.basename(file) filesize = os.path.getsize(file) return { "name": filename, "size": filesize } def _prepare_email_upload(filenames: List[str], message: str, sender: str, recipients: List[str]) -> str: """Given a list of filenames, message a sender and recipients prepare for the email upload. Return the parsed JSON response. """ j = { "files": [_file_name_and_size(f) for f in filenames], "from": sender, "message": message, "recipients": recipients, "ui_language": "en", } r = requests.post(WETRANSFER_UPLOAD_EMAIL_URL, json=j) return r.json() def _prepare_link_upload(filenames: List[str], message: str) -> str: """Given a list of filenames and a message prepare for the link upload. Return the parsed JSON response. """ j = { "files": [_file_name_and_size(f) for f in filenames], "message": message, "ui_language": "en", } r = requests.post(WETRANSFER_UPLOAD_LINK_URL, json=j) return r.json() def _prepare_file_upload(transfer_id: str, file: str) -> str: """Given a transfer_id and file prepare it for the upload. Return the parsed JSON response. """ j = _file_name_and_size(file) r = requests.post(WETRANSFER_FILES_URL.format(transfer_id=transfer_id), json=j) return r.json() def _upload_chunks(transfer_id: str, file_id: str, file: str, default_chunk_size: int = WETRANSFER_DEFAULT_CHUNK_SIZE) -> str: """Given a transfer_id, file_id and file upload it. Return the parsed JSON response. """ f = open(file, 'rb') chunk_number = 0 while True: chunk = f.read(default_chunk_size) chunk_size = len(chunk) if chunk_size == 0: break chunk_number += 1 j = { "chunk_crc": zlib.crc32(chunk), "chunk_number": chunk_number, "chunk_size": chunk_size, "retries": 0 } r = requests.post( WETRANSFER_PART_PUT_URL.format(transfer_id=transfer_id, file_id=file_id), json=j) url = r.json().get('url') r = requests.options(url, headers={ 'Origin': 'https://wetransfer.com', 'Access-Control-Request-Method': 'PUT', }) r = requests.put(url, data=chunk) j = { 'chunk_count': chunk_number } r = requests.put( WETRANSFER_FINALIZE_MPP_URL.format(transfer_id=transfer_id, file_id=file_id), json=j) return r.json() def _finalize_upload(transfer_id: str) -> str: """Given a transfer_id finalize the upload. Return the parsed JSON response. """ r = requests.put(WETRANSFER_FINALIZE_URL.format(transfer_id=transfer_id)) return r.json() def upload(files: List[str], message: str = '', sender: str = None, recipients: List[str] = []) -> str: """Given a list of files upload them and return the corresponding URL. Also accepts optional parameters: - `message': message used as a description of the transfer - `sender': email address used to receive an ACK if the upload is successfull. For every download by the recipients an email will be also sent - `recipients': list of email addresses of recipients. When the upload succeed every recipients will receive an email with a link If both sender and recipient parameters are passed the email upload will be used. Otherwise, the link upload will be used. Return the short URL of the transfer on success. """ # Check that all files exists for f in files: if not os.path.exists(f): return None # Check that there are no duplicates filenames # (despite possible different dirname()) filenames = [os.path.basename(f) for f in files] if len(files) != len(set(filenames)): return None transfer_id = None if sender and recipients: # email upload transfer_id = \ _prepare_email_upload(filenames, message, sender, recipients)['id'] else: # link upload transfer_id = _prepare_link_upload(filenames, message)['id'] for f in files: file_id = _prepare_file_upload(transfer_id, os.path.basename(f))['id'] _upload_chunks(transfer_id, file_id, f) return _finalize_upload(transfer_id)['shortened_url'] if __name__ == '__main__': import argparse ap = argparse.ArgumentParser( prog='transferwee', description='Download/upload files via wetransfer.com' ) sp = ap.add_subparsers(dest='action', help='action') # download subcommand dp = sp.add_parser('download', help='download files') dp.add_argument('-g', action='store_true', help='only print the direct link (without downloading it)') dp.add_argument('url', nargs='+', type=str, metavar='url', help='URL (we.tl/... or wetransfer.com/downloads/...)') # upload subcommand up = sp.add_parser('upload', help='upload files') up.add_argument('-m', type=str, default='', metavar='message', help='message description for the transfer') up.add_argument('-f', type=str, metavar='from', help='sender email') up.add_argument('-t', nargs='+', type=str, metavar='to', help='recipient emails') up.add_argument('files', nargs='+', type=str, metavar='file', help='files to upload') args = ap.parse_args() if args.action == 'download': if args.g: for u in args.url: print(download_url(u)) else: for u in args.url: download(u) exit(0) if args.action == 'upload': print(upload(args.files, args.m, args.f, args.t)) exit(0) # No action selected, print help message ap.print_help() exit(1) flameshot-0.6.0+git20191001/.travis/services/wetransfer.com.sh000077500000000000000000000016301354471500100236010ustar00rootroot00000000000000#!/bin/sh #========================================================================================================================= # WeTransfer is a service to send big or small files from A to B. # It can transfer any type of file - such as presentations, photos, videos, music or documents - to friends and colleagues. # You can send files up to 2 GB and they will be available for 7 days, with no registration. # API doc: https://developers.wetransfer.com/documentation # Using transferwee.py: https://github.com/iamleot/transferwee #========================================================================================================================= if [ $# -eq 0 ]; then echo "Usage: python3 transferwee.py FILE\n" exit 1 fi FILE=$1 if [ ! -f "$FILE" ]; then echo "File ${FILE} not found" exit 1 fi RESPONSE=$(python3 transferwee.py upload "${FILE}") echo "${RESPONSE}" # to terminal flameshot-0.6.0+git20191001/CONTRIBUTING.md000066400000000000000000000060741354471500100173340ustar00rootroot00000000000000# Contributing Contributions are welcome! Here's how you can help: - [Translating](#translations) - [Contributing code](#code) - [Reporting issues](#issues) - [Donating](#donations) ## Translations Check this nice official documentation from Qt docs as it explains how to translate for a project written with Qt: https://doc.qt.io/qt-5/linguist-translators.html #### Status: | Language | Code | Status | Contributors | | --------------------- | ----- | ----------- | ------------ | | Spanish | es | :bookmark:v0.1.0 | [lupoDharkael](https://github.com/lupoDharkael) | | Catalan | ca | :bookmark:v0.5.0 | [joamuran](https://github.com/joamuran) | | Russian | ru | :bookmark:v0.5.1 | [Shatur95](https://github.com/Shatur95) | | Chinese (Simplified) | zh_CN | :bookmark:v0.5.1 | [copie](https://github.com/copie), [hosiet](https://github.com/hosiet) | | Chinese (Traditional) | zh_TW | :bookmark:v0.5.1 | [PeterDaveHello](https://github.com/PeterDaveHello) | | Turkish | tr | :bookmark:v0.5.1 | [oltulu](https://github.com/oltulu) | | Georgian | ge | :bookmark:v0.5.1 | [giogziro95](https://github.com/giogziro95) | | French | fr | :bookmark:v0.5.1 | [ld892012](https://github.com/ld892012) | | Polish | pl | :bookmark:v0.5.1 | [napcok](https://github.com/napcok) | | Serbian | sr | :bookmark:v0.6.0 | [cobisimo](https://github.com/cobisimo) | | Ukrainian | uk | :bookmark:v0.6.0 | [vboden](https://github.com/vboden) | | German | de | :bookmark:v0.6.0 | [DaVukovic](https://github.com/DaVukovic) | ## Code 1. [Fork](https://help.github.com/articles/fork-a-repo/) the repository and [clone](https://help.github.com/articles/cloning-a-repository/) your fork. 2. Start coding! - Implement your feature. - Check your code works as expected. 3. Commit your changes to a new branch (not `master`, one change per branch) and push it: - Commit messages should: - Header line: explain the commit in one line (use the imperative) - Be descriptive. - Have a first line with less than *80 characters* and have a second line that is *empty* if you want to add a description. 4. Once you are happy with your changes, submit a pull request. - Open the pull-request. - Add a short description explaining briefly what you've done (or if it's a work-in-progress - what you need to do) ## Issues 1. Do a quick search on GitHub to check if the issue has already been reported. 2. [Open an issue](https://github.com/lupoDharkael/flameshot/issues/new) and describe the issue you are having - you could include: - Screenshots - Ways to reproduce the issue. - Your Flameshot version. - Your platform (e.g. Windows 10 or Ubuntu 15.04 x64) After reporting you should aim to answer questions or clarifications as this helps pinpoint the cause of the issue. ### 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). flameshot-0.6.0+git20191001/LICENSE000066400000000000000000001045051354471500100161060ustar00rootroot00000000000000 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.6.0+git20191001/README.md000066400000000000000000000340451354471500100163610ustar00rootroot00000000000000

Flameshot
Flameshot

Powerful yet simple to use screenshot software.

GNU/Linux Build Status Windows Build Status Latest Stable Release Total Downloads License Docs

## Preview ![image](img/preview/animatedUsage.gif) ## Index - [Features](#features) - [Usage](#usage) - [CLI configuration](#cli-configuration) - [Keyboard Shortcuts](#keyboard-shortcuts) - [Local](#local) - [Global](#global) - [On KDE Plasma desktop](#on-kde-plasma-desktop) - [Considerations](#considerations) - [Installation](#installation) - [Compilation](#compilation) - [Dependencies](#dependencies) - [Compile-time](#compile-time) - [Run-time](#run-time) - [Optional](#optional) - [Debian](#debian) - [Fedora](#fedora) - [Arch](#arch) - [Build](#build) - [Install](#install) - [Packaging](#packaging) - [License](#license) - [Contribute](#contribute) - [Donations](#donations) - [Acknowledgment](#acknowledgment) ## Features - Customizable appearance. - Easy to use. - In-app screenshot edition. - DBus interface. - Upload to Imgur. ## Usage Example commands: - Capture with GUI: ```shell flameshot gui ``` - Capture with GUI with custom save path: ```shell flameshot gui -p ~/myStuff/captures ``` - Capture with GUI after 2 seconds delay (can be useful to take screenshots of mouse hover tooltips, etc.): ```shell flameshot gui -d 2000 ``` - Fullscreen capture with custom save path (no GUI) and delayed: ```shell flameshot full -p ~/myStuff/captures -d 5000 ``` - Fullscreen capture with custom save path copying to clipboard: ```shell flameshot full -c -p ~/myStuff/captures ``` - Capture the screen containing the mouse and print the image (bytes) in PNG format: ```shell flameshot screen -r ``` - Capture the screen number 1 and copy it to the clipboard: ```shell flameshot screen -n 1 -c ``` 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 configuration menu: ```shell flameshot config ``` - Show the initial help message in the capture mode: ```shell flameshot config --showhelp true ``` - For more information about the available options use the help flag: ```shell 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 | | Spacebar | Toggle visibility of sidebar with options of the selected tool, color picker for the drawing color and history menu | | Right Click | Show the color wheel | | 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, chances 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: ```shell 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: ```shell 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 [Gnome Shell Extension Appindicator](https://github.com/Ubuntu/gnome-shell-extension-appindicator) 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 to launch a running instance of the program without taking actions. ## Installation There are packages available for a few distros: - [Arch](https://www.archlinux.org/packages/community/x86_64/flameshot/): `pacman -S flameshot` + Snapshot also available via AUR: [flameshot-git](https://aur.archlinux.org/packages/flameshot-git). - [Debian 10+](https://tracker.debian.org/pkg/flameshot): `apt install flameshot` + Package for Debian 9 ("Stretch") also [available via stretch-backports](https://backports.debian.org/). - [Ubuntu 18.04+](https://launchpad.net/ubuntu/+source/flameshot): `apt install flameshot` - [openSUSE](https://software.opensuse.org/package/flameshot) - [Void Linux](https://github.com/void-linux/void-packages/tree/master/srcpkgs/flameshot) (`xbps-install flameshot`) - [Docker](https://github.com/ManuelLR/docker-flameshot) - Fedora: `dnf install flameshot` - [Snap/Flatpak/AppImage](https://github.com/flameshotapp/packages) - Besides, generic packages available via [opensuse software repository](https://software.opensuse.org//download.html?project=home%3AVitzy&package=flameshot)
Expand this section to see what distros are using an up to date version of flameshot Packaging status
## Compilation To build the application in your system, you'll need to install the dependencies needed for it and Package names might be different for each distribution, see [Dependencies](#dependencies) below for more information. ### Dependencies #### Compile-time - Qt >= 5.3 + Development tools - GCC >= 4.9.2 #### Run-time - Qt + SVG #### Optional - Git - OpenSSL - CA Certificates #### Debian ```shell # Compile-time apt install g++ build-essential qt5-default qt5-qmake qttools5-dev-tools # Run-time apt install libqt5dbus5 libqt5network5 libqt5core5a libqt5widgets5 libqt5gui5 libqt5svg5-dev # Optional apt install git openssl ca-certificates ``` #### Fedora ```shell # Compile-time dnf install gcc-c++ qt5-devel qt5-qtbase-devel qt5-linguist # Run-time dnf install qt5-qtbase qt5-qtsvg-devel # Optional dnf install git openssl ca-certificates ``` #### Arch ```shell # Compile-time pacman -S base-devel git qt5-base qt5-tools # Run-time pacman -S qt5-svg # Optional pacman -S openssl ca-certificates ``` ### Build After installing all the dependencies, finally run the following commands in the sources root directory: ```shell mkdir build cd build qmake ../ make ``` ### Install Simply use `make install` with privileges. ## Packaging Having `git` installed is required if you're building Flameshot from a snapshot to have precise version information. In order to generate the instructions in the `Makefile` to install the application in `/usr` instead of in `/usr/local` you can pass the `packaging` option to `qmake` (`qmake CONFIG+=packaging`). If you want to install in a custom directory you can use the `INSTALL_ROOT` variable. **Example**: If you want to install Flameshot in `~/myBuilds/test`, you can execute the following to do so: ```shell qmake CONFIG+=packaging make INSTALL_ROOT=~/myBuilds/test install ``` ## License - The main code is licensed under [GPLv3](LICENSE) - The logo of Flameshot is licensed under [Free Art License v1.3](img/app/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. ## Contribute If you want to contribute check the [CONTRIBUTING.md](CONTRIBUTING.md) ## 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 with the following options: - [Paypal](https://www.paypal.me/lupoDharkael) - bitcoin:1K6oiUKWVjP3x9ZuW9C7NbDfcFkMx3G8ue ## 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.6.0+git20191001/appveyor.yml000066400000000000000000000056511354471500100174730ustar00rootroot00000000000000image: Visual Studio 2015 version: 0.6.{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" - copy "%APPVEYOR_BUILD_FOLDER%\build\translations\Internationalization_*.qm" "distrib\flameshot\translations" # 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_%flameshot_version%_win_%PLATFORM%.zip flameshot - appveyor-retry curl --upload-file ./flameshot_%flameshot_version%_win_%PLATFORM%.zip https://transfer.sh/flameshot_%flameshot_version%_win_%PLATFORM%.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.6.0+git20191001/dbus/000077500000000000000000000000001354471500100160315ustar00rootroot00000000000000flameshot-0.6.0+git20191001/dbus/make/000077500000000000000000000000001354471500100167465ustar00rootroot00000000000000flameshot-0.6.0+git20191001/dbus/make/org.dharkael.Flameshot.service000066400000000000000000000001121354471500100246040ustar00rootroot00000000000000[D-BUS Service] Name=org.dharkael.Flameshot Exec=/usr/local/bin/flameshot flameshot-0.6.0+git20191001/dbus/org.dharkael.Flameshot.xml000066400000000000000000000100311354471500100230300ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/dbus/org.freedesktop.Notifications.xml000066400000000000000000000024441354471500100244700ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/dbus/other-path/000077500000000000000000000000001354471500100201045ustar00rootroot00000000000000flameshot-0.6.0+git20191001/dbus/other-path/service-gen.sh000066400000000000000000000004021354471500100226430ustar00rootroot00000000000000#!/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.6.0+git20191001/dbus/package/000077500000000000000000000000001354471500100174245ustar00rootroot00000000000000flameshot-0.6.0+git20191001/dbus/package/org.dharkael.Flameshot.service000066400000000000000000000001041354471500100252630ustar00rootroot00000000000000[D-BUS Service] Name=org.dharkael.Flameshot Exec=/usr/bin/flameshot flameshot-0.6.0+git20191001/debian/000077500000000000000000000000001354471500100163165ustar00rootroot00000000000000flameshot-0.6.0+git20191001/debian/changelog000066400000000000000000000002141354471500100201650ustar00rootroot00000000000000flameshot (0.6.0-1) unstable; urgency=medium * Initial deb package. -- Boyuan Yang Wed, 27 Feb 2019 13:19:39 -0500 flameshot-0.6.0+git20191001/debian/compat000066400000000000000000000000021354471500100175140ustar00rootroot000000000000009 flameshot-0.6.0+git20191001/debian/control000066400000000000000000000016111354471500100177200ustar00rootroot00000000000000Source: flameshot Section: graphics Priority: optional Maintainer: Juanma Navarro Mañez Uploaders: Boyuan Yang , Build-Depends: debhelper (>= 9), qt5-qmake, qtbase5-dev, qttools5-dev-tools, libqt5svg5-dev, Standards-Version: 4.3.0 Homepage: https://github.com/lupoDharkael/flameshot Vcs-Browser: https://github.com/lupoDharkael/flameshot Vcs-Git: https://github.com/lupoDharkael/flameshot.git Package: flameshot Architecture: any Depends: libqt5svg5, ${shlibs:Depends}, ${misc:Depends}, Suggests: ca-certificates, openssl, Description: Powerful yet simple-to-use screenshot software Flameshot is a powerful yet simple-to-use screenshot software. Notable features include customizable appearance, in-app screenshot editing, D-Bus interface, experimental GNOME/KDE Wayland support, integration with Imgur and support for both GUI and CLI interface. flameshot-0.6.0+git20191001/debian/copyright000066400000000000000000000373511354471500100202620ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: flameshot Source: https://github.com/lupoDharkael/flameshot/ Files: * Copyright: 2016-2019 lupoDharkael License: GPL-3+ Comments: The author copied a few lines of code from KSnapshot regiongrabber.cpp revision 796531 (LGPL). Files: debian/* Copyright: 2017 Juanma Navarro Mañez 2018-2019 Boyuan Yang License: GPL-3+ Files: img/flameshot.* Copyright: 2017 lupoDharkael License: Free-Art-License-1.3 Files: docs/appdata/flameshot.appdata.xml Copyright: 2017-2019 lupoDharkael License: CC0-1.0 Files: img/buttonIconsBlack/* img/buttonIconsWhite/* Copyright: Google Inc. License: Apache-2.0 Files: src/widgets/capture/capturewidget.* Copyright: 2017 Alejandro Sirgo Rica 2017 Christian Kaiser 2007 Luca Gugelmann License: GPL-3+ Comments: Relicensed under GPL-3+ under flameshot project. . Originally based on Lightscreen areadialog.h, Copyright 2017 Christian Kaiser released under the GNU GPL2 . Originally based on KDE's KSnapshot regiongrabber.cpp, revision 796531, Copyright 2007 Luca Gugelmann released under the GNU LGPL Files: src/third-party/singleapplication/* Copyright: 2015 - 2016 Itay Grudev License: Expat Files: src/third-party/Qt-Color-Widgets/* Copyright: 2013-2017 Mattia Basaglia License: LGPL-3+ Comments: As a special exception, this library can be included in any project under the terms of any of the GNU licenses, distributing the whole project under a different GNU license, see LICENSE-EXCEPTION for details. . Linking 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. License: LGPL-3+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Lesser 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 Lesser General Public License for more details. . You should have received a copy of the GNU General Lesser Public License along with this program. If not, see . . On Debian systems, the complete text of the GNU Lesser General Public License version 3 can be found in "/usr/share/common-licenses/LGPL-3". License: Expat The MIT License (MIT) . 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. License: Apache-2.0 Google Material Design Icons are licensed under Apache License 2.0. . On Debian systems, the complete text of Apache License 2.0 can be found in "/usr/share/common-licenses/Apache-2.0". License: Free-Art-License-1.3 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 License: GPL-3+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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". License: CC0-1.0 On Debian systems, the complete text of the Creative Commons Zero v1.0 Universal License can be found in "/usr/share/common-licenses/CC0-1.0". flameshot-0.6.0+git20191001/debian/docs000066400000000000000000000000121354471500100171620ustar00rootroot00000000000000README.md flameshot-0.6.0+git20191001/debian/rules000077500000000000000000000012431354471500100173760ustar00rootroot00000000000000#!/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 export QT_SELECT := 5 %: dh $@ override_dh_auto_configure: # The existence of an empty .git directory triggers syncqt. mkdir .git || true dh_auto_configure -- CONFIG+=packaging CONFIG-=debug CONFIG+=release flameshot-0.6.0+git20191001/debian/source/000077500000000000000000000000001354471500100176165ustar00rootroot00000000000000flameshot-0.6.0+git20191001/debian/source/format000066400000000000000000000000141354471500100210240ustar00rootroot000000000000003.0 (quilt) flameshot-0.6.0+git20191001/docs/000077500000000000000000000000001354471500100160245ustar00rootroot00000000000000flameshot-0.6.0+git20191001/docs/appdata/000077500000000000000000000000001354471500100174365ustar00rootroot00000000000000flameshot-0.6.0+git20191001/docs/appdata/flameshot.appdata.xml000066400000000000000000000020311354471500100235470ustar00rootroot00000000000000 flameshot.desktop CC0-1.0 GPL-3.0-or-later 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/preview/usageStatic.png https://raw.githubusercontent.com/lupoDharkael/flameshot/master/img/preview/animatedUsage.gif https://github.com/lupoDharkael/flameshot https://github.com/lupoDharkael
flameshot-0.6.0+git20191001/docs/bash-completion/000077500000000000000000000000001354471500100211105ustar00rootroot00000000000000flameshot-0.6.0+git20191001/docs/bash-completion/flameshot000066400000000000000000000030341354471500100230150ustar00rootroot00000000000000# 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 launcher screen" screen_opts="--number --path --delay --raw -p -d -r -n" 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 --autostart -k -f -m -s -t -a" case "${prev}" in launcher) return 0 ;; screen) COMPREPLY=( $(compgen -W "$screen_opts --help -h" -- ${cur}) ) return 0 ;; 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|--number|-n) 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.6.0+git20191001/docs/desktopEntry/000077500000000000000000000000001354471500100205175ustar00rootroot00000000000000flameshot-0.6.0+git20191001/docs/desktopEntry/package/000077500000000000000000000000001354471500100221125ustar00rootroot00000000000000flameshot-0.6.0+git20191001/docs/desktopEntry/package/flameshot.desktop000066400000000000000000000037701354471500100254760ustar00rootroot00000000000000[Desktop Entry] Name=Flameshot Name[zh_CN]=火焰截图 GenericName=Screenshot tool GenericName[zh_CN]=屏幕截图工具 GenericName[pl]=Zrzuty ekranu GenericName[fr]=Outil de capture d'écran GenericName[ja]=スクリーンショットツール GenericName[ru]=Создание скриншотов GenericName[sr]=Снимач екрана GenericName[uk]=Інструмент скриншотів Comment=Powerful yet simple to use screenshot software. Comment[zh_CN]=强大又易用的屏幕截图软件 Comment[pl]=Proste w użyciu narzędzie do zrzutów ekranu Comment[fr]=Logiciel de capture d'écran puissant et simple d'utilisation. Comment[ja]=パワフルで使いやすいスクリーンショットソフトウェア。 Comment[ru]=Простой и функциональный инструмент для создания скриншотов Comment[sr]=Једноставан, а моћан алат за снимање екрана Comment[uk]=Потужний простий у використанні додаток для створення знімків екрану. Keywords=flameshot;screenshot;capture;shutter; Keywords[zh_CN]=flameshot;screenshot;capture;shutter;截图;屏幕; Keywords[fr]=flameshot;capture d'écran;capter;shutter; Keywords[ja]=flameshot;screenshot;capture;shutter;スクリーンショット;キャプチャー; Exec=flameshot Icon=flameshot Terminal=false Type=Application Categories=Graphics; StartupNotify=false Actions=Configure;Capture; [Desktop Action Configure] Name=Configure Name[zh_CN]=配置 Name[pl]=Konfiguruj Name[fr]=Configurer Name[ja]=設定 Name[ru]=Настройки Name[sr]=Подешавања Name[uk]=Налаштувати Exec=flameshot config [Desktop Action Capture] Name=Take screenshot Name[zh_CN]=进行截图 Name[pl]=Zrzut ekranu Name[fr]=Prendre une capture d'écran Name[ja]=スクリーンショットを撮る Name[ru]=Сделать скриншот Name[sr]=Сними екран Name[uk]=Зробити знімок Exec=flameshot gui --delay 500 flameshot-0.6.0+git20191001/docs/dev/000077500000000000000000000000001354471500100166025ustar00rootroot00000000000000flameshot-0.6.0+git20191001/docs/dev/package.md000066400000000000000000000002351354471500100205170ustar00rootroot00000000000000# 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.6.0+git20191001/docs/dev/release.md000066400000000000000000000004721354471500100205470ustar00rootroot00000000000000 What to do before 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. - Update .pro hardcoded version. - Run cppcheck --enable=all 2> err.txt - Run codespell flameshot-0.6.0+git20191001/docs/shortcuts-config/000077500000000000000000000000001354471500100213255ustar00rootroot00000000000000flameshot-0.6.0+git20191001/docs/shortcuts-config/flameshot-shortcuts-kde000066400000000000000000000045041354471500100260320ustar00rootroot00000000000000[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.6.0+git20191001/flameshot.pro000066400000000000000000000215531354471500100176060ustar00rootroot00000000000000#------------------------------------------------- # # 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) isEmpty(TAG_VERSION){ TAG_VERSION = v0.6.0 } DEFINES += APP_VERSION=\\\"$$TAG_VERSION\\\" QT += core gui widgets network svg 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/app/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 \ translations/Internationalization_ja.ts \ translations/Internationalization_pt_br.ts \ translations/Internationalization_sr.ts \ translations/Internationalization_uk.ts \ translations/Internationalization_de_DE.ts \ translations/Internationalization_sk.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/widgets/capture/buttonhandler.cpp \ src/widgets/infowindow.cpp \ src/config/configwindow.cpp \ src/widgets/capture/capturewidget.cpp \ src/widgets/capture/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/widgets/capture/capturebutton.cpp \ src/tools/pencil/penciltool.cpp \ src/tools/undo/undotool.cpp \ src/tools/redo/redotool.cpp \ src/tools/arrow/arrowtool.cpp \ src/tools/circle/circletool.cpp \ src/tools/copy/copytool.cpp \ src/tools/exit/exittool.cpp \ src/tools/imgur/imguruploadertool.cpp \ src/tools/line/linetool.cpp \ src/tools/marker/markertool.cpp \ src/tools/move/movetool.cpp \ src/tools/rectangle/rectangletool.cpp \ src/tools/save/savetool.cpp \ src/tools/selection/selectiontool.cpp \ src/tools/sizeindicator/sizeindicatortool.cpp \ src/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/utils/screenshotsaver.cpp \ src/tools/imgur/imguruploader.cpp \ src/widgets/loadspinner.cpp \ src/widgets/imagelabel.cpp \ src/widgets/notificationwidget.cpp \ src/widgets/capture/notifierbox.cpp \ src/utils/desktopinfo.cpp \ src/tools/launcher/applauncherwidget.cpp \ src/utils/desktopfileparse.cpp \ src/tools/launcher/launcheritemdelegate.cpp \ src/tools/blur/blurtool.cpp \ src/tools/pin/pintool.cpp \ src/tools/launcher/terminallauncher.cpp \ src/config/visualseditor.cpp \ src/config/extendedslider.cpp \ src/tools/launcher/openwithprogram.cpp \ src/tools/launcher/applaunchertool.cpp \ src/utils/pathinfo.cpp \ src/utils/colorutils.cpp \ src/tools/capturecontext.cpp \ src/widgets/capture/modificationcommand.cpp \ src/tools/abstractpathtool.cpp \ src/tools/abstracttwopointtool.cpp \ src/tools/abstractactiontool.cpp \ src/utils/globalvalues.cpp \ src/widgets/panel/utilitypanel.cpp \ src/widgets/capture/hovereventfilter.cpp \ src/widgets/capture/selectionwidget.cpp \ src/tools/pin/pinwidget.cpp \ src/widgets/capturelauncher.cpp \ src/tools/text/texttool.cpp \ src/tools/text/textwidget.cpp \ src/core/capturerequest.cpp \ src/tools/text/textconfig.cpp \ src/widgets/panel/sidepanelwidget.cpp HEADERS += src/widgets/capture/buttonhandler.h \ src/widgets/infowindow.h \ src/config/configwindow.h \ src/widgets/capture/capturewidget.h \ src/widgets/capture/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/tools/capturetool.h \ src/widgets/capture/capturebutton.h \ src/tools/pencil/penciltool.h \ src/tools/undo/undotool.h \ src/tools/redo/redotool.h \ src/tools/arrow/arrowtool.h \ src/tools/circle/circletool.h \ src/tools/copy/copytool.h \ src/tools/exit/exittool.h \ src/tools/imgur/imguruploadertool.h \ src/tools/line/linetool.h \ src/tools/marker/markertool.h \ src/tools/move/movetool.h \ src/tools/rectangle/rectangletool.h \ src/tools/save/savetool.h \ src/tools/selection/selectiontool.h \ src/tools/sizeindicator/sizeindicatortool.h \ src/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/utils/screenshotsaver.h \ src/tools/imgur/imguruploader.h \ src/widgets/loadspinner.h \ src/widgets/imagelabel.h \ src/widgets/notificationwidget.h \ src/widgets/capture/notifierbox.h \ src/utils/desktopinfo.h \ src/tools/launcher/applauncherwidget.h \ src/utils/desktopfileparse.h \ src/tools/launcher/launcheritemdelegate.h \ src/tools/blur/blurtool.h \ src/tools/pin/pintool.h \ src/tools/launcher/terminallauncher.h \ src/config/visualseditor.h \ src/config/extendedslider.h \ src/tools/launcher/openwithprogram.h \ src/utils/pathinfo.h \ src/tools/capturecontext.h \ src/tools/launcher/applaunchertool.h \ src/utils/globalvalues.h \ src/utils/colorutils.h \ src/widgets/capture/modificationcommand.h \ src/tools/abstractpathtool.h \ src/tools/abstracttwopointtool.h \ src/tools/abstractactiontool.h \ src/widgets/panel/utilitypanel.h \ src/widgets/capture/hovereventfilter.h \ src/widgets/capture/selectionwidget.h \ src/tools/pin/pinwidget.h \ src/widgets/capturelauncher.h \ src/tools/text/texttool.h \ src/tools/text/textwidget.h \ src/core/capturerequest.h \ src/tools/text/textconfig.h \ src/widgets/panel/sidepanelwidget.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 = $${PREFIX}/bin/ qmfile.path = $${PREFIX}/share/flameshot/translations/ qmfile.files = $${TRANSLATIONS_FILES} dbus.path = $${PREFIX}/share/dbus-1/interfaces/ dbus.files = dbus/org.dharkael.Flameshot.xml icon.path = $${PREFIX}/share/icons/hicolor/ icon.files = img/hicolor/* completion.path = $${PREFIX}/share/bash-completion/completions/ completion.files = docs/bash-completion/flameshot appdata.path = $${PREFIX}/share/metainfo/ appdata.files = docs/appdata/flameshot.appdata.xml desktopentry.path = $${PREFIX}/share/applications desktopentry.files = docs/desktopEntry/package/flameshot.desktop servicedbus.path = $${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 \ qmfile \ servicedbus \ dbus \ completion \ appdata } # Imgur API data include(src/imgur.pri) flameshot-0.6.0+git20191001/graphics.qrc000066400000000000000000000067351354471500100174160ustar00rootroot00000000000000 img/app/flameshot.svg img/app/flameshot.png img/material/black/undo-variant.svg img/material/black/text.svg img/material/black/square.svg img/material/black/square-outline.svg img/material/black/size_indicator.svg img/material/black/redo-variant.svg img/material/black/pin.svg img/material/black/pencil.svg img/material/black/open_with.svg img/material/black/name_edition.svg img/material/black/mouse.svg img/material/black/mouse-off.svg img/material/black/marker.svg img/material/black/line.svg img/material/black/graphics.svg img/material/black/format-text.svg img/material/black/format_underlined.svg img/material/black/format_strikethrough.svg img/material/black/format_italic.svg img/material/black/format_bold.svg img/material/black/exit-to-app.svg img/material/black/cursor-move.svg img/material/black/content-save.svg img/material/black/content-copy.svg img/material/black/config.svg img/material/black/colorize.svg img/material/black/cloud-upload.svg img/material/black/close.svg img/material/black/circle-outline.svg img/material/black/blur.svg img/material/black/arrow-bottom-left.svg img/material/white/undo-variant.svg img/material/white/text.svg img/material/white/square.svg img/material/white/square-outline.svg img/material/white/size_indicator.svg img/material/white/redo-variant.svg img/material/white/pin.svg img/material/white/pencil.svg img/material/white/open_with.svg img/material/white/name_edition.svg img/material/white/mouse.svg img/material/white/mouse-off.svg img/material/white/marker.svg img/material/white/line.svg img/material/white/graphics.svg img/material/white/format-text.svg img/material/white/format_underlined.svg img/material/white/format_strikethrough.svg img/material/white/format_italic.svg img/material/white/format_bold.svg img/material/white/exit-to-app.svg img/material/white/cursor-move.svg img/material/white/content-save.svg img/material/white/content-copy.svg img/material/white/config.svg img/material/white/colorize.svg img/material/white/cloud-upload.svg img/material/white/close.svg img/material/white/circle-outline.svg img/material/white/blur.svg img/material/white/arrow-bottom-left.svg flameshot-0.6.0+git20191001/img/000077500000000000000000000000001354471500100156505ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/app/000077500000000000000000000000001354471500100164305ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/app/flameshot.ico000066400000000000000000003557331354471500100211260ustar00rootroot00000000000000  + (+,@@ (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.6.0+git20191001/img/app/flameshot.png000066400000000000000000000125531354471500100211260ustar00rootroot00000000000000PNG  IHDR>asBIT|d pHYsetEXtSoftwarewww.inkscape.org<IDATxyxUյܛ9B &a'e *(WڪOʠ_Sljk_PHE(CBQ!`!$%@IDr~Kps>=gv^眽^kmuFYZzh0d ݁@ĺ/jݟ<gB 4 4RwBe)owcq FxE.$Skq)EL)/ȉANܤ# ;x& Vlr:L`&6y\"7kj؞Ep7VYdž!|Hw{T@U*܍%E֍Ƣm yb[6ԏ;%<Lw[|a1PD> w[L d) ,cC#ף- 퉧?\ dft4q @L8`!AQ|l+rM߭FGL)@6[*\)?4SnkCk1?8w՚$O=/!Z`>0o GU T XFz_ra}șZ'@;Q@: Nd}o*4DVvQ-%5Y/Ҝ8?\ݍ/dXNN{m+zs~݌tc۶5V` c1Zz=h@A֗C\(VrlW` md{ IN* wS3Y@ zom$? @tK=pO_{.XFܶfҩ>S?XAz ZV@G^b. HN*]CWW3,RlF9 ܧLM R-ㄷ5RJ. T "o# @}Mu`.XnߦЩORi&poƞ&ӻ~G@lK2QlCҹ*qfDį]}柀@ߐ½d%4gWcP4>xk?MkzWQT *lHȅ)PtL;í"6>Aw{4I(ߒ Jp2ʥk@ͱ:$NB˛Lw{O(ߜ(ݯ+əWpGZ]y<:='xN/3eL`)O!^C"9 cHvdl5ݽϹ'>Qv[xH[8IYh!ý<*D1fүy+/ u7X__("g&АR]£]~/YCOF.CcH_~O?\o$39H@´Yۧ `=,>`,m-cH9NSHI:mO81DϴYArF HC9PNMhS@ sUܪDJ6^QGLS)ZQL_F9Fa㬺H{Y0H`0=o58˝>SjK uz`XtTN"Tf_s%I|HRV7i_@1w1w?q ,%͵ZxJdo4@ʉbì'vFbWWap(} -]y ҹ #}̊jBKcun5?uR``W>C*vLz!$<5@ygIy@3@z/{t$R`).1A޾W_\2N|Kqv.%FRw48lVܒ|Rzڥ* \kw^j\=\7$I|QMŧu&e;͠ ^~ vT惰E`y x^N͵7t3 K7 2ߩP6#uD:BׁQK s0-_{y! 4tͫOš騰t0 ~7eOq MgUJ)7>Bz~j/v҇H"@HwlT ǨVz W |5۫šs37e?kP6|/ֻ`dt6$pY4&V^Ĺ#!wL\̆[_$~XK < *%|sZ`alfҙh元U?;Mk0)|M2-::W~` U_D׸[pxj`SS升]K&[Gض9-B=>G\4U{}&(ex4NGt8Xx:f2eOG=2}rP9{4 N˶+ .C8NGnt~/b <*@H|AeN/f.b`CtuƱwcK"'y.&s#`~l()ʗ|FHG}gĒpcЍξ~ի=W$7_OuTh|H+\!=d[P 7s»?X@5>Él_E$_iV;(̻ytNo) gzaOx~hݸJx_! |՘6D:;^>k3R)]ͺRpmWHkŲK%/W(gh o$̞{E+qY.g":\ a6ƑX_ `@ * 07gs+,ږ@yy2q#(& 5jĶG/"_u %WǕ$ATj.Cו9%Hxusr-۪#3uq@o^CL "@.?5 (x$WAɛ)+Lk:TZ*' *O/%wL.PScߧ&Sfѧd9AP$*RӳfJ$"{ sZC'Fju+@&Hx@-oݵTbԫ!//'=Muoݶ!i NzAp#N!E?MEM4 `,dqB9o%dm+ӡL46'{^C3/'0"v;(UJEm k ~+] G1MBLq_I0'XbV@ m~e/k!٘kDmԌ2! 3Xw@y-Kxl )4,SYQJR@n *|)eqIX疒[8.$lU%';R`Db|_ІXB$R,'[6 flameshot-0.6.0+git20191001/img/app/flameshotLogoLicense.txt000066400000000000000000000232431354471500100233030ustar00rootroot00000000000000Free 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.6.0+git20191001/img/hicolor/000077500000000000000000000000001354471500100173075ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/hicolor/128x128/000077500000000000000000000000001354471500100202445ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/hicolor/128x128/apps/000077500000000000000000000000001354471500100212075ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/hicolor/128x128/apps/flameshot.png000066400000000000000000000125531354471500100237050ustar00rootroot00000000000000PNG  IHDR>asBIT|d pHYsetEXtSoftwarewww.inkscape.org<IDATxyxUյܛ9B &a'e *(WڪOʠ_Sljk_PHE(CBQ!`!$%@IDr~Kps>=gv^眽^kmuFYZzh0d ݁@ĺ/jݟ<gB 4 4RwBe)owcq FxE.$Skq)EL)/ȉANܤ# ;x& Vlr:L`&6y\"7kj؞Ep7VYdž!|Hw{T@U*܍%E֍Ƣm yb[6ԏ;%<Lw[|a1PD> w[L d) ,cC#ף- 퉧?\ dft4q @L8`!AQ|l+rM߭FGL)@6[*\)?4SnkCk1?8w՚$O=/!Z`>0o GU T XFz_ra}șZ'@;Q@: Nd}o*4DVvQ-%5Y/Ҝ8?\ݍ/dXNN{m+zs~݌tc۶5V` c1Zz=h@A֗C\(VrlW` md{ IN* wS3Y@ zom$? @tK=pO_{.XFܶfҩ>S?XAz ZV@G^b. HN*]CWW3,RlF9 ܧLM R-ㄷ5RJ. T "o# @}Mu`.XnߦЩORi&poƞ&ӻ~G@lK2QlCҹ*qfDį]}柀@ߐ½d%4gWcP4>xk?MkzWQT *lHȅ)PtL;í"6>Aw{4I(ߒ Jp2ʥk@ͱ:$NB˛Lw{O(ߜ(ݯ+əWpGZ]y<:='xN/3eL`)O!^C"9 cHvdl5ݽϹ'>Qv[xH[8IYh!ý<*D1fүy+/ u7X__("g&АR]£]~/YCOF.CcH_~O?\o$39H@´Yۧ `=,>`,m-cH9NSHI:mO81DϴYArF HC9PNMhS@ sUܪDJ6^QGLS)ZQL_F9Fa㬺H{Y0H`0=o58˝>SjK uz`XtTN"Tf_s%I|HRV7i_@1w1w?q ,%͵ZxJdo4@ʉbì'vFbWWap(} -]y ҹ #}̊jBKcun5?uR``W>C*vLz!$<5@ygIy@3@z/{t$R`).1A޾W_\2N|Kqv.%FRw48lVܒ|Rzڥ* \kw^j\=\7$I|QMŧu&e;͠ ^~ vT惰E`y x^N͵7t3 K7 2ߩP6#uD:BׁQK s0-_{y! 4tͫOš騰t0 ~7eOq MgUJ)7>Bz~j/v҇H"@HwlT ǨVz W |5۫šs37e?kP6|/ֻ`dt6$pY4&V^Ĺ#!wL\̆[_$~XK < *%|sZ`alfҙh元U?;Mk0)|M2-::W~` U_D׸[pxj`SS升]K&[Gض9-B=>G\4U{}&(ex4NGt8Xx:f2eOG=2}rP9{4 N˶+ .C8NGnt~/b <*@H|AeN/f.b`CtuƱwcK"'y.&s#`~l()ʗ|FHG}gĒpcЍξ~ի=W$7_OuTh|H+\!=d[P 7s»?X@5>Él_E$_iV;(̻ytNo) gzaOx~hݸJx_! |՘6D:;^>k3R)]ͺRpmWHkŲK%/W(gh o$̞{E+qY.g":\ a6ƑX_ `@ * 07gs+,ږ@yy2q#(& 5jĶG/"_u %WǕ$ATj.Cו9%Hxusr-۪#3uq@o^CL "@.?5 (x$WAɛ)+Lk:TZ*' *O/%wL.PScߧ&Sfѧd9AP$*RӳfJ$"{ sZC'Fju+@&Hx@-oݵTbԫ!//'=Muoݶ!i NzAp#N!E?MEM4 `,dqB9o%dm+ӡL46'{^C3/'0"v;(UJEm k ~+] G1MBLq_I0'XbV@ m~e/k!٘kDmԌ2! 3Xw@y-Kxl )4,SYQJR@n *|)eqIX疒[8.$lU%';R`Db|_ІXB$R,'[6[:0'{Q~(E x_"UQv9Q0*Gws+MPM>f>xcL"H>8N`ʀ*N!Qjߒz&!Dٶv#bD8HmDi+R@jKuF\]8D vHD>G4 uW8`Q%+t!GR!r^!w,{,SvK9TrhHtZ"3*%͖ojr%"1oK?x[Uod 9$ ^*jrf8A$ @/IL九St:HfJ 35]PI]f0@ڦGHLqy݆Sc-KJd !bb&L4GĖ0)^>w;کN 1Z BH(ޏ"vkj;ضyyF-q$ G? F e GlY5`w5s"\`}՜oMFLPp L7 JQPUKZ 9y>^cMAB<>_ gt. !|MU_gY3Qc3}¢w`Xgb:YėQGH ( XkXHaCj0`]gd`ba= g GDZgo.ar#ːIu `F @dbIT.J &[GvN4AEc韰ISdʦGqGw`\p}$Gw< kFO7q_%4!}m7&Ј0k}N= Gf0ez}b: QG\paeoYLJD@ncy'sD~#.h-s.R9g-SU h7/i= 4iURb&SH!o UmE'x4lE#hk%߲}O7Y?lxG*i%F)<{>ܥIM=ql 9xAO3'dЃ^by <*?zQ+ѩϿQƽ;;T0C^\'2Vb[I^oszt#YiN$&N[<iP7)XNa6c@[߀S E@co^ / %\"m4fN:x\DO&5mo,B-cG')o S˝\/⍶4~1gQߊ3mUhn/*jc؏R2&{\B-:'B!rx'asTi@TwSQ/ғ*)UsvJ|cR[-a8@=& ! ?Zi}(k¸f6e3Û44OCF%qیO ua;IAg%g2| l KPkID { D%@&?)Ѩ7oɖIENDB`flameshot-0.6.0+git20191001/img/hicolor/scalable/000077500000000000000000000000001354471500100210555ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/hicolor/scalable/apps/000077500000000000000000000000001354471500100220205ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/hicolor/scalable/apps/flameshot.svg000066400000000000000000000022541354471500100245260ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/000077500000000000000000000000001354471500100174465ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/material/LICENSE.txt000066400000000000000000000261361354471500100213010ustar00rootroot00000000000000 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.6.0+git20191001/img/material/README.md000066400000000000000000000001251354471500100207230ustar00rootroot00000000000000Google Material Design Icons are licensed under Apache License 2.0 (see LICENSE.txt) flameshot-0.6.0+git20191001/img/material/black/000077500000000000000000000000001354471500100205225ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/material/black/arrow-bottom-left.png000066400000000000000000000003371354471500100246170ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<lIDATHc` AV_f``_~AbPib8> ,,j[@E&f͒"̂H( Gb3ⱀpD[F(E/R&#SIENDB`flameshot-0.6.0+git20191001/img/material/black/arrow-bottom-left.svg000066400000000000000000000001451354471500100246270ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/blur.png000066400000000000000000000002461354471500100221760ustar00rootroot00000000000000PNG  IHDRJ~smIDATxݓA !˼()֠= ,4shDˋf~ӗh<}c/nT A \#kHu-vd$opC]מQץ/[GC5IENDB`flameshot-0.6.0+git20191001/img/material/black/blur.svg000066400000000000000000000027351354471500100222160ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/circle-outline.png000066400000000000000000000007251354471500100241520ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/black/circle-outline.svg000066400000000000000000000003521354471500100241610ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/close.png000066400000000000000000000003651354471500100223410ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH1 E_GpO;qt) 1P'K?~؀@xn8`ƒp^4&iv.6I]:zulL?RPbZv^c0!\ p?E IENDB`flameshot-0.6.0+git20191001/img/material/black/close.svg000066400000000000000000000002371354471500100223520ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/cloud-upload.png000066400000000000000000000005301354471500100236160ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/black/cloud-upload.svg000066400000000000000000000003641354471500100236360ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/colorize.png000066400000000000000000000005141354471500100230560ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATH;n@ϋ0d ,Q@ Km!$ J` {'2@őn1 o@#|@6@.&F5ȱ! X\:&J%~0N_3%y̅ߔ[Ս:wNGγ:QkrRxHLDp[KB"π7 NIRx /eVЏryFIENDB`flameshot-0.6.0+git20191001/img/material/black/colorize.svg000066400000000000000000000004711354471500100230730ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/config.png000066400000000000000000000005501354471500100224750ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/black/config.svg000066400000000000000000000004301354471500100225050ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/content-copy.png000066400000000000000000000003401354471500100236470ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<mIDATHc`#b``xDL4 p, Y1b9q򘁁ADn<"rCπ X،`рZJZ}>&rOHNj]AT[n\IENDB`flameshot-0.6.0+git20191001/img/material/black/content-copy.svg000066400000000000000000000002761354471500100236720ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/content-save.png000066400000000000000000000004221354471500100236340ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATHA0 E!:HP.=rapaӐJL6i;N&gݭWrd [<D0 5wh\M{Ie`nysWzw w ZJo<($%륞%/`'M{-IENDB`flameshot-0.6.0+git20191001/img/material/black/content-save.svg000066400000000000000000000003601354471500100236500ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/cursor-move.png000066400000000000000000000004121354471500100235060ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATHUA 0 DON/l]M@/ mb ['=JJR7!hlB{b&u;%jR !$#CDV5rEQ vbS^HθTd0MZ;ײtk<: w]. *IENDB`flameshot-0.6.0+git20191001/img/material/black/cursor-move.svg000066400000000000000000000002621354471500100235240ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/exit-to-app.png000066400000000000000000000004321354471500100233760ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/black/exit-to-app.svg000066400000000000000000000003621354471500100234130ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/format-text.svg000066400000000000000000000005141354471500100235150ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/format_bold.png000066400000000000000000000005071354471500100235220ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATH= 1?J-ƒȶb1 flameshot-0.6.0+git20191001/img/material/black/format_italic.png000066400000000000000000000004201354471500100240410ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATH @F/ޣUex V*ԻC (lga(*mZD$1{@,5nqݱVHz !٨pw&vAޡ-v-_3l!հO"4PbEIENDB`flameshot-0.6.0+git20191001/img/material/black/format_italic.svg000066400000000000000000000002141354471500100240550ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/format_strikethrough.png000066400000000000000000000003021354471500100254750ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<?IDATHc` qyLdD4@6 =M8`4Q~buIENDB`flameshot-0.6.0+git20191001/img/material/black/format_strikethrough.svg000066400000000000000000000002221354471500100255110ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/format_underlined.png000066400000000000000000000004441354471500100247330ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATHA @ E_]عp7Tv.&b4ma>|BOqPIE?)`uCd tDTJ-=pQMZ w*~2vb]\b|;gO(X}bIENDB`flameshot-0.6.0+git20191001/img/material/black/format_underlined.svg000066400000000000000000000003171354471500100247450ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/graphics.png000066400000000000000000000003761354471500100230360ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATHK @.)!,tOPূaxMm&pO]?58|Ŭq~'s08+ID瑨Xr TTrJ$sߢɋ.a\j%_y_2'N,W%NIENDB`flameshot-0.6.0+git20191001/img/material/black/graphics.svg000066400000000000000000000005061354471500100230440ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/line.png000066400000000000000000000003321354471500100221550ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<gIDATH1@@EћM؄}ۄ),A1PHQȻf@5$q'g CDNtyqo%BIENDB`flameshot-0.6.0+git20191001/img/material/black/line.svg000066400000000000000000000002271354471500100221730ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/marker.png000066400000000000000000000005151354471500100225120ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH1NAOBHGxK`,B 7 x v_X^ffio裾KG,W:aUxӶ# lSSO%:с~34Z'BwdOt3FFvo 8O9pPxM~'p,)XTC9xBW,=?ۘ.RIENDB`flameshot-0.6.0+git20191001/img/material/black/marker.svg000066400000000000000000000005171354471500100225270ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/mouse-off.svg000066400000000000000000000005231354471500100231430ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/mouse.svg000066400000000000000000000002631354471500100223740ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/name_edition.png000066400000000000000000000002371354471500100236650ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<,IDATHc``0bOM3(4lJ^ 0` AisIENDB`flameshot-0.6.0+git20191001/img/material/black/name_edition.svg000066400000000000000000000001121354471500100236700ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/open_with.png000066400000000000000000000004161354471500100232250ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATHA GWy?" ppC՚&ka8hWaž fv,25ܝ Sx\ ,50 yKmZp6 E)8?TӀJ 3\"۩IENDB`flameshot-0.6.0+git20191001/img/material/black/open_with.svg000066400000000000000000000002571354471500100232430ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/pencil.png000066400000000000000000000003711354471500100225030ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH; 0EoB;wB00"@󆐀 @ G@z:ʹp l >AIzmhlkTҸ]R- @xs;P6?+%m8slh+j"IENDB`flameshot-0.6.0+git20191001/img/material/black/pencil.svg000066400000000000000000000003051354471500100225130ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/pin.png000066400000000000000000000003321354471500100220140ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<WIDATHc`ꀑJa"-B>`` fZ@{ 0\ |rY4R(& x*`h8IENDB`flameshot-0.6.0+git20191001/img/material/black/pin.svg000066400000000000000000000005501354471500100220310ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/redo-variant.png000066400000000000000000000005051354471500100236230ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATHiAᇸ`@h Va@S=( M (Ŏ ]77a3pt4J_gFi*$8"gC4PKнc+jE;,VaN4S4 "氐}<%C+# (I\{AJ!Tpr|-|Ouzi)H~ LIENDB`flameshot-0.6.0+git20191001/img/material/black/redo-variant.svg000066400000000000000000000003731354471500100236410ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/size_indicator.png000066400000000000000000000004071354471500100242370ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/black/size_indicator.svg000066400000000000000000000003251354471500100242510ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/square-outline.png000066400000000000000000000002571354471500100242110ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<`ԂQ F- *MU/ Q'T;PIENDB`flameshot-0.6.0+git20191001/img/material/black/square-outline.svg000066400000000000000000000001171354471500100242170ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/square.png000066400000000000000000000002351354471500100225300ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<*IDATHc`#?e8Z0j$5IENDB`flameshot-0.6.0+git20191001/img/material/black/square.svg000066400000000000000000000000761354471500100225460ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/text.png000066400000000000000000000001701354471500100222120ustar00rootroot00000000000000PNG  IHDR$$K P?IDATxc`40'6XPh2 LCӠQF 5h xS(?$n IENDB`flameshot-0.6.0+git20191001/img/material/black/text.svg000066400000000000000000000001651354471500100222310ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/black/undo-variant.png000066400000000000000000000004561354471500100236440ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/black/undo-variant.svg000066400000000000000000000003511354471500100236510ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/000077500000000000000000000000001354471500100205665ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/material/white/arrow-bottom-left.png000066400000000000000000000003431354471500100246600ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<pIDATH풻 0 v_e R0Q +% _꽳8w dU^s-_?5I@m-=[JɵcsBPěTQ8n^2q$| fIENDB`flameshot-0.6.0+git20191001/img/material/white/arrow-bottom-left.svg000066400000000000000000000001611354471500100246710ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/blur.png000066400000000000000000000002601354471500100222360ustar00rootroot00000000000000PNG  IHDRJ~swIDAT8c`2MXdN98>6SG 4?F' !n* GdHB 4a4\W TGH2iwZ:A4rqT^&IENDB`flameshot-0.6.0+git20191001/img/material/white/blur.svg000066400000000000000000000027511354471500100222600ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/circle-outline.png000066400000000000000000000007571354471500100242230ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/white/circle-outline.svg000066400000000000000000000003661354471500100242320ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/close.png000066400000000000000000000003661354471500100224060ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH1  )|X1!* Ų{w T?  \ X`1lp;ϵ9嬓cb;j>g/)$J%hȢTª0$"Dz3   IENDB`flameshot-0.6.0+git20191001/img/material/white/close.svg000066400000000000000000000002531354471500100224140ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/cloud-upload.png000066400000000000000000000005431354471500100236660ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/white/cloud-upload.svg000066400000000000000000000004001354471500100236710ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/colorize.png000066400000000000000000000005111354471500100231170ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATHұi@@ai9@3 YZ&@M>BDF:Tw+;K?آlH޻Oyw I@>)NrkA-?IENDB`flameshot-0.6.0+git20191001/img/material/white/colorize.svg000066400000000000000000000005051354471500100231350ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/config.png000066400000000000000000000005511354471500100225420ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/white/config.svg000066400000000000000000000004441354471500100225560ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/content-copy.png000066400000000000000000000003631354471500100237200ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH 0 q RqCIEB4"w䨮&"M1U[QnAa&t{7#* |&yLro vDea`˙) 69FnL7y IENDB`flameshot-0.6.0+git20191001/img/material/white/content-copy.svg000066400000000000000000000003121354471500100237250ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/content-save.png000066400000000000000000000004471354471500100237070ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH10 ECTꁸ+7YgzYR7A2IJK @?7 V4KLǍsk >$%YO[A zo?@M+xmWzUrRrQr:"-V+SуdOM+-#>ٜ("ݴGtizly}v:dIENDB`flameshot-0.6.0+git20191001/img/material/white/content-save.svg000066400000000000000000000003741354471500100237210ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/cursor-move.png000066400000000000000000000004151354471500100235550ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/white/cursor-move.svg000066400000000000000000000002761354471500100235750ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/exit-to-app.png000066400000000000000000000004521354471500100234440ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH풱 0Eψ m{d72#BELl),_5^-=]"shSY@ flameshot-0.6.0+git20191001/img/material/white/format-text.png000066400000000000000000000004131354471500100235440ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH픽 0FRfhH&63 AGs26\!ʺs3$7W@{o8$@z-@2;i8&3KZ^NHZ]Hh>VA@;E;f cf97m7xIENDB`flameshot-0.6.0+git20191001/img/material/white/format-text.svg000066400000000000000000000005301354471500100235570ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/format_bold.png000066400000000000000000000005141354471500100235640ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATH풱AECIDE!(7A(EQY1$=ռܙ\_5xr&Y):4NΟ$Efv)‘>]ӹZQ`}Id1}X><>}iֆU%ŒIrRs[)jJ$m*"E3ZA%%yj~5IENDB`flameshot-0.6.0+git20191001/img/material/white/format_bold.svg000066400000000000000000000005151354471500100236000ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/format_italic.png000066400000000000000000000004411354471500100241100ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATH 0DgC@(;p VU s&+!yRr;Z#UrFf_FQ#XIJtԘwI:Y 6=`ǛsQsh{kW rhf]y4ׯJe:1az1fIENDB`flameshot-0.6.0+git20191001/img/material/white/format_italic.svg000066400000000000000000000002301354471500100241170ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/format_strikethrough.png000066400000000000000000000003151354471500100255450ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<JIDATH; 9~bA7:DH[~ H-en<@V:7 *[ t`IENDB`flameshot-0.6.0+git20191001/img/material/white/format_strikethrough.svg000066400000000000000000000002361354471500100255620ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/format_underlined.png000066400000000000000000000004461354471500100250010ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATHA @ E+Xo(<4C7whn" N1Pa M&I:'7Ov^O)c5 u@0ρ^<8kh_ռ]@#5~ d)gZh W 8xJy2oWrK s#oK-̶7yIENDB`flameshot-0.6.0+git20191001/img/material/white/format_underlined.svg000066400000000000000000000003331354471500100250070ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/graphics.png000066400000000000000000000004151354471500100230740ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATHTA =?Zob$q^L0Ie%`:3r Ie^³xDGՐd.%>A/'h!-A(4BzZSu罃[}7uG`>P;؏$_'냺>;IENDB`flameshot-0.6.0+git20191001/img/material/white/graphics.svg000066400000000000000000000005221354471500100231060ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/line.png000066400000000000000000000003141354471500100222210ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<YIDATHӡ0D4A&`#@d[s)9P l*T'7> >'j@/|.pdHn7f?fe=IENDB`flameshot-0.6.0+git20191001/img/material/white/line.svg000066400000000000000000000002431354471500100222350ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/marker.png000066400000000000000000000005261354471500100225600ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/white/marker.svg000066400000000000000000000005331354471500100225710ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/mouse-off.svg000066400000000000000000000005371354471500100232140ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/mouse.svg000066400000000000000000000002771354471500100224450ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/name_edition.png000066400000000000000000000002471354471500100237320ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<4IDATHc``0 ?E22Da#a (ԒIENDB`flameshot-0.6.0+git20191001/img/material/white/name_edition.svg000066400000000000000000000001261354471500100237410ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/open_with.png000066400000000000000000000004441354471500100232720ustar00rootroot00000000000000PNG  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.6.0+git20191001/img/material/white/open_with.svg000066400000000000000000000022731354471500100233070ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/pencil.png000066400000000000000000000004171354471500100225500ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH퓱 04l` X 6H!2R!t4FXP#_e/[*`e-w@LJ4\?_BHyoZFwNR#i~HM }ˋ>A`Gw3y$`+Ϥx8^`QIENDB`flameshot-0.6.0+git20191001/img/material/white/pencil.svg000066400000000000000000000003211354471500100225550ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/pin.png000066400000000000000000000003461354471500100220650ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs+tEXtSoftwarewww.inkscape.org<cIDATHA c矦@iI {%A.S&fϕ(04NM/mHP,mdܟ@c^.Ľ5r.zR:3=?@I:IENDB`flameshot-0.6.0+git20191001/img/material/white/pin.svg000066400000000000000000000005411354471500100220750ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/redo-variant.png000066400000000000000000000004751354471500100236750ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH 0EZp;PBA*]A=\Ů hccHzB˽ 5YqW`_ArJ%H8,zsNtR - p"o*|cr 4^\qgrr8|Cr ]_ࣖAiNQ(dtb=D* Jv_ lG&v8IENDB`flameshot-0.6.0+git20191001/img/material/white/redo-variant.svg000066400000000000000000000004071354471500100237030ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/size_indicator.png000066400000000000000000000004241354471500100243020ustar00rootroot00000000000000PNG  IHDR``HIDATx10na @Y 8 ]wĶnľV>U^jjT}n[WS! BBom̟};bfeɐl4 Ӏ֞@@@@@p\ T4U4tzɭ>&u*}RT_ }85˞}'&iIENDB`flameshot-0.6.0+git20191001/img/material/white/size_indicator.svg000066400000000000000000000003411354471500100243130ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/square-outline.png000066400000000000000000000002701354471500100242500ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<EIDATHc`#2b(##\&jr)[Z0j):` H $&`{IENDB`flameshot-0.6.0+git20191001/img/material/white/square-outline.svg000066400000000000000000000001331354471500100242610ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/square.png000066400000000000000000000002451354471500100225750ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<2IDATHc`#2b(##\&jZ0jZ0j( Fe$w*IENDB`flameshot-0.6.0+git20191001/img/material/white/square.svg000066400000000000000000000001121354471500100226010ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/text.png000066400000000000000000000001711354471500100222570ustar00rootroot00000000000000PNG  IHDR$$K P@IDATxc`oO,h9o@ 80s05MF 5hԠQ%NE`IENDB`flameshot-0.6.0+git20191001/img/material/white/text.svg000066400000000000000000000001251354471500100222710ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/material/white/undo-variant.png000066400000000000000000000004601354471500100237030ustar00rootroot00000000000000PNG  IHDRw= pHYsodtEXtSoftwarewww.inkscape.org<IDATH 0CT)U*ݡ8+B^M=/!\fxCf_ wpf[{Ջz 4Nj`[$ `AvH<7@\tPڵ^$ZsZLb2!7*6%p6t('IENDB`flameshot-0.6.0+git20191001/img/material/white/undo-variant.svg000066400000000000000000000003651354471500100237220ustar00rootroot00000000000000 flameshot-0.6.0+git20191001/img/preview/000077500000000000000000000000001354471500100173315ustar00rootroot00000000000000flameshot-0.6.0+git20191001/img/preview/animatedUsage.gif000066400000000000000000012102101354471500100225640ustar00rootroot00000000000000GIF89ah  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.6.0+git20191001/img/preview/usageStatic.png000066400000000000000000002356251354471500100223300ustar00rootroot00000000000000PNG  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.6.0+git20191001/rpm/000077500000000000000000000000001354471500100156725ustar00rootroot00000000000000flameshot-0.6.0+git20191001/rpm/flameshot.spec000066400000000000000000000035401354471500100205320ustar00rootroot00000000000000Name: flameshot Version: 0.6.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: qt5-qtsvg-devel BuildRequires: git Requires: qt5-qtbase >= 5.3.0 Requires: qt5-qttools Requires: qt5-qtsvg %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}/bash-completion/completions/%{name} %{_datadir}/icons/hicolor %changelog * Sat Aug 18 2018 Zetao Yang - 0.6.0-1 - Updated for flameshot 0.6.0 - More details, please see https://flameshot.js.org/#/changelog?id=v060 * Tue Jan 09 2018 Zetao Yang - 0.5.0-1 - Initial package for flameshot 0.5.0 - More details, please see https://flameshot.js.org/#/changelog?id=v051 flameshot-0.6.0+git20191001/src/000077500000000000000000000000001354471500100156635ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/cli/000077500000000000000000000000001354471500100164325ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/cli/commandargument.cpp000066400000000000000000000030651354471500100223230ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/cli/commandargument.h000066400000000000000000000023351354471500100217670ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/cli/commandlineparser.cpp000066400000000000000000000303171354471500100226450ustar00rootroot00000000000000// Copyright(c) 2017-2019 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"}, QStringLiteral("Displays version information")); auto helpOption = CommandOption({"h", "help"}, QStringLiteral("Displays this help")); 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 = option.dashedNames(); QString joinedDashedOptions = dashedOptions.join(QStringLiteral(", ")); 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 += QLatin1String("Options:\n"); QString linePadding = QStringLiteral(" ").repeated(size + 4).prepend("\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() .replace(QLatin1String("\n"), linePadding)); } if (!arguments.isEmpty()) { result += QLatin1String("\n"); } } if (!arguments.isEmpty()) { result += QLatin1String("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(QLatin1String("=")); 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(QLatin1String("--")); 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(QLatin1String("."))) err += QLatin1String("."); 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 = versionOption.dashedNames(); 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(QLatin1String("-"))) { 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 = option.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(QStringLiteral(" "))) .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 = helpOption.dashedNames(); 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.6.0+git20191001/src/cli/commandlineparser.h000066400000000000000000000061701354471500100223120ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 { explicit 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.6.0+git20191001/src/cli/commandoption.cpp000066400000000000000000000063671354471500100220210ustar00rootroot00000000000000// Copyright(c) 2017-2019 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; } QStringList CommandOption::dashedNames() const { QStringList dashedNames; for (const QString &name: m_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; } 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 = QLatin1String("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.6.0+git20191001/src/cli/commandoption.h000066400000000000000000000040141354471500100214510ustar00rootroot00000000000000// Copyright(c) 2017-2019 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; QStringList dashedNames() 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.6.0+git20191001/src/config/000077500000000000000000000000001354471500100171305ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/config/buttonlistview.cpp000066400000000000000000000073441354471500100227460ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/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()); m_buttonItem->setIcon(tool->icon(bgColor, false)); 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); // TODO refactor so we don't need external sorts using bt = CaptureButton::ButtonType; std::sort(m_listButtons.begin(), m_listButtons.end(), [](bt a, bt b){ return CaptureButton::getPriorityByButton(a) < CaptureButton::getPriorityByButton(b); }); } 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.6.0+git20191001/src/config/buttonlistview.h000066400000000000000000000024521354471500100224060ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/widgets/capture/capturebutton.h" #include class ButtonListView : public QListWidget { public: explicit 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.6.0+git20191001/src/config/clickablelabel.cpp000066400000000000000000000020361354471500100225460ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 *) { emit clicked(); } flameshot-0.6.0+git20191001/src/config/clickablelabel.h000066400000000000000000000020611354471500100222110ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/config/configwindow.cpp000066400000000000000000000062461354471500100223410ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/utils/colorutils.h" #include "src/utils/confighandler.h" #include "src/utils/pathinfo.h" #include "src/widgets/capture/capturebutton.h" #include "src/config/geneneralconf.h" #include "src/config/filenameeditor.h" #include "src/config/strftimechooserwidget.h" #include "src/config/visualseditor.h" #include "src/utils/globalvalues.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 = GlobalValues::buttonBaseSize() * 12; setMinimumSize(size, size); setWindowIcon(QIcon(":img/app/flameshot.svg")); setWindowTitle(tr("Configuration")); auto changedSlot = [this](QString s){ QStringList files = m_configWatcher->files(); if (!files.contains(s)) { this->m_configWatcher->addPath(s); } 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 isDark = ColorUtils::colorIsDark(background); QString modifier = isDark ? PathInfo::whiteIconPath() : PathInfo::blackIconPath(); // visuals m_visuals = new VisualsEditor(); addTab(m_visuals, QIcon(modifier + "graphics.svg"), tr("Interface")); // filename m_filenameEditor = new FileNameEditor(); addTab(m_filenameEditor, QIcon(modifier + "name_edition.svg"), tr("Filename Editor")); // general m_generalConfig = new GeneneralConf(); addTab(m_generalConfig, QIcon(modifier + "config.svg"), 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.6.0+git20191001/src/config/configwindow.h000066400000000000000000000023651354471500100220040ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/config/extendedslider.cpp000066400000000000000000000033641354471500100226450ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/config/extendedslider.h000066400000000000000000000022331354471500100223040ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/config/filenameeditor.cpp000066400000000000000000000101641354471500100226250ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/config/filenameeditor.h000066400000000000000000000030421354471500100222670ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/config/geneneralconf.cpp000066400000000000000000000176621354471500100224560ustar00rootroot00000000000000// Copyright(c) 2017-2019 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(); initCloseAfterCapture(); initCopyAndCloseAfterUpload(); // 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()); m_closeAfterCapture->setChecked(config.closeAfterScreenshotValue()); m_copyAndCloseAfterUpload->setChecked(config.copyAndCloseAfterUploadEnabled()); #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) 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::closeAfterCaptureChanged(bool checked) { ConfigHandler().setCloseAfterScreenshot(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"), QStringLiteral("flameshot.conf")); // Cancel button if (fileName.isNull()) { return; } QFile targetFile(fileName); if (targetFile.exists()) { targetFile.remove(); } 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() { #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) 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::stateChanged, 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); } void GeneneralConf::initCloseAfterCapture() { m_closeAfterCapture = new QCheckBox(tr("Close after capture"), this); ConfigHandler config; bool checked = config.closeAfterScreenshotValue(); m_closeAfterCapture->setChecked(checked); m_closeAfterCapture->setToolTip(tr("Close after taking a screenshot")); m_layout->addWidget(m_closeAfterCapture); connect(m_closeAfterCapture, &QCheckBox::clicked, this, &GeneneralConf::closeAfterCaptureChanged); } void GeneneralConf::initCopyAndCloseAfterUpload() { m_copyAndCloseAfterUpload = new QCheckBox(tr("Copy URL after upload"), this); ConfigHandler config; m_copyAndCloseAfterUpload->setChecked(config.copyAndCloseAfterUploadEnabled()); m_copyAndCloseAfterUpload->setToolTip(tr("Copy URL and close window after upload")); m_layout->addWidget(m_copyAndCloseAfterUpload); connect(m_copyAndCloseAfterUpload, &QCheckBox::clicked, [](bool checked) { ConfigHandler().setCopyAndCloseAfterUploadEnabled(checked); }); }flameshot-0.6.0+git20191001/src/config/geneneralconf.h000066400000000000000000000036101354471500100221070ustar00rootroot00000000000000// Copyright(c) 2017-2019 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: explicit 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 closeAfterCaptureChanged(bool checked); void importConfiguration(); void exportFileConfiguration(); void resetConfiguration(); private: QVBoxLayout *m_layout; QCheckBox *m_sysNotifications; QCheckBox *m_showTray; QCheckBox *m_helpMessage; QCheckBox *m_autostart; QCheckBox *m_closeAfterCapture; QCheckBox *m_copyAndCloseAfterUpload; QPushButton *m_importButton; QPushButton *m_exportButton; QPushButton *m_resetButton; void initShowHelp(); void initShowDesktopNotification(); void initShowTrayIcon(); void initConfingButtons(); void initAutostart(); void initCloseAfterCapture(); void initCopyAndCloseAfterUpload(); }; flameshot-0.6.0+git20191001/src/config/strftimechooserwidget.cpp000066400000000000000000000056251354471500100242700ustar00rootroot00000000000000// Copyright(c) 2017-2019 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](){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.6.0+git20191001/src/config/strftimechooserwidget.h000066400000000000000000000020441354471500100237250ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/config/uicoloreditor.cpp000066400000000000000000000141451354471500100225240ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "src/utils/globalvalues.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 = GlobalValues::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 = GlobalValues::buttonBaseSize() / 3; int frameSize = GlobalValues::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(QStringLiteral("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 changes 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(QStringLiteral("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.6.0+git20191001/src/config/uicoloreditor.h000066400000000000000000000033171354471500100221700ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/widgets/capture/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.6.0+git20191001/src/config/visualseditor.cpp000066400000000000000000000061531354471500100225360ustar00rootroot00000000000000// Copyright(c) 2017-2019 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->setFocusPolicy(Qt::NoFocus); 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(QStringLiteral("0%"))); localLayout->addWidget(m_opacitySlider); localLayout->addWidget(new QLabel(QStringLiteral("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.6.0+git20191001/src/config/visualseditor.h000066400000000000000000000024231354471500100221770ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/core/000077500000000000000000000000001354471500100166135ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/core/capturerequest.cpp000066400000000000000000000047151354471500100224020ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "capturerequest.h" #include "src/utils/screenshotsaver.h" #include #include CaptureRequest::CaptureRequest(CaptureRequest::CaptureMode mode, const uint delay, const QString &path, const QVariant &data, CaptureRequest::ExportTask tasks) : m_mode(mode), m_delay(delay), m_path(path), m_tasks(tasks), m_data(data), m_forcedID(false), m_id(0) { } void CaptureRequest::setStaticID(uint id) { m_forcedID = true; m_id = id; } uint CaptureRequest::id() const { if (m_forcedID) { return m_id; } uint id = 0; QVectorv; v << qHash(m_mode) << qHash(m_delay * QDateTime::currentMSecsSinceEpoch()) << qHash(m_path) << qHash(m_tasks) << m_data.toInt(); for(uint i : v) { id ^= i + 0x9e3779b9 + (id << 6) + (id >> 2); } return id; } CaptureRequest::CaptureMode CaptureRequest::captureMode() const { return m_mode; } uint CaptureRequest::delay() const { return m_delay; } QString CaptureRequest::path() const { return m_path; } QVariant CaptureRequest::data() const { return m_data; } void CaptureRequest::addTask(CaptureRequest::ExportTask task) { m_tasks |= task; } void CaptureRequest::exportCapture(const QPixmap &p) { if ((m_tasks & ExportTask::FILESYSTEM_SAVE_TASK) != ExportTask::NO_TASK) { if (m_path.isEmpty()) { ScreenshotSaver().saveToFilesystemGUI(p); } else { ScreenshotSaver().saveToFilesystem(p, m_path); } } if ((m_tasks & ExportTask::CLIPBOARD_SAVE_TASK) != ExportTask::NO_TASK) { ScreenshotSaver().saveToClipboard(p); } } flameshot-0.6.0+git20191001/src/core/capturerequest.h000066400000000000000000000042301354471500100220370ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 CaptureRequest { public: enum CaptureMode { FULLSCREEN_MODE, GRAPHICAL_MODE, SCREEN_MODE, }; enum ExportTask { NO_TASK = 0, CLIPBOARD_SAVE_TASK = 1, FILESYSTEM_SAVE_TASK = 2, }; CaptureRequest(CaptureMode mode, const uint delay = 0, const QString &path = QLatin1String(""), const QVariant &data = QVariant(), ExportTask tasks = NO_TASK); void setStaticID(uint id); uint id() const; uint delay() const; QString path() const; QVariant data() const; CaptureMode captureMode() const; void addTask(ExportTask task); void exportCapture(const QPixmap &p); private: CaptureMode m_mode; uint m_delay; QString m_path; ExportTask m_tasks; QVariant m_data; bool m_forcedID; uint m_id; }; using eTask = CaptureRequest::ExportTask; inline eTask operator|(const eTask &a, const eTask &b) { return static_cast(static_cast(a) | static_cast(b)); } inline eTask operator&(const eTask &a, const eTask &b) { return static_cast(static_cast(a) & static_cast(b)); } inline eTask& operator|=(eTask &a, const eTask &b) { a = static_cast(static_cast(a) | static_cast(b)); return a; } flameshot-0.6.0+git20191001/src/core/controller.cpp000066400000000000000000000206501354471500100215050ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/widgets/capture/capturewidget.h" #include "src/utils/confighandler.h" #include "src/widgets/infowindow.h" #include "src/config/configwindow.h" #include "src/widgets/capture/capturebutton.h" #include "src/widgets/capturelauncher.h" #include "src/utils/systemnotification.h" #include "src/utils/screengrabber.h" #include #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) || defined(Q_OS_UNIX) 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->requestCapture(CaptureRequest(CaptureRequest::GRAPHICAL_MODE)); }); #endif QString StyleSheet = CaptureButton::globalStyleSheet(); qApp->setStyleSheet(StyleSheet); } Controller *Controller::getInstance() { static Controller c; return &c; } void Controller::enableExports() { connect(this, &Controller::captureTaken, this, &Controller::handleCaptureTaken); connect(this, &Controller::captureFailed, this, &Controller::handleCaptureFailed); } void Controller::requestCapture(const CaptureRequest &request) { uint id = request.id(); m_requestMap.insert(id, request); switch (request.captureMode()) { case CaptureRequest::FULLSCREEN_MODE: doLater(request.delay(), this, [this, id](){ this->startFullscreenCapture(id); }); break; case CaptureRequest::SCREEN_MODE: { int &&number = request.data().toInt(); doLater(request.delay(), this, [this, id, number](){ this->startScreenGrab(id, number); }); break; } case CaptureRequest::GRAPHICAL_MODE: { QString &&path = request.path(); doLater(request.delay(), this, [this, id, path](){ this->startVisualCapture(id, path); }); break; } default: emit captureFailed(id); break; } } // creation of a new capture in GUI mode void Controller::startVisualCapture(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); //m_captureWindow = new CaptureWidget(id, forcedSavePath, false); // debug 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(); //m_captureWindow->show(); // Debug #endif } else { emit captureFailed(id); } } void Controller::startScreenGrab(const uint id, const int screenNumber) { bool ok = true; int n = screenNumber; if (n < 0) { QPoint globalCursorPos = QCursor::pos(); n = qApp->desktop()->screenNumber(globalCursorPos); } QPixmap p(ScreenGrabber().grabScreen(n, ok)); if (ok) { emit captureTaken(id, p); } else { emit captureFailed(id); } } // 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::openLauncherWindow() { CaptureLauncher *w = new CaptureLauncher(); w->show(); } void Controller::enableTrayIcon() { if (m_trayIcon) { return; } ConfigHandler().setDisabledTrayIcon(false); QAction *captureAction = new QAction(tr("&Take Screenshot"), this); connect(captureAction, &QAction::triggered, this, [this](){ // Wait 400 ms to hide the QMenu doLater(400, this, [this](){ this->startVisualCapture(); }); }); QAction *launcherAction = new QAction(tr("&Open Launcher"), this); connect(launcherAction, &QAction::triggered, this, &Controller::openLauncherWindow); 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(captureAction); trayIconMenu->addAction(launcherAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(configAction); trayIconMenu->addAction(infoAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(quitAction); m_trayIcon = new QSystemTrayIcon(); m_trayIcon->setToolTip(QStringLiteral("Flameshot")); m_trayIcon->setContextMenu(trayIconMenu); QIcon trayicon = QIcon::fromTheme("flameshot-tray", QIcon(":img/app/flameshot.png")); m_trayIcon->setIcon(trayicon); auto trayIconActivated = [this](QSystemTrayIcon::ActivationReason r){ if (r == QSystemTrayIcon::Trigger) { startVisualCapture(); } }; connect(m_trayIcon, &QSystemTrayIcon::activated, this, trayIconActivated); m_trayIcon->show(); } void Controller::disableTrayIcon() { #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) 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(); } } void Controller::startFullscreenCapture(const uint id) { bool ok = true; QPixmap p(ScreenGrabber().grabEntireDesktop(ok)); if (ok) { emit captureTaken(id, p); } else { emit captureFailed(id); } } void Controller::handleCaptureTaken(uint id, QPixmap p) { auto it = m_requestMap.find(id); if (it != m_requestMap.end()) { it.value().exportCapture(p); m_requestMap.erase(it); } if (ConfigHandler().closeAfterScreenshotValue()) { QApplication::quit(); } } void Controller::handleCaptureFailed(uint id) { m_requestMap.remove(id); if (ConfigHandler().closeAfterScreenshotValue()) { QApplication::quit(); } } void Controller::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(); } flameshot-0.6.0+git20191001/src/core/controller.h000066400000000000000000000050211354471500100211450ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/core/capturerequest.h" #include #include #include #include #include #include class CaptureWidget; class ConfigWindow; class InfoWindow; class QSystemTrayIcon; using lambda = std::function; class Controller : public QObject { Q_OBJECT public: static Controller* getInstance(); Controller(const Controller&) = delete; void operator =(const Controller&) = delete; void enableExports(); signals: void captureTaken(uint id, QPixmap p); void captureFailed(uint id); public slots: void requestCapture(const CaptureRequest &request); void openConfigWindow(); void openInfoWindow(); void openLauncherWindow(); void enableTrayIcon(); void disableTrayIcon(); void sendTrayNotification(const QString &text, const QString &title = QStringLiteral("Flameshot Info"), const int timeout = 5000); void updateConfigComponents(); private slots: void startFullscreenCapture(const uint id = 0); void startVisualCapture(const uint id = 0, const QString &forcedSavePath = QString()); void startScreenGrab(const uint id = 0, const int screenNumber = -1); void handleCaptureTaken(uint id, QPixmap p); void handleCaptureFailed(uint id); private: Controller(); // replace QTimer::singleShot introduced in Qt 5.4 // the actual target Qt version is 5.3 void doLater(int msec, QObject *receiver, lambda func); QMap m_requestMap; QPointer m_captureWindow; QPointer m_infoWindow; QPointer m_configWindow; QPointer m_trayIcon; }; flameshot-0.6.0+git20191001/src/core/flameshotdbusadapter.cpp000066400000000000000000000067641354471500100235350ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/utils/screenshotsaver.h" #include "src/utils/systemnotification.h" #include FlameshotDBusAdapter::FlameshotDBusAdapter(QObject *parent) : QDBusAbstractAdaptor(parent) { auto controller = Controller::getInstance(); connect(controller, &Controller::captureFailed, this, &FlameshotDBusAdapter::captureFailed); connect(controller, &Controller::captureTaken, this, &FlameshotDBusAdapter::handleCaptureTaken); } FlameshotDBusAdapter::~FlameshotDBusAdapter() { } void FlameshotDBusAdapter::graphicCapture(QString path, int delay, uint id) { CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path); // if (toClipboard) { // req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK); // } req.setStaticID(id); Controller::getInstance()->requestCapture(req); } void FlameshotDBusAdapter::fullScreen( QString path, bool toClipboard, int delay, uint id) { CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay, path); if (toClipboard) { req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK); } if (!path.isEmpty()) { req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK); } req.setStaticID(id); Controller::getInstance()->requestCapture(req); } void FlameshotDBusAdapter::openLauncher() { Controller::getInstance()->openLauncherWindow(); } void FlameshotDBusAdapter::captureScreen(int number, QString path, bool toClipboard, int delay, uint id) { CaptureRequest req(CaptureRequest::SCREEN_MODE, delay, path, number); if (toClipboard) { req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK); } if (!path.isEmpty()) { req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK); } req.setStaticID(id); Controller::getInstance()->requestCapture(req); } void FlameshotDBusAdapter::openConfig() { Controller::getInstance()->openConfigWindow(); } void FlameshotDBusAdapter::trayIconEnabled(bool enabled) { auto controller = Controller::getInstance(); if (enabled) { controller->enableTrayIcon(); } else { controller->disableTrayIcon(); } } void FlameshotDBusAdapter::autostartEnabled(bool enabled) { ConfigHandler().setStartupLaunch(enabled); auto controller = Controller::getInstance(); // Autostart is not saved in a .ini file, requires manual update controller->updateConfigComponents(); } void FlameshotDBusAdapter::handleCaptureTaken(uint id, const QPixmap &p) { QByteArray byteArray; QBuffer buffer(&byteArray); p.save(&buffer, "PNG"); emit captureTaken(id, byteArray); } flameshot-0.6.0+git20191001/src/core/flameshotdbusadapter.h000066400000000000000000000032621354471500100231700ustar00rootroot00000000000000// Copyright(c) 2017-2019 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: explicit 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 captureScreen(int number, QString path, bool toClipboard, int delay, uint id); Q_NOREPLY void openLauncher(); Q_NOREPLY void openConfig(); Q_NOREPLY void trayIconEnabled(bool enabled); Q_NOREPLY void autostartEnabled(bool enabled); private slots: void handleCaptureTaken(uint id, const QPixmap &p); }; flameshot-0.6.0+git20191001/src/core/globalshortcutfilter.cpp000066400000000000000000000033041354471500100235610ustar00rootroot00000000000000// Copyright(c) 2017-2019 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()->requestCapture( CaptureRequest(CaptureRequest::GRAPHICAL_MODE)); return true; } return false; } flameshot-0.6.0+git20191001/src/core/globalshortcutfilter.h000066400000000000000000000025561354471500100232360ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 = nullptr); 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.6.0+git20191001/src/imgur.pri000066400000000000000000000003111354471500100175150ustar00rootroot00000000000000# Use default Imgur client_id if user did not pass # this variable to qmake isEmpty(IMGUR_CLIENT_ID) { IMGUR_CLIENT_ID = "313baf0c7b4d3ff" } DEFINES += IMGUR_CLIENT_ID=\\\"$${IMGUR_CLIENT_ID}\\\" flameshot-0.6.0+git20191001/src/main.cpp000066400000000000000000000453631354471500100173260ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "src/core/capturerequest.h" #include #include #include #include #include #include #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) #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, qtTranslator; QStringList trPaths = PathInfo::translationsPaths(); for (const QString &path: trPaths) { bool match = translator.load(QLocale(), QStringLiteral("Internationalization"), QStringLiteral("_"), path); if (match) { break; } } qtTranslator.load(QLocale::system(), "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath)); app.installTranslator(&translator); app.installTranslator(&qtTranslator); app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); app.setApplicationName(QStringLiteral("flameshot")); app.setOrganizationName(QStringLiteral("Dharkael")); auto c = Controller::getInstance(); #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) new FlameshotDBusAdapter(c); QDBusConnection dbus = QDBusConnection::sessionBus(); if (!dbus.isConnected()) { SystemNotification().sendMessage( QObject::tr("Unable to connect via DBus")); } dbus.registerObject(QStringLiteral("/"), c); dbus.registerService(QStringLiteral("org.dharkael.Flameshot")); #endif // Exporting captures must be connected after the dbus interface // or the dbus signal gets blocked until we end the exports. c->enableExports(); return app.exec(); } #ifndef Q_OS_WIN /*--------------| * CLI parsing | * ------------*/ QCoreApplication app(argc, argv); app.setApplicationName(QStringLiteral("flameshot")); app.setOrganizationName(QStringLiteral("Dharkael")); app.setApplicationVersion(qApp->applicationVersion()); CommandLineParser parser; // Add description parser.setDescription( QStringLiteral("Powerful yet simple to use screenshot software.")); parser.setGeneralErrorMessage(QStringLiteral("See 'flameshot --help'.")); // Arguments CommandArgument fullArgument(QStringLiteral("full"), QStringLiteral("Capture the entire desktop.")); CommandArgument launcherArgument(QStringLiteral("launcher"), QStringLiteral("Open the capture launcher.")); CommandArgument guiArgument(QStringLiteral("gui"), QStringLiteral("Start a manual capture in GUI mode.")); CommandArgument configArgument(QStringLiteral("config"), QStringLiteral("Configure flameshot.")); CommandArgument screenArgument(QStringLiteral("screen"), QStringLiteral("Capture a single screen.")); // Options CommandOption pathOption( {"p", "path"}, QStringLiteral("Path where the capture will be saved"), QStringLiteral("path")); CommandOption clipboardOption( {"c", "clipboard"}, QStringLiteral("Save the capture to the clipboard")); CommandOption delayOption( {"d", "delay"}, QStringLiteral("Delay time in milliseconds"), QStringLiteral("milliseconds")); CommandOption filenameOption( {"f", "filename"}, QStringLiteral("Set the filename pattern"), QStringLiteral("pattern")); CommandOption trayOption( {"t", "trayicon"}, QStringLiteral("Enable or disable the trayicon"), QStringLiteral("bool")); CommandOption autostartOption( {"a", "autostart"}, QStringLiteral("Enable or disable run at startup"), QStringLiteral("bool")); CommandOption showHelpOption( {"s", "showhelp"}, QStringLiteral("Show the help message in the capture mode"), QStringLiteral("bool")); CommandOption mainColorOption( {"m", "maincolor"}, QStringLiteral("Define the main UI color"), QStringLiteral("color-code")); CommandOption contrastColorOption( {"k", "contrastcolor"}, QStringLiteral("Define the contrast UI color"), QStringLiteral("color-code")); CommandOption rawImageOption( {"r", "raw"}, QStringLiteral("Print raw PNG capture")); CommandOption screenNumberOption( {"n", "number"}, QStringLiteral("Define the screen to capture,\ndefault: screen containing the cursor"), QStringLiteral("Screen number"), QStringLiteral("-1")); // Add checkers auto colorChecker = [](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 = QStringLiteral("Invalid delay, it must be higher than 0"); const QString numberErr = QStringLiteral("Invalid screen number, it must be non negative"); auto numericChecker = [](const QString &delayValue) -> bool { int value = delayValue.toInt(); return value >= 0; }; const QString pathErr = QStringLiteral("Invalid path, it must be a real path in the system"); auto pathChecker = [pathErr](const QString &pathValue) -> bool { bool res = QDir(pathValue).exists(); if (!res) { SystemNotification().sendMessage(QObject::tr(pathErr.toLatin1().data())); } return res; }; const QString booleanErr = QStringLiteral("Invalid value, it must be defined as 'true' or 'false'"); auto booleanChecker = [](const QString &value) -> bool { return value == QLatin1String("true") || value == QLatin1String("false"); }; contrastColorOption.addChecker(colorChecker, colorErr); mainColorOption.addChecker(colorChecker, colorErr); delayOption.addChecker(numericChecker, delayErr); pathOption.addChecker(pathChecker, pathErr); trayOption.addChecker(booleanChecker, booleanErr); autostartOption.addChecker(booleanChecker, booleanErr); showHelpOption.addChecker(booleanChecker, booleanErr); screenNumberOption.addChecker(numericChecker, numberErr); // Relationships parser.AddArgument(guiArgument); parser.AddArgument(screenArgument); parser.AddArgument(fullArgument); parser.AddArgument(launcherArgument); parser.AddArgument(configArgument); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); parser.AddOptions({ pathOption, delayOption, rawImageOption }, guiArgument); parser.AddOptions({ screenNumberOption, clipboardOption, pathOption, delayOption, rawImageOption }, screenArgument); parser.AddOptions({ pathOption, clipboardOption, delayOption, rawImageOption }, fullArgument); parser.AddOptions({ autostartOption, 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(launcherArgument)) { // LAUNCHER QDBusMessage m = QDBusMessage::createMethodCall(QStringLiteral("org.dharkael.Flameshot"), QStringLiteral("/"), QLatin1String(""), QStringLiteral("openLauncher")); QDBusConnection sessionBus = QDBusConnection::sessionBus(); if (!sessionBus.isConnected()) { SystemNotification().sendMessage( QObject::tr("Unable to connect via DBus")); } sessionBus.call(m); } else if (parser.isSet(guiArgument)) { // GUI QString pathValue = parser.value(pathOption); int delay = parser.value(delayOption).toInt(); bool isRaw = parser.isSet(rawImageOption); DBusUtils dbusUtils; CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, pathValue); uint id = req.id(); // Send message QDBusMessage m = QDBusMessage::createMethodCall(QStringLiteral("org.dharkael.Flameshot"), QStringLiteral("/"), QLatin1String(""), QStringLiteral("graphicCapture")); m << pathValue << delay << id; QDBusConnection sessionBus = QDBusConnection::sessionBus(); dbusUtils.checkDBusConnection(sessionBus); sessionBus.call(m); if (isRaw) { dbusUtils.connectPrintCapture(sessionBus, id); QTimer t; t.setInterval(delay + 1000 * 60 * 15); // 15 minutes timeout QObject::connect(&t, &QTimer::timeout, qApp, &QCoreApplication::quit); t.start(); // wait return 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 out(stdout); out << "Invalid format, set where to save the content with one of " << "the following flags:\n " << pathOption.dashedNames().join(QStringLiteral(", ")) << "\n " << rawImageOption.dashedNames().join(QStringLiteral(", ")) << "\n " << clipboardOption.dashedNames().join(QStringLiteral(", ")) << "\n\n"; parser.parse(QStringList() << argv[0] << QStringLiteral("full") << QStringLiteral("-h")); goto finish; } CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay, pathValue); if (toClipboard) { req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK); } if (!pathValue.isEmpty()) { req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK); } uint id = req.id(); DBusUtils dbusUtils; // Send message QDBusMessage m = QDBusMessage::createMethodCall(QStringLiteral("org.dharkael.Flameshot"), QStringLiteral("/"), QLatin1String(""), QStringLiteral("fullScreen")); m << pathValue << toClipboard << delay << id; QDBusConnection sessionBus = QDBusConnection::sessionBus(); dbusUtils.checkDBusConnection(sessionBus); sessionBus.call(m); if (isRaw) { dbusUtils.connectPrintCapture(sessionBus, id); // timeout just in case QTimer t; t.setInterval(delay + 2000); QObject::connect(&t, &QTimer::timeout, qApp, &QCoreApplication::quit); t.start(); // wait return app.exec(); } } else if (parser.isSet(screenArgument)) { // SCREEN QString numberStr = parser.value(screenNumberOption); int number = numberStr.startsWith(QLatin1String("-")) ? -1 : numberStr.toInt(); 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 out(stdout); out << "Invalid format, set where to save the content with one of " << "the following flags:\n " << pathOption.dashedNames().join(QStringLiteral(", ")) << "\n " << rawImageOption.dashedNames().join(QStringLiteral(", ")) << "\n " << clipboardOption.dashedNames().join(QStringLiteral(", ")) << "\n\n"; parser.parse(QStringList() << argv[0] << QStringLiteral("screen") << QStringLiteral("-h")); goto finish; } CaptureRequest req(CaptureRequest::SCREEN_MODE, delay, pathValue, number); if (toClipboard) { req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK); } if (!pathValue.isEmpty()) { req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK); } uint id = req.id(); DBusUtils dbusUtils; // Send message QDBusMessage m = QDBusMessage::createMethodCall(QStringLiteral("org.dharkael.Flameshot"), QStringLiteral("/"), QLatin1String(""), QStringLiteral("captureScreen")); m << number << pathValue << toClipboard << delay << id; QDBusConnection sessionBus = QDBusConnection::sessionBus(); dbusUtils.checkDBusConnection(sessionBus); sessionBus.call(m); if (isRaw) { dbusUtils.connectPrintCapture(sessionBus, id); // timeout just in case QTimer t; t.setInterval(delay + 2000); QObject::connect(&t, &QTimer::timeout, qApp, &QCoreApplication::quit); t.start(); // wait return app.exec(); } } else if (parser.isSet(configArgument)) { // CONFIG bool autostart = parser.isSet(autostartOption); 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 (autostart) { QDBusMessage m = QDBusMessage::createMethodCall(QStringLiteral("org.dharkael.Flameshot"), QStringLiteral("/"), QLatin1String(""), QStringLiteral("autostartEnabled")); if (parser.value(autostartOption) == QLatin1String("false")) { m << false; } else if (parser.value(autostartOption) == QLatin1String("true")) { m << true; } QDBusConnection sessionBus = QDBusConnection::sessionBus(); if (!sessionBus.isConnected()) { SystemNotification().sendMessage( QObject::tr("Unable to connect via DBus")); } sessionBus.call(m); } 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(QStringLiteral("org.dharkael.Flameshot"), QStringLiteral("/"), QLatin1String(""), QStringLiteral("trayIconEnabled")); if (parser.value(trayOption) == QLatin1String("false")) { m << false; } else if (parser.value(trayOption) == QLatin1String("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) == QLatin1String("false")) { config.setShowHelp(false); } else if (parser.value(showHelpOption) == QLatin1String("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(QStringLiteral("org.dharkael.Flameshot"), QStringLiteral("/"), QLatin1String(""), QStringLiteral("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.6.0+git20191001/src/third-party/000077500000000000000000000000001354471500100201325ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/third-party/Qt-Color-Widgets/000077500000000000000000000000001354471500100231765ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/third-party/Qt-Color-Widgets/COPYING000066400000000000000000000167431354471500100242440ustar00rootroot00000000000000 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.6.0+git20191001/src/third-party/Qt-Color-Widgets/LICENSE-EXCEPTION000066400000000000000000000016641354471500100255460ustar00rootroot00000000000000Linking 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.6.0+git20191001/src/third-party/Qt-Color-Widgets/README.md000066400000000000000000000043521354471500100244610ustar00rootroot00000000000000Color 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.6.0+git20191001/src/third-party/Qt-Color-Widgets/color_widgets.pri000066400000000000000000000017061354471500100265620ustar00rootroot00000000000000# 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.6.0+git20191001/src/third-party/Qt-Color-Widgets/color_widgets.pro000066400000000000000000000023741354471500100265720ustar00rootroot00000000000000# # 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.6.0+git20191001/src/third-party/Qt-Color-Widgets/include/000077500000000000000000000000001354471500100246215ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/third-party/Qt-Color-Widgets/include/ColorWheel000066400000000000000000000000331354471500100266030ustar00rootroot00000000000000#include "color_wheel.hpp" flameshot-0.6.0+git20191001/src/third-party/Qt-Color-Widgets/include/color_wheel.hpp000066400000000000000000000120441354471500100276350ustar00rootroot00000000000000/** * \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 = nullptr); ~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.6.0+git20191001/src/third-party/Qt-Color-Widgets/src/000077500000000000000000000000001354471500100237655ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/third-party/Qt-Color-Widgets/src/alphaback.png000066400000000000000000000003201354471500100263740ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME**`RtEXtCommentCreated with GIMPW+IDAT8cLKKgI301PF  gώ7CldPEIENDB`flameshot-0.6.0+git20191001/src/third-party/Qt-Color-Widgets/src/color_utils.cpp000066400000000000000000000046651354471500100270420ustar00rootroot00000000000000/** * \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.6.0+git20191001/src/third-party/Qt-Color-Widgets/src/color_utils.hpp000066400000000000000000000036221354471500100270370ustar00rootroot00000000000000/** * \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.6.0+git20191001/src/third-party/Qt-Color-Widgets/src/color_wheel.cpp000066400000000000000000000373611354471500100270050ustar00rootroot00000000000000/** * \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; explicit 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(); emit colorSelected(color()); 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); } emit colorSelected(color()); 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; 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(); 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(); 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.6.0+git20191001/src/third-party/Qt-Color-Widgets/src/color_widgets.qrc000066400000000000000000000001511354471500100273350ustar00rootroot00000000000000 alphaback.png flameshot-0.6.0+git20191001/src/third-party/singleapplication/000077500000000000000000000000001354471500100236375ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/third-party/singleapplication/CHANGELOG.md000066400000000000000000000117011354471500100254500ustar00rootroot00000000000000Changelog ========= __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.6.0+git20191001/src/third-party/singleapplication/LICENSE000066400000000000000000000022321354471500100246430ustar00rootroot00000000000000The 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.6.0+git20191001/src/third-party/singleapplication/README.md000066400000000000000000000217441354471500100251260ustar00rootroot00000000000000SingleApplication ================= 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.6.0+git20191001/src/third-party/singleapplication/Windows.md000066400000000000000000000026411354471500100256160ustar00rootroot00000000000000Windows 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.6.0+git20191001/src/third-party/singleapplication/singleapplication.cpp000066400000000000000000000353451354471500100300620ustar00rootroot00000000000000// 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( QStringLiteral("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]() { emit this->slotClientConnectionClosed( nextConnSocket, instanceId ); } ); QObject::connect( nextConnSocket, &QLocalSocket::readyRead, this, [nextConnSocket, instanceId, this]() { emit this->slotDataAvailable( nextConnSocket, instanceId ); } ); if( connectionType == NewInstance || ( connectionType == SecondaryInstance && options & SingleApplication::Mode::SecondaryNotification ) ) { emit q->instanceStarted(); } if( nextConnSocket->bytesAvailable() > 0 ) { emit this->slotDataAvailable( nextConnSocket, instanceId ); } } void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId ) { Q_Q(SingleApplication); emit q->receivedMessage( instanceId, dataSocket->readAll() ); } void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId ) { if( closedSocket->bytesAvailable() > 0 ) 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.6.0+git20191001/src/third-party/singleapplication/singleapplication.h000066400000000000000000000112671354471500100275240ustar00rootroot00000000000000// 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.6.0+git20191001/src/third-party/singleapplication/singleapplication.pri000066400000000000000000000005001354471500100300530ustar00rootroot00000000000000QT += 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.6.0+git20191001/src/third-party/singleapplication/singleapplication_p.h000066400000000000000000000052741354471500100300440ustar00rootroot00000000000000// 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.6.0+git20191001/src/tools/000077500000000000000000000000001354471500100170235ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/abstractactiontool.cpp000066400000000000000000000035441354471500100234340ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "abstractactiontool.h" AbstractActionTool::AbstractActionTool(QObject *parent) : CaptureTool(parent) { } bool AbstractActionTool::isValid() const { return true; } bool AbstractActionTool::isSelectable() const { return false; } bool AbstractActionTool::showMousePreview() const { return false; } void AbstractActionTool::undo(QPixmap &pixmap) { Q_UNUSED(pixmap); } void AbstractActionTool::process(QPainter &painter, const QPixmap &pixmap, bool recordUndo) { Q_UNUSED(painter); Q_UNUSED(pixmap); Q_UNUSED(recordUndo); } void AbstractActionTool::paintMousePreview( QPainter &painter, const CaptureContext &context) { Q_UNUSED(painter); Q_UNUSED(context); } void AbstractActionTool::drawEnd(const QPoint &p) { Q_UNUSED(p); } void AbstractActionTool::drawMove(const QPoint &p) { Q_UNUSED(p); } void AbstractActionTool::drawStart(const CaptureContext &context) { Q_UNUSED(context); } void AbstractActionTool::colorChanged(const QColor &c) { Q_UNUSED(c); } void AbstractActionTool::thicknessChanged(const int th) { Q_UNUSED(th); } flameshot-0.6.0+git20191001/src/tools/abstractactiontool.h000066400000000000000000000030271354471500100230750ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 AbstractActionTool : public CaptureTool { Q_OBJECT public: explicit AbstractActionTool(QObject *parent = nullptr); bool isValid() const override; bool isSelectable() const override; bool showMousePreview() const override; void undo(QPixmap &pixmap) override; void process(QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) override; void paintMousePreview(QPainter &painter, const CaptureContext &context) override; public slots: void drawEnd(const QPoint &p) override; void drawMove(const QPoint &p) override; void drawStart(const CaptureContext &context) override; void colorChanged(const QColor &c) override; void thicknessChanged(const int th) override; }; flameshot-0.6.0+git20191001/src/tools/abstractpathtool.cpp000066400000000000000000000046411354471500100231120ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "abstractpathtool.h" AbstractPathTool::AbstractPathTool(QObject *parent) : CaptureTool(parent), m_thickness(0), m_padding(0) { } bool AbstractPathTool::isValid() const { return m_points.length() > 1; } bool AbstractPathTool::closeOnButtonPressed() const { return false; } bool AbstractPathTool::isSelectable() const { return true; } bool AbstractPathTool::showMousePreview() const { return true; } void AbstractPathTool::undo(QPixmap &pixmap) { QPainter p(&pixmap); const int val = m_thickness + m_padding; QRect area = m_backupArea + QMargins(val, val, val, val); p.drawPixmap(area.intersected(pixmap.rect()) .topLeft(), m_pixmapBackup); } void AbstractPathTool::drawEnd(const QPoint &p) { Q_UNUSED(p); } void AbstractPathTool::drawMove(const QPoint &p) { addPoint(p); } void AbstractPathTool::colorChanged(const QColor &c) { m_color = c; } void AbstractPathTool::thicknessChanged(const int th) { m_thickness = th; } void AbstractPathTool::updateBackup(const QPixmap &pixmap) { const int val = m_thickness + m_padding; QRect area = m_backupArea.normalized() + QMargins(val, val, val, val); m_pixmapBackup = pixmap.copy(area); } void AbstractPathTool::addPoint(const QPoint &point) { if (m_backupArea.left() > point.x()) { m_backupArea.setLeft(point.x()); } else if (m_backupArea.right() < point.x()) { m_backupArea.setRight(point.x()); } if (m_backupArea.top() > point.y()) { m_backupArea.setTop(point.y()); } else if (m_backupArea.bottom() < point.y()) { m_backupArea.setBottom(point.y()); } m_points.append(point); } flameshot-0.6.0+git20191001/src/tools/abstractpathtool.h000066400000000000000000000031711354471500100225540ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 AbstractPathTool : public CaptureTool { Q_OBJECT public: explicit AbstractPathTool(QObject *parent = nullptr); bool isValid() const override; bool closeOnButtonPressed() const override; bool isSelectable() const override; bool showMousePreview() const override; void undo(QPixmap &pixmap) override; public slots: void drawEnd(const QPoint &p) override; void drawMove(const QPoint &p) override; void colorChanged(const QColor &c) override; void thicknessChanged(const int th) override; protected: void updateBackup(const QPixmap &pixmap); void addPoint(const QPoint &point); QPixmap m_pixmapBackup; QRect m_backupArea; QColor m_color; QVector m_points; int m_thickness; // use m_padding to extend the area of the backup int m_padding; }; flameshot-0.6.0+git20191001/src/tools/abstracttwopointtool.cpp000066400000000000000000000073271354471500100240450ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "abstracttwopointtool.h" #include namespace { const double ADJ_UNIT = std::atan(1.0); const int DIRS_NUMBER = 4; enum UNIT { HORIZ_DIR = 0, DIAG1_DIR = 1, VERT_DIR = 2, DIAG2_DIR = 3 }; const double ADJ_DIAG_UNIT = 2 * ADJ_UNIT; const int DIAG_DIRS_NUMBER = 2; enum DIAG_UNIT { DIR1 = 0, DIR2 = 1 }; } AbstractTwoPointTool::AbstractTwoPointTool(QObject *parent) : CaptureTool(parent), m_thickness(0), m_padding(0) { } bool AbstractTwoPointTool::isValid() const { return (m_points.first != m_points.second); } bool AbstractTwoPointTool::closeOnButtonPressed() const { return false; } bool AbstractTwoPointTool::isSelectable() const { return true; } bool AbstractTwoPointTool::showMousePreview() const { return true; } void AbstractTwoPointTool::undo(QPixmap &pixmap) { QPainter p(&pixmap); p.drawPixmap(backupRect(pixmap.rect()).topLeft(), m_pixmapBackup); } void AbstractTwoPointTool::drawEnd(const QPoint &p) { Q_UNUSED(p); } void AbstractTwoPointTool::drawMove(const QPoint &p) { m_points.second = p; } void AbstractTwoPointTool::drawMoveWithAdjustment(const QPoint &p) { m_points.second = m_points.first + adjustedVector(p - m_points.first); } void AbstractTwoPointTool::colorChanged(const QColor &c) { m_color = c; } void AbstractTwoPointTool::thicknessChanged(const int th) { m_thickness = th; } void AbstractTwoPointTool::updateBackup(const QPixmap &pixmap) { m_pixmapBackup = pixmap.copy(backupRect(pixmap.rect())); } QRect AbstractTwoPointTool::backupRect(const QRect &limits) const { QRect r = QRect(m_points.first, m_points.second).normalized(); const int val = m_thickness + m_padding; r += QMargins(val, val, val, val); return r.intersected(limits); } QPoint AbstractTwoPointTool::adjustedVector(QPoint v) const { if (m_supportsOrthogonalAdj && m_supportsDiagonalAdj) { int dir = ( static_cast(round(atan2(-v.y(), v.x()) / ADJ_UNIT)) + DIRS_NUMBER ) % DIRS_NUMBER; if (dir == UNIT::HORIZ_DIR) { v.setY(0); } else if (dir == UNIT::VERT_DIR) { v.setX(0); } else if (dir == UNIT::DIAG1_DIR) { int newX = (v.x() - v.y()) / 2; int newY = -newX; v.setX(newX); v.setY(newY); } else { int newX = (v.x() + v.y()) / 2; int newY = newX; v.setX(newX); v.setY(newY); } } else if (m_supportsDiagonalAdj) { int dir = ( static_cast(round((atan2(-v.y(), v.x()) - ADJ_DIAG_UNIT / 2) / ADJ_DIAG_UNIT)) + DIAG_DIRS_NUMBER ) % DIAG_DIRS_NUMBER; if (dir == DIAG_UNIT::DIR1) { int newX = (v.x() - v.y()) / 2; int newY = -newX; v.setX(newX); v.setY(newY); } else { int newX = (v.x() + v.y()) / 2; int newY = newX; v.setX(newX); v.setY(newY); } } return v; } flameshot-0.6.0+git20191001/src/tools/abstracttwopointtool.h000066400000000000000000000034731354471500100235100ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 AbstractTwoPointTool : public CaptureTool { Q_OBJECT public: explicit AbstractTwoPointTool(QObject *parent = nullptr); bool isValid() const override; bool closeOnButtonPressed() const override; bool isSelectable() const override; bool showMousePreview() const override; void undo(QPixmap &pixmap) override; public slots: void drawEnd(const QPoint &p) override; void drawMove(const QPoint &p) override; void drawMoveWithAdjustment(const QPoint &p) override; void colorChanged(const QColor &c) override; void thicknessChanged(const int th) override; protected: void updateBackup(const QPixmap &pixmap); QRect backupRect(const QRect &limits) const; QPixmap m_pixmapBackup; QPair m_points; QColor m_color; int m_thickness; // use m_padding to extend the area of the backup int m_padding; bool m_supportsOrthogonalAdj = false; bool m_supportsDiagonalAdj = false; private: QPoint adjustedVector(QPoint v) const; }; flameshot-0.6.0+git20191001/src/tools/arrow/000077500000000000000000000000001354471500100201555ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/arrow/arrowtool.cpp000066400000000000000000000072771354471500100227260ustar00rootroot00000000000000// Copyright(c) 2017-2019 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" namespace { #define PADDING_VALUE 2 const int ArrowWidth = 10; const int ArrowHeight = 18; QPainterPath getArrowHead(QPoint p1, QPoint p2, const int thickness) { QLineF base(p1, p2); // Create the vector for the position of the base of the arrowhead QLineF temp(QPoint(0,0), p2-p1); int val = ArrowHeight + thickness*4; if (base.length() < val) { val = (base.length() + thickness*2); } temp.setLength(base.length() + thickness*2 - val); // Move across the line up to the head QPointF bottonTranslation(temp.p2()); // Rotate base of the arrowhead base.setLength(ArrowWidth + thickness*2); base.setAngle(base.angle() + 90); // Move to the correct point QPointF temp2 = p1 - base.p2(); // Center it QPointF centerTranslation((temp2.x()/2), (temp2.y()/2)); base.translate(bottonTranslation); base.translate(centerTranslation); QPainterPath path; path.moveTo(p2); path.lineTo(base.p1()); path.lineTo(base.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); int val = ArrowHeight + thickness*4; if (l.length() < val) { val = (l.length() + thickness*2); } l.setLength(l.length() + thickness*2 - val); return l.toLine(); } } // unnamed namespace ArrowTool::ArrowTool(QObject *parent) : AbstractTwoPointTool(parent) { m_padding = ArrowWidth / 2; m_supportsOrthogonalAdj = true; m_supportsDiagonalAdj = true; } QIcon ArrowTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "arrow-bottom-left.svg"); } QString ArrowTool::name() const { return tr("Arrow"); } QString ArrowTool::nameID() { return QLatin1String(""); } QString ArrowTool::description() const { return tr("Set the Arrow as the paint tool"); } CaptureTool* ArrowTool::copy(QObject *parent) { return new ArrowTool(parent); } void ArrowTool::process(QPainter &painter, const QPixmap &pixmap, bool recordUndo) { if (recordUndo) { updateBackup(pixmap); } painter.setPen(QPen(m_color, m_thickness)); painter.drawLine(getShorterLine(m_points.first, m_points.second, m_thickness)); painter.fillPath(getArrowHead(m_points.first, m_points.second, m_thickness), QBrush(m_color)); } void ArrowTool::paintMousePreview(QPainter &painter, const CaptureContext &context) { painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.drawLine(context.mousePos, context.mousePos); } void ArrowTool::drawStart(const CaptureContext &context) { m_color = context.color; m_thickness = context.thickness + PADDING_VALUE; m_points.first = context.mousePos; m_points.second = context.mousePos; } void ArrowTool::pressed(const CaptureContext &context) { Q_UNUSED(context); } flameshot-0.6.0+git20191001/src/tools/arrow/arrowtool.h000066400000000000000000000030151354471500100223550ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstracttwopointtool.h" #include class ArrowTool : public AbstractTwoPointTool { Q_OBJECT public: explicit ArrowTool(QObject *parent = nullptr); QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; void process( QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) override; void paintMousePreview(QPainter &painter, const CaptureContext &context) override; public slots: void drawStart(const CaptureContext &context) override; void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/blur/000077500000000000000000000000001354471500100177675ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/blur/blurtool.cpp000066400000000000000000000052041354471500100223360ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 #include BlurTool::BlurTool(QObject *parent) : AbstractTwoPointTool(parent) { } QIcon BlurTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "blur.svg"); } QString BlurTool::name() const { return tr("Blur"); } QString BlurTool::nameID() { return QLatin1String(""); } QString BlurTool::description() const { return tr("Set Blur as the paint tool"); } CaptureTool* BlurTool::copy(QObject *parent) { return new BlurTool(parent); } void BlurTool::process(QPainter &painter, const QPixmap &pixmap, bool recordUndo) { if (recordUndo) { updateBackup(pixmap); } QPoint &p0 = m_points.first; QPoint &p1 = m_points.second; auto pixelRatio = pixmap.devicePixelRatio(); QRect selection = QRect(p0, p1).normalized(); QRect selectionScaled = QRect(p0 * pixelRatio, p1 * pixelRatio).normalized(); QGraphicsBlurEffect *blur = new QGraphicsBlurEffect; blur->setBlurRadius(10); QGraphicsPixmapItem *item = new QGraphicsPixmapItem ( pixmap.copy(selectionScaled)); 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::paintMousePreview(QPainter &painter, const CaptureContext &context) { Q_UNUSED(context); Q_UNUSED(painter); } void BlurTool::drawStart(const CaptureContext &context) { m_thickness = context.thickness; m_points.first = context.mousePos; m_points.second = context.mousePos; } void BlurTool::pressed(const CaptureContext &context) { Q_UNUSED(context); } flameshot-0.6.0+git20191001/src/tools/blur/blurtool.h000066400000000000000000000027671354471500100220160ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstracttwopointtool.h" class BlurTool : public AbstractTwoPointTool { Q_OBJECT public: explicit BlurTool(QObject *parent = nullptr); QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; void process( QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) override; void paintMousePreview(QPainter &painter, const CaptureContext &context) override; public slots: void drawStart(const CaptureContext &context) override; void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/capturecontext.cpp000066400000000000000000000017341354471500100226040ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "capturecontext.h" QPixmap CaptureContext::selectedScreenshotArea() const { if (selection.isNull()) { return screenshot; } else { return screenshot.copy(selection); } } flameshot-0.6.0+git20191001/src/tools/capturecontext.h000066400000000000000000000030071354471500100222440ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 struct CaptureContext { // screenshot with modifications QPixmap screenshot; // unmodified screenshot QPixmap origScreenshot; // Selection area QRect selection; // Widget dimensions QRect widgetDimensions; // Selected tool color QColor color; // Path where the content has to be saved QString savePath; // Ofset of the capture widget based on the system's screen (top-left) QPoint widgetOffset; // Mouse position inside the widget QPoint mousePos; // Value of the desired thickness int thickness; // Mode of the capture widget bool fullscreen; QPixmap selectedScreenshotArea() const ; }; flameshot-0.6.0+git20191001/src/tools/capturetool.h000066400000000000000000000134071354471500100215420ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/capturecontext.h" #include "src/utils/colorutils.h" #include "src/utils/pathinfo.h" #include #include class CaptureTool : public QObject { Q_OBJECT public: // Request actions on the main widget enum Request { // Call close() in the editor. REQ_CLOSE_GUI, // Call hide() in the editor. REQ_HIDE_GUI, // Select the whole screen. REQ_SELECT_ALL, // Disable the selection. REQ_HIDE_SELECTION, // Undo the last active modification in the stack. REQ_UNDO_MODIFICATION, // Redo the next modification in the stack. REQ_REDO_MODIFICATION, // Remove all the modifications. REQ_CLEAR_MODIFICATIONS, // Disable the active tool. REQ_MOVE_MODE, // Open the color picker under the mouse. REQ_SHOW_COLOR_PICKER, // Open/Close the side-panel. REQ_TOGGLE_SIDEBAR, // Call update() in the editor. REQ_REDRAW, // Append this tool to the undo/redo stack REQ_APPEND_TO_STACK, // Notify is the screenshot has been saved. REQ_CAPTURE_DONE_OK, // Instance this->widget()'s widget inside the editor under the mouse. REQ_ADD_CHILD_WIDGET, // Instance this->widget()'s widget as a window which closes after // closing the editor. REQ_ADD_CHILD_WINDOW, // Instance this->widget()'s widget which handles its own lifetime. REQ_ADD_EXTERNAL_WIDGETS, }; explicit CaptureTool(QObject *parent = nullptr) : QObject(parent){} // Returns false when the tool is in an inconsistent state and shouldn't // be included in the tool undo/redo stack. virtual bool isValid() const = 0; // Close the capture after the process() call if the tool was activated // from a button press. virtual bool closeOnButtonPressed() const = 0; // If the tool keeps active after the selection. virtual bool isSelectable() const = 0; // Enable mouse preview. virtual bool showMousePreview() const = 0; // The icon of the tool. // inEditor is true when the icon is requested inside the editor // and false otherwise. virtual QIcon icon(const QColor &background, bool inEditor) const = 0; // Name displayed for the tool, this could be translated with tr() virtual QString name() const = 0; // Codename for the tool, this hsouldn't change as it is used as ID // for the tool in the internals of Flameshot static QString nameID(); // Short description of the tool. virtual QString description() const = 0; // if the type is TYPE_WIDGET the widget is loaded in the main widget. // If the type is TYPE_EXTERNAL_WIDGET it is created outside as an // individual widget. virtual QWidget* widget() { return nullptr; } // When the tool is selected this method is called and the widget is added // to the configuration panel inside the main widget. virtual QWidget* configurationWidget() { return nullptr; } // Permanent configuration used in the configuration outside of the // capture. virtual QWidget* permanentConfigurationWidget() { return nullptr; } // Return a copy of the tool virtual CaptureTool* copy(QObject *parent = nullptr) = 0; // revert changes virtual void undo(QPixmap &pixmap) = 0; // Called every time the tool has to draw // recordUndo indicates when the tool should save the information // for the undo(), if the value is false calling undo() after // that process should not modify revert the changes. virtual void process(QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) = 0; // When the tool is selected, this is called when the mouse moves virtual void paintMousePreview(QPainter &painter, const CaptureContext &context) = 0; signals: void requestAction(Request r); protected: QString iconPath(const QColor &c) const { return ColorUtils::colorIsDark(c) ? PathInfo::whiteIconPath() : PathInfo::blackIconPath(); } public slots: // On mouse release. virtual void drawEnd(const QPoint &p) = 0; // Mouse pressed and moving, called once a pixel. virtual void drawMove(const QPoint &p) = 0; // Called when drawMove is needed with an adjustment; // should be overridden in case an adjustment is applicable. virtual void drawMoveWithAdjustment(const QPoint &p) { drawMove(p); } // Called when the tool is activated. virtual void drawStart(const CaptureContext &context) = 0; // Called right after pressign the button which activates the tool. virtual void pressed(const CaptureContext &context) = 0; // Called when the color is changed in the editor. virtual void colorChanged(const QColor &c) = 0; // Called when the thickness of the tool is updated in the editor. virtual void thicknessChanged(const int th) = 0; }; flameshot-0.6.0+git20191001/src/tools/circle/000077500000000000000000000000001354471500100202645ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/circle/circletool.cpp000066400000000000000000000042751354471500100231370ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 namespace { #define PADDING_VALUE 2 } CircleTool::CircleTool(QObject *parent) : AbstractTwoPointTool(parent) { m_supportsDiagonalAdj = true; } QIcon CircleTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "circle-outline.svg"); } QString CircleTool::name() const { return tr("Circle"); } QString CircleTool::nameID() { return QLatin1String(""); } QString CircleTool::description() const { return tr("Set the Circle as the paint tool"); } CaptureTool* CircleTool::copy(QObject *parent) { return new CircleTool(parent); } void CircleTool::process(QPainter &painter, const QPixmap &pixmap, bool recordUndo) { if (recordUndo) { updateBackup(pixmap); } painter.setPen(QPen(m_color, m_thickness)); painter.drawEllipse(QRect(m_points.first, m_points.second)); } void CircleTool::paintMousePreview(QPainter &painter, const CaptureContext &context) { painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.drawLine(context.mousePos, context.mousePos); } void CircleTool::drawStart(const CaptureContext &context) { m_color = context.color; m_thickness = context.thickness + PADDING_VALUE; m_points.first = context.mousePos; m_points.second = context.mousePos; } void CircleTool::pressed(const CaptureContext &context) { Q_UNUSED(context); } flameshot-0.6.0+git20191001/src/tools/circle/circletool.h000066400000000000000000000027731354471500100226050ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstracttwopointtool.h" class CircleTool : public AbstractTwoPointTool { Q_OBJECT public: explicit CircleTool(QObject *parent = nullptr); QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; void process( QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) override; void paintMousePreview(QPainter &painter, const CaptureContext &context) override; public slots: void drawStart(const CaptureContext &context) override; void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/copy/000077500000000000000000000000001354471500100177755ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/copy/copytool.cpp000066400000000000000000000031441354471500100223530ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "src/utils/screenshotsaver.h" #include CopyTool::CopyTool(QObject *parent) : AbstractActionTool(parent) { } bool CopyTool::closeOnButtonPressed() const { return true; } QIcon CopyTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "content-copy.svg"); } QString CopyTool::name() const { return tr("Copy"); } QString CopyTool::nameID() { return QLatin1String(""); } QString CopyTool::description() const { return tr("Copy the selection into the clipboard"); } CaptureTool* CopyTool::copy(QObject *parent) { return new CopyTool(parent); } void CopyTool::pressed(const CaptureContext &context) { emit requestAction(REQ_CAPTURE_DONE_OK); ScreenshotSaver().saveToClipboard(context.selectedScreenshotArea()); } flameshot-0.6.0+git20191001/src/tools/copy/copytool.h000066400000000000000000000024351354471500100220220ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractactiontool.h" class CopyTool : public AbstractActionTool { Q_OBJECT public: explicit CopyTool(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; public slots: void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/exit/000077500000000000000000000000001354471500100177745ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/exit/exittool.cpp000066400000000000000000000027611354471500100223550ustar00rootroot00000000000000// Copyright(c) 2017-2019 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) : AbstractActionTool(parent) { } bool ExitTool::closeOnButtonPressed() const { return true; } QIcon ExitTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "close.svg"); } QString ExitTool::name() const { return tr("Exit"); } QString ExitTool::nameID() { return QLatin1String(""); } QString ExitTool::description() const { return tr("Leave the capture screen"); } CaptureTool* ExitTool::copy(QObject *parent) { return new ExitTool(parent); } void ExitTool::pressed(const CaptureContext &context) { Q_UNUSED(context); emit requestAction(REQ_CLOSE_GUI); } flameshot-0.6.0+git20191001/src/tools/exit/exittool.h000066400000000000000000000024351354471500100220200ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractactiontool.h" class ExitTool : public AbstractActionTool { Q_OBJECT public: explicit ExitTool(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; public slots: void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/imgur/000077500000000000000000000000001354471500100201465ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/imgur/imguruploader.cpp000066400000000000000000000146601354471500100235400ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 #include #include ImgurUploader::ImgurUploader(const QPixmap &capture, QWidget *parent) : QWidget(parent), m_pixmap(capture) { setWindowTitle(tr("Upload to Imgur")); setWindowIcon(QIcon(":img/app/flameshot.svg")); 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) { QJsonDocument response = QJsonDocument::fromJson(reply->readAll()); QJsonObject json = response.object(); QJsonObject data = json[QStringLiteral("data")].toObject(); m_imageURL.setUrl(data[QStringLiteral("link")].toString()); m_deleteImageURL.setUrl(QStringLiteral("https://imgur.com/delete/%1").arg( data[QStringLiteral("deletehash")].toString())); if (ConfigHandler().copyAndCloseAfterUploadEnabled()) { QApplication::clipboard()->setText(m_imageURL.toString()); SystemNotification().sendMessage(QObject::tr("URL copied to clipboard.")); close(); } else { 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(QStringLiteral("title"), QStringLiteral("flameshot_screenshot")); QString description = FileNameHandler().parsedPattern(); urlQuery.addQueryItem(QStringLiteral("description"), description); QUrl url(QStringLiteral("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", QStringLiteral("Client-ID %1").arg(IMGUR_CLIENT_ID).toUtf8()); 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_openDeleteUrlButton = new QPushButton(tr("Delete image")); m_toClipboardButton = new QPushButton(tr("Image to Clipboard.")); m_hLayout->addWidget(m_copyUrlButton); m_hLayout->addWidget(m_openUrlButton); m_hLayout->addWidget(m_openDeleteUrlButton); m_hLayout->addWidget(m_toClipboardButton); connect(m_copyUrlButton, &QPushButton::clicked, this, &ImgurUploader::copyURL); connect(m_openUrlButton, &QPushButton::clicked, this, &ImgurUploader::openURL); connect(m_openDeleteUrlButton, &QPushButton::clicked, this, &ImgurUploader::openDeleteURL); 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::openDeleteURL() { bool successful = QDesktopServices::openUrl(m_deleteImageURL); if (!successful) { m_notification->showMessage(tr("Unable to open the URL.")); } } void ImgurUploader::copyImage() { QApplication::clipboard()->setPixmap(m_pixmap); m_notification->showMessage(tr("Screenshot copied to clipboard.")); } flameshot-0.6.0+git20191001/src/tools/imgur/imguruploader.h000066400000000000000000000034251354471500100232020ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 &capture, QWidget *parent = nullptr); private slots: void handleReply(QNetworkReply *reply); void startDrag(); void openURL(); void copyURL(); void openDeleteURL(); 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_openDeleteUrlButton; QPushButton *m_copyUrlButton; QPushButton *m_toClipboardButton; QUrl m_imageURL; QUrl m_deleteImageURL; NotificationWidget *m_notification; void upload(); void onUploadOk(); }; flameshot-0.6.0+git20191001/src/tools/imgur/imguruploadertool.cpp000066400000000000000000000034471354471500100244370ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "imguruploader.h" #include ImgurUploaderTool::ImgurUploaderTool(QObject *parent) : AbstractActionTool(parent) { } bool ImgurUploaderTool::closeOnButtonPressed() const { return true; } QIcon ImgurUploaderTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "cloud-upload.svg"); } QString ImgurUploaderTool::name() const { return tr("Image Uploader"); } QString ImgurUploaderTool::nameID() { return QLatin1String(""); } QString ImgurUploaderTool::description() const { return tr("Upload the selection to Imgur"); } QWidget* ImgurUploaderTool::widget() { return new ImgurUploader(capture); } CaptureTool* ImgurUploaderTool::copy(QObject *parent) { return new ImgurUploaderTool(parent); } void ImgurUploaderTool::pressed(const CaptureContext &context) { capture = context.selectedScreenshotArea(); emit requestAction(REQ_CAPTURE_DONE_OK); emit requestAction(REQ_ADD_EXTERNAL_WIDGETS); } flameshot-0.6.0+git20191001/src/tools/imgur/imguruploadertool.h000066400000000000000000000025571354471500100241050ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractactiontool.h" class ImgurUploaderTool : public AbstractActionTool { Q_OBJECT public: explicit ImgurUploaderTool(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; QWidget* widget() override; CaptureTool* copy(QObject *parent = nullptr) override; public slots: void pressed(const CaptureContext &context) override; private: QPixmap capture; }; flameshot-0.6.0+git20191001/src/tools/launcher/000077500000000000000000000000001354471500100206245ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/launcher/applaunchertool.cpp000066400000000000000000000033261354471500100245340ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "applaunchertool.h" #include "applauncherwidget.h" AppLauncher::AppLauncher(QObject *parent) : AbstractActionTool(parent) { } bool AppLauncher::closeOnButtonPressed() const { return true; } QIcon AppLauncher::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "open_with.svg"); } QString AppLauncher::name() const { return tr("App Launcher"); } QString AppLauncher::nameID() { return QLatin1String(""); } QString AppLauncher::description() const { return tr("Choose an app to open the capture"); } QWidget* AppLauncher::widget() { return new AppLauncherWidget(capture); } CaptureTool* AppLauncher::copy(QObject *parent) { return new AppLauncher(parent); } void AppLauncher::pressed(const CaptureContext &context) { capture = context.selectedScreenshotArea(); emit requestAction(REQ_CAPTURE_DONE_OK); emit requestAction(REQ_ADD_EXTERNAL_WIDGETS); } flameshot-0.6.0+git20191001/src/tools/launcher/applaunchertool.h000066400000000000000000000025431354471500100242010ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractactiontool.h" class AppLauncher : public AbstractActionTool { Q_OBJECT public: explicit AppLauncher(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; QWidget* widget() override; CaptureTool* copy(QObject *parent = nullptr) override; public slots: void pressed(const CaptureContext &context) override; private: QPixmap capture; }; flameshot-0.6.0+git20191001/src/tools/launcher/applauncherwidget.cpp000066400000000000000000000211111354471500100250320ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/launcher/launcheritemdelegate.h" #include "src/utils/globalvalues.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/app/flameshot.svg")); setWindowTitle(tr("Open With")); m_keepOpen = ConfigHandler().keepOpenAppLauncherValue(); QString dirLocal = QDir::homePath() + "/.local/share/applications/"; QDir appsDirLocal(dirLocal); m_parser.processDirectory(appsDirLocal); QString dir = QStringLiteral("/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 = GlobalValues::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), QLatin1String("")); m_tabWidget->setTabToolTip(m_tabWidget->count(), cat); if (cat == QLatin1String("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 << QStringLiteral("AudioVideo") << QStringLiteral("Audio") << QStringLiteral("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(QStringLiteral("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(GlobalValues::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.6.0+git20191001/src/tools/launcher/applauncherwidget.h000066400000000000000000000034361354471500100245110ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/tools/launcher/launcheritemdelegate.cpp000066400000000000000000000047511354471500100255120ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/utils/globalvalues.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 = GlobalValues::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 = GlobalValues::buttonBaseSize(); return QSize(size * 3.2, size * 3.7); } flameshot-0.6.0+git20191001/src/tools/launcher/launcheritemdelegate.h000066400000000000000000000023221354471500100251470ustar00rootroot00000000000000// Copyright(c) 2017-2019 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; }; flameshot-0.6.0+git20191001/src/tools/launcher/openwithprogram.cpp000066400000000000000000000033561354471500100245640ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/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.6.0+git20191001/src/tools/launcher/openwithprogram.h000066400000000000000000000015361354471500100242270ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/tools/launcher/terminallauncher.cpp000066400000000000000000000040241354471500100246650ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/tools/launcher/terminallauncher.h000066400000000000000000000021271354471500100243340ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/tools/line/000077500000000000000000000000001354471500100177525ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/line/linetool.cpp000066400000000000000000000042611354471500100223060ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 namespace { #define PADDING_VALUE 2 } LineTool::LineTool(QObject *parent) : AbstractTwoPointTool(parent) { m_supportsOrthogonalAdj = true; m_supportsDiagonalAdj = true; } QIcon LineTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "line.svg"); } QString LineTool::name() const { return tr("Line"); } QString LineTool::nameID() { return QLatin1String(""); } QString LineTool::description() const { return tr("Set the Line as the paint tool"); } CaptureTool* LineTool::copy(QObject *parent) { return new LineTool(parent); } void LineTool::process(QPainter &painter, const QPixmap &pixmap, bool recordUndo) { if (recordUndo) { updateBackup(pixmap); } painter.setPen(QPen(m_color, m_thickness)); painter.drawLine(m_points.first, m_points.second); } void LineTool::paintMousePreview(QPainter &painter, const CaptureContext &context) { painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.drawLine(context.mousePos, context.mousePos); } void LineTool::drawStart(const CaptureContext &context) { m_color = context.color; m_thickness = context.thickness + PADDING_VALUE; m_points.first = context.mousePos; m_points.second = context.mousePos; } void LineTool::pressed(const CaptureContext &context) { Q_UNUSED(context); } flameshot-0.6.0+git20191001/src/tools/line/linetool.h000066400000000000000000000027671354471500100217640ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstracttwopointtool.h" class LineTool : public AbstractTwoPointTool { Q_OBJECT public: explicit LineTool(QObject *parent = nullptr); QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; void process( QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) override; void paintMousePreview(QPainter &painter, const CaptureContext &context) override; public slots: void drawStart(const CaptureContext &context) override; void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/marker/000077500000000000000000000000001354471500100203045ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/marker/markertool.cpp000066400000000000000000000047611354471500100231770ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 namespace { #define PADDING_VALUE 14 } MarkerTool::MarkerTool(QObject *parent) : AbstractTwoPointTool(parent) { m_supportsOrthogonalAdj = true; m_supportsDiagonalAdj = true; } QIcon MarkerTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "marker.svg"); } QString MarkerTool::name() const { return tr("Marker"); } QString MarkerTool::nameID() { return QLatin1String(""); } QString MarkerTool::description() const { return tr("Set the Marker as the paint tool"); } CaptureTool* MarkerTool::copy(QObject *parent) { return new MarkerTool(parent); } void MarkerTool::process(QPainter &painter, const QPixmap &pixmap, bool recordUndo) { if (recordUndo) { updateBackup(pixmap); } painter.setCompositionMode(QPainter::CompositionMode_Multiply); painter.setOpacity(0.35); painter.setPen(QPen(m_color, m_thickness)); painter.drawLine(m_points.first, m_points.second); } void MarkerTool::paintMousePreview(QPainter &painter, const CaptureContext &context) { painter.setCompositionMode(QPainter::CompositionMode_Multiply); painter.setOpacity(0.35); painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.drawLine(context.mousePos, context.mousePos); } void MarkerTool::drawStart(const CaptureContext &context) { m_color = context.color; m_thickness = context.thickness + PADDING_VALUE; m_points.first = context.mousePos; m_points.second = context.mousePos; } void MarkerTool::pressed(const CaptureContext &context) { Q_UNUSED(context); } void MarkerTool::thicknessChanged(const int th) { m_thickness = th + PADDING_VALUE; } flameshot-0.6.0+git20191001/src/tools/marker/markertool.h000066400000000000000000000030551354471500100226370ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstracttwopointtool.h" class MarkerTool : public AbstractTwoPointTool { Q_OBJECT public: explicit MarkerTool(QObject *parent = nullptr); QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; void process( QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) override; void paintMousePreview(QPainter &painter, const CaptureContext &context) override; public slots: void drawStart(const CaptureContext &context) override; void pressed(const CaptureContext &context) override; void thicknessChanged(const int th) override; }; flameshot-0.6.0+git20191001/src/tools/move/000077500000000000000000000000001354471500100177715ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/move/movetool.cpp000066400000000000000000000027671354471500100223550ustar00rootroot00000000000000// Copyright(c) 2017-2019 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) : AbstractActionTool(parent) { } bool MoveTool::closeOnButtonPressed() const { return false; } QIcon MoveTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "cursor-move.svg"); } QString MoveTool::name() const { return tr("Move"); } QString MoveTool::nameID() { return QLatin1String(""); } QString MoveTool::description() const { return tr("Move the selection area"); } CaptureTool* MoveTool::copy(QObject *parent) { return new MoveTool(parent); } void MoveTool::pressed(const CaptureContext &context) { Q_UNUSED(context); emit requestAction(REQ_MOVE_MODE); } flameshot-0.6.0+git20191001/src/tools/move/movetool.h000066400000000000000000000024351354471500100220120ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractactiontool.h" class MoveTool : public AbstractActionTool { Q_OBJECT public: explicit MoveTool(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; public slots: void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/pencil/000077500000000000000000000000001354471500100202755ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/pencil/penciltool.cpp000066400000000000000000000042061354471500100231530ustar00rootroot00000000000000// Copyright(c) 2017-2019 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) : AbstractPathTool(parent) { } QIcon PencilTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "pencil.svg"); } QString PencilTool::name() const { return tr("Pencil"); } QString PencilTool::nameID() { return QLatin1String(""); } QString PencilTool::description() const { return tr("Set the Pencil as the paint tool"); } CaptureTool* PencilTool::copy(QObject *parent) { return new PencilTool(parent); } void PencilTool::process(QPainter &painter, const QPixmap &pixmap, bool recordUndo) { if (recordUndo) { updateBackup(pixmap); } painter.setPen(QPen(m_color, m_thickness)); painter.drawPolyline(m_points.data(), m_points.size()); } void PencilTool::paintMousePreview(QPainter &painter, const CaptureContext &context) { painter.setPen(QPen(context.color, context.thickness + 2)); painter.drawLine(context.mousePos, context.mousePos); } void PencilTool::drawStart(const CaptureContext &context) { m_color = context.color; m_thickness = context.thickness + 2; m_points.append(context.mousePos); m_backupArea.setTopLeft(context.mousePos); m_backupArea.setBottomRight(context.mousePos); } void PencilTool::pressed(const CaptureContext &context) { Q_UNUSED(context); } flameshot-0.6.0+git20191001/src/tools/pencil/penciltool.h000066400000000000000000000027641354471500100226270ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractpathtool.h" class PencilTool : public AbstractPathTool { Q_OBJECT public: explicit PencilTool(QObject *parent = nullptr); QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; void process( QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) override; void paintMousePreview(QPainter &painter, const CaptureContext &context) override; public slots: void drawStart(const CaptureContext &context) override; void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/pin/000077500000000000000000000000001354471500100176115ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/pin/pintool.cpp000066400000000000000000000037211354471500100220040ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "pintool.h" #include "src/tools/pin/pinwidget.h" PinTool::PinTool(QObject *parent) : AbstractActionTool(parent) { } bool PinTool::closeOnButtonPressed() const { return true; } QIcon PinTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "pin.svg"); } QString PinTool::name() const { return tr("Pin Tool"); } QString PinTool::nameID() { return QLatin1String(""); } QString PinTool::description() const { return tr("Pin image on the desktop"); } QWidget* PinTool::widget() { PinWidget *w = new PinWidget(m_pixmap); const int &&m = w->margin(); QRect adjusted_pos = m_geometry + QMargins(m, m, m, m); w->setGeometry(adjusted_pos); return w; } CaptureTool* PinTool::copy(QObject *parent) { return new PinTool(parent); } void PinTool::pressed(const CaptureContext &context) { emit requestAction(REQ_CAPTURE_DONE_OK); m_geometry = context.selection; m_geometry.setTopLeft(m_geometry.topLeft() + context.widgetOffset); m_pixmap = context.selectedScreenshotArea(); emit requestAction(REQ_ADD_EXTERNAL_WIDGETS); } flameshot-0.6.0+git20191001/src/tools/pin/pintool.h000077500000000000000000000026361354471500100214600ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractactiontool.h" class PinTool : public AbstractActionTool { Q_OBJECT public: explicit PinTool(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; QWidget* widget() override; CaptureTool* copy(QObject *parent = nullptr) override; public slots: void pressed(const CaptureContext &context) override; private: QRect m_geometry; QPixmap m_pixmap; }; flameshot-0.6.0+git20191001/src/tools/pin/pinwidget.cpp000066400000000000000000000064601354471500100223150ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "pinwidget.h" #include "src/utils/confighandler.h" #include #include #include #include #include PinWidget::PinWidget(const QPixmap &pixmap, QWidget *parent) : QWidget(parent), m_pixmap(pixmap) { setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); //set the bottom widget background transparent setAttribute(Qt::WA_TranslucentBackground); ConfigHandler conf; m_baseColor = conf.uiMainColorValue(); m_hoverColor = conf.uiContrastColorValue(); m_layout = new QVBoxLayout(this); const int margin = this->margin(); m_layout->setContentsMargins(margin, margin, margin, margin); m_shadowEffect = new QGraphicsDropShadowEffect(this); m_shadowEffect->setColor(m_baseColor); m_shadowEffect->setBlurRadius(2 * margin); m_shadowEffect->setOffset(0, 0); setGraphicsEffect(m_shadowEffect); m_label = new QLabel(); m_label->setPixmap(m_pixmap); m_layout->addWidget(m_label); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this, SLOT(close())); new QShortcut(Qt::Key_Escape, this, SLOT(close())); } int PinWidget::margin() const { return 7; } void PinWidget::wheelEvent(QWheelEvent *e) { int val = e->delta() > 0 ? 15 : -15; int newWidth = qBound(50, m_label->width() + val, maximumWidth()); int newHeight = qBound(50, m_label->height() + val, maximumHeight()); QSize size(newWidth, newHeight); setScaledPixmap(size); adjustSize(); e->accept(); } void PinWidget::enterEvent(QEvent *) { m_shadowEffect->setColor(m_hoverColor); } void PinWidget::leaveEvent(QEvent *) { m_shadowEffect->setColor(m_baseColor); } void PinWidget::mouseDoubleClickEvent(QMouseEvent *) { close(); } void PinWidget::mousePressEvent(QMouseEvent *e) { m_dragStart = e->globalPos(); m_offsetX = e->localPos().x() / width(); m_offsetY = e->localPos().y() / height(); } void PinWidget::mouseMoveEvent(QMouseEvent *e) { const QPoint delta = e->globalPos() - m_dragStart; int offsetW = width() * m_offsetX; int offsetH = height() * m_offsetY; move(m_dragStart.x() + delta.x() - offsetW, m_dragStart.y() + delta.y() - offsetH); } void PinWidget::setScaledPixmap(const QSize &size) { const qreal scale = qApp->devicePixelRatio(); QPixmap scaledPixmap = m_pixmap.scaled(size * scale, Qt::KeepAspectRatio, Qt::SmoothTransformation); scaledPixmap.setDevicePixelRatio(scale); m_label->setPixmap(scaledPixmap); } flameshot-0.6.0+git20191001/src/tools/pin/pinwidget.h000066400000000000000000000030161354471500100217540ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 QLabel; class PinWidget : public QWidget { Q_OBJECT public: explicit PinWidget(const QPixmap &pixmap, QWidget *parent = nullptr); int margin() const; protected: void wheelEvent(QWheelEvent *e); void mouseDoubleClickEvent(QMouseEvent *); void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void enterEvent(QEvent *); void leaveEvent(QEvent *); private: void setScaledPixmap(const QSize &size); QPixmap m_pixmap; QVBoxLayout *m_layout; QLabel *m_label; QPoint m_dragStart; qreal m_offsetX, m_offsetY; QGraphicsDropShadowEffect *m_shadowEffect; QColor m_baseColor, m_hoverColor; }; flameshot-0.6.0+git20191001/src/tools/rectangle/000077500000000000000000000000001354471500100207675ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/rectangle/rectangletool.cpp000066400000000000000000000044061354471500100243410ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 namespace { #define PADDING_VALUE 2 } RectangleTool::RectangleTool(QObject *parent) : AbstractTwoPointTool(parent) { m_supportsDiagonalAdj = true; } QIcon RectangleTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "square.svg"); } QString RectangleTool::name() const { return tr("Rectangle"); } QString RectangleTool::nameID() { return QLatin1String(""); } QString RectangleTool::description() const { return tr("Set the Rectangle as the paint tool"); } CaptureTool* RectangleTool::copy(QObject *parent) { return new RectangleTool(parent); } void RectangleTool::process(QPainter &painter, const QPixmap &pixmap, bool recordUndo) { if (recordUndo) { updateBackup(pixmap); } painter.setPen(QPen(m_color, m_thickness)); painter.setBrush(QBrush(m_color)); painter.drawRect(QRect(m_points.first, m_points.second)); } void RectangleTool::paintMousePreview(QPainter &painter, const CaptureContext &context) { painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.drawLine(context.mousePos, context.mousePos); } void RectangleTool::drawStart(const CaptureContext &context) { m_color = context.color; m_thickness = context.thickness + PADDING_VALUE; m_points.first = context.mousePos; m_points.second = context.mousePos; } void RectangleTool::pressed(const CaptureContext &context) { Q_UNUSED(context); } flameshot-0.6.0+git20191001/src/tools/rectangle/rectangletool.h000066400000000000000000000030011354471500100237740ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstracttwopointtool.h" class RectangleTool : public AbstractTwoPointTool { Q_OBJECT public: explicit RectangleTool(QObject *parent = nullptr); QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; void process( QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) override; void paintMousePreview(QPainter &painter, const CaptureContext &context) override; public slots: void drawStart(const CaptureContext &context) override; void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/redo/000077500000000000000000000000001354471500100177545ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/redo/redotool.cpp000066400000000000000000000030031354471500100223030ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "redotool.h" #include RedoTool::RedoTool(QObject *parent) : AbstractActionTool(parent) { } bool RedoTool::closeOnButtonPressed() const { return false; } QIcon RedoTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "redo-variant.svg"); } QString RedoTool::name() const { return tr("Redo"); } QString RedoTool::nameID() { return QLatin1String(""); } QString RedoTool::description() const { return tr("Redo the next modification"); } CaptureTool* RedoTool::copy(QObject *parent) { return new RedoTool(parent); } void RedoTool::pressed(const CaptureContext &context) { Q_UNUSED(context); emit requestAction(REQ_REDO_MODIFICATION); } flameshot-0.6.0+git20191001/src/tools/redo/redotool.h000066400000000000000000000024361354471500100217610ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractactiontool.h" class RedoTool : public AbstractActionTool { Q_OBJECT public: explicit RedoTool(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; public slots: void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/save/000077500000000000000000000000001354471500100177615ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/save/savetool.cpp000066400000000000000000000037151354471500100223270ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "src/utils/screenshotsaver.h" #include SaveTool::SaveTool(QObject *parent) : AbstractActionTool(parent) { } bool SaveTool::closeOnButtonPressed() const { return true; } QIcon SaveTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "content-save.svg"); } QString SaveTool::name() const { return tr("Save"); } QString SaveTool::nameID() { return QLatin1String(""); } QString SaveTool::description() const { return tr("Save the capture"); } CaptureTool* SaveTool::copy(QObject *parent) { return new SaveTool(parent); } void SaveTool::pressed(const CaptureContext &context) { if (context.savePath.isEmpty()) { emit requestAction(REQ_HIDE_GUI); bool ok = ScreenshotSaver().saveToFilesystemGUI( context.selectedScreenshotArea()); if (ok) { emit requestAction(REQ_CAPTURE_DONE_OK); } } else { bool ok = ScreenshotSaver().saveToFilesystem( context.selectedScreenshotArea(), context.savePath); if (ok) { emit requestAction(REQ_CAPTURE_DONE_OK); } } } flameshot-0.6.0+git20191001/src/tools/save/savetool.h000066400000000000000000000024351354471500100217720ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractactiontool.h" class SaveTool : public AbstractActionTool { Q_OBJECT public: explicit SaveTool(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; public slots: void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/selection/000077500000000000000000000000001354471500100210105ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/selection/selectiontool.cpp000066400000000000000000000044671354471500100244120ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 namespace { #define PADDING_VALUE 2 } SelectionTool::SelectionTool(QObject *parent) : AbstractTwoPointTool(parent) { m_supportsDiagonalAdj = true; } bool SelectionTool::closeOnButtonPressed() const { return false; } QIcon SelectionTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "square-outline.svg"); } QString SelectionTool::name() const { return tr("Rectangular Selection"); } QString SelectionTool::nameID() { return QLatin1String(""); } QString SelectionTool::description() const { return tr("Set Selection as the paint tool"); } CaptureTool* SelectionTool::copy(QObject *parent) { return new SelectionTool(parent); } void SelectionTool::process(QPainter &painter, const QPixmap &pixmap, bool recordUndo) { if (recordUndo) { updateBackup(pixmap); } painter.setPen(QPen(m_color, m_thickness)); painter.drawRect(QRect(m_points.first, m_points.second)); } void SelectionTool::paintMousePreview(QPainter &painter, const CaptureContext &context) { painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.drawLine(context.mousePos, context.mousePos); } void SelectionTool::drawStart(const CaptureContext &context) { m_color = context.color; m_thickness = context.thickness + PADDING_VALUE; m_points.first = context.mousePos; m_points.second = context.mousePos; } void SelectionTool::pressed(const CaptureContext &context) { Q_UNUSED(context); } flameshot-0.6.0+git20191001/src/tools/selection/selectiontool.h000066400000000000000000000030511354471500100240430ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstracttwopointtool.h" class SelectionTool : public AbstractTwoPointTool { Q_OBJECT public: explicit SelectionTool(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; void process( QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) override; void paintMousePreview(QPainter &painter, const CaptureContext &context) override; public slots: void drawStart(const CaptureContext &context) override; void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/sizeindicator/000077500000000000000000000000001354471500100216725ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/sizeindicator/sizeindicatortool.cpp000066400000000000000000000031601354471500100261430ustar00rootroot00000000000000// Copyright(c) 2017-2019 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) : AbstractActionTool(parent) { } bool SizeIndicatorTool::closeOnButtonPressed() const { return false; } QIcon SizeIndicatorTool::icon(const QColor &background, bool inEditor) const { return inEditor ? QIcon() : QIcon(iconPath(background) + "size_indicator.svg"); } QString SizeIndicatorTool::name() const { return tr("Selection Size Indicator"); } QString SizeIndicatorTool::nameID() { return QLatin1String(""); } QString SizeIndicatorTool::description() const { return tr("Show the dimensions of the selection (X Y)"); } CaptureTool* SizeIndicatorTool::copy(QObject *parent) { return new SizeIndicatorTool(parent); } void SizeIndicatorTool::pressed(const CaptureContext &context) { Q_UNUSED(context); } flameshot-0.6.0+git20191001/src/tools/sizeindicator/sizeindicatortool.h000066400000000000000000000024571354471500100256200ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractactiontool.h" class SizeIndicatorTool : public AbstractActionTool { Q_OBJECT public: explicit SizeIndicatorTool(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; public slots: void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/tools/text/000077500000000000000000000000001354471500100200075ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/text/textconfig.cpp000066400000000000000000000072751354471500100227000ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "textconfig.h" #include "src/utils/colorutils.h" #include "src/utils/pathinfo.h" #include #include #include #include #include TextConfig::TextConfig(QWidget *parent) : QWidget(parent) { m_layout = new QVBoxLayout(this); QFontDatabase fontDB; QComboBox *fontsCB = new QComboBox(); connect(fontsCB, &QComboBox::currentTextChanged, this, &TextConfig::fontFamilyChanged); fontsCB->addItems(fontDB.families()); // TODO save family in config int index = fontsCB->findText(font().family()); fontsCB->setCurrentIndex(index); QColor bgColor(palette().background().color()); QString iconPrefix = ColorUtils::colorIsDark(bgColor) ? PathInfo::whiteIconPath() : PathInfo::blackIconPath(); m_strikeOutButton = new QPushButton( QIcon(iconPrefix + "format_strikethrough.svg"), QLatin1String("")); m_strikeOutButton->setCheckable(true); connect(m_strikeOutButton, &QPushButton::clicked, this, &TextConfig::fontStrikeOutChanged); m_strikeOutButton->setToolTip(tr("StrikeOut")); m_underlineButton = new QPushButton( QIcon(iconPrefix + "format_underlined.svg"), QLatin1String("")); m_underlineButton->setCheckable(true); connect(m_underlineButton, &QPushButton::clicked, this, &TextConfig::fontUnderlineChanged); m_underlineButton->setToolTip(tr("Underline")); m_weightButton = new QPushButton( QIcon(iconPrefix + "format_bold.svg"), QLatin1String("")); m_weightButton->setCheckable(true); connect(m_weightButton, &QPushButton::clicked, this, &TextConfig::weightButtonPressed); m_weightButton->setToolTip(tr("Bold")); m_italicButton = new QPushButton( QIcon(iconPrefix + "format_italic.svg"), QLatin1String("")); m_italicButton->setCheckable(true); connect(m_italicButton, &QPushButton::clicked, this, &TextConfig::fontItalicChanged); m_italicButton->setToolTip(tr("Italic")); QHBoxLayout *modifiersLayout = new QHBoxLayout(); m_layout->addWidget(fontsCB); modifiersLayout->addWidget(m_strikeOutButton); modifiersLayout->addWidget(m_underlineButton); modifiersLayout->addWidget(m_weightButton); modifiersLayout->addWidget(m_italicButton); m_layout->addLayout(modifiersLayout); } void TextConfig::setUnderline(const bool u) { m_underlineButton->setChecked(u); } void TextConfig::setStrikeOut(const bool s) { m_strikeOutButton->setChecked(s); } void TextConfig::setWeight(const int w) { m_weightButton->setChecked(static_cast(w) == QFont::Bold); } void TextConfig::setItalic(const bool i) { m_italicButton->setChecked(i); } void TextConfig::weightButtonPressed(const bool w) { if (w) { emit fontWeightChanged(QFont::Bold); } else { emit fontWeightChanged(QFont::Normal); } } flameshot-0.6.0+git20191001/src/tools/text/textconfig.h000066400000000000000000000031201354471500100223260ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 QPushButton; class TextConfig : public QWidget { Q_OBJECT public: explicit TextConfig(QWidget *parent = nullptr); void setUnderline(const bool u); void setStrikeOut(const bool s); void setWeight(const int w); void setItalic(const bool i); signals: void fontFamilyChanged(const QString &f); void fontUnderlineChanged(const bool underlined); void fontStrikeOutChanged(const bool dashed); void fontWeightChanged(const QFont::Weight w); void fontItalicChanged(const bool italic); public slots: private slots: void weightButtonPressed(const bool w); private: QVBoxLayout *m_layout; QPushButton *m_strikeOutButton; QPushButton *m_underlineButton; QPushButton *m_weightButton; QPushButton *m_italicButton; }; flameshot-0.6.0+git20191001/src/tools/text/texttool.cpp000066400000000000000000000130271354471500100224000ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "texttool.h" #include "textwidget.h" #include "textconfig.h" #define BASE_POINT_SIZE 8 TextTool::TextTool(QObject *parent) : CaptureTool(parent), m_size(1) { } bool TextTool::isValid() const { return !m_text.isEmpty(); } bool TextTool::closeOnButtonPressed() const { return false; } bool TextTool::isSelectable() const { return true; } bool TextTool::showMousePreview() const { return false; } QIcon TextTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "text.svg"); } QString TextTool::name() const { return tr("Text"); } QString TextTool::nameID() { return QLatin1String(""); } QString TextTool::description() const { return tr("Add text to your capture"); } QWidget *TextTool::widget() { TextWidget *w = new TextWidget(); w->setTextColor(m_color); m_font.setPointSize(m_size + BASE_POINT_SIZE); w->setFont(m_font); connect(w, &TextWidget::textUpdated, this, &TextTool::updateText); m_widget = w; return w; } QWidget *TextTool::configurationWidget() { m_confW = new TextConfig(); connect(m_confW, &TextConfig::fontFamilyChanged, this, &TextTool::updateFamily); connect(m_confW, &TextConfig::fontItalicChanged, this, &TextTool::updateFontItalic); connect(m_confW, &TextConfig::fontStrikeOutChanged, this, &TextTool::updateFontStrikeOut); connect(m_confW, &TextConfig::fontUnderlineChanged, this, &TextTool::updateFontUnderline); connect(m_confW, &TextConfig::fontWeightChanged, this, &TextTool::updateFontWeight); m_confW->setItalic(m_font.italic()); m_confW->setUnderline(m_font.underline()); m_confW->setStrikeOut(m_font.strikeOut()); m_confW->setWeight(m_font.weight()); return m_confW; } CaptureTool *TextTool::copy(QObject *parent) { TextTool *tt = new TextTool(parent); connect(m_confW, &TextConfig::fontFamilyChanged, tt, &TextTool::updateFamily); connect(m_confW, &TextConfig::fontItalicChanged, tt, &TextTool::updateFontItalic); connect(m_confW, &TextConfig::fontStrikeOutChanged, tt, &TextTool::updateFontStrikeOut); connect(m_confW, &TextConfig::fontUnderlineChanged, tt, &TextTool::updateFontUnderline); connect(m_confW, &TextConfig::fontWeightChanged, tt, &TextTool::updateFontWeight); tt->m_font = m_font; return tt; } void TextTool::undo(QPixmap &pixmap) { QPainter p(&pixmap); p.drawPixmap(m_backupArea.topLeft(), m_pixmapBackup); } void TextTool::process(QPainter &painter, const QPixmap &pixmap, bool recordUndo) { if (m_text.isEmpty()) { return; } QFontMetrics fm(m_font); QSize size(fm.boundingRect(QRect(), 0, m_text).size()); m_backupArea.setSize(size); if (recordUndo) { m_pixmapBackup = pixmap.copy(m_backupArea + QMargins(0, 0, 5, 5)); } // draw text painter.setFont(m_font); painter.setPen(m_color); painter.drawText(m_backupArea + QMargins(-5, -5, 5, 5), m_text); } void TextTool::paintMousePreview(QPainter &painter, const CaptureContext &context) { Q_UNUSED(painter); Q_UNUSED(context); } void TextTool::drawEnd(const QPoint &p) { m_backupArea.moveTo(p); } void TextTool::drawMove(const QPoint &p) { m_widget->move(p); } void TextTool::drawStart(const CaptureContext &context) { m_color = context.color; m_size = context.thickness; emit requestAction(REQ_ADD_CHILD_WIDGET); } void TextTool::pressed(const CaptureContext &context) { Q_UNUSED(context); } void TextTool::colorChanged(const QColor &c) { m_color = c; if (m_widget) { m_widget->setTextColor(c); } } void TextTool::thicknessChanged(const int th) { m_size = th; m_font.setPointSize(m_size + BASE_POINT_SIZE); if (m_widget) { m_widget->setFont(m_font); } } void TextTool::updateText(const QString &s) { m_text = s; } void TextTool::setFont(const QFont &f) { m_font = f; if (m_widget) { m_widget->setFont(f); } } void TextTool::updateFamily(const QString &s) { m_font.setFamily(s); if (m_widget) { m_widget->setFont(m_font); } } void TextTool::updateFontUnderline(const bool underlined) { m_font.setUnderline(underlined); if (m_widget) { m_widget->setFont(m_font); } } void TextTool::updateFontStrikeOut(const bool s) { m_font.setStrikeOut(s); if (m_widget) { m_widget->setFont(m_font); } } void TextTool::updateFontWeight(const QFont::Weight w) { m_font.setWeight(w); if (m_widget) { m_widget->setFont(m_font); } } void TextTool::updateFontItalic(const bool italic) { m_font.setItalic(italic); if (m_widget) { m_widget->setFont(m_font); } } flameshot-0.6.0+git20191001/src/tools/text/texttool.h000066400000000000000000000050401354471500100220410ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/capturetool.h" #include class TextWidget; class TextConfig; class TextTool : public CaptureTool { Q_OBJECT public: explicit TextTool(QObject *parent = nullptr); bool isValid() const override; bool closeOnButtonPressed() const override; bool isSelectable() const override; bool showMousePreview() const override; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; QWidget* widget() override; QWidget* configurationWidget() override; CaptureTool* copy(QObject *parent = nullptr) override; void undo(QPixmap &pixmap) override; void process( QPainter &painter, const QPixmap &pixmap, bool recordUndo = false) override; void paintMousePreview(QPainter &painter, const CaptureContext &context) override; public slots: void drawEnd(const QPoint &p) override; void drawMove(const QPoint &p) override; void drawStart(const CaptureContext &context) override; void pressed(const CaptureContext &context) override; void colorChanged(const QColor &c) override; void thicknessChanged(const int th) override; private slots: void updateText(const QString &s); void setFont(const QFont &f); void updateFamily(const QString &s); void updateFontUnderline(const bool underlined); void updateFontStrikeOut(const bool s); void updateFontWeight(const QFont::Weight w); void updateFontItalic(const bool italic); private: QFont m_font; QString m_text; int m_size; QColor m_color; QPixmap m_pixmapBackup; QRect m_backupArea; QPointer m_widget; QPointer m_confW; }; flameshot-0.6.0+git20191001/src/tools/text/textwidget.cpp000066400000000000000000000053521354471500100227100ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "textwidget.h" TextWidget::TextWidget(QWidget *parent) : QTextEdit(parent) { setStyleSheet(QStringLiteral("TextWidget { background: transparent; }")); connect(this, &TextWidget::textChanged, this, &TextWidget::adjustSize); connect(this, &TextWidget::textChanged, this, &TextWidget::emitTextUpdated); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setContextMenuPolicy(Qt::NoContextMenu); } void TextWidget::showEvent(QShowEvent *e) { QFont font; QFontMetrics fm(font); setFixedWidth(fm.lineSpacing() *6); setFixedHeight(fm.lineSpacing() * 2.5); m_baseSize = size(); m_minSize = m_baseSize; QTextEdit::showEvent(e); adjustSize(); } void TextWidget::resizeEvent(QResizeEvent *e) { m_minSize.setHeight(qMin(m_baseSize.height(), height())); m_minSize.setWidth(qMin(m_baseSize.width(), width())); QTextEdit::resizeEvent(e); } void TextWidget::setFont(const QFont &f) { QTextEdit::setFont(f); adjustSize(); } void TextWidget::updateFont(const QFont &f) { setFont(f); } void TextWidget::setFontPointSize(qreal s) { QFont f = font(); f.setPointSize(s); setFont(f); } void TextWidget::setTextColor(const QColor &c) { QString s(QStringLiteral("TextWidget { background: transparent; color: %1; }")); setStyleSheet(s.arg(c.name())); } void TextWidget::adjustSize() { QString &&text = this->toPlainText(); QFontMetrics fm(font()); QRect bounds = fm.boundingRect(QRect(), 0, text); int pixelsWide = bounds.width() + fm.lineSpacing(); int pixelsHigh = bounds.height() * 1.15 + fm.lineSpacing(); if (pixelsWide < m_minSize.width()) { pixelsWide = m_minSize.width(); } if (pixelsHigh < m_minSize.height()) { pixelsHigh = m_minSize.height(); } this->setFixedSize(pixelsWide, pixelsHigh); } void TextWidget::emitTextUpdated() { emit textUpdated(this->toPlainText()); } flameshot-0.6.0+git20191001/src/tools/text/textwidget.h000066400000000000000000000025061354471500100223530ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 TextWidget : public QTextEdit { Q_OBJECT public: explicit TextWidget(QWidget *parent = nullptr); void adjustSize(); void setFont(const QFont &f); protected: void showEvent(QShowEvent *e); void resizeEvent(QResizeEvent *e); signals: void textUpdated(const QString &s); public slots: void updateFont(const QFont &f); void setTextColor(const QColor &c); void setFontPointSize(qreal s); private slots: void emitTextUpdated(); private: QSize m_baseSize; QSize m_minSize; }; flameshot-0.6.0+git20191001/src/tools/toolfactory.cpp000066400000000000000000000065341354471500100221040ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "arrow/arrowtool.h" #include "circle/circletool.h" #include "copy/copytool.h" #include "exit/exittool.h" #include "imgur/imguruploadertool.h" #include "line/linetool.h" #include "marker/markertool.h" #include "move/movetool.h" #include "pencil/penciltool.h" #include "rectangle/rectangletool.h" #include "save/savetool.h" #include "selection/selectiontool.h" #include "sizeindicator/sizeindicatortool.h" #include "undo/undotool.h" #include "launcher/applaunchertool.h" #include "blur/blurtool.h" #include "redo/redotool.h" #include "pin/pintool.h" #include "text/texttool.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_DRAWER: 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_REDO: tool = new RedoTool(parent); break; case CaptureButton::TYPE_OPEN_APP: tool = new AppLauncher(parent); break; case CaptureButton::TYPE_BLUR: tool = new BlurTool(parent); break; case CaptureButton::TYPE_PIN: tool = new PinTool(parent); break; case CaptureButton::TYPE_TEXT: tool = new TextTool(parent); break; default: tool = nullptr; break; } return tool; } flameshot-0.6.0+git20191001/src/tools/toolfactory.h000066400000000000000000000023431354471500100215430ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/widgets/capture/capturebutton.h" #include "src/tools/capturetool.h" #include class CaptureTool; class ToolFactory : public QObject { Q_OBJECT public: explicit ToolFactory(QObject *parent = nullptr); ToolFactory(const ToolFactory &) = delete; ToolFactory & operator=(const ToolFactory &) = delete; CaptureTool* CreateTool( CaptureButton::ButtonType t, QObject *parent = nullptr); }; flameshot-0.6.0+git20191001/src/tools/undo/000077500000000000000000000000001354471500100177705ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/tools/undo/undotool.cpp000066400000000000000000000030031354471500100223330ustar00rootroot00000000000000// Copyright(c) 2017-2019 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) : AbstractActionTool(parent) { } bool UndoTool::closeOnButtonPressed() const { return false; } QIcon UndoTool::icon(const QColor &background, bool inEditor) const { Q_UNUSED(inEditor); return QIcon(iconPath(background) + "undo-variant.svg"); } QString UndoTool::name() const { return tr("Undo"); } QString UndoTool::nameID() { return QLatin1String(""); } QString UndoTool::description() const { return tr("Undo the last modification"); } CaptureTool* UndoTool::copy(QObject *parent) { return new UndoTool(parent); } void UndoTool::pressed(const CaptureContext &context) { Q_UNUSED(context); emit requestAction(REQ_UNDO_MODIFICATION); } flameshot-0.6.0+git20191001/src/tools/undo/undotool.h000066400000000000000000000024361354471500100220110ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/abstractactiontool.h" class UndoTool : public AbstractActionTool { Q_OBJECT public: explicit UndoTool(QObject *parent = nullptr); bool closeOnButtonPressed() const; QIcon icon(const QColor &background, bool inEditor) const override; QString name() const override; static QString nameID(); QString description() const override; CaptureTool* copy(QObject *parent = nullptr) override; public slots: void pressed(const CaptureContext &context) override; }; flameshot-0.6.0+git20191001/src/utils/000077500000000000000000000000001354471500100170235ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/utils/colorutils.cpp000066400000000000000000000024771354471500100217400ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "colorutils.h" inline qreal getColorLuma(const QColor &c) { return 0.30 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF(); } bool ColorUtils::colorIsDark(const QColor &c) { bool isWhite = false; if (getColorLuma(c) <= 0.60) { isWhite = true; } return isWhite; } QColor ColorUtils::contrastColor(const QColor &c) { int change = colorIsDark(c) ? 30 : -45; return QColor(qBound(0, c.red() + change, 255), qBound(0, c.green() + change, 255), qBound(0, c.blue() + change, 255)); } flameshot-0.6.0+git20191001/src/utils/colorutils.h000066400000000000000000000016561354471500100214030ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 namespace ColorUtils { // namespace bool colorIsDark(const QColor &c); QColor contrastColor(const QColor &c); } // namespace flameshot-0.6.0+git20191001/src/utils/confighandler.cpp000066400000000000000000000275611354471500100223450ustar00rootroot00000000000000// Copyright(c) 2017-2019 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(QStringLiteral("buttons"))) { // TODO: remove toList in v1.0 QVector buttonsInt = m_settings.value(QStringLiteral("buttons")).value >().toVector(); bool modified = normalizeButtons(buttonsInt); if (modified) { m_settings.setValue(QStringLiteral("buttons"), QVariant::fromValue(buttonsInt.toList())); } buttons = fromIntToButton(buttonsInt); } else { // Default tools buttons << CaptureButton::TYPE_PENCIL << CaptureButton::TYPE_DRAWER << 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_REDO << CaptureButton::TYPE_COPY << CaptureButton::TYPE_SAVE << CaptureButton::TYPE_EXIT << CaptureButton::TYPE_IMAGEUPLOADER << CaptureButton::TYPE_OPEN_APP << CaptureButton::TYPE_PIN << CaptureButton::TYPE_TEXT; } using bt = CaptureButton::ButtonType; std::sort(buttons.begin(), buttons.end(), [](bt a, bt b){ return CaptureButton::getPriorityByButton(a) < CaptureButton::getPriorityByButton(b); }); return buttons; } void ConfigHandler::setButtons(const QVector &buttons) { QVector l = fromButtonToInt(buttons); normalizeButtons(l); // TODO: remove toList in v1.0 m_settings.setValue(QStringLiteral("buttons"), QVariant::fromValue(l.toList())); } QVector ConfigHandler::getUserColors() { QVector colors; const QVector &defaultColors = { Qt::darkRed, Qt::red, Qt::yellow, Qt::green, Qt::darkGreen, Qt::cyan, Qt::blue, Qt::magenta, Qt::darkMagenta }; if (m_settings.contains(QStringLiteral("userColors"))) { for (const QString &hex : m_settings.value(QStringLiteral("userColors")).toStringList()) { if (QColor::isValidColor(hex)) { colors.append(QColor(hex)); } } if (colors.isEmpty()) { colors = defaultColors; } } else { colors = defaultColors; } return colors; } void ConfigHandler::setUserColors(const QVector &l) { QStringList hexColors; for (const QColor &color : l) { hexColors.append(color.name()); } m_settings.setValue(QStringLiteral("userColors"), QVariant::fromValue(hexColors)); } QString ConfigHandler::savePathValue() { return m_settings.value(QStringLiteral("savePath")).toString(); } void ConfigHandler::setSavePath(const QString &savePath) { m_settings.setValue(QStringLiteral("savePath"), savePath); } QColor ConfigHandler::uiMainColorValue() { QColor res = QColor(116, 0, 150); if (m_settings.contains(QStringLiteral("uiColor"))) { QString hex = m_settings.value(QStringLiteral("uiColor")).toString(); if (QColor::isValidColor(hex)) { res = QColor(hex); } } return res; } void ConfigHandler::setUIMainColor(const QColor &c) { m_settings.setValue(QStringLiteral("uiColor"), c.name()); } QColor ConfigHandler::uiContrastColorValue() { QColor res = QColor(86, 0, 120); if (m_settings.contains(QStringLiteral("contastUiColor"))) { QString hex = m_settings.value(QStringLiteral("contastUiColor")).toString(); if (QColor::isValidColor(hex)) { res = QColor(hex); } } return res; } void ConfigHandler::setUIContrastColor(const QColor &c) { m_settings.setValue(QStringLiteral("contastUiColor"), c.name()); } QColor ConfigHandler::drawColorValue() { QColor res(Qt::red); if (m_settings.contains(QStringLiteral("drawColor"))) { QString hex = m_settings.value(QStringLiteral("drawColor")).toString(); if (QColor::isValidColor(hex)) { res = QColor(hex); } } return res; } void ConfigHandler::setDrawColor(const QColor &c) { m_settings.setValue(QStringLiteral("drawColor"), c.name()); } bool ConfigHandler::showHelpValue() { bool res = true; if (m_settings.contains(QStringLiteral("showHelp"))) { res = m_settings.value(QStringLiteral("showHelp")).toBool(); } return res; } void ConfigHandler::setShowHelp(const bool showHelp) { m_settings.setValue(QStringLiteral("showHelp"), showHelp); } bool ConfigHandler::desktopNotificationValue() { bool res = true; if (m_settings.contains(QStringLiteral("showDesktopNotification"))) { res = m_settings.value(QStringLiteral("showDesktopNotification")).toBool(); } return res; } void ConfigHandler::setDesktopNotification(const bool showDesktopNotification) { m_settings.setValue(QStringLiteral("showDesktopNotification"), showDesktopNotification); } QString ConfigHandler::filenamePatternValue() { return m_settings.value(QStringLiteral("filenamePattern")).toString(); } void ConfigHandler::setFilenamePattern(const QString &pattern) { return m_settings.setValue(QStringLiteral("filenamePattern"), pattern); } bool ConfigHandler::disabledTrayIconValue() { bool res = false; if (m_settings.contains(QStringLiteral("disabledTrayIcon"))) { res = m_settings.value(QStringLiteral("disabledTrayIcon")).toBool(); } return res; } void ConfigHandler::setDisabledTrayIcon(const bool disabledTrayIcon) { m_settings.setValue(QStringLiteral("disabledTrayIcon"), disabledTrayIcon); } int ConfigHandler::drawThicknessValue() { int res = 0; if (m_settings.contains(QStringLiteral("drawThickness"))) { res = m_settings.value(QStringLiteral("drawThickness")).toInt(); } return res; } void ConfigHandler::setdrawThickness(const int thickness) { m_settings.setValue(QStringLiteral("drawThickness"), thickness); } bool ConfigHandler::keepOpenAppLauncherValue() { return m_settings.value(QStringLiteral("keepOpenAppLauncher")).toBool(); } void ConfigHandler::setKeepOpenAppLauncher(const bool keepOpen) { m_settings.setValue(QStringLiteral("keepOpenAppLauncher"), keepOpen); } bool ConfigHandler::startupLaunchValue() { bool res = false; if (m_settings.contains(QStringLiteral("startupLaunch"))) { res = m_settings.value(QStringLiteral("startupLaunch")).toBool(); } if (res != verifyLaunchFile()) { setStartupLaunch(res); } return res; } bool ConfigHandler::verifyLaunchFile() { bool res = false; #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) 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) || defined(Q_OS_UNIX) QString path = QDir::homePath() + "/.config/autostart/"; QDir autostartDir(path); if (!autostartDir.exists()) { autostartDir.mkpath("."); } QFile file(path + "Flameshot.desktop"); 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 m_settings.setValue(QStringLiteral("startupLaunch"), start); } int ConfigHandler::contrastOpacityValue() { int opacity = 190; if (m_settings.contains(QStringLiteral("contrastOpacity"))) { opacity = m_settings.value(QStringLiteral("contrastOpacity")).toInt(); opacity = qBound(0, opacity, 255); } return opacity; } void ConfigHandler::setContrastOpacity(const int transparency) { m_settings.setValue(QStringLiteral("contrastOpacity"), transparency); } bool ConfigHandler::closeAfterScreenshotValue() { return m_settings.value(QStringLiteral("closeAfterScreenshot")).toBool(); } void ConfigHandler::setCloseAfterScreenshot(const bool close) { m_settings.setValue(QStringLiteral("closeAfterScreenshot"), close); } bool ConfigHandler::copyAndCloseAfterUploadEnabled() { return m_settings.value(QStringLiteral("copyAndCloseAfterUpload")).toBool(); } void ConfigHandler::setCopyAndCloseAfterUploadEnabled(const bool value) { m_settings.setValue(QStringLiteral("copyAndCloseAfterUpload"), value); } 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(QStringLiteral("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; } } 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.6.0+git20191001/src/utils/confighandler.h000066400000000000000000000050351354471500100220020ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/widgets/capture/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 verifyLaunchFile(); bool startupLaunchValue(); void setStartupLaunch(const bool); int contrastOpacityValue(); void setContrastOpacity(const int); bool closeAfterScreenshotValue(); void setCloseAfterScreenshot(const bool); bool copyAndCloseAfterUploadEnabled(); void setCopyAndCloseAfterUploadEnabled(const bool); 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.6.0+git20191001/src/utils/dbusutils.cpp000066400000000000000000000042201354471500100215430ustar00rootroot00000000000000// Copyright(c) 2017-2019 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) { } void DBusUtils::connectPrintCapture(QDBusConnection &session, uint id) { m_id = id; // captureTaken session.connect(QStringLiteral("org.dharkael.Flameshot"), QStringLiteral("/"), QLatin1String(""), QStringLiteral("captureTaken"), this, SLOT(captureTaken(uint, QByteArray))); // captureFailed session.connect(QStringLiteral("org.dharkael.Flameshot"), QStringLiteral("/"), QLatin1String(""), QStringLiteral("captureFailed"), this, SLOT(captureFailed(uint))); } void DBusUtils::checkDBusConnection(const QDBusConnection &connection) { if (!connection.isConnected()) { SystemNotification().sendMessage(tr("Unable to connect via DBus")); qApp->exit(1); } } 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 aborted\n"; qApp->exit(1); } } flameshot-0.6.0+git20191001/src/utils/dbusutils.h000066400000000000000000000023411354471500100212120ustar00rootroot00000000000000// Copyright(c) 2017-2019 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); void connectPrintCapture(QDBusConnection &session, uint id); void checkDBusConnection(const QDBusConnection &connection); public slots: void captureTaken(uint id, QByteArray rawImage); void captureFailed(uint id); private: uint m_id; }; flameshot-0.6.0+git20191001/src/utils/desktopfileparse.cpp000066400000000000000000000126501354471500100230770ustar00rootroot00000000000000// Copyright(c) 2017-2019 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(QStringLiteral("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() != QLatin1String("[Desktop Entry]")) { } // start parsing while (!in.atEnd()) { QString line = in.readLine(); if (line.startsWith(QLatin1String("Icon"))) { res.icon = QIcon::fromTheme( line.mid(line.indexOf(QLatin1String("="))+1).trimmed(), m_defaultIcon); } else if (!nameLocaleSet && line.startsWith(QLatin1String("Name"))) { if (line.startsWith(m_localeName) || line.startsWith(m_localeNameShort)) { res.name = line.mid(line.indexOf(QLatin1String("="))+1).trimmed(); nameLocaleSet = true; } else if (line.startsWith(QLatin1String("Name="))) { res.name = line.mid(line.indexOf(QLatin1String("="))+1).trimmed(); } } else if (!descriptionLocaleSet && line.startsWith(QLatin1String("Comment"))) { if (line.startsWith(m_localeDescription) || line.startsWith(m_localeDescriptionShort)) { res.description = line.mid(line.indexOf(QLatin1String("="))+1).trimmed(); descriptionLocaleSet = true; } else if (line.startsWith(QLatin1String("Comment="))) { res.description = line.mid(line.indexOf(QLatin1String("="))+1).trimmed(); } } else if (line.startsWith(QLatin1String("Exec"))) { if (line.contains(QLatin1String("%"))) { res.exec = line.mid(line.indexOf(QLatin1String("="))+1) .trimmed(); } else { ok = false; break; } } else if (line.startsWith(QLatin1String("Type"))) { if (line.contains(QLatin1String("Application"))) { isApplication = true; } } else if (line.startsWith(QLatin1String("Categories"))) { res.categories = line.mid(line.indexOf(QLatin1String("="))+1).split(QStringLiteral(";")); } else if (line == QLatin1String("NoDisplay=true")) { ok = false; break; } else if (line == QLatin1String("Terminal=true")) { res.showInTerminal = true; } // ignore the other entries else if (line.startsWith(QLatin1String("["))) { 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.6.0+git20191001/src/utils/desktopfileparse.h000066400000000000000000000037721354471500100225510ustar00rootroot00000000000000// Copyright(c) 2017-2019 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( const QString &name, const QString &description, const 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.6.0+git20191001/src/utils/desktopinfo.cpp000066400000000000000000000036441354471500100220630ustar00rootroot00000000000000// Copyright(c) 2017-2019 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(QStringLiteral("XDG_CURRENT_DESKTOP")); XDG_SESSION_TYPE = e.value(QStringLiteral("XDG_SESSION_TYPE")); WAYLAND_DISPLAY = e.value(QStringLiteral("WAYLAND_DISPLAY")); KDE_FULL_SESSION = e.value(QStringLiteral("KDE_FULL_SESSION")); GNOME_DESKTOP_SESSION_ID = e.value(QStringLiteral("GNOME_DESKTOP_SESSION_ID")); DESKTOP_SESSION = e.value(QStringLiteral("DESKTOP_SESSION")); } bool DesktopInfo::waylandDectected() { return XDG_SESSION_TYPE == QLatin1String("wayland") || WAYLAND_DISPLAY.contains(QLatin1String("wayland"), Qt::CaseInsensitive); } DesktopInfo::WM DesktopInfo::windowManager() { DesktopInfo::WM res = DesktopInfo::OTHER; if (XDG_CURRENT_DESKTOP.contains(QLatin1String("GNOME"), Qt::CaseInsensitive) || !GNOME_DESKTOP_SESSION_ID.isEmpty()) { res = DesktopInfo::GNOME; } else if (!KDE_FULL_SESSION.isEmpty() || DESKTOP_SESSION == QLatin1String("kde-plasma")) { res = DesktopInfo::KDE; } return res; } flameshot-0.6.0+git20191001/src/utils/desktopinfo.h000066400000000000000000000022661354471500100215270ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/utils/filenamehandler.cpp000066400000000000000000000072601354471500100226520ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 = name; if (name.isEmpty()) { res = QLatin1String("%F_%H-%M"); } std::time_t t = std::time(NULL); char *tempData = QStringTocharArr(res); 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(QLatin1String("/"), QStringLiteral("⁄")).replace(QLatin1String(":"), QLatin1String("-")); 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(QLatin1String("/"))) { directory += QLatin1String("/"); } // 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 += QLatin1String("_"); int i = 1; while (true) { checkFile.setFile( directory + filename + QString::number(i) + ".png"); if (!checkFile.exists()) { filename += QString::number(i); break; } ++i; } } } flameshot-0.6.0+git20191001/src/utils/filenamehandler.h000066400000000000000000000027071354471500100223200ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/utils/globalvalues.cpp000066400000000000000000000016731354471500100222160ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "globalvalues.h" #include #include int GlobalValues::buttonBaseSize() { return QApplication::fontMetrics().lineSpacing() * 2.2; } flameshot-0.6.0+git20191001/src/utils/globalvalues.h000066400000000000000000000015161354471500100216570ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 namespace GlobalValues { int buttonBaseSize(); } flameshot-0.6.0+git20191001/src/utils/pathinfo.cpp000066400000000000000000000032041354471500100213360ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 const QString PathInfo::whiteIconPath() { return QStringLiteral(":/img/material/white/"); } const QString PathInfo::blackIconPath() { return QStringLiteral(":/img/material/black/"); } QStringList PathInfo::translationsPaths() { QString binaryPath = QFileInfo(qApp->applicationDirPath()) .absoluteFilePath(); QString trPath = QDir::toNativeSeparators(binaryPath + "/translations") ; #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) return QStringList() << QStringLiteral(APP_PREFIX) + "/share/flameshot/translations" << trPath << QStringLiteral("/usr/share/flameshot/translations") << QStringLiteral("/usr/local/share/flameshot/translations"); #elif defined(Q_OS_WIN) return QStringList() << trPath; #endif } flameshot-0.6.0+git20191001/src/utils/pathinfo.h000066400000000000000000000017071354471500100210110ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 namespace PathInfo { // namespace const QString whiteIconPath(); const QString blackIconPath(); QStringList translationsPaths(); } // namespace flameshot-0.6.0+git20191001/src/utils/screengrabber.cpp000066400000000000000000000112721354471500100223360ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "src/utils/systemnotification.h" #include #include #include #include #include #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) #include #include #include #endif ScreenGrabber::ScreenGrabber(QObject *parent) : QObject(parent) { } QPixmap ScreenGrabber::grabEntireDesktop(bool &ok) { ok = true; #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) 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(QStringLiteral("Screenshot"), false, false, path); if (reply.value()) { res = QPixmap(path); QFile dbusResult(path); dbusResult.remove(); } 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(QStringLiteral("screenshotFullscreen")); res = QPixmap(reply.value()); if (!res.isNull()) { QFile dbusResult(reply.value()); dbusResult.remove(); } break; } default: ok = false; break; } if (!ok) { SystemNotification().sendMessage(tr("Unable to capture screen")); } 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()) ); auto screenNumber = QApplication::desktop()->screenNumber(); QScreen *screen = QApplication::screens()[screenNumber]; p.setDevicePixelRatio(screen->devicePixelRatio()); return p; } QPixmap ScreenGrabber::grabScreen(int screenNumber, bool &ok) { QPixmap p; bool isVirtual = QApplication::desktop()->isVirtualDesktop(); if (isVirtual || m_info.waylandDectected()) { p = grabEntireDesktop(ok); if (ok) { QPoint topLeft(0, 0); #ifdef Q_OS_WIN for (QScreen *const screen : QGuiApplication::screens()) { QPoint topLeftScreen = screen->geometry().topLeft(); if (topLeft.x() > topLeftScreen.x() || topLeft.y() > topLeftScreen.y()) { topLeft = topLeftScreen; } } #endif QRect geometry = QApplication::desktop()-> screenGeometry(screenNumber); geometry.moveTo(geometry.topLeft() - topLeft); p = p.copy(geometry); } } else { p = QApplication::desktop()->screen(screenNumber)->grab(); ok = true; } return p; } flameshot-0.6.0+git20191001/src/utils/screengrabber.h000066400000000000000000000021071354471500100220000ustar00rootroot00000000000000// Copyright(c) 2017-2019 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); QPixmap grabScreen(int screenNumber, bool &ok); private: DesktopInfo m_info; }; flameshot-0.6.0+git20191001/src/utils/screenshotsaver.cpp000066400000000000000000000065621354471500100227560ustar00rootroot00000000000000// Copyright(c) 2017-2019 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) { SystemNotification().sendMessage( QObject::tr("Capture saved to clipboard")); QApplication::clipboard()->setPixmap(capture); } bool ScreenshotSaver::saveToFilesystem(const QPixmap &capture, const QString &path) { QString completePath = FileNameHandler().generateAbsolutePath(path); completePath += QLatin1String(".png"); bool ok = capture.save(completePath); QString saveMessage; QString notificationPath = completePath; if (ok) { ConfigHandler().setSavePath(path); saveMessage = QObject::tr("Capture saved as ") + completePath; } else { saveMessage = QObject::tr("Error trying to save as ") + completePath; notificationPath = ""; } SystemNotification().sendMessage(saveMessage, notificationPath); return ok; } bool ScreenshotSaver::saveToFilesystemGUI(const QPixmap &capture) { bool ok = false; while (!ok) { QString savePath = QFileDialog::getSaveFileName( nullptr, QString(), FileNameHandler().absoluteSavePath() + ".png", QLatin1String("Portable Network Graphic file (PNG) (*.png);;BMP file (*.bmp);;JPEG file (*.jpg)")); if (savePath.isNull()) { break; } if (!savePath.endsWith(QLatin1String(".png"), Qt::CaseInsensitive) && !savePath.endsWith(QLatin1String(".bmp"), Qt::CaseInsensitive) && !savePath.endsWith(QLatin1String(".jpg"), Qt::CaseInsensitive)) { savePath += QLatin1String(".png"); } ok = capture.save(savePath); if (ok) { QString pathNoFile = savePath.left(savePath.lastIndexOf(QLatin1String("/"))); ConfigHandler().setSavePath(pathNoFile); QString msg = QObject::tr("Capture saved as ") + savePath; SystemNotification().sendMessage(msg, savePath); } else { QString msg = QObject::tr("Error trying to save as ") + savePath; QMessageBox saveErrBox( QMessageBox::Warning, QObject::tr("Save Error"), msg); saveErrBox.setWindowIcon(QIcon(":img/app/flameshot.svg")); saveErrBox.exec(); } } return ok; } flameshot-0.6.0+git20191001/src/utils/screenshotsaver.h000066400000000000000000000020461354471500100224140ustar00rootroot00000000000000// Copyright(c) 2017-2019 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); bool saveToFilesystem(const QPixmap &capture, const QString &path); bool saveToFilesystemGUI(const QPixmap &capture); }; flameshot-0.6.0+git20191001/src/utils/systemnotification.cpp000066400000000000000000000041361354471500100234660ustar00rootroot00000000000000#include "systemnotification.h" #include "src/utils/confighandler.h" #include #include #ifndef Q_OS_WIN #include #include #include #else #endif #include "src/core/controller.h" #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) 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) { m_interface = nullptr; } #endif void SystemNotification::sendMessage(const QString &text, const QString &savePath) { sendMessage(text, tr("Flameshot Info"), savePath); } void SystemNotification::sendMessage( const QString &text, const QString &title, const QString &savePath, const int timeout) { if(!ConfigHandler().desktopNotificationValue()) { return; } #ifndef Q_OS_WIN QList args; QVariantMap hintsMap; if (!savePath.isEmpty()) { QUrl fullPath = QUrl::fromLocalFile(savePath); // allows the notification to be dragged and dropped hintsMap[QStringLiteral("x-kde-urls")] = QStringList({fullPath.toString()}); } args << (qAppName()) //appname << static_cast(0) //id << "flameshot" //icon << title //summary << text //body << QStringList() //actions << hintsMap //hints << timeout; //timeout m_interface->callWithArgumentList(QDBus::AutoDetect, QStringLiteral("Notify"), args); #else auto c = Controller::getInstance(); c->sendTrayNotification(text, title, timeout); #endif } flameshot-0.6.0+git20191001/src/utils/systemnotification.h000066400000000000000000000024041354471500100231270ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 &savePath = {}); void sendMessage(const QString &text, const QString &title, const QString &savePath, const int timeout = 5000); private: QDBusInterface *m_interface; }; flameshot-0.6.0+git20191001/src/utils/waylandutils.cpp000066400000000000000000000001501354471500100222430ustar00rootroot00000000000000#include "waylandutils.h" WaylandUtils::WaylandUtils() { } bool WaylandUtils::waylandDetected() { } flameshot-0.6.0+git20191001/src/utils/waylandutils.h000066400000000000000000000002551354471500100217160ustar00rootroot00000000000000#ifndef WAYLANDUTILS_H #define WAYLANDUTILS_H class WaylandUtils { public: WaylandUtils(); static bool waylandDetected(); private: }; #endif // WAYLANDUTILS_H flameshot-0.6.0+git20191001/src/widgets/000077500000000000000000000000001354471500100173315ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/widgets/capture/000077500000000000000000000000001354471500100207745ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/widgets/capture/buttonhandler.cpp000066400000000000000000000324641354471500100243620ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "src/utils/globalvalues.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 = intersectWithAreas(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) { m_selection = selection; 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 button 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 auxiliary 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 auxiliary 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; } QRect ButtonHandler::intersectWithAreas(const QRect &rect) { QRect res; for(const QRect &r : m_screenRegions.rects()) { QRect temp = rect.intersected(r); if (temp.height() * temp.width() > res.height() * res.width()) { res = temp; } } return res; } void ButtonHandler::init() { m_separator = GlobalValues::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)); // Bottom 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)); // Auxiliary 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() { int &s = m_buttonExtendedSize; m_selection = m_selection + QMargins(s, s, s, s); m_selection = intersectWithAreas(m_selection); } void ButtonHandler::positionButtonsInside(int index) { // Position the buttons in the botton-center of the main but inside of the // selection. QRect mainArea = m_selection; mainArea = intersectWithAreas(mainArea); const int buttonsPerRow = (mainArea.width()) / (m_buttonExtendedSize); if (buttonsPerRow == 0) { return; } QPoint center = QPoint(mainArea.center().x(), mainArea.bottom() - m_buttonExtendedSize); while (m_vectorButtons.size() > index) { int addCounter = buttonsPerRow; addCounter = qBound(0, addCounter, m_vectorButtons.size() - index); QVector positions = horizontalPoints(center, addCounter, true); moveButtonsToPoints(positions, index); center.setY(center.y() - 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 = GlobalValues::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; } } void ButtonHandler::updateScreenRegions(const QRect &rect) { m_screenRegions = QRegion(rect); } flameshot-0.6.0+git20191001/src/widgets/capture/buttonhandler.h000066400000000000000000000051051354471500100240170ustar00rootroot00000000000000// Copyright(c) 2017-2019 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); explicit ButtonHandler(QObject *parent = nullptr); void hideSectionUnderMouse(const QPoint &p); bool isVisible() const; bool buttonsAreInside() const; size_t size() const; void setButtons(const QVector); bool contains(const QPoint &p) const; void updateScreenRegions(const QVector &rects); void updateScreenRegions(const QRect &rect); public slots: void updatePosition(const QRect &selection); 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; QRect intersectWithAreas(const QRect &rect); 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.6.0+git20191001/src/widgets/capture/capturebutton.cpp000066400000000000000000000153741354471500100244110ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/widgets/capture/capturewidget.h" #include "src/utils/confighandler.h" #include "src/tools/capturetool.h" #include "src/tools/toolfactory.h" #include "src/utils/globalvalues.h" #include "src/utils/colorutils.h" #include #include #include #include #include #include // Button represents a single button of the capture widget, it can enable // multiple functionality. 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); setFocusPolicy(Qt::NoFocus); resize(GlobalValues::buttonBaseSize(), GlobalValues::buttonBaseSize()); setMask(QRegion(QRect(-1,-1, GlobalValues::buttonBaseSize()+2, GlobalValues::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(GlobalValues::buttonBaseSize(), GlobalValues::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 = ColorUtils::contrastColor(m_mainColor); // foreground color QString color = ColorUtils::colorIsDark(mainColor) ? "white" : "black"; return baseSheet.arg(mainColor.name()).arg(contrast.name()) .arg(GlobalValues::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 = ColorUtils::contrastColor(m_mainColor); // foreground color QString color = ColorUtils::colorIsDark(m_mainColor) ? "white" : "black"; return baseSheet.arg(m_mainColor.name()).arg(contrast.name()) .arg(GlobalValues::buttonBaseSize()/2).arg(color); } // get icon returns the icon for the type of button QIcon CaptureButton::icon() const { return m_tool->icon(m_mainColor, true); } void CaptureButton::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { emit pressedButton(this); emit pressed(); } } void CaptureButton::animatedShow() { if(!isVisible()) { show(); m_emergeAnimation->start(); connect(m_emergeAnimation, &QPropertyAnimation::finished, this, [](){ }); } } CaptureTool *CaptureButton::tool() const { return m_tool; } void CaptureButton::setColor(const QColor &c) { m_mainColor = c; setStyleSheet(styleSheet()); updateIcon(); } QColor CaptureButton::m_mainColor = ConfigHandler().uiMainColorValue(); static std::map buttonTypeOrder { { CaptureButton::TYPE_PENCIL, 0 }, { CaptureButton::TYPE_DRAWER, 1 }, { CaptureButton::TYPE_ARROW, 2 }, { CaptureButton::TYPE_SELECTION, 3 }, { CaptureButton::TYPE_RECTANGLE, 4 }, { CaptureButton::TYPE_CIRCLE, 5 }, { CaptureButton::TYPE_MARKER, 6 }, { CaptureButton::TYPE_TEXT, 7 }, { CaptureButton::TYPE_BLUR, 8 }, { CaptureButton::TYPE_SELECTIONINDICATOR, 9 }, { CaptureButton::TYPE_MOVESELECTION, 10 }, { CaptureButton::TYPE_UNDO, 11 }, { CaptureButton::TYPE_REDO, 12 }, { CaptureButton::TYPE_COPY, 13 }, { CaptureButton::TYPE_SAVE, 14 }, { CaptureButton::TYPE_EXIT, 15 }, { CaptureButton::TYPE_IMAGEUPLOADER, 16 }, { CaptureButton::TYPE_OPEN_APP, 17 }, { CaptureButton::TYPE_PIN, 18 }, }; 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_DRAWER, CaptureButton::TYPE_ARROW, CaptureButton::TYPE_SELECTION, CaptureButton::TYPE_RECTANGLE, CaptureButton::TYPE_CIRCLE, CaptureButton::TYPE_MARKER, CaptureButton::TYPE_TEXT, CaptureButton::TYPE_BLUR, CaptureButton::TYPE_SELECTIONINDICATOR, CaptureButton::TYPE_MOVESELECTION, CaptureButton::TYPE_UNDO, CaptureButton::TYPE_REDO, CaptureButton::TYPE_COPY, CaptureButton::TYPE_SAVE, CaptureButton::TYPE_EXIT, CaptureButton::TYPE_IMAGEUPLOADER, CaptureButton::TYPE_OPEN_APP, CaptureButton::TYPE_PIN, }; flameshot-0.6.0+git20191001/src/widgets/capture/capturebutton.h000066400000000000000000000051411354471500100240450ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 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_DRAWER = 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, TYPE_REDO = 16, TYPE_PIN = 17, TYPE_TEXT = 18, }; #if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) Q_ENUMS(ButtonType) #else Q_ENUM(ButtonType) #endif CaptureButton() = delete; explicit CaptureButton(const ButtonType, QWidget *parent = nullptr); static QString globalStyleSheet(); static QVector getIterableButtonTypes(); static int getPriorityByButton(CaptureButton::ButtonType); QString name() const; QString description() const; QIcon icon() const; QString styleSheet() 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 = nullptr); ButtonType m_buttonType; QPropertyAnimation *m_emergeAnimation; static QColor m_mainColor; void initButton(); void updateIcon(); }; flameshot-0.6.0+git20191001/src/widgets/capture/capturewidget.cpp000066400000000000000000000766171354471500100243700ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "capturewidget.h" #include "src/widgets/capture/hovereventfilter.h" #include "src/widgets/panel/sidepanelwidget.h" #include "src/utils/colorutils.h" #include "src/utils/globalvalues.h" #include "src/widgets/capture/notifierbox.h" #include "src/widgets/capture/colorpicker.h" #include "src/utils/screengrabber.h" #include "src/utils/systemnotification.h" #include "src/utils/screenshotsaver.h" #include "src/core/controller.h" #include "src/widgets/capture/modificationcommand.h" #include #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 &savePath, bool fullScreen, QWidget *parent) : QWidget(parent), m_mouseIsClicked(false), m_rightClick(false), m_newSelection(false), m_grabbing(false), m_captureDone(false), m_previewEnabled(true), m_adjustmentButtonPressed(false), m_activeButton(nullptr), m_activeTool(nullptr), m_toolWidget(nullptr), m_mouseOverHandle(SelectionWidget::NO_SIDE), m_id(id) { // Base config of the widget m_eventFilter = new HoverEventFilter(this); connect(m_eventFilter, &HoverEventFilter::hoverIn, this, &CaptureWidget::childEnter); connect(m_eventFilter, &HoverEventFilter::hoverOut, this, &CaptureWidget::childLeave); setAttribute(Qt::WA_DeleteOnClose); m_showInitialMsg = m_config.showHelpValue(); m_opacity = m_config.contrastOpacityValue(); setMouseTracking(true); initContext(savePath, fullScreen); initShortcuts(); #ifdef Q_OS_WIN // Top left of the whole set of screens QPoint topLeft(0,0); #endif if (fullScreen) { // Grab Screenshot bool ok = true; m_context.screenshot = ScreenGrabber().grabEntireDesktop(ok); if(!ok) { SystemNotification().sendMessage(tr("Unable to capture screen")); this->close(); } m_context.origScreenshot = m_context.screenshot; #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 (m_context.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(); initSelection(); updateCursor(); // Init color picker m_colorPicker = new ColorPicker(this); connect(m_colorPicker, &ColorPicker::colorSelected, this, &CaptureWidget::setDrawColor); m_colorPicker->hide(); // Init notification widget m_notifierBox = new NotifierBox(this); m_notifierBox->hide(); connect(&m_undoStack, &QUndoStack::indexChanged, this, [this](int){ this->update(); }); initPanel(); } CaptureWidget::~CaptureWidget() { if (m_captureDone) { emit captureTaken(m_id, this->pixmap()); } else { emit captureFailed(m_id); } m_config.setdrawThickness(m_context.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); makeChild(b); connect(b, &CaptureButton::pressedButton, this, &CaptureWidget::setState); connect(b->tool(), &CaptureTool::requestAction, this, &CaptureWidget::handleButtonSignal); vectorButtons << b; } m_buttonHandler->setButtons(vectorButtons); } QPixmap CaptureWidget::pixmap() { QPixmap p; if (m_toolWidget && m_activeTool) { p = m_context.selectedScreenshotArea().copy(); QPainter painter(&p); m_activeTool->process(painter, p); } else { p = m_context.selectedScreenshotArea(); } return m_context.selectedScreenshotArea(); } void CaptureWidget::deleteToolwidgetOrClose() { if (m_toolWidget) { m_toolWidget->deleteLater(); m_toolWidget = nullptr; } else { close(); } } void CaptureWidget::paintEvent(QPaintEvent *) { QPainter painter(this); painter.drawPixmap(0, 0, m_context.screenshot); if (m_activeTool && m_mouseIsClicked) { painter.save(); m_activeTool->process(painter, m_context.screenshot); painter.restore(); } else if (m_activeButton && m_activeButton->tool()->showMousePreview() && m_previewEnabled) { painter.save(); m_activeButton->tool()->paintMousePreview(painter, m_context); painter.restore(); } QColor overlayColor(0, 0, 0, m_opacity); painter.setBrush(overlayColor); QRect r; if (m_selection->isVisible()) { r = m_selection->geometry().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." "\nPress Space to open the side panel."); // 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((ColorUtils::colorIsDark(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->isVisible()) { // paint handlers painter.setPen(m_uiColor); painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(m_uiColor); for(auto r: m_selection->handlerAreas()) { 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; // Click using a tool if (m_activeButton) { if (m_activeTool) { if (m_activeTool->isValid() && m_toolWidget) { pushToolToStack(); } else { m_activeTool->deleteLater(); } if (m_toolWidget) { m_toolWidget->deleteLater(); return; } } m_activeTool = m_activeButton->tool()->copy(this); connect(this, &CaptureWidget::colorChanged, m_activeTool, &CaptureTool::colorChanged); connect(this, &CaptureWidget::thicknessChanged, m_activeTool, &CaptureTool::thicknessChanged); connect(m_activeTool, &CaptureTool::requestAction, this, &CaptureWidget::handleButtonSignal); m_activeTool->drawStart(m_context); return; } m_dragStartPoint = e->pos(); m_selection->saveGeometry(); // New selection if (!m_selection->geometry().contains(e->pos()) && m_mouseOverHandle == SelectionWidget::NO_SIDE) { m_selection->setGeometry(QRect(e->pos(), e->pos())); m_selection->setVisible(false); m_newSelection = true; m_buttonHandler->hide(); update(); } else { m_grabbing = true; } } updateCursor(); } void CaptureWidget::mouseMoveEvent(QMouseEvent *e) { m_context.mousePos = e->pos(); if (m_mouseIsClicked && !m_activeButton) { if (m_buttonHandler->isVisible()) { m_buttonHandler->hide(); } if (m_newSelection) { m_selection->setVisible(true); m_selection->setGeometry( QRect(m_dragStartPoint, m_context.mousePos).normalized()); update(); } else if (m_mouseOverHandle == SelectionWidget::NO_SIDE) { // Moving the whole selection QRect initialRect = m_selection->savedGeometry().normalized(); QPoint newTopLeft = initialRect.topLeft() + (e->pos() - m_dragStartPoint); QRect finalRect(newTopLeft, initialRect.size()); if (finalRect.left() < rect().left()) { finalRect.setLeft(rect().left()); } else if (finalRect.right() > rect().right()) { finalRect.setRight(rect().right()); } if (finalRect.top() < rect().top()) { finalRect.setTop(rect().top()); } else if (finalRect.bottom() > rect().bottom()) { finalRect.setBottom(rect().bottom()); } m_selection->setGeometry(finalRect.normalized().intersected(rect())); update(); } else { // Dragging a handle QRect r = m_selection->savedGeometry(); QPoint offset = e->pos() - m_dragStartPoint; bool symmetryMod = qApp->keyboardModifiers() & Qt::ShiftModifier; using sw = SelectionWidget; if (m_mouseOverHandle == sw::TOPLEFT_SIDE || m_mouseOverHandle == sw::TOP_SIDE || m_mouseOverHandle == sw::TOPRIGHT_SIDE) { // dragging one of the top handles r.setTop(r.top() + offset.y()); if (symmetryMod) { r.setBottom(r.bottom() - offset.y()); } } if (m_mouseOverHandle == sw::TOPLEFT_SIDE || m_mouseOverHandle == sw::LEFT_SIDE || m_mouseOverHandle == sw::BOTTONLEFT_SIDE) { // dragging one of the left handles r.setLeft(r.left() + offset.x()); if (symmetryMod) { r.setRight(r.right() - offset.x()); } } if (m_mouseOverHandle == sw::BOTTONLEFT_SIDE || m_mouseOverHandle == sw::BOTTON_SIDE || m_mouseOverHandle == sw::BOTTONRIGHT_SIDE) { // dragging one of the bottom handles r.setBottom(r.bottom() + offset.y()); if (symmetryMod) { r.setTop(r.top() - offset.y()); } } if (m_mouseOverHandle == sw::TOPRIGHT_SIDE || m_mouseOverHandle == sw::RIGHT_SIDE || m_mouseOverHandle == sw::BOTTONRIGHT_SIDE) { // dragging one of the right handles r.setRight(r.right() + offset.x()); if (symmetryMod) { r.setLeft(r.left() - offset.x()); } } m_selection->setGeometry(r.intersected(rect()).normalized()); update(); } } else if (m_mouseIsClicked && m_activeTool) { // drawing with a tool if (m_adjustmentButtonPressed) { m_activeTool->drawMoveWithAdjustment(e->pos()); } else { m_activeTool->drawMove(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_context.mousePos); if (containsMouse) { m_buttonHandler->hide(); } else { m_buttonHandler->show(); } } } else if (m_activeButton && m_activeButton->tool()->showMousePreview()) { update(); } else { if (!m_selection->isVisible()) { return; } m_mouseOverHandle = m_selection->getMouseSide(m_context.mousePos); updateCursor(); } } void CaptureWidget::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) { m_colorPicker->hide(); m_rightClick = false; // when we end the drawing we have to register the last point and //add the temp modification to the list of modifications } else if (m_mouseIsClicked && m_activeTool) { m_activeTool->drawEnd(m_context.mousePos); if (m_activeTool->isValid()) { pushToolToStack(); } else if (!m_toolWidget){ m_activeTool->deleteLater(); m_activeTool = nullptr; } } // Show the buttons after the resize of the selection or the creation // of a new one. if (!m_buttonHandler->isVisible() && m_selection->isVisible()) { // Don't go outside QRect newGeometry = m_selection->geometry().intersected(rect()); // normalize if (newGeometry.width() <= 0) { int left = newGeometry.left(); newGeometry.setLeft(newGeometry.right()); newGeometry.setRight(left); } if (newGeometry.height() <= 0) { int top = newGeometry.top(); newGeometry.setTop(newGeometry.bottom()); newGeometry.setBottom(top); } m_selection->setGeometry(newGeometry); m_context.selection = extendedRect(&newGeometry); updateSizeIndicator(); m_buttonHandler->updatePosition(newGeometry); m_buttonHandler->show(); } m_mouseIsClicked = false; m_newSelection = false; m_grabbing = false; updateCursor(); } void CaptureWidget::keyPressEvent(QKeyEvent *e) { if (!m_selection->isVisible()) { return; } else if (e->key() == Qt::Key_Up && m_selection->geometry().top() > rect().top()) { m_selection->move(QPoint(m_selection->x(), m_selection->y() -1)); QRect newGeometry = m_selection->geometry().intersected(rect()); m_context.selection = extendedRect(&newGeometry); m_buttonHandler->updatePosition(m_selection->geometry()); update(); } else if (e->key() == Qt::Key_Down && m_selection->geometry().bottom() < rect().bottom()) { m_selection->move(QPoint(m_selection->x(), m_selection->y() +1)); QRect newGeometry = m_selection->geometry().intersected(rect()); m_context.selection = extendedRect(&newGeometry); m_buttonHandler->updatePosition(m_selection->geometry()); update(); } else if (e->key() == Qt::Key_Left && m_selection->geometry().left() > rect().left()) { m_selection->move(QPoint(m_selection->x() -1, m_selection->y())); m_buttonHandler->updatePosition(m_selection->geometry()); update(); } else if (e->key() == Qt::Key_Right && m_selection->geometry().right() < rect().right()) { m_selection->move(QPoint(m_selection->x() +1, m_selection->y())); QRect newGeometry = m_selection->geometry().intersected(rect()); m_context.selection = extendedRect(&newGeometry); m_buttonHandler->updatePosition(m_selection->geometry()); update(); } else if (e->key() == Qt::Key_Control) { m_adjustmentButtonPressed = true; } } void CaptureWidget::keyReleaseEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Control) { m_adjustmentButtonPressed = false; } } void CaptureWidget::wheelEvent(QWheelEvent *e) { m_context.thickness += e->delta() / 120; m_context.thickness = qBound(0, m_context.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_context.thickness)); if (m_activeButton && m_activeButton->tool()->showMousePreview()) { update(); } emit thicknessChanged(m_context.thickness); } void CaptureWidget::resizeEvent(QResizeEvent *e) { QWidget::resizeEvent(e); m_context.widgetDimensions = rect(); m_context.widgetOffset = mapToGlobal(QPoint(0,0)); m_panel->setFixedHeight(height()); if (!m_context.fullscreen) { m_buttonHandler->updateScreenRegions(rect()); } } void CaptureWidget::moveEvent(QMoveEvent *e) { QWidget::moveEvent(e); m_context.widgetOffset = mapToGlobal(QPoint(0,0)); } void CaptureWidget::initContext(const QString &savePath, bool fullscreen) { m_context.widgetDimensions = rect(); m_context.color = m_config.drawColorValue(); m_context.savePath = savePath; m_context.widgetOffset = mapToGlobal(QPoint(0,0)); m_context.mousePos= mapFromGlobal(QCursor::pos()); m_context.thickness = m_config.drawThicknessValue(); m_context.fullscreen = fullscreen; } void CaptureWidget::initPanel() { m_panel = new UtilityPanel(this); makeChild(m_panel); QRect panelRect = rect(); if (m_context.fullscreen) { panelRect = QGuiApplication::primaryScreen()->geometry(); } panelRect.moveTo(mapFromGlobal(panelRect.topLeft())); panelRect.setWidth(m_colorPicker->width() * 3); m_panel->setGeometry(panelRect); SidePanelWidget *sidePanel = new SidePanelWidget(&m_context.screenshot); connect(sidePanel, &SidePanelWidget::colorChanged, this, &CaptureWidget::setDrawColor); connect(sidePanel, &SidePanelWidget::thicknessChanged, this, &CaptureWidget::setDrawThickness); connect(this, &CaptureWidget::colorChanged, sidePanel, &SidePanelWidget::updateColor); connect(this, &CaptureWidget::thicknessChanged, sidePanel, &SidePanelWidget::updateThickness); connect(sidePanel, &SidePanelWidget::togglePanel, m_panel, &UtilityPanel::toggle); sidePanel->colorChanged(m_context.color); sidePanel->thicknessChanged(m_context.thickness); m_panel->pushWidget(sidePanel); m_panel->pushWidget(new QUndoView(&m_undoStack, this)); } void CaptureWidget::initSelection() { m_selection = new SelectionWidget(m_uiColor, this); connect(m_selection, &SelectionWidget::animationEnded, this, [this](){ this->m_buttonHandler->updatePosition(this->m_selection->geometry()); }); m_selection->setVisible(false); m_selection->setGeometry(QRect()); } void CaptureWidget::setState(CaptureButton *b) { if (!b) { return; } if (m_toolWidget) { m_toolWidget->deleteLater(); if (m_activeTool->isValid()) { pushToolToStack(); } } if (m_activeButton != b) { processTool(b->tool()); } // Only close activated from button if (b->tool()->closeOnButtonPressed()) { close(); } if (b->tool()->isSelectable()) { if (m_activeButton != b) { QWidget *confW = b->tool()->configurationWidget(); m_panel->addToolWidget(confW); if (m_activeButton) { m_activeButton->setColor(m_uiColor); } m_activeButton = b; m_activeButton->setColor(m_contrastUiColor); } else if (m_activeButton) { m_panel->clearToolWidget(); m_activeButton->setColor(m_uiColor); m_activeButton = nullptr; } update(); // clear mouse preview } } void CaptureWidget::processTool(CaptureTool *t) { auto backup = m_activeTool; // The tool is active during the pressed(). m_activeTool = t; t->pressed(m_context); m_activeTool = backup; } void CaptureWidget::handleButtonSignal(CaptureTool::Request r) { switch (r) { case CaptureTool::REQ_CLEAR_MODIFICATIONS: m_undoStack.setIndex(0); update(); 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->setVisible(false); updateCursor(); break; case CaptureTool::REQ_SELECT_ALL: m_selection->setGeometryAnimated(rect()); break; case CaptureTool::REQ_UNDO_MODIFICATION: m_undoStack.undo(); break; case CaptureTool::REQ_REDO_MODIFICATION: m_undoStack.redo(); break; case CaptureTool::REQ_REDRAW: update(); break; case CaptureTool::REQ_TOGGLE_SIDEBAR: m_panel->toggle(); break; case CaptureTool::REQ_SHOW_COLOR_PICKER: // TODO break; case CaptureTool::REQ_MOVE_MODE: setState(m_activeButton); // Disable the actual button break; case CaptureTool::REQ_CAPTURE_DONE_OK: m_captureDone = true; break; case CaptureTool::REQ_ADD_CHILD_WIDGET: if (!m_activeTool) { break; } if (m_toolWidget) { m_toolWidget->deleteLater(); } m_toolWidget = m_activeTool->widget(); if (m_toolWidget) { makeChild(m_toolWidget); m_toolWidget->move(m_context.mousePos); m_toolWidget->show(); m_toolWidget->setFocus(); } break; case CaptureTool::REQ_ADD_CHILD_WINDOW: if (!m_activeTool) { break; } else { QWidget *w = m_activeTool->widget(); connect(this, &CaptureWidget::destroyed, w, &QWidget::deleteLater); w->show(); } break; case CaptureTool::REQ_ADD_EXTERNAL_WIDGETS: if (!m_activeTool) { break; } else { QWidget *w = m_activeTool->widget(); w->setAttribute(Qt::WA_DeleteOnClose); w->show(); } break; default: break; } } void CaptureWidget::setDrawColor(const QColor &c) { m_context.color = c; ConfigHandler().setDrawColor(m_context.color); emit colorChanged(c); } void CaptureWidget::setDrawThickness(const int &t) { m_context.thickness = qBound(0, t, 100); ConfigHandler().setdrawThickness(m_context.thickness); emit thicknessChanged(m_context.thickness); } void CaptureWidget::leftResize() { if (m_selection->isVisible() && m_selection->geometry().right() > m_selection->geometry().left()) { m_selection->setGeometry(m_selection->geometry() + QMargins(0, 0, -1, 0)); QRect newGeometry = m_selection->geometry().intersected(rect()); m_context.selection = extendedRect(&newGeometry); m_buttonHandler->updatePosition(m_selection->geometry()); updateSizeIndicator(); update(); } } void CaptureWidget::rightResize() { if (m_selection->isVisible() && m_selection->geometry().right() < rect().right()) { m_selection->setGeometry(m_selection->geometry() + QMargins(0, 0, 1, 0)); QRect newGeometry = m_selection->geometry().intersected(rect()); m_context.selection = extendedRect(&newGeometry); m_buttonHandler->updatePosition(m_selection->geometry()); updateSizeIndicator(); update(); } } void CaptureWidget::upResize() { if (m_selection->isVisible() && m_selection->geometry().bottom() > m_selection->geometry().top()) { m_selection->setGeometry(m_selection->geometry() + QMargins(0, 0, 0, -1)); QRect newGeometry = m_selection->geometry().intersected(rect()); m_context.selection = extendedRect(&newGeometry); m_buttonHandler->updatePosition(m_selection->geometry()); updateSizeIndicator(); update(); } } void CaptureWidget::downResize() { if (m_selection->isVisible() && m_selection->geometry().bottom() < rect().bottom()) { m_selection->setGeometry(m_selection->geometry() + QMargins(0, 0, 0, 1)); QRect newGeometry = m_selection->geometry().intersected(rect()); m_context.selection = extendedRect(&newGeometry); m_buttonHandler->updatePosition(m_selection->geometry()); updateSizeIndicator(); 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::CTRL + Qt::SHIFT + Qt::Key_Z), this, SLOT(redo())); 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_Space, this, SLOT(togglePanel())); new QShortcut(Qt::Key_Escape, this, SLOT(deleteToolwidgetOrClose())); new QShortcut(Qt::Key_Return, this, SLOT(copyScreenshot())); new QShortcut(Qt::Key_Enter, this, SLOT(copyScreenshot())); } 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_activeButton) { using sw = SelectionWidget; if (m_mouseOverHandle != sw::NO_SIDE){ // cursor on the handlers switch (m_mouseOverHandle) { case sw::TOPLEFT_SIDE: case sw::BOTTONRIGHT_SIDE: setCursor(Qt::SizeFDiagCursor); break; case sw::TOPRIGHT_SIDE: case sw::BOTTONLEFT_SIDE: setCursor(Qt::SizeBDiagCursor); break; case sw::LEFT_SIDE: case sw::RIGHT_SIDE: setCursor(Qt::SizeHorCursor); break; case sw::TOP_SIDE: case sw::BOTTON_SIDE: setCursor(Qt::SizeVerCursor); break; default: break; } } else if (m_selection->isVisible() && m_selection->geometry().contains(m_context.mousePos)) { setCursor(Qt::OpenHandCursor); } else { setCursor(Qt::CrossCursor); } } else { setCursor(Qt::CrossCursor); } } void CaptureWidget::pushToolToStack() { auto mod = new ModificationCommand( &m_context.screenshot, m_activeTool); disconnect(this, &CaptureWidget::colorChanged, m_activeTool, &CaptureTool::colorChanged); disconnect(this, &CaptureWidget::thicknessChanged, m_activeTool, &CaptureTool::thicknessChanged); if (m_panel->toolWidget()) { disconnect(m_panel->toolWidget(), nullptr, m_activeTool, nullptr); } m_undoStack.push(mod); m_activeTool = nullptr; } void CaptureWidget::makeChild(QWidget *w) { w->setParent(this); w->installEventFilter(m_eventFilter); } void CaptureWidget::togglePanel() { m_panel->toggle(); } void CaptureWidget::childEnter() { m_previewEnabled = false; update(); } void CaptureWidget::childLeave() { m_previewEnabled = true; update(); } void CaptureWidget::copyScreenshot() { m_captureDone = true; ScreenshotSaver().saveToClipboard(pixmap()); close(); } void CaptureWidget::saveScreenshot() { m_captureDone = true; hide(); if (m_context.savePath.isEmpty()) { ScreenshotSaver().saveToFilesystemGUI(pixmap()); } else { ScreenshotSaver().saveToFilesystem(pixmap(), m_context.savePath); } close(); } void CaptureWidget::undo() { m_undoStack.undo(); } void CaptureWidget::redo() { m_undoStack.redo(); } QRect CaptureWidget::extendedSelection() const { if (!m_selection->isVisible()) return QRect(); QRect r = m_selection->geometry(); return extendedRect(&r); } QRect CaptureWidget::extendedRect(QRect *r) const { auto devicePixelRatio = m_context.screenshot.devicePixelRatio(); return QRect(r->left() * devicePixelRatio, r->top() * devicePixelRatio, r->width() * devicePixelRatio, r->height() * devicePixelRatio); } flameshot-0.6.0+git20191001/src/widgets/capture/capturewidget.h000066400000000000000000000105721354471500100240210ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/capturecontext.h" #include "src/tools/capturetool.h" #include "src/utils/confighandler.h" #include "src/widgets/capture/selectionwidget.h" #include "src/widgets/panel/utilitypanel.h" #include "buttonhandler.h" #include #include #include class QPaintEvent; class QResizeEvent; class QMouseEvent; class CaptureModification; class QNetworkAccessManager; class QNetworkReply; class ColorPicker; class Screenshot; class NotifierBox; class HoverEventFilter; class CaptureWidget : public QWidget { Q_OBJECT public: explicit CaptureWidget(const uint id = 0, const QString &savePath = QString(), bool fullScreen = true, QWidget *parent = nullptr); ~CaptureWidget(); void updateButtons(); QPixmap pixmap(); public slots: void deleteToolwidgetOrClose(); signals: void captureTaken(uint id, QPixmap p); void captureFailed(uint id); void colorChanged(const QColor &c); void thicknessChanged(const int thickness); private slots: // TODO replace with tools void copyScreenshot(); void saveScreenshot(); void undo(); void redo(); void togglePanel(); void childEnter(); void childLeave(); void leftResize(); void rightResize(); void upResize(); void downResize(); void setState(CaptureButton *b); void processTool(CaptureTool *t); void handleButtonSignal(CaptureTool::Request r); void setDrawColor(const QColor &c); void setDrawThickness(const int &t); protected: void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *); void wheelEvent(QWheelEvent *); void resizeEvent(QResizeEvent *); void moveEvent(QMoveEvent *); // Context information CaptureContext m_context; // Main ui color QColor m_uiColor; // Secondary ui color QColor m_contrastUiColor; // Outside selection opacity int m_opacity; // utility flags bool m_mouseIsClicked; bool m_rightClick; bool m_newSelection; bool m_grabbing; bool m_showInitialMsg; bool m_captureDone; bool m_previewEnabled; bool m_adjustmentButtonPressed; private: void initContext(const QString &savePath, bool fullscreen); void initPanel(); void initSelection(); void initShortcuts(); void updateSizeIndicator(); void updateCursor(); void pushToolToStack(); void makeChild(QWidget *w); QRect extendedSelection() const; QRect extendedRect(QRect *r) const; QUndoStack m_undoStack; QPointer m_sizeIndButton; // Last pressed button QPointer m_activeButton; QPointer m_activeTool; QPointer m_toolWidget; ButtonHandler *m_buttonHandler; UtilityPanel *m_panel; ColorPicker *m_colorPicker; ConfigHandler m_config; NotifierBox *m_notifierBox; HoverEventFilter *m_eventFilter; SelectionWidget *m_selection; QPoint m_dragStartPoint; SelectionWidget::SideType m_mouseOverHandle; uint m_id; }; flameshot-0.6.0+git20191001/src/widgets/capture/colorpicker.cpp000066400000000000000000000074221354471500100240210ustar00rootroot00000000000000/// Copyright(c) 2017-2019 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/utils/globalvalues.h" #include #include ColorPicker::ColorPicker(QWidget *parent) : QWidget(parent) { ConfigHandler config; m_colorList = config.getUserColors(); m_colorAreaSize = GlobalValues::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); emit colorSelected(m_drawColor); update(); break; } } } QVector ColorPicker::handleMask() const { QVector areas; for (const QRect &rect: m_colorAreaList) { areas.append(rect); } return areas; } flameshot-0.6.0+git20191001/src/widgets/capture/colorpicker.h000066400000000000000000000024251354471500100234640ustar00rootroot00000000000000// Copyright(c) 2017-2019 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); QColor drawColor(); void show(); void hide(); signals: void colorSelected(QColor c); 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.6.0+git20191001/src/widgets/capture/hovereventfilter.cpp000066400000000000000000000030771354471500100251020ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 #include "hovereventfilter.h" #include HoverEventFilter::HoverEventFilter(QObject *parent) : QObject(parent) { } bool HoverEventFilter::eventFilter(QObject *watched, QEvent *event) { QEvent::Type t = event->type(); switch (t) { case QEvent::Enter: emit hoverIn(watched); break; case QEvent::Leave: emit hoverOut(watched); break; default: break; } return false; } flameshot-0.6.0+git20191001/src/widgets/capture/hovereventfilter.h000066400000000000000000000026521354471500100245450ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 class HoverEventFilter : public QObject { Q_OBJECT public: explicit HoverEventFilter(QObject *parent = nullptr); signals: void hoverIn(QObject *); void hoverOut(QObject *); protected: bool eventFilter(QObject *watched, QEvent *event); }; flameshot-0.6.0+git20191001/src/widgets/capture/modificationcommand.cpp000066400000000000000000000022321354471500100255030ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "modificationcommand.h" #include ModificationCommand::ModificationCommand(QPixmap *p, CaptureTool *t) : m_pixmap(p), m_tool(t) { setText(t->name()); } void ModificationCommand::undo() { m_tool->undo(*m_pixmap); } void ModificationCommand::redo() { QPainter p(m_pixmap); p.setRenderHint(QPainter::Antialiasing); m_tool->process(p, *m_pixmap, true); } flameshot-0.6.0+git20191001/src/widgets/capture/modificationcommand.h000066400000000000000000000021251354471500100251510ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/tools/capturetool.h" class ModificationCommand : public QUndoCommand { public: ModificationCommand(QPixmap *, CaptureTool *); virtual void undo() override; virtual void redo() override; private: QPixmap *m_pixmap; QScopedPointer m_tool; }; flameshot-0.6.0+git20191001/src/widgets/capture/notifierbox.cpp000066400000000000000000000043551354471500100240370ustar00rootroot00000000000000// Copyright(c) 2017-2019 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/utils/colorutils.h" #include "src/utils/globalvalues.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 = (ColorUtils::colorIsDark(m_bgColor) ? Qt::white : Qt::black); m_bgColor.setAlpha(180); const int size = (GlobalValues::buttonBaseSize() + GlobalValues::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(); } void NotifierBox::showColor(const QColor &color) { Q_UNUSED(color); m_message = QLatin1String(""); } flameshot-0.6.0+git20191001/src/widgets/capture/notifierbox.h000066400000000000000000000023331354471500100234760ustar00rootroot00000000000000// Copyright(c) 2017-2019 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); void showColor(const QColor &color); private: QTimer *m_timer; QString m_message; QColor m_bgColor; QColor m_foregroundColor; }; flameshot-0.6.0+git20191001/src/widgets/capture/selectionwidget.cpp000066400000000000000000000105601354471500100246730ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "selectionwidget.h" #include "src/utils/globalvalues.h" #include #include SelectionWidget::SelectionWidget(const QColor &c, QWidget *parent) : QWidget(parent), m_color(c) { m_animation = new QPropertyAnimation(this, "geometry", this); m_animation->setEasingCurve(QEasingCurve::InOutQuad); m_animation->setDuration(200); connect(m_animation, &QPropertyAnimation::finished, this, &SelectionWidget::animationEnded); setAttribute(Qt::WA_TransparentForMouseEvents); int sideVal = GlobalValues::buttonBaseSize() * 0.6; int handleSide = sideVal / 2; const QRect areaRect(0, 0, sideVal, sideVal); const QRect handleRect(0, 0, handleSide, handleSide); m_TLHandle = m_TRHandle = m_BLHandle = m_BRHandle = m_LHandle = m_THandle = m_RHandle = m_BHandle= handleRect; m_TLArea = m_TRArea = m_BLArea = m_BRArea = areaRect; m_areaOffset = QPoint(-sideVal/2, -sideVal/2); m_handleOffset = QPoint(-handleSide/2, -handleSide/2); } SelectionWidget::SideType SelectionWidget::getMouseSide(const QPoint &point) const { if (m_TLArea.contains(point)) { return TOPLEFT_SIDE; } else if (m_TRArea.contains(point)) { return TOPRIGHT_SIDE; } else if (m_BLArea.contains(point)) { return BOTTONLEFT_SIDE; } else if (m_BRArea.contains(point)) { return BOTTONRIGHT_SIDE; } else if (m_LArea.contains(point)) { return LEFT_SIDE; } else if (m_TArea.contains(point)) { return TOP_SIDE; } else if (m_RArea.contains(point)) { return RIGHT_SIDE; } else if (m_BArea.contains(point)) { return BOTTON_SIDE; } else { return NO_SIDE; } } QVector SelectionWidget::handlerAreas() { QVector areas; areas << m_TLHandle << m_TRHandle << m_BLHandle << m_BRHandle <setStartValue(geometry()); m_animation->setEndValue(r); m_animation->start(); } } void SelectionWidget::saveGeometry() { m_geometryBackup = geometry(); } QRect SelectionWidget::savedGeometry() { return m_geometryBackup; } void SelectionWidget::paintEvent(QPaintEvent *) { QPainter p(this); p.setPen(m_color); p.drawRect(rect() + QMargins(0, 0, -1, -1)); } void SelectionWidget::resizeEvent(QResizeEvent *) { updateAreas(); } void SelectionWidget::moveEvent(QMoveEvent *) { updateAreas(); } void SelectionWidget::updateColor(const QColor &c) { m_color = c; } void SelectionWidget::updateAreas() { QRect r = rect(); m_TLArea.moveTo(m_areaOffset + pos()); m_TRArea.moveTo(r.topRight() + m_areaOffset + pos()); m_BLArea.moveTo(r.bottomLeft() + m_areaOffset + pos()); m_BRArea.moveTo(r.bottomRight() + m_areaOffset + pos()); m_LArea = QRect(m_TLArea.bottomLeft(), m_BLArea.topRight()); m_TArea = QRect(m_TLArea.topRight(), m_TRArea.bottomLeft()); m_RArea = QRect(m_TRArea.bottomLeft(), m_BRArea.topRight()); m_BArea = QRect(m_BLArea.topRight(), m_BRArea.bottomLeft()); m_TLHandle.moveTo(m_TLArea.center() + m_handleOffset); m_BLHandle.moveTo(m_BLArea.center() + m_handleOffset); m_TRHandle.moveTo(m_TRArea.center() + m_handleOffset); m_BRHandle.moveTo(m_BRArea.center() + m_handleOffset); m_LHandle.moveTo(m_LArea.center() + m_handleOffset); m_THandle.moveTo(m_TArea.center() + m_handleOffset); m_RHandle.moveTo(m_RArea.center() + m_handleOffset); m_BHandle.moveTo(m_BArea.center() + m_handleOffset); } flameshot-0.6.0+git20191001/src/widgets/capture/selectionwidget.h000066400000000000000000000041531354471500100243410ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 QPropertyAnimation; class SelectionWidget : public QWidget { Q_OBJECT public: enum SideType { TOPLEFT_SIDE, BOTTONLEFT_SIDE, TOPRIGHT_SIDE, BOTTONRIGHT_SIDE, TOP_SIDE, BOTTON_SIDE, RIGHT_SIDE, LEFT_SIDE, NO_SIDE, }; explicit SelectionWidget(const QColor &c, QWidget *parent = nullptr); SideType getMouseSide(const QPoint &point) const; QVector handlerAreas(); void setGeometryAnimated(const QRect &r); void saveGeometry(); QRect savedGeometry(); protected: void paintEvent(QPaintEvent *); void resizeEvent(QResizeEvent *); void moveEvent(QMoveEvent *); signals: void animationEnded(); public slots: void updateColor(const QColor &c); private: void updateAreas(); QPropertyAnimation *m_animation; QColor m_color; QPoint m_areaOffset; QPoint m_handleOffset; QRect m_geometryBackup; // 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; QRect m_TLArea, m_TRArea, m_BLArea, m_BRArea; QRect m_LArea, m_TArea, m_RArea, m_BArea; }; flameshot-0.6.0+git20191001/src/widgets/capturelauncher.cpp000066400000000000000000000122321354471500100232220ustar00rootroot00000000000000// 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 "capturelauncher.h" #include "src/core/controller.h" #include "src/widgets/imagelabel.h" #include "src/widgets/notificationwidget.h" #include "src/utils/screengrabber.h" #include #include #include #include #include #include #include #include #include #include // https://github.com/KDE/spectacle/blob/941c1a517be82bed25d1254ebd735c29b0d2951c/src/Gui/KSWidget.cpp // https://github.com/KDE/spectacle/blob/941c1a517be82bed25d1254ebd735c29b0d2951c/src/Gui/KSMainWindow.cpp CaptureLauncher::CaptureLauncher(QWidget *parent) : QWidget(parent), m_id(0) { setAttribute(Qt::WA_DeleteOnClose); connect(Controller::getInstance(), &Controller::captureTaken, this, &CaptureLauncher::captureTaken); connect(Controller::getInstance(), &Controller::captureFailed, this, &CaptureLauncher::captureFailed); m_imageLabel = new ImageLabel(this); bool ok; m_imageLabel->setScreenshot(ScreenGrabber().grabEntireDesktop(ok)); if (!ok) { } m_imageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); connect(m_imageLabel, &ImageLabel::dragInitiated, this, &CaptureLauncher::startDrag); QGridLayout *layout = new QGridLayout(this); layout->addWidget(m_imageLabel, 0, 0); m_CaptureModeLabel = new QLabel(tr("Capture Mode")); m_captureType = new QComboBox(); m_captureType->setMinimumWidth(240); // TODO remember number m_captureType->insertItem(1, tr("Rectangular Region"), CaptureRequest::GRAPHICAL_MODE); m_captureType->insertItem(2, tr("Full Screen (All Monitors)"), CaptureRequest::FULLSCREEN_MODE); //m_captureType->insertItem(3, tr("Single Screen"), CaptureRequest::SCREEN_MODE); m_delaySpinBox = new QSpinBox(); m_delaySpinBox->setSingleStep(1.0); m_delaySpinBox->setMinimum(0.0); m_delaySpinBox->setMaximum(999.0); m_delaySpinBox->setSpecialValueText(tr("No Delay")); m_delaySpinBox->setMinimumWidth(160); // with QT 5.7 qOverload(&QSpinBox::valueChanged), connect(m_delaySpinBox, static_cast(&QSpinBox::valueChanged), this, [this](int val) { QString sufix = val == 1 ?tr(" second") : tr(" seconds"); this->m_delaySpinBox->setSuffix(sufix); }); m_launchButton = new QPushButton(tr("Take new screenshot")); m_launchButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(m_launchButton, &QPushButton::pressed, this, &CaptureLauncher::startCapture); m_launchButton->setFocus(); QFormLayout *captureModeForm = new QFormLayout; captureModeForm->addRow(tr("Area:"), m_captureType); captureModeForm->addRow(tr("Delay:"), m_delaySpinBox); captureModeForm->setContentsMargins(24, 0, 0, 0); m_mainLayout = new QVBoxLayout(); m_mainLayout->addStretch(1); m_mainLayout->addWidget(m_CaptureModeLabel); m_mainLayout->addLayout(captureModeForm); m_mainLayout->addStretch(10); m_mainLayout->addWidget(m_launchButton, 1 , Qt::AlignCenter); m_mainLayout->setContentsMargins(10, 0, 0, 10); layout->addLayout(m_mainLayout, 0 ,1); layout->setColumnMinimumWidth(0, 320); layout->setColumnMinimumWidth(1, 320); } // HACK: https://github.com/KDE/spectacle/blob/fa1e780b8bf3df3ac36c410b9ece4ace041f401b/src/Gui/KSMainWindow.cpp#L70 void CaptureLauncher::startCapture() { hide(); auto mode = static_cast( m_captureType->currentData().toInt()); CaptureRequest req(mode, 600 + m_delaySpinBox->value() * 1000); m_id = req.id(); Controller::getInstance()->requestCapture(req); } void CaptureLauncher::startDrag() { QDrag *dragHandler = new QDrag(this); QMimeData *mimeData = new QMimeData; mimeData->setImageData(m_imageLabel->pixmap()); dragHandler->setMimeData(mimeData); dragHandler->setPixmap(m_imageLabel->pixmap() ->scaled(256, 256, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); dragHandler->exec(); } void CaptureLauncher::captureTaken(uint id, QPixmap p) { if (id == m_id) { m_id = 0; m_imageLabel->setScreenshot(p); show(); } } void CaptureLauncher::captureFailed(uint id) { if (id == m_id) { m_id = 0; show(); } } flameshot-0.6.0+git20191001/src/widgets/capturelauncher.h000066400000000000000000000026011354471500100226660ustar00rootroot00000000000000// 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 QCheckBox; class QPushButton; class QVBoxLayout; class QComboBox; class QSpinBox; class QLabel; class ImageLabel; class CaptureLauncher : public QWidget { Q_OBJECT public: explicit CaptureLauncher(QWidget *parent = nullptr); private slots: void startCapture(); void startDrag(); void captureTaken(uint id, QPixmap p); void captureFailed(uint id); private: QSpinBox *m_delaySpinBox; QComboBox *m_captureType; QVBoxLayout *m_mainLayout; QPushButton *m_launchButton; QLabel *m_CaptureModeLabel; ImageLabel *m_imageLabel; uint m_id; }; flameshot-0.6.0+git20191001/src/widgets/imagelabel.cpp000066400000000000000000000052331354471500100221220ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/widgets/imagelabel.h000066400000000000000000000032561354471500100215720ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 = nullptr); 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.6.0+git20191001/src/widgets/infowindow.cpp000066400000000000000000000117401354471500100222230ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) #include #include #include #include #endif // InfoWindow show basic information about the usage of Flameshot InfoWindow::InfoWindow(QWidget *parent) : QWidget(parent) { setAttribute(Qt::WA_DeleteOnClose); setWindowIcon(QIcon(":img/app/flameshot.svg")); setWindowTitle(tr("About")); #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) QRect position = frameGeometry(); QScreen *screen = QGuiApplication::screenAt(QCursor::pos()); position.moveCenter(screen->availableGeometry().center()); move(position.topLeft()); #endif 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("SPACEBAR"), 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("Toggle visibility of sidebar with options of the selected tool"), 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)))); } // Read-only table items for (int x = 0; x < table->rowCount(); ++x) { for (int y = 0; y < table->columnCount(); ++y) { QTableWidgetItem *item = table->item(x, y); item->setFlags(item->flags() ^ Qt::ItemIsEditable); } } // 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(QStringLiteral("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 " + QStringLiteral(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.6.0+git20191001/src/widgets/infowindow.h000066400000000000000000000022241354471500100216650ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/widgets/loadspinner.cpp000066400000000000000000000050651354471500100223610ustar00rootroot00000000000000// Copyright(c) 2017-2019 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, &QTimer::timeout, this, &LoadSpinner::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.6.0+git20191001/src/widgets/loadspinner.h000066400000000000000000000024251354471500100220230ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/widgets/notificationwidget.cpp000066400000000000000000000045771354471500100237440ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/widgets/notificationwidget.h000066400000000000000000000024351354471500100234000ustar00rootroot00000000000000// Copyright(c) 2017-2019 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.6.0+git20191001/src/widgets/panel/000077500000000000000000000000001354471500100204305ustar00rootroot00000000000000flameshot-0.6.0+git20191001/src/widgets/panel/sidepanelwidget.cpp000066400000000000000000000140261354471500100243070ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "sidepanelwidget.h" #include "src/utils/pathinfo.h" #include "src/utils/colorutils.h" #include #include #include #include #include #include class QColorPickingEventFilter : public QObject { public: explicit QColorPickingEventFilter( SidePanelWidget *pw, QObject *parent = nullptr) : QObject(parent), m_pw(pw) {} bool eventFilter(QObject *, QEvent *event) override { event->accept(); switch (event->type()) { case QEvent::MouseMove: return m_pw->handleMouseMove(static_cast(event)); case QEvent::MouseButtonPress: return m_pw->handleMouseButtonPressed( static_cast(event)); case QEvent::KeyPress: return m_pw->handleKeyPress(static_cast(event)); default: break; } return false; } private: SidePanelWidget *m_pw; }; //////////////////////// SidePanelWidget::SidePanelWidget(QPixmap *p, QWidget *parent) : QWidget(parent), m_pixmap(p), m_eventFilter(nullptr) { m_layout = new QVBoxLayout(this); QFormLayout *colorForm = new QFormLayout(); m_thicknessSlider = new QSlider(Qt::Horizontal); m_thicknessSlider->setValue(m_thickness); m_colorLabel = new QLabel(); m_colorLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); colorForm->addRow(tr("Active thickness:"), m_thicknessSlider); colorForm->addRow(tr("Active color:"), m_colorLabel); m_layout->addLayout(colorForm); connect(m_thicknessSlider, &QSlider::sliderReleased, this, &SidePanelWidget::updateCurrentThickness); connect(this, &SidePanelWidget::thicknessChanged, this, &SidePanelWidget::updateThickness); QColor background = this->palette().background().color(); bool isDark = ColorUtils::colorIsDark(background); QString modifier = isDark ? PathInfo::whiteIconPath() : PathInfo::blackIconPath(); QIcon grabIcon(modifier + "colorize.svg"); m_colorGrabButton = new QPushButton(grabIcon, QLatin1String("")); updateGrabButton(false); connect(m_colorGrabButton, &QPushButton::pressed, this, &SidePanelWidget::colorGrabberActivated); m_layout->addWidget(m_colorGrabButton); m_colorWheel = new color_widgets::ColorWheel(this); m_colorWheel->setColor(m_color); connect(m_colorWheel, &color_widgets::ColorWheel::mouseReleaseOnColor, this, &SidePanelWidget::colorChanged); connect(m_colorWheel, &color_widgets::ColorWheel::colorChanged, this, &SidePanelWidget::updateColorNoWheel); m_layout->addWidget(m_colorWheel); } void SidePanelWidget::updateColor(const QColor &c) { m_color = c; m_colorLabel->setStyleSheet( QStringLiteral("QLabel { background-color : %1; }").arg(c.name())); m_colorWheel->setColor(m_color); } void SidePanelWidget::updateThickness(const int &t) { m_thickness = qBound(0, t, 100); m_thicknessSlider->setValue(m_thickness); } void SidePanelWidget::updateColorNoWheel(const QColor &c) { m_color = c; m_colorLabel->setStyleSheet( QStringLiteral("QLabel { background-color : %1; }").arg(c.name())); } void SidePanelWidget::updateCurrentThickness() { emit thicknessChanged(m_thicknessSlider->value()); } void SidePanelWidget::colorGrabberActivated() { grabKeyboard(); grabMouse(Qt::CrossCursor); setMouseTracking(true); m_colorBackup = m_color; if (!m_eventFilter) { m_eventFilter = new QColorPickingEventFilter(this, this); } installEventFilter(m_eventFilter); updateGrabButton(true); } void SidePanelWidget::releaseColorGrab() { setMouseTracking(false); removeEventFilter(m_eventFilter); releaseMouse(); releaseKeyboard(); setFocus(); updateGrabButton(false); } QColor SidePanelWidget::grabPixmapColor(const QPoint &p) { QColor c; if (m_pixmap) { QPixmap pixel = m_pixmap->copy(QRect(p, p)); c = pixel.toImage().pixel(0,0); } return c; } bool SidePanelWidget::handleKeyPress(QKeyEvent *e) { if (e->key() == Qt::Key_Space) { emit togglePanel(); } else if (e->key() == Qt::Key_Escape) { releaseColorGrab(); updateColor(m_colorBackup); } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { updateColor(grabPixmapColor(QCursor::pos())); releaseColorGrab(); emit colorChanged(m_color); } return true; } bool SidePanelWidget::handleMouseButtonPressed(QMouseEvent *e) { if (m_colorGrabButton->geometry().contains(e->pos()) || e->button() == Qt::RightButton) { updateColorNoWheel(m_colorBackup); } else if (e->button() == Qt::LeftButton) { updateColor(grabPixmapColor(QCursor::pos())); } releaseColorGrab(); emit colorChanged(m_color); return true; } bool SidePanelWidget::handleMouseMove(QMouseEvent *e) { updateColorNoWheel(grabPixmapColor(e->globalPos())); return true; } void SidePanelWidget::updateGrabButton(const bool activated) { if (activated) { m_colorGrabButton->setText(tr("Press ESC to cancel")); } else { m_colorGrabButton->setText(tr("Grab Color")); } } flameshot-0.6.0+git20191001/src/widgets/panel/sidepanelwidget.h000066400000000000000000000037761354471500100237660ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "color_wheel.hpp" class QVBoxLayout; class QPushButton; class QLabel; class QColorPickingEventFilter; class QSlider; class SidePanelWidget : public QWidget { Q_OBJECT friend class QColorPickingEventFilter; public: explicit SidePanelWidget(QPixmap *p, QWidget *parent = nullptr); signals: void colorChanged(const QColor &c); void thicknessChanged(const int &t); void togglePanel(); public slots: void updateColor(const QColor &c); void updateThickness(const int &t); private slots: void updateColorNoWheel(const QColor &c); void updateCurrentThickness(); private slots: void colorGrabberActivated(); void releaseColorGrab(); private: QColor grabPixmapColor(const QPoint &p); bool handleKeyPress(QKeyEvent *e); bool handleMouseButtonPressed(QMouseEvent *e); bool handleMouseMove(QMouseEvent *e); void updateGrabButton(const bool activated); QVBoxLayout *m_layout; QPushButton *m_colorGrabButton; color_widgets::ColorWheel *m_colorWheel; QLabel *m_colorLabel; QPixmap *m_pixmap; QColor m_colorBackup; QColor m_color; QSlider *m_thicknessSlider; int m_thickness; QColorPickingEventFilter *m_eventFilter; }; flameshot-0.6.0+git20191001/src/widgets/panel/utilitypanel.cpp000066400000000000000000000063371354471500100236700ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 "utilitypanel.h" #include #include #include #include #include UtilityPanel::UtilityPanel(QWidget *parent) : QWidget(parent) { initInternalPanel(); setAttribute(Qt::WA_TransparentForMouseEvents); setCursor(Qt::ArrowCursor); m_showAnimation = new QPropertyAnimation(m_internalPanel, "geometry", this); m_showAnimation->setEasingCurve(QEasingCurve::InOutQuad); m_showAnimation->setDuration(300); m_hideAnimation = new QPropertyAnimation(m_internalPanel, "geometry", this); m_hideAnimation->setEasingCurve(QEasingCurve::InOutQuad); m_hideAnimation->setDuration(300); connect(m_hideAnimation, &QPropertyAnimation::finished, m_internalPanel, &QWidget::hide); } QWidget *UtilityPanel::toolWidget() const { return m_toolWidget; } void UtilityPanel::addToolWidget(QWidget *w) { if (m_toolWidget) { m_toolWidget->deleteLater(); } if (w) { m_toolWidget = w; m_upLayout->addWidget(w); } } void UtilityPanel::clearToolWidget() { if (m_toolWidget) { m_toolWidget->deleteLater(); } } void UtilityPanel::pushWidget(QWidget *w) { m_layout->addWidget(w); } void UtilityPanel::toggle() { if (m_internalPanel->isHidden()) { setAttribute(Qt::WA_TransparentForMouseEvents, false); m_showAnimation->setStartValue(QRect(-width(), 0, 0, height())); m_showAnimation->setEndValue(QRect(0, 0, width(), height())); m_internalPanel->show(); m_showAnimation->start(); } else { setAttribute(Qt::WA_TransparentForMouseEvents); m_hideAnimation->setStartValue(QRect(0, 0, width(), height())); m_hideAnimation->setEndValue(QRect(-width(), 0, 0, height())); m_hideAnimation->start(); } } void UtilityPanel::initInternalPanel() { m_internalPanel = new QScrollArea(this); m_internalPanel->setAttribute(Qt::WA_NoMousePropagation); QWidget *widget = new QWidget(); m_internalPanel->setWidget(widget); m_internalPanel->setWidgetResizable(true); m_layout = new QVBoxLayout(); m_upLayout = new QVBoxLayout(); m_layout->addLayout(m_upLayout); widget->setLayout(m_layout); QColor bgColor = palette().background().color(); bgColor.setAlphaF(0.0); m_internalPanel->setStyleSheet(QStringLiteral("QScrollArea {background-color: %1}") .arg(bgColor.name())); m_internalPanel->hide(); } flameshot-0.6.0+git20191001/src/widgets/panel/utilitypanel.h000066400000000000000000000027161354471500100233320ustar00rootroot00000000000000// Copyright(c) 2017-2019 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 QPropertyAnimation; class QScrollArea; class UtilityPanel : public QWidget { Q_OBJECT public: explicit UtilityPanel(QWidget *parent = nullptr); QWidget* toolWidget() const; void addToolWidget(QWidget *w); void clearToolWidget(); void pushWidget(QWidget *w); signals: void mouseEnter(); void mouseLeave(); public slots: void toggle(); private: void initInternalPanel(); QPointer m_toolWidget; QScrollArea *m_internalPanel; QVBoxLayout *m_upLayout; QVBoxLayout *m_layout; QPropertyAnimation *m_showAnimation; QPropertyAnimation *m_hideAnimation; }; flameshot-0.6.0+git20191001/translations/000077500000000000000000000000001354471500100176155ustar00rootroot00000000000000flameshot-0.6.0+git20191001/translations/Internationalization_ca.ts000066400000000000000000001054701354471500100250440ustar00rootroot00000000000000 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 Set the Arrow as the paint tool Estableix la fletxa com a eina de dibuix BlurTool Blur Desenfocament Set Blur as the paint tool Estableix el desenfocament com a eina de dibuix CaptureWidget Unable to capture screen Impossible capturar la pantalla 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. Press Space to open the side panel. CircleTool Circle Cercle Set the Circle as the paint tool Estableix el cercle com a eina de dibuix ConfigWindow Configuration Configuració Interface Interfície Filename Editor Editor de noms General General Controller &Configuration &Configuració &Information &Informació &Quit &Ix &Take Screenshot CopyTool Copy Copia Copy the selection into the clipboard 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ó 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 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. Delete image ImgurUploaderTool Image Uploader Puja la imatge Upload 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ó Toggle visibility of sidebar with options of the selected tool Show color picker Mostra el selector de color Change the tool's thickness Canvia el gruix de l'eina 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 Set the Line as the paint tool Estableix la línia com a eina de dibuix MarkerTool Marker Marcador Set 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 Set the Pencil as the paint tool Estableix el llapis com a eina de dibuix PinTool Pin Tool Pin image on the desktop QObject 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 Capture saved to clipboard RectangleTool Rectangle Rectangle Set the Rectangle as the paint tool Estableix el rectangle com a eina de dibuix RedoTool Redo Redo the next modification SaveTool Save Guarda Save the capture Guarda la captura ScreenGrabber Unable to capture screen Imposible capturar la pantalla SelectionTool Rectangular Selection Selecció rectangular Set Selection as the paint tool Estableix la selecció com a eina de dibuix SidePanelWidget Active thickness: Active color: Press ESC to cancel Grab Color SizeIndicatorTool Selection Size Indicator Indicador de mida de selecció Show 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) 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) Time (%H-%M-%S) Time (%H-%M) SystemNotification Flameshot Info TextConfig StrikeOut Underline Bold Italic TextTool Text Add text to your capture 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.6.0+git20191001/translations/Internationalization_de_DE.ts000066400000000000000000001055771354471500100254310ustar00rootroot00000000000000 AppLauncher App Launcher Anwendungs Starter Choose an app to open the capture Wähle eine Anwendung um die Auswahl zu öffnen AppLauncherWidget Open With Öffne mit Launch in terminal Starte in der Konsole Keep open after selection Nach Auswahl geöffnet lassen Error Fehler Unable to write in Kein Schreibzugriff auf Unable to launch in terminal. Kann im Terminal nicht geöffnet werden. ArrowTool Arrow Pfeil Set the Arrow as the paint tool Wähle den Pfeil als Werkzeug BlurTool Blur Verwischen Set Blur as the paint tool Wähle Verwischen als Werkzeug CaptureWidget Unable to capture screen Bereich kann nicht erfasst werden 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. Press Space to open the side panel. Wähle einen Bereich mit der Maus oder drücke ESC um zu beenden. Drücke Eingabe um den Bereich aufzunehmen. Drücke die rechte Maustacke um die Farbe auszuwählen. Benutze das Mausrad um die Dicke des Werkzeugs auszuwählen. Drücke die Leertaste um das Seitenmenü zu öffnen. CircleTool Circle Kreis Set the Circle as the paint tool Wähle den Kreis als Werkzeug ConfigWindow Configuration Einstellungen Interface Benutzeroberfläche Filename Editor Dateinamen Editor General Allgemein Controller &Take Screenshot &Bildschirmaufnahme anfertigen &Configuration &Einstellungen &Information &Informationen &Quit &Beenden CopyTool Copy Kopieren Copy the selection into the clipboard Auswahl in die Zwischenablage kopieren DBusUtils Unable to connect via DBus Kann nicht via DBus verbinden ExitTool Exit Beenden Leave the capture screen Auswahl beenden FileNameEditor Edit the name of your captures: Bearbeite den Namen deiner Aufnahmen: Edit: Bearbeite: Preview: Vorschau: Save Speichern Saves the pattern Speichere die Vorlage Reset Zurücksetzen Restores the saved pattern Setzt die gespeicherte Vorlage zurück Clear Löschen Deletes the name Löscht den Namen GeneneralConf Import Importieren Error Fehler Unable to read file. Datei kann nicht gelesen werden. Unable to write file. Datei kann nicht geschrieben werden. Save File Datei speichern Confirm Reset Zurücksetzen bestätigen Are you sure you want to reset the configuration? Sind Sie sicher, dass sie die Konfiguration zurücksetzen wollen? Show help message Hilfetext anzeigen Show the help message at the beginning in the capture mode. Hilfetext am Start der Auswahl anzeigen. Show desktop notifications Zeige Desktopbenachrichtigungen Show tray icon Zeige Taskleistensymbol Show the systemtray icon Zeigt das Taskleistensymbol Configuration File Konfigurationsdatei Export Exportieren Reset Zurücksetzen Launch at startup Automatisch starten Launch Flameshot Starte Flameshot ImgurUploader Upload to Imgur Zu Imgur hochladen Uploading Image Bild hochladen Copy URL URL kopieren Open URL URL öffnen Delete image Bild löschen Image to Clipboard. Bild in Zwischenablage. Unable to open the URL. Kann URL nicht öffnen. URL copied to clipboard. URL kopiert. Screenshot copied to clipboard. Bildschirmaufnahme in Zwischenablage kopiert. ImgurUploaderTool Image Uploader Bild hochladen Upload the selection to Imgur Auswahl zu Imgur hochladen InfoWindow About Über SPACEBAR Leertaste Right Click Rechtsklick Mouse Wheel Mausrad Move selection 1px Verschiebe Auswahl um 1px Resize selection 1px Größenänderung um 1px Quit capture Auswahl verlassen Copy to clipboard In Zwischenablage kopieren Save selection as a file Speichere Auswahl als Datei Undo the last modification Letze Änderungen zurücksetzen Toggle visibility of sidebar with options of the selected tool Öffne/Schließe Seitenauswahlmenü des gewählten Werkzeugs Show color picker Zeige Farbauswahl Change the tool's thickness Ändere die Dicke des Werkzeugs Available shortcuts in the screen capture mode. Verfügbare Tastenkürzel im Aufnahmemodus. Key Taste Description Beschreibung <u><b>License</b></u> <u><b>Lizenz</b></u> <u><b>Version</b></u> <u><b>Version</b></u> <u><b>Shortcuts</b></u> <u><b>Tastenkürzel</b></u> LineTool Line Linie Set the Line as the paint tool Wähle Linie als Werkzeug MarkerTool Marker Markierer Set the Marker as the paint tool Wähle den Markierer als Werkzeug MoveTool Move Bewege Move the selection area Bewege den Auswahlbereich PencilTool Pencil Stift Set the Pencil as the paint tool Wähle den Stift als Werkzeug PinTool Pin Tool Pinnwand Werkzeug Pin image on the desktop Pinne Bild auf den Dekstop QObject Save Error Speicherfehler Capture saved as Aufnahme gespeichert als Capture saved to clipboard Aufnahme in Zwischenablage gespeichert Error trying to save as Fehler beim Speichern unter Unable to connect via DBus Kann nicht via DBus verbinden Error Fehler Unable to write in Kein Schreibzugriff auf RectangleTool Rectangle Rechteck Set the Rectangle as the paint tool Wähle ausgefülltes Rechteck als Werkzeug RedoTool Redo Wiederholen Redo the next modification Wiederhole die nächste Veränderung SaveTool Save Speichern Save the capture Speichere die Aufnahme ScreenGrabber Unable to capture screen Kann Bereich nicht aufnehmen SelectionTool Rectangular Selection Rechteckige Auswahl Set Selection as the paint tool Wähle Rechteck als Werkzeug SidePanelWidget Active thickness: Aktuelle Dicke Active color: Aktuelle Farbe: Press ESC to cancel Drücke ESC für Abbruch Grab Color Wähle Farbe SizeIndicatorTool Selection Size Indicator Auswahlgrößen Indentifikator Show the dimensions of the selection (X Y) Zeige die Dimensionen der Auswahl (X Y) StrftimeChooserWidget Century (00-99) Jarhhundert (00-99) Year (00-99) Jahr (00-99) Year (2000) Jahr (2000) Month Name (jan) Monatsname (Jan) Month Name (january) Monatsname (Januar) Month (01-12) Monat (01-12) Week Day (1-7) Wochentag (1-7) Week (01-53) Woche (01-53) Day Name (mon) Tagesname (Mon) Day Name (monday) Tagesname (Montag) Day (01-31) Tag (01-31) Day of Month (1-31) Tag des Monats (1-31) Day (001-366) Tag (001-366) Time (%H-%M-%S) Zeit (%H-%M-%S) Time (%H-%M) Zeit (%H-%M) Hour (00-23) Stunde (00-23) Hour (01-12) Stunde (01-12) Minute (00-59) Minute (00-59) Second (00-59) Sekunde (00-59) Full Date (%m/%d/%y) Komplettes Datum (%m/%d/%y) Full Date (%Y-%m-%d) Komplettes Datum (%Y-%m-%d) SystemNotification Flameshot Info Flameshot Info TextConfig StrikeOut Durchstreichen Underline Unterstrichen Bold Fettdruck Italic Kursiv TextTool Text Text Add text to your capture Füge Text zur Auswahl hinzu UIcolorEditor UI Color Editor UI Farb Editor Change the color moving the selectors and see the changes in the preview buttons. Ändere die Farbauswahl und betrachte die Vorschau in den Vorschau-Buttons. Select a Button to modify it Wähle einen Button um ihn zu verändern Main Color Hauptfarbe Click on this button to set the edition mode of the main color. Wähle diesen Button um den Bearbeitungsmodus der Hauptfarbe zu wählen. Contrast Color Kontrastfarbe Click on this button to set the edition mode of the contrast color. Wähle diesen Button um den Bearbeitungsmodus der Kontrastfarbe zu wählen. UndoTool Undo Verwerfen Undo the last modification Letzte Änderung verwerfen VisualsEditor Opacity of area outside selection: Deckkraft des Bereichs außerhalb der Auswahl: Button Selection Button Auswahl Select All Alle wählen flameshot-0.6.0+git20191001/translations/Internationalization_es.ts000066400000000000000000001057221354471500100250700ustar00rootroot00000000000000 AppLauncher App Launcher Lanzador de Aplicaciones Choose an app to open the capture Elige 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 Set the Arrow as the paint tool Establece la Flecha como herramienta de dibujo BlurTool Blur Desenfoque Set 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. Press Space to open the side panel. 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. Presiona Espacio para abrir el panel lateral. CircleTool Circle Círculo Set the Circle as the paint tool Establece el Círculo como herramienta de dibujo ConfigWindow Configuration Configuración Interface Interfaz Filename Editor Editor de Nombre General General Controller &Take Screenshot &Tomar captura de pantalla &Configuration &Configuración &Information &Información &Quit &Salir CopyTool Copy Copiar Copy the selection 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 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 Delete image Borrar imagen 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 Upload 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 Mover la selección 1px Resize selection 1px Redimensionar la selección 1px Quit capture Salir de la captura Copy to clipboard Copiar al portapapeles Save selection as a file Guardar la selección como un archivo Undo the last modification Deshacer la última modificación Toggle visibility of sidebar with options of the selected tool Alternar la visualización de la barra lateral de opciones de la herramienta seleccionada Show color picker Mostrar 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. 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 Set the Line as the paint tool Establece la Línea como herramienta de dibujo MarkerTool Marker Marcador Set 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 Set the Pencil as the paint tool Establece el Lápiz como herramienta de dibujo PinTool Pin Tool Chincheta Pin image on the desktop Fija la imagen sobre el escritorio QObject Save Error Error al Guardar Capture saved as Captura guardada como Capture saved to clipboard Captura guardada en el portapapeles 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 Set the Rectangle as the paint tool Establece el Rectángulo como herramienta de dibujo RedoTool Redo Rehacer Redo the next modification Rehacer la siguiente modificación SaveTool Save Guardar Save the capture Guardar la captura ScreenGrabber Unable to capture screen Imposible capturar la pantalla SelectionTool Rectangular Selection Selección Rectangular Set Selection as the paint tool Establece la Selección como herramienta de dibujo SidePanelWidget Active thickness: Espesor activo: Active color: Color activo: Press ESC to cancel Presiona ESC para cancelar Grab Color Tomar Color SizeIndicatorTool Selection Size Indicator Indicador de Tamaño de Selección Show 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) SystemNotification Flameshot Info Información de Flameshot TextConfig StrikeOut Tachado Underline Subrayado Bold Negrita Italic Cursiva TextTool Text Texto Add text to your capture Agregar texto a la captura 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.6.0+git20191001/translations/Internationalization_fr.ts000066400000000000000000001105561354471500100250710ustar00rootroot00000000000000 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 Set the Arrow as the paint tool Sélectionner l'outil Flèche BlurTool Blur Flou Set 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. Press Space to open the side panel. Sélectionner une zone avec la souris ou appuyer sur Echap pour quitter Appuyer sur Entrée pour capturer l'écran Effectuer un clic droit pour afficher le sélecteur de couleurs. Utiliser la molette de la souris pour changer l'épaisseur de l'outil. Appuyer sur Espace pour ouvrir le panneau latéral. CircleTool Circle Ellipse Set the Circle as the paint tool Sélectionner l'outil Ellipse SidePanelWidget Active color: Couleur actuelle: Press ESC to cancel Appuyer sur Echap pour annuler Grab Color Saisir la couleur ConfigWindow Configuration Configuration Interface Interface Filename Editor Editeur de Noms General Général Controller &Take Screenshot &Capturer l'écran &Configuration &Configuration &Information &Informations &Quit &Quitter CopyTool Copy Copier Copy the selection into the clipboard Copier 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 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 Démarrer Flameshot Close after capture Fermer après une capture Close after taking a screenshot Fermer l'application après une capture d'écran 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 Delete image 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 Upload 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 Toggle visibility of sidebar with options of the selected tool 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. 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 Set the Line as the paint tool Sélectionner l'outil Ligne MarkerTool Marker Surligneur Set 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 Set the Pencil as the paint tool Sélectionner l'outil Crayon PinTool Pin Tool Outil Épinglage Pin image on the desktop Épingler l'image sur le bureau QObject Save Error Erreur lors de la sauvegarde Capture saved as Capture d'écran sauvegardée sous Capture saved to clipboard Capture d'écran copiée dans le Presse-papier Error trying to save as Erreur lors de la sauvegarde sous Unable to connect via DBus Impossible de se connecter via DBus Error Erreur Unable to write in Imposible d'écrire par dessus RectangleTool Rectangle Rectangle plein Set the Rectangle as the paint tool Sélectionner l'outil Rectangle plein RedoTool Redo Rétablir Redo the next modification Refaire la prochaine modification SaveTool Save Sauvegarder Save the capture Sauvegarder la capture d'écran ScreenGrabber Unable to capture screen Imposible de capturer l'écran SelectionTool Rectangular Selection Rectangle Set Selection as the paint tool Sélectionner l'outil Rectangle SidePanelWidget Active thickness: Active color: Press ESC to cancel Grab Color SizeIndicatorTool Selection Size Indicator Indicateur de la taille de la sélection Show 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) Heure (%H-%M-%S) Time (%H-%M) Heure (%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) SystemNotification Flameshot Info Info Flameshot TextConfig StrikeOut Rayer Underline Souligner Bold Gras Italic Italique TextTool Text Texte Add text to your capture Ajouter du texte à la capture 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.6.0+git20191001/translations/Internationalization_hu.ts000066400000000000000000000511511354471500100250710ustar00rootroot00000000000000 AppLauncher App Launcher Alkalmazás indító Choose an app to open the capture Válassz egy alkalmazást hogy elinduljon a felvétel AppLauncherWidget Open With Megnyitás ezzel Launch in terminal Futtatás terminálban Keep open after selection Kiválasztás után maradjon nyitva Error Hiba Unable to launch in terminal. Nem lehet megnyitni a terminálban. Unable to write in Nem lehet írni ArrowTool Arrow Nyíl Set the Arrow as the paint tool Beállítja a nyíl eszközt festő eszközként BlurTool Blur Homályosítás Set Blur as the paint tool Beállítja a Homályosítás eszközt festő eszközként 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. Válassz egy területet egérrel, vagy nyomj Esc-et a kilépéshez. Nyomj entert a felvételhez. Kattints job egérgombal a szín választásához. Használd a görgőt az eszköz vastagságának állítására. Unable to capture screen Nem lehet felvételt készíteni CircleTool Circle Kör Set the Circle as the paint tool Beálítja a Kör eszközt festő eszközként ConfigWindow Configuration Beállítások Interface Interfész Filename Editor Fájlnév szerkesztő General Általános Controller &Configuration &Konfiguráció &Information &Információ &Quit &Bezár CopyTool Copy Másol Copies the selecion into the clipboard Másolja a kiválasztott területet DBusUtils Unable to connect via DBus Nem lehet csatlakozni DBus-al ExitTool Exit Bezár Leave the capture screen Bezárja a felvevőt FileNameEditor Edit the name of your captures: Szerkeszd a nevét a felvételeidnek: Edit: Szerkeszt: Preview: Előnézet: Save Mentés Saves the pattern Minta mentése Reset Visszaállítás Restores the saved pattern Visszaállítja a mentett mintát Clear Töröl Deletes the name Törli a nevet FileNameHandler screenshot Képernyőmentés FlameshotDBusAdapter Unable to capture screen Nem lehet képernyőképet készíteni GeneneralConf Show help message Mutassa a segítséget Show the help message at the beginning in the capture mode. Mutassa a segítséget a felvevő mód kezdetekor. Show desktop notifications Mutassa az asztali üzeneteket Show tray icon Tray ikon mutatása Show the systemtray icon Systemtray ikon mutatása Import Importálás Error Hiba Unable to read file. Nem lehet olvasni a fájlt. Unable to write file. Nem lehet írni a fájlt. Save File Fájl mentése Confirm Reset Visszaállítás elfogadása Are you sure you want to reset the configuration? Biztos vagy benne hogy viszaállítod a beállításokat? Configuration File Konfigurációs fájl Export Export Reset Visszaállítás Launch at startup Indítás rendszerinduláskor Launch Flameshot Flameshot indítása ImgurUploader Upload to Imgur Feltöltés Imgur -ra Uploading Image Kép felötlése Copy URL URL másolása Open URL URL megnyitása Image to Clipboard. Kép a vágolapra. Unable to open the URL. Nem lehet az URL-t megnyitni. URL copied to clipboard. URL másolva a vágólapra. Screenshot copied to clipboard. Képernyőmentés másolva a vágólapra. ImgurUploaderTool Image Uploader Kép feltöltő Upload the selection to Imgur Feltölti a kiválasztott képet az Imgur -ra InfoWindow About Információ Right Click jobb egérgomb Mouse Wheel Görgő Move selection 1px Kijelölés mozgatása 1px Resize selection 1px Kijelölés méretezése 1 px Quit capture Felvétel bezárása Copy to clipboard Másolás vágólapra Save selection as a file Kijelölés mentése fájlba Undo the last modification Utolsó módosítás visszavonása Show color picker Színválasztó mutatása Change the tool's thickness Vastagság állítása Key Kulcs Description Leírás <u><b>License</b></u> <u><b>License</b></u> <u><b>Version</b></u> <u><b>Verzió</b></u> <u><b>Shortcuts</b></u> <u><b>Gyorsbillentyűk</b></u> Available shortcuts in the screen capture mode. Elérhető gyorsbillentyűk a képernyőfelvétel módban. LineTool Line Vonal Set the Line as the paint tool Beállítja a Vonal eszközt festő eszközként MarkerTool Marker Jelölő Set the Marker as the paint tool Beállítja a Jelölő eszközt festő eszközként MoveTool Move Mozgató Move the selection area Mozgatja a kiválasztott területet PencilTool Pencil Ceruza Set the Pencil as the paint tool Beállítja a Ceruza eszközt festő eszközként QObject Save Error Mentési hiba Capture saved as It is hard to esxpress such stence in hungary eg. Capture saved as JPG in hungary : A felvétel JPG -ben mentve lett. (Better solution using expressions in string like: Capture saved as %s ) Felvétel mentve a következőként Error trying to save as Hiba a mentés közben a következőként Unable to connect via DBus Nem lehet D-Bus -on keresztül csatlakozni Error Hiba Unable to write in Nem írni Capture saved to clipboard Felvétel mentve a vágólapra RectangleTool Rectangle Téglalap Set the Rectangle as the paint tool Beállítja a Téglalap eszközt festő eszközként RedoTool Redo Újra SaveTool Save Mentés Save the capture Menti a felvételt SelectionTool Rectangular Selection Téglalapos kijelölő Set Selection as the paint tool Beállítja a Téglalapos kijelölő eszközt Festő eszközként SizeIndicatorTool Selection Size Indicator Kiválasztott terület méretének indikátora Show the dimensions of the selection (X Y) Mutatja a dimenzióját a kijelölésnek (X Y) StrftimeChooserWidget Century (00-99) Század (00-99) Year (00-99) Év (00-99) Year (2000) Év (2000) Month Name (jan) Hónapnév (Jan) Month Name (january) Hónapnév (Január) Month (01-12) Hónap (01-12) Week Day (1-7) Hét napja (1-7) Week (01-53) Hét (01-53) Day Name (mon) Nap neve (Csüt) Day Name (monday) Nap neve (Csütörtök) Day (01-31) Nap (01-31) Day of Month (1-31) Nap a hónapban (1-31) Day (001-366) Nap (001-366) Time (%H:%M:%S) Idő (%H:%M:%S) Time (%H:%M) Idő (%H:%M) Hour (00-23) Óra (00-23) Hour (01-12) Óra (01-12) Minute (00-59) Perc (00-59) Second (00-59) Másodperc (00-59) Full Date (%m/%d/%y) Teljes dátum (%m/%d/%y) Full Date (%Y-%m-%d) Teljes dátum (%Y-%m-%d) UIcolorEditor UI Color Editor UI Szín szerkesztő Change the color moving the selectors and see the changes in the preview buttons. Válassz színt az egér mozgatásával és nézd a változást az előnézeti gombokon. Select a Button to modify it Válassz gombot módosítani Main Color Fő szín Click on this button to set the edition mode of the main color. Kattints a gombra hogy beállítsd a szerkesztő módját a fő színnek. Contrast Color Kontraszt szín Click on this button to set the edition mode of the contrast color. Kattints erre a gombra hogy beállítsd a szerkesztő módját a kontraszt színnek. UndoTool Undo Vissza Undo the last modification Visszavonja az utolsó módosítást VisualsEditor Opacity of area outside selection: Átlátszósága a kijelölésen kívüli területnek: Button Selection Gomb választás Select All Összes kiválasztása flameshot-0.6.0+git20191001/translations/Internationalization_ja.ts000066400000000000000000001074051354471500100250530ustar00rootroot00000000000000 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 矢印 Set the Arrow as the paint tool ペイントツールとして「矢印」をセットする BlurTool Blur ぼかし Set 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. Press Space to open the side panel. マウスで領域を選択、Esc を押すと終了。 Enter を押すと画面をキャプチャー。 マウスの右ボタンでカラーピッカーを表示。 マウスホイールでツールの太さ等を変更。 スペースを押すとサイドパネルを開く。 CircleTool Circle 円形 Set the Circle as the paint tool ペイントツールとして「円形」をセットする ConfigWindow Configuration 設定 Interface インターフェース Filename Editor ファイル名エディター General 全般 Controller &Take Screenshot スクリーンショットを撮る(&T) &Configuration 設定(&C) &Information 情報(&I) &Quit 終了(&Q) CopyTool Copy コピー Copy the selection 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 名前を削除する 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 URL をコピー Open URL URL を開く Delete image 画像を削除 Image to Clipboard. 画像をクリップボードへ。 Unable to open the URL. URL を開けません。 URL copied to clipboard. URL をクリップボードにコピーしました。 Screenshot copied to clipboard. スクリーンショットをクリップボードにコピーしました。 ImgurUploaderTool Image Uploader 画像アップローダー Upload 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 最後の変更を元に戻す Toggle visibility of sidebar with options of the selected tool Show color picker カラーピッカーを表示する Change the tool's thickness ツールの値 (太さや濃さ) を変更する 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 直線 Set the Line as the paint tool ペイントツールとして「直線」をセットする MarkerTool Marker マーカー Set the Marker as the paint tool ペイントツールとして「マーカー」をセットする MoveTool Move 移動 Move the selection area 選択範囲を移動する PencilTool Pencil 鉛筆 Set the Pencil as the paint tool ペイントツールとして「鉛筆」をセットする PinTool Pin Tool 固定ツール Pin image on the desktop 選択範囲をデスクトップ上に配置する QObject Save Error 保存エラー Capture saved as キャプチャーを保存しました: Capture saved to clipboard キャプチャーをクリップボードに保存しました Error trying to save as 保存時にエラーが発生しました: Unable to connect via DBus DBus に接続できません Error エラー Unable to write in 書き込めません: RectangleTool Rectangle 矩形 Set the Rectangle as the paint tool ペイントツールとして「矩形」をセットする RedoTool Redo やり直し Redo the next modification 次の変更にやり直す SaveTool Save 保存 Save the capture キャプチャーを保存する ScreenGrabber Unable to capture screen 画面をキャプチャーできません SelectionTool Rectangular Selection 矩形選択 Set Selection as the paint tool ペイントツールとして「矩形選択」をセットする SidePanelWidget Active thickness: Active color: アクティブな色: Press ESC to cancel ESC でキャンセル Grab Color 色の取得 SizeIndicatorTool Selection Size Indicator 選択サイズインジケーター Show 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) 月 (jan) Month Name (january) 月 (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) SystemNotification Flameshot Info Flameshot の情報 TextConfig StrikeOut 取り消し線 Underline 下線 Bold 太字 Italic 斜体 TextTool Text テキスト Add text to your capture キャプチャーにテキストを追加する 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.6.0+git20191001/translations/Internationalization_ka.ts000066400000000000000000001163521354471500100250550ustar00rootroot00000000000000 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 ისარი Set the Arrow as the paint tool ისრის ხელსაწყოს არჩევა სახატავად BlurTool Blur გაბუნდოვნება Set 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. Press Space to open the side panel. CircleTool Circle წრე Set the Circle as the paint tool წრის ხელსაწყოს არჩევა სახატავად ConfigWindow Configuration პარამეტრები Interface ინტერფეისი Filename Editor ფაილის სახელის რედაქტორი General ზოგადი Controller &Take Screenshot &Configuration &პარამეტრები &Information &ინფორმაცია &Quit &გამოსვლა CopyTool Copy კოპირება Copy the selection 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 სახელის წაშლა 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-ის გახსნა Delete image Image to Clipboard. სურათის გაცვლის ბუფერში გაგზავნა Unable to open the URL. URL-ის გახსნა ვერ მოხერხდა. URL copied to clipboard. URL დაკოპირდა გაცვლის ბუფერში. Screenshot copied to clipboard. სურათი დაკოპირდა გაცვლის ბუფერში. ImgurUploaderTool Image Uploader სურათის ამტვირთველი Upload 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 ბოლო ცვლილების გაუქმება Toggle visibility of sidebar with options of the selected tool 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 ხაზი Set the Line as the paint tool ხაზის ხელსაწყოს არჩევა სახატავად MarkerTool Marker მარკერი Set the Marker as the paint tool მარკერის ხელსაწყოს არჩევა სახატავად MoveTool Move გადაადგილება Move the selection area შერჩეული არის გადაადგილება PencilTool Pencil ფანქარი Set the Pencil as the paint tool ფანქრის ხელსაწყოს არჩევა სახატავად PinTool Pin Tool Pin image on the desktop QObject Save Error შეცდომა შენახვისას Capture saved as სურათი შენახულია როგორც: Capture saved to clipboard Error trying to save as შეცდომა მცდელობისას შენახულიყო როგორც: Unable to connect via DBus DBus-ით დაკავშირება ვერ მოხერხდა Error შეცდომა Unable to write in შემდეგ მისამართზე ჩაწერა ვერ მოხერხდა: RectangleTool Rectangle მართკუთხედი Set the Rectangle as the paint tool მართკუთხედის ხელსაწყოს არჩევა სახატავად RedoTool Redo Redo the next modification SaveTool Save შენახვა Save the capture სურათის შენახვა ScreenGrabber Unable to capture screen ეკრანის გადაღება ვერ მოხერხდა SelectionTool Rectangular Selection მართკუთხა შერჩევა Set Selection as the paint tool შერჩევის ხელსაწყოს არჩევა სახატავად SidePanelWidget Active thickness: Active color: Press ESC to cancel Grab Color SizeIndicatorTool Selection Size Indicator შერჩეულის ზომის მაჩვენებელი Show 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) Time (%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) SystemNotification Flameshot Info TextConfig StrikeOut Underline Bold Italic TextTool Text Add text to your capture 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.6.0+git20191001/translations/Internationalization_nl.ts000066400000000000000000001055261354471500100250740ustar00rootroot00000000000000 AppLauncher App Launcher App-starter Choose an app to open the capture Kies een app om de schermafdruk mee te openen AppLauncherWidget Open With Openen met Launch in terminal Openen in terminalvenster Keep open after selection Openhouden na selectie Error Fout Unable to write in Kan niet schrijven naar Unable to launch in terminal. Kan niet openen in terminalvenster. ArrowTool Arrow Cursor Set the Arrow as the paint tool Cursor instellen als verfgereedschap BlurTool Blur Vervaging Set Blur as the paint tool Vervaging instellen als verfgereedschap CaptureWidget Unable to capture screen Kan scherm niet vastleggen 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. Press Space to open the side panel. Selecteer een gebied met de cursor of druk op Esc om af te sluiten. Druk op Enter om het scherm vast te leggen. Klik met de rechtermuisknop om de kleurkiezer te tonen. Gebruik het muiswiel om de gereedschapsdikte aan te passen. Druk op spatie om het zijpaneel te openen. CircleTool Circle Cirkel Set the Circle as the paint tool Cirkel instellen als verfgereedschap ConfigWindow Configuration Configuratie Interface Uiterlijk Filename Editor Bestandsnaambewerker General Algemeen Controller &Take Screenshot Schermafdruk &maken &Configuration &Configuratie &Information &Informatie &Quit &Afsluiten CopyTool Copy Kopiëren Copy the selection into the clipboard Selectie kopiëren naar klembord DBusUtils Unable to connect via DBus Kan niet verbinden via DBus ExitTool Exit Afsluiten Leave the capture screen Verlaat het vastlegscherm FileNameEditor Edit the name of your captures: Bewerk de naam van je schermafdrukken: Edit: Bewerken: Preview: Voorbeeld: Save Opslaan Saves the pattern Slaat het patroon op Reset Standaardwaarden Restores the saved pattern Herstelt het standaardpatroon Clear Wissen Deletes the name Wist de naam GeneneralConf Import Importeren Error Fout Unable to read file. Kan bestand niet uitlezen. Unable to write file. Kan bestand niet wegschrijven. Save File Bestand opslaan Confirm Reset Herstellen bevestigen Are you sure you want to reset the configuration? Weet je zeker dat je de standwaardwaarden van de configuratie wilt herstellen? Show help message Uitleg tonen Show the help message at the beginning in the capture mode. Toont een bericht met uitleg bij het openen van de vastlegmodus. Show desktop notifications Bureaubladmeldingen tonen Show tray icon Systeemvakpictogram tonen Show the systemtray icon Toont het systeemvakpictogram Configuration File Configuratiebestand Export Exporteren Reset Standaardwaarden Launch at startup Automatisch opstarten Launch Flameshot Flameshot openen ImgurUploader Upload to Imgur Uploaden naar Imgur Uploading Image Bezig met uploaden van afbeelding... Copy URL URL kopiëren Open URL URL openen Delete image Afbeelding verwijderen Image to Clipboard. Afbeelding naar klembord. Unable to open the URL. Kan URL niet openen. URL copied to clipboard. URL gekopieerd naar klembord. Screenshot copied to clipboard. Schermafdruk gekopieerd naar klembord. ImgurUploaderTool Image Uploader Afbeeldingsuploader Upload the selection to Imgur Upload de selectie naar Imgur InfoWindow About Over Right Click Rechtsklikken Mouse Wheel Muiswiel Move selection 1px Selectie 1px verplaatsen Resize selection 1px Afmetingen van selectie 1px aanpassen Quit capture Vastleggen afsluiten Copy to clipboard Kopiëren naar klembord Save selection as a file Selectie opslaan als bestand Undo the last modification Laatste wijziging ongedaan maken Toggle visibility of sidebar with options of the selected tool Zijbalk met gereedschapsopties tonen/verbergen Show color picker Kleurkiezer tonen Change the tool's thickness Wijzig de gereedschapsdikte Available shortcuts in the screen capture mode. Beschikbare sneltoetsen in de vastlegmodus. Key Toets Description Omschrijving <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 Lijn Set the Line as the paint tool Lijn instellen als verfgereedschap MarkerTool Marker Markeerstift Set the Marker as the paint tool Markeerstift instellen als verfgereedschap MoveTool Move Verplaatsen Move the selection area Selectiegebied verplaatsen PencilTool Pencil Potlood Set the Pencil as the paint tool Potlood instellen als verfgereedschap PinTool Pin Tool Vastmaken Pin image on the desktop Afbeelding vastmaken op bureaublad QObject Save Error Fout tijdens opslaan Capture saved as Schermafdruk opgeslagen als Capture saved to clipboard Schermafdruk vastgelegd op klembord Error trying to save as Fout tijdens opslaan als Unable to connect via DBus Kan niet verbinden via DBus Error Fout Unable to write in Kan niet wegschrijven naar RectangleTool Rectangle Rechthoek Set the Rectangle as the paint tool Rechthoek instellen als verfgereedschap RedoTool Redo Opnieuw Redo the next modification Volgende wijziging opnieuw toepassen SaveTool Save Сачувај Opslaan Save the capture Schermafdruk opslaan ScreenGrabber Unable to capture screen Kan scherm niet vastleggen SelectionTool Rectangular Selection Rechthoekige selectie Set Selection as the paint tool Selectie instellen als verfgereedschap SidePanelWidget Active thickness: Actieve dikte: Active color: Actieve kleur: Press ESC to cancel Druk op Esc om te annuleren Grab Color Kleur opnemen SizeIndicatorTool Selection Size Indicator Grootteindicatie van selectie Show the dimensions of the selection (X Y) Toon de afmetingen van de selectie (X Y) StrftimeChooserWidget Century (00-99) Eeuw (00-99) Year (00-99) Jaar (00-99) Year (2000) Jaar (2000) Month Name (jan) Naam van de maand (јаn) Month Name (january) Naam van de maand (јаnuari) Month (01-12) Maand (01-12) Week Day (1-7) Weekdag (1-7) Week (01-53) Week (01-53) Day Name (mon) Naam van de dag (ma) Day Name (monday) Naam van de dag (maandag) Day (01-31) Dag (01-31) Day of Month (1-31) Dag van de maand (1-31) Day (001-366) Dag (001-366) Time (%H-%M-%S) Tijd (%H-%M-%S) Time (%H-%M) Tijd (%H-%M) Hour (00-23) Uur (00-23) Hour (01-12) Uur (01-12) Minute (00-59) Minuten (00-59) Second (00-59) Seconden (00-59) Full Date (%m/%d/%y) Volledige datum (%m/%d/%y) Full Date (%Y-%m-%d) Volledige datum (%Y-%m-%d) SystemNotification Flameshot Info Flameshot-informatie TextConfig StrikeOut Doorhalen Underline Onderstrepen Bold Vetgedrukt Italic Cursief TextTool Text Tekst Add text to your capture Voeg tekst toe aan je schermafdruk UIcolorEditor UI Color Editor Kleurenschemabewerker Change the color moving the selectors and see the changes in the preview buttons. Wijzig de kleur d.m.v. de selectie-indicators en bekijk de wijzigingen op de voorbeeldknoppen. Select a Button to modify it Kies een te bewerken knop Main Color Hoofdkleur Click on this button to set the edition mode of the main color. Klik op deze knop om de hoofdkleur te bwerken. Contrast Color Contrastkleur Click on this button to set the edition mode of the contrast color. Klik op deze knop om de contrastkleur te bewerken. UndoTool Undo Ongedaan mken Undo the last modification Laatste wijziging ongedaan maken VisualsEditor Opacity of area outside selection: Doorzichtigheid van gebied buiten selectie: Button Selection Knopselectie Select All Alles selecteren flameshot-0.6.0+git20191001/translations/Internationalization_pl.ts000066400000000000000000001050101354471500100250620ustar00rootroot00000000000000 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 Set the Arrow as the paint tool Rysowanie strzałek BlurTool Blur Rozmycie Set 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. Press Space to open the side panel. Wybierz obszar za pomocą myszy lub wciśnij Esc aby wyjść. Wciśnij Enter, aby wykonać zrzut ekranu. Prawy klik, aby pokazać próbnik kolorów. Spacja, aby pokazać panel boczny. CircleTool Circle Okręgi Set the Circle as the paint tool Rysowanie okręgów i elips ConfigWindow Configuration Konfiguracja Interface Interfejs Filename Editor Edytor nazw plików General Ogólne Controller &Take Screenshot &Zrzut ekranu &Configuration &Konfiguracja &Information &Informacje &Quit &Wyjdź CopyTool Copy Kopiuj Copy the selection into the clipboard 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 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 Delete image Usuń obrazek 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 Upload 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ę Toggle visibility of sidebar with options of the selected tool 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. 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 Set the Line as the paint tool Ustawia linię jako narzędzie do rysowania MarkerTool Marker Marker Set 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 Set the Pencil as the paint tool Ustawia ołówek jako narzędzie do rysowania PinTool Pin Tool Narzędzie przypinania Pin image on the desktop Przypnij obrazek do pulpitu QObject Save Error Błąd zapisu Capture saved as Zaznaczenie zapisano jako Capture saved to clipboard Zrzut skopiowano do schowka 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 Set the Rectangle as the paint tool Ustawia prostokąt jako narzędzie do rysowania RedoTool Redo Cofnij Redo the next modification SaveTool Save Zapisz Save the capture Zapisz zaznaczenie ScreenGrabber Unable to capture screen Nie można przechwycić ekranu SelectionTool Rectangular Selection Zaznaczenie prostokątne Set Selection as the paint tool Ustawia zaznaczenie prostokątne jako narzędzie do rysowania SidePanelWidget Active thickness: Active color: Aktywny kolor: Press ESC to cancel Wciśnij ESC, aby anulować Grab Color Pobierz kolor SizeIndicatorTool Selection Size Indicator Miernik zaznaczenia Show 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) SystemNotification Flameshot Info Flameshot Info TextConfig StrikeOut Przekreślenie Underline Podkreślenie Bold Pogrubienie Italic Kursywa TextTool Text Tekst Add text to your capture Dodaje tekst do zrzutu 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.6.0+git20191001/translations/Internationalization_pt_br.ts000066400000000000000000001052711354471500100255660ustar00rootroot00000000000000 AppLauncher App Launcher App Launcher Choose an app to open the capture Escolha uma aplicação para abrir a captura AppLauncherWidget Open With Abrir Com Launch in terminal Abrir no terminal Keep open after selection Manter aberto após seleção Error Erro Unable to write in Não é possível escrever em Unable to launch in terminal. Não foi possível abrir no terminal. ArrowTool Arrow Flecha Set the Arrow as the paint tool Usa a Flecha como ferramenta de desenho BlurTool Blur Desfoque Set Blur as the paint tool Usa o Desfoque como ferramenta de desenho CaptureWidget Unable to capture screen Não foi possível capturar a tela 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. Press Space to open the side panel. Selecione uma área com o mouse, ou precione Esc para sair. Pressione Enter para capturar a tela. Pressione o botão direito do mouse para abrir o seletor de cores. Use a roda do mouse para aumentar a grossura do pincel. Pressione espaço abrir o painel lateral. CircleTool Circle Círculo Set the Circle as the paint tool Usa o Círculo como ferramenta de desenho ConfigWindow Configuration Configuração Interface Interface Filename Editor Editor de nome de arquivo General Geral Controller &Take Screenshot &Tirar Screenshot &Configuration &Configuração &Information &Informações &Quit &Sair CopyTool Copy Copiar Copy the selection into the clipboard Copia a seleção para o clipboard DBusUtils Unable to connect via DBus Não foi possível conectar via DBus ExitTool Exit Sair Leave the capture screen Sair da ferramenta de captura FileNameEditor Edit the name of your captures: Edite o nome das suas capturas: Edit: Editar: Preview: Preview: Save Salvar Saves the pattern Salva o padrão Reset Reiniciar Restores the saved pattern Restaura o padrão salvo Clear Limpar Deletes the name Deleta o nome GeneneralConf Import Importar Error Erro Unable to read file. Não foi possível ler o arquivo. Unable to write file. Não foi possível escrever no arquivo. Save File Salvar Arquivo Confirm Reset Confirmar Reset Are you sure you want to reset the configuration? Tem certeza que deseja resetar a configuração? Show help message Mostrar mensagem de ajuda Show the help message at the beginning in the capture mode. Mostrar mensagem de ajuda no início do modo de captura. Show desktop notifications Mostrar notificações de Desktop Show tray icon Mostrar ícone de tray Show the systemtray icon Mosrar ícone na barra de aplicações Configuration File Arquivo de Configurações Export Exportar Reset Reset Launch at startup Iniciar junto com o sistema Launch Flameshot Iniciar Flameshot ImgurUploader Upload to Imgur Upload no Imgur Uploading Image Upando Imagem Copy URL Copiar URL Open URL Abrir URL Delete image Deletar imagem Image to Clipboard. Imagem no Clipboard. Unable to open the URL. Não foi possível abrir a URL. URL copied to clipboard. URL copiada para o clipboard. Screenshot copied to clipboard. Screenshot copiada para o clipboard. ImgurUploaderTool Image Uploader Uploader de imagens Upload the selection to Imgur Upa a seleção no Imgur InfoWindow About Sobre Right Click Botão Direito Mouse Wheel Roda do mouse Move selection 1px Move a seleção em 1px Resize selection 1px Redimensiona a seleção em 1px Quit capture Sair da captura Copy to clipboard Copiar ao clipboard Save selection as a file Salva seleção em um arquivo Undo the last modification Desfazer última modificação Toggle visibility of sidebar with options of the selected tool Show color picker Mostra seletor de cores Change the tool's thickness Muda a grossura do pincel Available shortcuts in the screen capture mode. Atalhos disponívels na tela de captura. Key Tecla Description Descrição <u><b>License</b></u> <u><b>Licença</b></u> <u><b>Version</b></u> <u><b>Versão</b></u> <u><b>Shortcuts</b></u> <u><b>Atalhos</b></u> LineTool Line Linha Set the Line as the paint tool Usa a Linha como ferramenta de desenho MarkerTool Marker Marcador Set the Marker as the paint tool Usa o marcador como ferramenta de desenho MoveTool Move Mover Move the selection area Move a área de seleção PencilTool Pencil Pincel Set the Pencil as the paint tool Usa o Lápis como ferramenta de desenho PinTool Pin Tool Ferramenta de Pin Pin image on the desktop Pinnar imagem no desktop QObject Save Error Salvar erro Capture saved as Captura salva como Capture saved to clipboard Captura salva no clipboard Error trying to save as Erro tentando salvar como Unable to connect via DBus Não foi possível conectar via DBus Error Erro Unable to write in Não foi possível escrever em RectangleTool Rectangle Retângulo Set the Rectangle as the paint tool Seta o Retângulo como ferramenta de desenho RedoTool Redo Refazer Redo the next modification Refazer última modificação SaveTool Save Salvar Save the capture Salva a captura ScreenGrabber Unable to capture screen Não foi possível capturar a tela SelectionTool Rectangular Selection Seleção Retangular Set Selection as the paint tool Estabelece o Selecionador como ferramenta de desenho SidePanelWidget Active thickness: Active color: Cor ativa: Press ESC to cancel Presione Esc para cancelar Grab Color Usar Cor SizeIndicatorTool Selection Size Indicator Indicador do Tamanho da Seleção Show the dimensions of the selection (X Y) Mostra a dimensão da seleção (X Y) StrftimeChooserWidget Century (00-99) Século (00-99) Year (00-99) Ano (00-99) Year (2000) Ano (2000) Month Name (jan) Nome do mês (jan) Month Name (january) Nome do mês (janeiro) Month (01-12) Mês (01-12) Week Day (1-7) Dia da semana (1-7) Week (01-53) Semana (01-53) Day Name (mon) Nome do dia (seg) Day Name (monday) Nome do dia (segunda) Day (01-31) Dia (01-31) Day of Month (1-31) Dia do Mês (1-31) Day (001-366) Dia (001-366) Time (%H-%M-%S) Tempo (%H-%M-%S) Time (%H-%M) Tempo (%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) Data Completa (%m/%d/%y) Full Date (%Y-%m-%d) Data Completa (%Y-%m-%d) SystemNotification Flameshot Info Informações do Flameshot TextConfig StrikeOut Sobrescrito Underline Sublinhado Bold Negrito Italic Itálico TextTool Text Texto Add text to your capture Adicionar texto à captura UIcolorEditor UI Color Editor Interface de Edição de Cores Change the color moving the selectors and see the changes in the preview buttons. Modifique a cor movendo os seletores e veja as mudanças nos botões de preview. Select a Button to modify it Selecione um botão para modificá-lo Main Color Cor Principal Click on this button to set the edition mode of the main color. Clique neste botão para setar o modo de edição da cor principal. Contrast Color Cor de Contraste Click on this button to set the edition mode of the contrast color. Clique neste botão para setar o modo de edição da cor de contraste. UndoTool Undo Desfazer Undo the last modification Desfaz a última modificação VisualsEditor Opacity of area outside selection: Opacidade da área de seleção: Button Selection Botão de seleção Select All Selecionar Todos flameshot-0.6.0+git20191001/translations/Internationalization_ru.ts000066400000000000000000001134571354471500100251130ustar00rootroot00000000000000 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 Стрелка Set the Arrow as the paint tool Выбрать Стрелку инструментом для рисования BlurTool Blur Размытие Set 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. Press Space to open the side panel. Выберите область с помощью мыши или нажмите Esc чтобы выйти. Нажмите Enter чтобы захватить экран. Нажмите правую кнопку мыши чтобы показать выбор цвета. Используйте колесо мыши чтобы выбрать толщину текущего инструмента. Нажмите Пробел чтобы открыть боковую панель. CircleTool Circle Окружность Set the Circle as the paint tool Выбрать Окружность инструментом для рисования ConfigWindow Configuration Настройка Interface Интерфейс Filename Editor Редактор имен файлов General Общие Controller &Take Screenshot &Сделать снимок &Configuration &Настройка &Information &Информация &Quit &Выход CopyTool Copy Скопировать Copy the selection 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 Удаляет имя 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 Delete image Удалить изображение Image to Clipboard. Изображение в буфер обмена. Unable to open the URL. Не удалось открыть URL. URL copied to clipboard. URL скопирован в буфер обмена. Screenshot copied to clipboard. Снимок скопирован в буфер обмена. ImgurUploaderTool Image Uploader Отправка изображений Upload 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 Отменить последнее изменение Toggle visibility of sidebar with options of the selected tool Показать боковую панель с настройками выбранного инструмента 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 Линия Set the Line as the paint tool Выбрать Линию инструментом для рисования MarkerTool Marker Маркер Set the Marker as the paint tool Выбрать Маркер инструментом для рисования MoveTool Move Перемещение Move the selection area Выбрать Перемещение инструментом для рисования PencilTool Pencil Карандаш Set the Pencil as the paint tool Выбрать Карандаш инструментом для рисования PinTool Pin Tool Булавка Pin image on the desktop Прикрепить изображение к рабочему столу QObject Save Error Ошибка сохранения Capture saved as Снимок сохранён как Capture saved to clipboard Снимок сохранён в буфер обмена Error trying to save as Ошибка при попытке сохранить как Unable to connect via DBus Не удалось подключиться через DBus Error Ошибка Unable to write in Не удалось сохранить RectangleTool Rectangle Прямоугольник Set the Rectangle as the paint tool Выбрать Прямоугольник инструментом для рисования RedoTool Redo Повторить Redo the next modification Повторить последнее изменение SaveTool Save Сохранить Save the capture Сохранить снимок ScreenGrabber Unable to capture screen Не удалось захватить экран SelectionTool Rectangular Selection Прямоугольное выделение Set Selection as the paint tool Выбрать Прямоугольное выделение инструментом для рисования SidePanelWidget Active thickness: Активная толщина: Active color: Активный цвет: Press ESC to cancel Нажмите Esc для отмены Grab Color Захватить цвет с экрана SizeIndicatorTool Selection Size Indicator Индикатор размера выделения Show 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) SystemNotification Flameshot Info Flameshot Инфо TextConfig StrikeOut Зачеркнутый Underline Подчеркнутый Bold Полужирный Italic Курсив TextTool Text Текст Add text to your capture Добавить текст на снимок 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.6.0+git20191001/translations/Internationalization_sk.ts000066400000000000000000001130361354471500100250730ustar00rootroot00000000000000 AppLauncher App Launcher Spúšťač aplikácií Choose an app to open the capture Vyberte aplikáciu na otvorenie snímky obrazovky AppLauncherWidget Open With Otvoriť s Launch in terminal Otvoriť v termináli Keep open after selection Nechať otvorené po výbere Error Chyba Unable to write in Zlyhal zápis do Unable to launch in terminal. Nepodarilo sa spustiť v termináli. ArrowTool Arrow Šípka Set the Arrow as the paint tool Nastaviť Šípku ako nástroj pre úpravy BlurTool Blur Rozmazanie Set Blur as the paint tool Nastaviť Rozmazanie ako nástroj pre úpravy CaptureLauncher <b>Capture Mode</b> <b>Režim zachytávania</b> Rectangular Region Pravouhlá oblasť Full Screen (All Monitors) Celá obrazovka (všetky monitory) No Delay Bez oneskorenia second sekunda seconds sekundy Take new screenshot Urobiť novú snímku Area: Oblasť: Delay: Oneskorenie: CaptureWidget Unable to capture screen Nepodarilo sa zachytiť obrazovku 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. Press Space to open the side panel. Vyberte oblasť snímania pomocou myši alebo stlačte Esc pre ukončenie. Stlačte Enter pre zachytenie obrazovky. Kliknite pravým tlačidlom pre zobrazenie nástroja pre výber farby. Použite kolečko myši pre zmenu hrúbky vybraného nástroja. Stlačte medzerník pre otvorenie postranného panelu. CircleTool Circle Kruh Set the Circle as the paint tool ConfigWindow Configuration Konfigurácia Interface Interfejs Filename Editor Editor názvov súborov General Všeobecné Controller &Take Screenshot &Vytvoriť snímku &Open Launcher &Configuration &Konfigurácia &Information &Informácie &Quit &Ukončiť CopyTool Copy Kopírovať Copy the selection into the clipboard Kopírovať výber do schránky DBusUtils Unable to connect via DBus Nie je možné pripojiť sa prostredníctvom DBus ExitTool Exit Ukončiť Leave the capture screen Opustiť obrazovku so zachytávaním obrazovky FileNameEditor Edit the name of your captures: Upraviť meno vašich snímok obrazovky: Edit: Upraviť: Preview: Náhľad: Save Uložiť Saves the pattern Uloží vzor Reset Resetovať Restores the saved pattern Vráti zmeny Clear Vyčistiť Deletes the name Vymaže meno GeneneralConf Import Importovať Error Chyba Unable to read file. Zlyhalo čítanie súboru. Unable to write file. Zlyhal zápis do súboru. Save File Uložiť súbor Confirm Reset Potvrdiť Reset Are you sure you want to reset the configuration? Naozaj si želáte resetovať aktuálnu konfiguráciu? Show help message Zobraziť nápovedu Show the help message at the beginning in the capture mode. Zobraziť nápovedu na začiatku počas režimu zachytávania obrazovky. Show desktop notifications Zobraziť systémové upozornenia Show tray icon Zobraziť stavovú ikonu Show the systemtray icon Zobraziť ikonu v stavovej oblasti Configuration File Súbor s konfiguráciou Export Exportovať Reset Resetovať Launch at startup Spúšťať pri štarte Launch Flameshot Spustiť Flameshot Close after capture Zavrieť po vytvorení snímky Close after taking a screenshot Zatvoriť po vytvorení snímky obrazovky ImgurUploader Upload to Imgur Nahrať na Imgur Uploading Image Nahrávam obrázok Copy URL Kopírovať URL Open URL Otvoriť URL Delete image Vymazať obrázok Image to Clipboard. Obrázok do schránky. Unable to open the URL. Nepodarilo sa otvoriť URL. URL copied to clipboard. URL skopírovaná do schránky. Screenshot copied to clipboard. Snímka obrazovky bola skopírovaná do schránky. ImgurUploaderTool Image Uploader Uploader obrázkov Upload the selection to Imgur Nahrať výber na Imgur InfoWindow About O programe SPACEBAR MEDZERNÍK Right Click Kliknutie pravým tlačidlom Mouse Wheel Kolečko myši Move selection 1px Presunúť výber o 1 px Resize selection 1px Zmeniť rozmery výberu o 1 px Quit capture Ukončiť zachytávanie obrazovky Copy to clipboard Kopírovať do schránky Save selection as a file Zapísať výber do súboru Undo the last modification Vrátiť poslednú úpravu Toggle visibility of sidebar with options of the selected tool Prepnúť viditeľnosť bočnej lišty s možnosťami vybraného nástroja Show color picker Zobraziť dialóg na výber farby Change the tool's thickness Zmena hrúbky nástroja Available shortcuts in the screen capture mode. Dostupné klávesové skratky v režime zachytávania obrazovky. Key Kláves Description Popis <u><b>License</b></u> <u><b>Licencia</b></u> <u><b>Version</b></u> <u><b>Verzia</b></u> <u><b>Shortcuts</b></u> <u><b>Klávesové skratky</b></u> LineTool Line Čiara Set the Line as the paint tool Nastaviť Čiaru ako nástroj pre úpravy MarkerTool Marker Fixka Set the Marker as the paint tool Nastaviť Fixku ako nástroj pre úpravy MoveTool Move Presun Move the selection area Presunúť oblasť výberu PencilTool Pencil Ceruzka Set the Pencil as the paint tool Nastaviť Ceruzku ako nástroj pre úpravy PinTool Pin Tool Špendlík Pin image on the desktop Pripnúť obrázok na plochu QObject Unable to connect via DBus Nie je možné pripojiť sa prostredníctvom DBus Error Chyba Unable to write in Zlyhal zápis do Capture saved to clipboard Snímka uložená do schránky Capture saved as Snímka uložená ako Error trying to save as Chyba pri ukladaní do Save Error Chyba pri ukladaní RectangleTool Rectangle Obdĺžnik Set the Rectangle as the paint tool Nastaviť Obdĺžnik ako nástroj pre úpravy RedoTool Redo Znova Redo the next modification Zopakovať úpravu SaveTool Save Uložiť Save the capture Uložiť snímku obrazovky ScreenGrabber Unable to capture screen Nepodarilo sa zachytiť obrazovku SelectionTool Rectangular Selection Obdĺžnikový výber Set Selection as the paint tool Nastaviť Výber ako nástroj pre úpravy SidePanelWidget Active thickness: Aktívna hrúbka: Active color: Aktívna farba: Press ESC to cancel Stlačte ESC pre zrušenie Grab Color Snímať farbu SizeIndicatorTool Selection Size Indicator Ukazovateľ veľkosti výberu Show the dimensions of the selection (X Y) Zobraziť rozmery výberu (X Y) StrftimeChooserWidget Century (00-99) Storočie (00-99) Year (00-99) Rok (00-99) Year (2000) Rok (2000) Month Name (jan) Meno mesiaca (jan) Month Name (january) Meno mesiaca (január) Month (01-12) Mesiac (01-12) Week Day (1-7) Deň v týždni (1-7) Week (01-53) Týždeň (01-53) Day Name (mon) Meno dňa (pon) Day Name (monday) Meno dňa (pondelok) Day (01-31) Deň (01-31) Day of Month (1-31) Deň v mesiaci (1-31) Day (001-366) Deň (001-366) Time (%H-%M-%S) Čas (%H-%M-%S) Time (%H-%M) Čas (%H-%M) Hour (00-23) Hodina (00-23) Hour (01-12) Hodina (01-12) Minute (00-59) Minúta (00-59) Second (00-59) Sekunda (00-59) Full Date (%m/%d/%y) Celý dátum (%m/%d/%y) Full Date (%Y-%m-%d) Celý dátum (%Y-%m-%d) SystemNotification Flameshot Info Informácie o programe Flameshot TextConfig StrikeOut Preškrtnuté Underline Podčiarknuté Bold Tučné Italic Kurzíva TextTool Text Text Add text to your capture Pridať text do snímky UIcolorEditor UI Color Editor Editor farieb interfejsu Change the color moving the selectors and see the changes in the preview buttons. Presunom bežcov nastavte farbu a sledujte tieto zmeny v náhľade. Select a Button to modify it Kliknite na tlačidlo pre jeho úpravu Main Color Hlavná farba Click on this button to set the edition mode of the main color. Pre nastavenie hlavnej farby kliknite na toto tlačidlo. Contrast Color Kontrastná farba Click on this button to set the edition mode of the contrast color. Pre nastavenie kontrastnej farby kliknite na toto tlačidlo. UndoTool Undo Späť Undo the last modification Vrátiť poslednú úpravu VisualsEditor Opacity of area outside selection: Priehľadnosť oblasti mimo výberu: Button Selection Výber tlačidiel Select All Vybrať všetky flameshot-0.6.0+git20191001/translations/Internationalization_sr.ts000066400000000000000000001122461354471500100251040ustar00rootroot00000000000000 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 Стрелица Set the Arrow as the paint tool Избор цртања стрелице BlurTool Blur Замућење Set 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. Press Space to open the side panel. Изаберите област мишем или притисните Esc за излаз. Притисните Enter за снимак целог екрана. Десним кликом миша бирате боју. Можете користити точкић миша за избор дебљине алатки. Притисните размак на тастатури за приказ помоћног панела. CircleTool Circle Круг Set the Circle as the paint tool Избор цртања круга ConfigWindow Configuration Подешавања Interface Изглед Filename Editor Избор имена датотеке General Опште Controller &Take Screenshot &Направи снимак екрана &Configuration &Подешавања &Information Ин&формације &Quit &Излаз CopyTool Copy Запамти Copy the selection 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 Брише име 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 Запамти интернет адресу Open URL Посети интернет адресу Delete image Избриши слику Image to Clipboard. Сачувај у привремену меморију. Unable to open the URL. Нисам успео да посетим интернет адресу. URL copied to clipboard. Интернет адреса је сачувана у привременој меморији. Screenshot copied to clipboard. Слика је сачувана у привременој меморији. ImgurUploaderTool Image Uploader Објављивање слике Upload 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 Поништи последње измене Toggle visibility of sidebar with options of the selected tool 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 Линија Set the Line as the paint tool Избор цртања линије MarkerTool Marker Маркер Set the Marker as the paint tool Избор цртања маркером MoveTool Move Премештање Move the selection area Премешта изабрану област PencilTool Pencil Оловка Set the Pencil as the paint tool Избор цртања оловком PinTool Pin Tool Закачка Pin image on the desktop Закачи слику за радну површину QObject Save Error Грешка приликом упусивања Capture saved as Сачувај снимак као Capture saved to clipboard Снимак је сачуван у привремену меморију Error trying to save as Грешка приликом уписивања као Unable to connect via DBus Нисам успео да се повежем кроз DBus Error Грешка Unable to write in Нисам успео са сачувам RectangleTool Rectangle Правоугаоник Set the Rectangle as the paint tool Избор цртања обојеног правоугаоника RedoTool Redo Понови Redo the next modification Понови поништену измену SaveTool Save Сачувај Сохранить Save the capture Сачувај снимак ScreenGrabber Unable to capture screen Нисам успео да снимим екран SelectionTool Rectangular Selection Правоугаони оквир Set Selection as the paint tool Избор цртања правоугаоног оквира SidePanelWidget Active thickness: Active color: Активна боја: Press ESC to cancel Притисните ESC за прекид Grab Color Преузмите боју SizeIndicatorTool Selection Size Indicator Приказ величине избора Show 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) SystemNotification Flameshot Info Информације о Flameshot-у TextConfig StrikeOut Прецртано Underline Подвучено Bold Задебљано Italic Накошено TextTool Text Текст Add text to your capture Додаје текст на снимак 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.6.0+git20191001/translations/Internationalization_tr.ts000066400000000000000000001052271354471500100251060ustar00rootroot00000000000000 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 Yazma mümkün değil Unable to launch in terminal. Terminalde başlatılamadı. ArrowTool Arrow Ok Set the Arrow as the paint tool Oku çizim aracı olarak ayarlar BlurTool Blur Bulanıklık Set Blur as the paint tool Bulnıklığı boyama aracı olarak ayarlar CaptureWidget Unable to capture screen Ekran resmi alınamadı 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. Press Space to open the side panel. 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çiciyi göstermek için farenin sağ tuşuna tıklayın. Aracınızın kalınlığını değiştirmek için Fare Tekerleğini kullanın. Yan paneli açmak için Boşluk tuşuna basın. CircleTool Circle Çember Set the Circle as the paint tool Çemberi boyama aracı olarak ayarlar ConfigWindow Configuration Ayarlar Interface Arayüz Filename Editor Dosya Adı Düzenleyici General Genel Controller &Take Screenshot &Ekran Resmi Al &Configuration &Ayarlar &Information &Bilgi &Quit &Çıkış CopyTool Copy Kopyala Copy the selection 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 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? Ayarları 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'ı başlat ImgurUploader Upload to Imgur Imgur'a yükle Uploading Image Resim Yükleniyor Copy URL URL Kopyala Open URL URL Aç Delete image Resmi sil 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ı Upload 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 1px seçimini hareket ettir Resize selection 1px 1px seçimini yeniden boyutlandır Quit capture Çı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 Toggle visibility of sidebar with options of the selected tool 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. 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 Set the Line as the paint tool Çizgiyi boyama aracı olarak ayarlar MarkerTool Marker İşaretleyici Set the Marker as the paint tool İşaretleyiciyi boyama aracı olarak ayarlar MoveTool Move Oynat Move the selection area Seçim alanını hareket ettir PencilTool Pencil Kurşun Kalem Set the Pencil as the paint tool Kurşun Kalemi çizim aracı olarak ayarlar PinTool Pin Tool Pin Aracı Pin image on the desktop Masaüstündeki PIN resmi QObject Save Error Kaydetme Hatası Capture saved as Yakalama farklı kaydedildi Capture saved to clipboard Yakalama panoya kaydedildi Error trying to save as Farklı kaydetmeye çalışılırken hata oluştu Unable to connect via DBus DBus ile bağlanılamadı Error Hata Unable to write in Yazma mümkün değil RectangleTool Rectangle Dikdörtgen Set the Rectangle as the paint tool Dikdörtgeni boyama aracı olarak ayarlar RedoTool Redo Yeniden Redo the next modification SaveTool Save Kaydet Save the capture Yakalamayı kaydet ScreenGrabber Unable to capture screen Ekran resmi alınamadı SelectionTool Rectangular Selection Dikdörtgen Seçim Set Selection as the paint tool Seçimi boyama aracı olarak ayarlar SidePanelWidget Active thickness: Active color: Aktif Renk: Press ESC to cancel Çıkmak için ESC'ye tıklayın Grab Color SizeIndicatorTool Selection Size Indicator Seçim Boyutu Göstergesi Show 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) Time (%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) SystemNotification Flameshot Info Flameshot Hakkında TextConfig StrikeOut Underline Altçizgi Bold Kalın Italic Eğik TextTool Text Metin Add text to your capture Bilgisayardan yazı ekle 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 buton 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 butonu 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 butonu tıklayın. UndoTool Undo Geri Undo the last modification Son değişikliği geri al VisualsEditor Opacity of area outside selection: Seçimin dışındaki alanın opaklığı: Button Selection Buton Seçimi Select All Tümünü Seç flameshot-0.6.0+git20191001/translations/Internationalization_uk.ts000066400000000000000000001130621354471500100250740ustar00rootroot00000000000000 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 Стрілка Set the Arrow as the paint tool Вибрати стрілку інструментом малювання BlurTool Blur Розмиття Set 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. Press Space to open the side panel. Виберіть область мишкою або натисніть Esc для виходу. Натисніть Enter щоб захопити екран. Натисніть праву кнопку миші, щоб показати вибір кольору. Використовуйте колесо миші для зміни товщини вибраного інструменту. Натисніть Пробіл, щоб відкрити бічну панель. CircleTool Circle Коло Set the Circle as the paint tool Вибрати коло інструментом малювання ConfigWindow Configuration Налаштування Interface Інтерфейс Filename Editor Редактор імені файлів General Загальне Controller &Take Screenshot &Зробити знімок &Configuration &Налаштування &Information &Інформація &Quit Ви&йти CopyTool Copy Копіювати Copy the selection 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 Видаляє ім'я 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 Delete image Видалити зображення Image to Clipboard. Зображення до буферу обміну. Unable to open the URL. Не вдалось відкрити URL. URL copied to clipboard. URL скопійовано до буферу обміну. Screenshot copied to clipboard. Знімок скопійовано до буферу обміну. ImgurUploaderTool Image Uploader Вивантаження зображень Upload 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 Скасувати останню зміну Toggle visibility of sidebar with options of the selected tool Переключити видимість бічної панелі 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 Лінія Set the Line as the paint tool Вибрати лінію інструментом малювання MarkerTool Marker Маркер Set the Marker as the paint tool Вибрати маркер інструментом малювання MoveTool Move Переміщення Move the selection area Перемістити вибір PencilTool Pencil Олівець Set the Pencil as the paint tool Вибрати олівець інструментом малювання PinTool Pin Tool Прикріплення Pin image on the desktop Прикріпити зображення до робочого столу QObject Save Error Помилка збереження Capture saved as Знімок збережено як Capture saved to clipboard Знімок збережено до буферу обміну Error trying to save as Помилка під час збереження як Unable to connect via DBus Не вдалось підключитись через DBus Error Помилка Unable to write in Не вдалось зберегти RectangleTool Rectangle Прямокутник Set the Rectangle as the paint tool Вибрати прямокутник інструментом малювання RedoTool Redo Повторити Redo the next modification Повторити наступну зміну SaveTool Save Зберегти Save the capture Зберегти знімок ScreenGrabber Unable to capture screen Не вдалось захопити екран SelectionTool Rectangular Selection Прямокутне виділення Set Selection as the paint tool Вибрати прямокутне виділення інструментом малювання SidePanelWidget Active thickness: Активна товщина: Active color: Активний колір: Press ESC to cancel Натисніть Esc для скасування Grab Color Визначити колір з екрану SizeIndicatorTool Selection Size Indicator Індикатор розміру виділення Show 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) SystemNotification Flameshot Info Довідка Flameshot TextConfig StrikeOut Перекреслення Underline Підкреслення Bold Жирний Italic Курсив TextTool Text Текст Add text to your capture Додати текст на знімок 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.6.0+git20191001/translations/Internationalization_zh_CN.ts000066400000000000000000001113501354471500100254540ustar00rootroot00000000000000 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 箭头 Set the Arrow as the paint tool 选择箭头作为绘画工具 BlurTool Blur 模糊 Set Blur as the paint tool 选择模糊作为绘画工具 CaptureLauncher <b>Capture Mode</b> <b>捕获模式</b> Rectangular Region 方形区域 Full Screen (All Monitors) 全屏(所有显示器) No Delay 无延迟 second seconds Take new screenshot 获取新屏幕截图 Area: 区域: Delay: 延迟: 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. Press Space to open the side panel. 用鼠标选择一个区域,或按 Esc 退出。 按 Enter 键捕捉屏幕。 按住鼠标右键显示颜色选择器。 使用鼠标滚轮来改变绘画工具的宽度。 按下空格键以打开侧边面板。 CircleTool Circle 圆环 Set the Circle as the paint tool 选择圆环作为绘画工具 ConfigWindow Configuration 配置 Interface 界面 Filename Editor 文件名编辑器 General 常规 Controller &Take Screenshot 进行截图(&T) &Open Launcher 打开启动器(&O) &Configuration 配置(&C) &Information 信息(&I) &Quit 退出(&Q) CopyTool Copy 复制 Copy the selection 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 删除这个名字 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 Close after capture 捕获后关闭 Close after taking a screenshot 获取屏幕截图后关闭 ImgurUploader Upload to Imgur 上传到Imgur Uploading Image 正在上传 Copy URL 复制链接 Open URL 打开链接 Delete image 删除图像 Image to Clipboard. 保存文件到剪贴板。 Unable to open the URL. 无法打开此链接。 URL copied to clipboard. 复制链接到剪贴板。 Screenshot copied to clipboard. 截图复制到剪贴板。 ImgurUploaderTool Image Uploader 上传图片 Upload the selection to Imgur 上传选择到 Imgur InfoWindow About 关于 SPACEBAR 空格 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 撤消上次修改 Toggle visibility of sidebar with options of the selected tool 切换侧边栏可见性 Show color picker 显示颜色选择器 Change the tool's thickness 改变工具的厚度 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 直线 Set the Line as the paint tool 将直线线设置为绘画工具 MarkerTool Marker 标记 Set the Marker as the paint tool 将标记设置为绘画工具 MoveTool Move 移动 Move the selection area 移动选择区域 PencilTool Pencil 铅笔 Set the Pencil as the paint tool 将铅笔设置为绘画工具 PinTool Pin Tool 贴图工具 Pin image on the desktop 在桌面上固定图像 QObject Save Error 保存错误 Capture saved as 捕获已保存为 Capture saved to clipboard 捕获已保存至剪贴板 Error trying to save as 尝试另存为时出错 Unable to connect via DBus 无法通过DBus进行连接 Error 错误 Unable to write in 无法写入 RectangleTool Rectangle 实心矩形 Set the Rectangle as the paint tool 将实心矩形设置为绘画工具 RedoTool Redo 重做 Redo the next modification 重做上次修改 SaveTool Save 保存 Save the capture 保存捕获 ScreenGrabber Unable to capture screen 无法捕获屏幕 SelectionTool Rectangular Selection 矩形选择 Set Selection as the paint tool 将矩形选择设置为绘画工具 SidePanelWidget Active thickness: 当前宽度: Active color: 活动颜色: Press ESC to cancel 按下 ESC 键以取消 Grab Color 获取颜色 SizeIndicatorTool Selection Size Indicator 选择尺寸指示 Show 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) 月(1月 - 12月) 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) SystemNotification Flameshot Info Flameshot 消息 TextConfig StrikeOut 删除线 Underline 下划线 Bold 粗体 Italic 斜体 TextTool Text 文本 Add text to your capture 在您的捕获中添加文本 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.6.0+git20191001/translations/Internationalization_zh_TW.ts000066400000000000000000001034641354471500100255150ustar00rootroot00000000000000 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 箭頭 Set the Arrow as the paint tool 選擇箭頭作為繪製工具 BlurTool Blur 模糊 Set 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. Press Space to open the side panel. CircleTool Circle 圈型 Set the Circle as the paint tool 選擇圈型作為繪畫工具 ConfigWindow Configuration 設定 Interface 介面 Filename Editor 檔案名稱編輯器 General 一般 Controller &Take Screenshot &Configuration &設定 &Information &資訊 &Quit &結束 CopyTool Copy 複製 Copy the selection 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 刪除這個名稱 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 ImgurUploader Upload to Imgur 上傳到 Imgur Uploading Image 正在上傳 Copy URL 複製連結 Open URL 打開連結 Delete image Image to Clipboard. 將檔案複製到剪貼簿 Unable to open the URL. 無法打開此連結 URL copied to clipboard. 連結已複製到剪貼簿 Screenshot copied to clipboard. 截圖已複製到剪貼簿 ImgurUploaderTool Image Uploader 上傳圖片 Upload 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 復原上次修改 Toggle visibility of sidebar with options of the selected tool Show color picker 顯示顏色選擇器 Change the tool's thickness 改變工具的寬度 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 直線 Set the Line as the paint tool 將直線線設定為繪畫工具 MarkerTool Marker 標記 Set the Marker as the paint tool 將標記設定為繪畫工具 MoveTool Move 移動 Move the selection area 移動選擇區域 PencilTool Pencil 鉛筆 Set the Pencil as the paint tool 將鉛筆設定為繪畫工具 PinTool Pin Tool Pin image on the desktop QObject Save Error 存檔錯誤 Capture saved as 截圖已另存為 Capture saved to clipboard Error trying to save as 嘗試另存新檔時發生錯誤 Unable to connect via DBus 無法透過 DBus 進行連接 Error 錯誤 Unable to write in 無法寫入 RectangleTool Rectangle 實心矩形 Set the Rectangle as the paint tool 將實心矩形設定為繪畫工具 RedoTool Redo Redo the next modification SaveTool Save 儲存 Save the capture 儲存擷取 ScreenGrabber Unable to capture screen 無法擷取螢幕 SelectionTool Rectangular Selection 矩形選擇 Set Selection as the paint tool 將矩形選擇設定為繪畫工具 SidePanelWidget Active thickness: Active color: Press ESC to cancel Grab Color SizeIndicatorTool Selection Size Indicator 選擇尺寸指示 Show 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) Time (%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) SystemNotification Flameshot Info TextConfig StrikeOut Underline Bold Italic TextTool Text Add text to your capture 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 全選