Showing preview only (3,068K chars total). Download the full file or copy to clipboard to get everything.
Repository: persepolisdm/persepolis
Branch: master
Commit: 109e95261fa2
Files: 124
Total size: 2.9 MB
Directory structure:
gitextract_m5nz38oz/
├── .github/
│ ├── ISSUE_TEMPLATE
│ └── contributing.md
├── .gitignore
├── .pep8
├── .travis.yml
├── .tx/
│ └── config
├── LICENSE
├── README.md
├── check_dependencies.py
├── clear.py
├── man/
│ ├── meson.build
│ └── persepolis.1
├── meson.build
├── persepolis/
│ ├── .pep8
│ ├── Persepolis Download Manager.py
│ ├── __init__.py
│ ├── __main__.py
│ ├── constants/
│ │ ├── Browser.py
│ │ ├── Os.py
│ │ ├── Version.py
│ │ └── __init__.py
│ ├── gui/
│ │ ├── .pep8
│ │ ├── __init__.py
│ │ ├── about_ui.py
│ │ ├── addlink_ui.py
│ │ ├── after_download_ui.py
│ │ ├── customized_widgets.py
│ │ ├── log_window_ui.py
│ │ ├── mainwindow_ui.py
│ │ ├── progress_ui.py
│ │ ├── resources.py
│ │ ├── setting_ui.py
│ │ ├── text_queue_ui.py
│ │ └── video_finder_progress_ui.py
│ ├── meson.build
│ ├── persepolis.py
│ └── scripts/
│ ├── .pep8
│ ├── __init__.py
│ ├── about.py
│ ├── addlink.py
│ ├── after_download.py
│ ├── browser_integration.py
│ ├── browser_plugin_queue.py
│ ├── bubble.py
│ ├── check_proxy.py
│ ├── compatibility.py
│ ├── data_base.py
│ ├── download_link.py
│ ├── error_window.py
│ ├── initialization.py
│ ├── log_window.py
│ ├── logger.py
│ ├── mainwindow.py
│ ├── newopen.py
│ ├── osCommands.py
│ ├── persepolis.py
│ ├── persepolis_lib_prime.py
│ ├── play.py
│ ├── progress.py
│ ├── properties.py
│ ├── queue.py
│ ├── queue_prime.py
│ ├── setting.py
│ ├── shutdown.py
│ ├── spider.py
│ ├── startup.py
│ ├── text_queue.py
│ ├── useful_tools.py
│ ├── video_finder.py
│ ├── video_finder_addlink.py
│ ├── video_finder_progress.py
│ └── ytdlp_downloader.py
├── requirements.md
├── requirements.txt
├── resources/
│ ├── PersepolisBI.py
│ ├── dark_style.qss
│ ├── light_style.qss
│ ├── locales/
│ │ ├── ui.qm
│ │ ├── ui.ts
│ │ ├── ui_ar.qm
│ │ ├── ui_ar.ts
│ │ ├── ui_de.qm
│ │ ├── ui_de.ts
│ │ ├── ui_es_ES.qm
│ │ ├── ui_es_ES.ts
│ │ ├── ui_fa_IR.qm
│ │ ├── ui_fa_IR.ts
│ │ ├── ui_fr_FR.qm
│ │ ├── ui_fr_FR.ts
│ │ ├── ui_hu.qm
│ │ ├── ui_hu.ts
│ │ ├── ui_ko.qm
│ │ ├── ui_ko.ts
│ │ ├── ui_nl_NL.qm
│ │ ├── ui_nl_NL.ts
│ │ ├── ui_pl_PL.qm
│ │ ├── ui_pl_PL.ts
│ │ ├── ui_pt.qm
│ │ ├── ui_pt.ts
│ │ ├── ui_pt_BR.qm
│ │ ├── ui_pt_BR.ts
│ │ ├── ui_ru.qm
│ │ ├── ui_ru.ts
│ │ ├── ui_sv.qm
│ │ ├── ui_sv.ts
│ │ ├── ui_tr.qm
│ │ ├── ui_tr.ts
│ │ ├── ui_tr_TR.qm
│ │ ├── ui_tr_TR.ts
│ │ ├── ui_zh_CN.qm
│ │ ├── ui_zh_CN.ts
│ │ ├── ui_zh_TW.qm
│ │ └── ui_zh_TW.ts
│ ├── meson.build
│ ├── resources.qrc
│ ├── resources_generator.sh
│ ├── translation_files.pro
│ └── translators.txt
├── test/
│ ├── .pep8
│ └── test.py
├── uninstall.py
└── xdg/
├── com.github.persepolisdm.persepolis.appdata.xml
├── com.github.persepolisdm.persepolis.desktop.in
└── meson.build
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE
================================================
**System Details:**
* Operating System: ?
* Distro(For GNU/Linux and BSD users): ?
* Desktop Environment(For GNU/Linux and BSD users): ?
* Persepolis Version: ?
* How do you install Persepolis? (Repositories, source, ...)
* _Please attach log files if crash or paste error message_
**Issue Description and steps to reproduce:**
#### Write in English language please, Thanks :)
#### Feel free to edit or delete lines in this template if it is necessary.
#### Please report only one Issue (Bug or feature request or ...) in one issue! and open new Issue for another one :)
================================================
FILE: .github/contributing.md
================================================
Please read our [contribution instruction](https://github.com/persepolisdm/persepolis/wiki/Home-en#contributers-guide).
================================================
FILE: .gitignore
================================================
__pycache__/
*.pyc
.env
*.orig
root/
build/
builddir/
persepolis.egg-info/
man/persepolis.1.gz
.idea/
.mypy_cache
persepolis_wenv/
test/ffmpeg
resources/ffmpeg
dist/
*.spec
venv_dir/
test/ffmpeg.exe
Persepolis\ Download\ Manager.build/
Persepolis\ Download\ Manager.dist/
Persepolis\ Download\ Manager.onefile-build/
================================================
FILE: .pep8
================================================
[pycodestyle]
max_line_length = 120
ignore = E501,E722,W503
================================================
FILE: .travis.yml
================================================
language: python
dist: bionic
sudo: required
python:
- "3.6"
virtualenv:
system_site_packages: true
addons:
apt:
update: true
packages:
python3
aria2
sound-theme-freedesktop
libnotify-bin
libqt5svg5
python3-pyqt5.qtsvg
python3-setuptools
python3-pip
python3-pyqt5
pulseaudio
python3-psutil
ffmpeg
before_install:
- sudo pip3 install youtube-dl requests setproctitle
install: true
script:
- sudo python3 setup.py install
- persepolis --version
after_success:
- pip3 install transifex-client==0.12.5
- sudo echo $'[https://www.transifex.com]\napi_hostname = https://api.transifex.com\nhostname = https://www.transifex.com\nusername = '"$TRANSIFEX_USER"$'\npassword = '"$TRANSIFEX_PASSWORD"$'\n' > ~/.transifexrc
- tx push -s
================================================
FILE: .tx/config
================================================
[main]
host = https://www.transifex.com
[persepolis-translations.ui]
file_filter = resources/locales/ui_<lang>.ts
minimum_perc = 0
source_file = resources/locales/ui.ts
source_lang = en
type = QT
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
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 <http://www.gnu.org/licenses/>.
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
<http://www.gnu.org/licenses/>.
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
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
================================================
FILE: README.md
================================================
<p align="center">
<img src="https://persepolisdm.github.io/img/screen/persepolisـreadme.png" width="128px"/>
</p>
<h1 align="center">Persepolis Download Manager</h1>
[](https://github.com/persepolisdm/persepolis/releases) [](https://github.com/persepolisdm/persepolis) [](https://github.com/persepolisdm/persepolis/blob/master/LICENSE) [](https://travis-ci.org/persepolisdm/persepolis) [](https://github.com/persepolisdm/persepolis/commits/master) [](https://github.com/persepolisdm/persepolis/graphs/contributors) [](https://github.com/persepolisdm/persepolis/commits/master) [](https://aur.archlinux.org/packages/persepolis-git) [](https://twitter.com/persepolisdm)
> **Content**
> - [About](https://github.com/persepolisdm/persepolis#about)
> - [How to install PersepolisDM](https://github.com/persepolisdm/persepolis/wiki)
> - [FAQ](https://github.com/persepolisdm/persepolis#faq)
> - [Screenshots](https://github.com/persepolisdm/persepolis#screenshots)
> - [Credits](https://github.com/persepolisdm/persepolis#credits)
### **About**
Persepolis is a download manager written in Python. Persepolis is a sample of free and open-source software. It's developed for GNU/Linux distributions, BSDs, macOS, and Microsoft Windows.
### **Features**
- Multi-segment downloading (64 connections)
- Scheduling downloads
- Download queuing
- Downloading videos from Youtube and ...
- and many more!
Demonstration clip:
[](https://www.youtube.com/watch?v=QHdMShFgzhQ)
### How to install PersepolisDM?
> Please checkout the Persepolis [wiki](https://github.com/persepolisdm/persepolis/wiki)
### **FAQ**
> **Where does the name come from?**
> > [From Wikipedia:](https://en.wikipedia.org/wiki/Persepolis) Persepolis (Greek: Περσέπολις Persépolis; "the Persian city") or Parsa (Old Persian: 𐎱𐎠𐎼𐎿 Pārsa; "Persia"),
also known as Takht-e-Jamshid (Persian: تخت جمشيد Taxt e Jamšid; "Throne of Jamshid"),
was the ceremonial capital of the Achaemenid Empire (ca. 550–330 BC).
Persepolis is situated 60 km northeast of the city of Shiraz in Fars Province, Iran. The earliest remains of Persepolis date back to 515 BC.
It exemplifies the Achaemenid style of architecture. UNESCO declared the ruins of Persepolis a World Heritage Site in 1979.
> **How can I install Persepolis?**
> > Read [our wiki](https://github.com/persepolisdm/persepolis/wiki) or check the [Persepolis website](https://persepolisdm.github.io) for more information.
### **Screenshots**
|GNU/Linux|BSD|
|:---:|:---:|
|||
|Mac OSX|Windows|
|:---:|:---:|
|||
### Credits
**Alireza Amirsamimi:** Persepolis lead developer and manager
[GitHub](https://github.com/alireza-amirsamimi) | [E-mail](mailto:alireza.amirsamimi@gmail.com)
**Mohammadreza Abdollahzadeh:** Arch Linux and BSD support
[GitHub](https://github.com/morealaz) | [E-mail](mailto:morealaz@gmail.com)
**Mostafa Asadi:** Ubuntu, Debian and Windows support
[GitHub](https://github.com/mostafaasadi) | [E-mail](mailto:mostafaasadi73@gmail.com)
**Sadegh Alirezaie:** Persepolis website support
[GitHub](https://github.com/Alirezaies) | [E-mail](mailto:alirezaie@sadegh.org)
**Jafar Akhondali:** Browsers add-ons support
[GitHub](https://github.com/JafarAkhondali) | [E-mail](mailto:jafar.akhondali@yahoo.com)
**Kia Hamedi:** Mac OSX support
[GitHub](https://github.com/Kiahamedi) | [E-mail](mailto:me@kiahamedi.com)
**H Rostami:** UI translation, Fedora & OpenSuse support
[GitHub](https://github.com/hayyan71) | [E-mail](mailto:hayyan71@yahoo.com)
**Ehsan Titish:** Mac OSX support
[GitHub](https://github.com/Maders) | [E-mail](mailto:me@maders.ir)
**MohammadAmin Vahedinia:** Mac OSX support
[GitHub](https://github.com/Mr0Null) | [E-mail](mailto:persepolisdm@vahedinia.me)
[Persepolis website (En)](https://persepolisdm.github.io/) | [Persepolis website (Fa)](https://persepolisdm.github.io/fa) | [Twitter](https://twitter.com/persepolisdm) | [Telegram Channel](https://telegram.me/persepolisdm)
### Acknowledgments:
[YT-DLP project](https://github.com/yt-dlp/yt-dlp)
[FFmpeg project](https://github.com/FFmpeg/FFmpeg)
[PySide project](https://wiki.qt.io/Qt_for_Python)
[Python Requests project](https://github.com/psf/requests)
---
_Are there any mistakes in README.md? Report it in the [issue tracker](https://github.com/persepolisdm/persepolis/issues) or correct it by yourself._
================================================
FILE: check_dependencies.py
================================================
#!/usr/bin/env python3
# coding: utf-8
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import os
import platform
# finding os platform
os_type = platform.system()
# Checking dependencies!
not_installed = ''
# PyQt5 or PySide6
try:
import PySide6
print('python3-pyside6 is found')
pyside6_is_installed = True
except ImportError:
pyside6_is_installed = False
if not(pyside6_is_installed):
try:
import PyQt5
print('python3-pyqt5 is found')
except ImportError:
print('Error : python3-pyqt5 or pyside6 must be installed!')
not_installed = not_installed + '(PyQt5 or PySide6) '
# python3-requests
try:
import requests
print('python3-requests is found!')
except ImportError:
print('Error : requests is not installed!')
not_installed = not_installed + 'python3-requests, '
# python3-urllib3
try:
import urllib3
print('python3-urllib3 is found!')
except ImportError:
print('Error : urllib3 is not installed!')
not_installed = not_installed + 'python3-urllib3, '
# python3-setproctitle
try:
import setproctitle
print('python3-setproctitle is found!')
except ImportError:
print("Warning: setproctitle is not installed!")
not_installed = not_installed + 'python3-setproctitle, '
# python3-PySocks
try:
import socks
print('python3-pysocks is found!')
except ImportError:
print("Warning: python3-pysocks is not installed!")
not_installed = not_installed + 'python3-pysocks, '
# psutil
try:
import psutil
print('python3-psutil is found!')
except ImportError:
print("Warning: python3-psutil is not installed!")
not_installed = not_installed + 'psutil, '
# yt_dlp
try:
import yt_dlp
print('yt-dlp is found')
except ImportError:
print('Warning: yt-dlp is not installed!')
not_installed = not_installed + 'yt-dlp, '
# ffmpeg
answer = os.system('ffmpeg -version 1>/dev/null')
if answer != 0:
print("Warning: ffmpeg not installed!")
not_installed = not_installed + 'ffmpeg, '
else:
print('ffmpeg is found!')
if os_type == 'Linux':
try:
from dasbus.connection import SessionMessageBus
print('python3-dasbus is found!')
except ImportError:
print('python3-dasbus is not installed!')
not_installed = not_installed + 'python3-dasbus,'
if not_installed != '':
print('########################')
print('####### WARNING ########')
print('########################')
print('Some dependencies are not installed .It causes some problems for persepolis! : \n')
print(not_installed + '\n\n')
print('Read this link for more information: \n')
print('https://github.com/persepolisdm/persepolis/wiki/git-installation-instruction\n\n')
================================================
FILE: clear.py
================================================
#!/usr/bin/env python3
# coding: utf-8
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import os
import warnings
import sys
import platform
import shutil
from persepolis.constants import OS
# finding os platform
os_type = platform.system()
if os_type == 'Linux' or os_type == 'FreeBSD' or os_type == 'OpenBSD':
print(os_type + " detected!")
else:
print('This script is only work for GNU/Linux or BSD!')
sys.exit(1)
# finding current directory
cwd = os.path.abspath(__file__)
setup_dir = os.path.dirname(cwd)
# clearing __pycache__
src_pycache = os.path.join(setup_dir, 'persepolis', '__pycache__')
gui_pycache = os.path.join(setup_dir, 'persepolis', 'gui', '__pycache__')
scripts_pycache = os.path.join(setup_dir, 'persepolis', 'scripts', '__pycache__')
constants_pycache = os.path.join(setup_dir, 'persepolis', 'constants', '__pycache__')
for folder in [src_pycache, gui_pycache, scripts_pycache, constants_pycache]:
if os.path.isdir(folder):
shutil.rmtree(folder)
print(str(folder)
+ ' is removed!')
uid = os.getuid()
if uid != 0:
print('Run this script as root\n\
if you want to clean unwanted files that created by setup tools')
sys.exit(1)
# finding current directory
cwd = os.path.abspath(__file__)
setup_dir = os.path.dirname(cwd)
# clearing __pycache__
src_pycache = os.path.join(setup_dir, 'persepolis', '__pycache__')
gui_pycache = os.path.join(setup_dir, 'persepolis', 'gui', '__pycache__')
scripts_pycache = os.path.join(setup_dir, 'persepolis', 'scripts', '__pycache__')
constants_pycache = os.path.join(setup_dir, 'persepolis', 'constants', '__pycache__')
for folder in [src_pycache, gui_pycache, scripts_pycache, constants_pycache]:
if os.path.isdir(folder):
shutil.rmtree(folder)
print(str(folder)
+ ' is removed!')
# clear unwanted files!
for folder in ['build', 'dist', 'root', 'persepolis.egg-info']:
if os.path.isdir(folder):
shutil.rmtree(folder)
print(str(folder)
+ ' is removed!')
man_page = 'man/persepolis.1.gz'
if os.path.isfile(man_page):
os.remove('man/persepolis.1.gz')
================================================
FILE: man/meson.build
================================================
# creating man page file
persepolis_man_page='persepolis.1'
install_man(persepolis_man_page)
================================================
FILE: man/persepolis.1
================================================
.TH "Persepolis" "1" "July 14, 2025" "5.2.0" "persepolis"
.SH NAME
persepolis \- Persepolis Download Manager
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.\" Man page generated from reStructuredText.
.
.SH SYNOPSIS
.sp
\fBpersepolis\fP --link [<URI>] [<OPTIONS>]
.SH DESCRIPTION
.sp
Persepolis Download Manager is a feature-full utility for easier and faster downloads with aria2.
It support HTTP(S) & FTP.Persepolis configures aria2 automatically
for maximum speed and it has a GUI for the ease of use.
You can adjust start time and end time for downloads.Persepolis can shutdown
system after download. You can integrate persepolis with your browser(read persepolis wiki on github page).
.SH OPTIONS
.SS Basic Options
.INDENT 0.0
.TP
.B \--link
Your Download link.(Use "" for links)
$ persepolis --link "https://www.google.com/images/srpr/logo11w.png"
.UNINDENT
.INDENT 0.0
.TP
.B \--referrer
Set an http referrer (Referer). This affects all http/https downloads. If * is given, the download URI is also used as the referrer.
.UNINDENT
.INDENT 0.0
.TP
.B \--load-cookies
Set cookies file path.
.UNINDENT
.INDENT 0.0
.TP
.B \--agent
Set user agent for HTTP(S) downloads. Default: aria2/$VERSION, $VERSION is replaced by package version.
.UNINDENT
.INDENT 0.0
.TP
.B \--headers
Append HEADER to HTTP request header.
.UNINDENT
.INDENT 0.0
.TP
.B \--name
The file name of the downloaded file.
.UNINDENT
.INDENT 0.0
.TP
.B \--default
Restore default settings.
.UNINDENT
.INDENT 0.0
.TP
.B \--clear
Clear download list and user setting!
.UNINDENT
.INDENT 0.0
.TP
.B \--tray
Persepolis starts in tray icon. It's useful when you want to put persepolis in system's startup.
.UNINDENT
.INDENT 0.0
.TP
.B \--version
Showing persepolis version.
.UNINDENT
.INDENT 0.0
.TP
.B \--help
Persepolis help.
.UNINDENT
.INDENT 0.0
.TP
.SH MORE HELP
for configuration with firefox flashgot please see README.md file on github
https://github.com/persepolisdm/persepolis
.SH SEE ALSO
aria2c(1)
.SH AUTHOR
.B AliReza AmirSamimi
.UNINDENT
.INDENT 0.0
.TP
.B Github page
https://github.com/persepolisdm/persepolis
.UNINDENT
.INDENT 0.0
.TP
.B PersepolisDM Telegram Channel
https://telegram.me/persepolisdm
================================================
FILE: meson.build
================================================
project('persepolis',
version: '5.2.0',
meson_version: '>=0.61.2')
python = import('python')
python3 = python.find_installation('python3')
if not python3.found()
error('No valid python3 installation found!')
endif
# run dependency check script
meson.add_install_script('check_dependencies.py')
prefix = get_option('prefix')
bindir = join_paths(prefix, get_option('bindir'))
datadir = join_paths(prefix, get_option('datadir'))
pythondir = join_paths(prefix, python3.get_path('purelib'))
pkgdatadir = join_paths(datadir, meson.project_name())
pkgappid = 'com.github.persepolisdm.persepolis'
appdatadir = join_paths(datadir, 'metainfo')
desktopdir = join_paths(datadir, 'applications')
persepolisdir = python3.get_install_dir(subdir: 'persepolis')
icondir = join_paths(datadir, 'icons', 'hicolor', 'scalable', 'apps')
subdir('persepolis')
subdir('man')
subdir('xdg')
subdir('resources')
================================================
FILE: persepolis/.pep8
================================================
[pycodestyle]
max_line_length = 120
================================================
FILE: persepolis/Persepolis Download Manager.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# this file is created for building persepolis with pyinstaller.
from persepolis.scripts import persepolis
persepolis.main()
================================================
FILE: persepolis/__init__.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# import sys
# sys.path.insert(1, '.')
================================================
FILE: persepolis/__main__.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from persepolis.scripts import persepolis
persepolis.main()
================================================
FILE: persepolis/constants/Browser.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
class BROWSER:
CHROME = 'chrome'
CHROMIUM = 'chromium'
OPERA = 'opera'
VIVALDI = 'vivaldi'
FIREFOX = 'firefox'
BRAVE = 'brave'
LIBREWOLF = 'librewolf'
CHROME_FAMILY = [CHROME, CHROMIUM, VIVALDI, OPERA, BRAVE]
FIREFOX_FAMILY = [FIREFOX, LIBREWOLF]
LIST = [CHROME, CHROMIUM, OPERA, VIVALDI, FIREFOX, BRAVE]
================================================
FILE: persepolis/constants/Os.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
class OS:
LINUX = 'Linux'
WINDOWS = 'Windows'
FREE_BSD = 'FreeBSD'
OPEN_BSD = 'OpenBSD'
OSX = DARWIN = 'Darwin'
BSD_FAMILY = [FREE_BSD, OPEN_BSD]
UNIX_LIKE = [FREE_BSD, OPEN_BSD, LINUX]
LIST = [LINUX, WINDOWS, FREE_BSD, OPEN_BSD, OSX]
================================================
FILE: persepolis/constants/Version.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
class VERSION:
version_str = '5.2.0'
================================================
FILE: persepolis/constants/__init__.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# import sys
# sys.path.insert(1, '.')
from .Os import OS
from .Browser import BROWSER
from .Version import VERSION
================================================
FILE: persepolis/gui/.pep8
================================================
[pycodestyle]
max_line_length = 120
================================================
FILE: persepolis/gui/__init__.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# import sys
# sys.path.insert(1, '.')
================================================
FILE: persepolis/gui/about_ui.py
================================================
# -*- coding: utf-8 -*-
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
try:
from PySide6.QtWidgets import QWidget, QTabWidget, QHBoxLayout, QVBoxLayout, QLabel, QTextEdit, QPushButton
from PySide6.QtCore import Qt, QSize, QTranslator, QCoreApplication, QLocale
from PySide6.QtGui import QIcon, QFont
pyside6_is_installed = True
except ImportError:
from PyQt5.QtWidgets import QWidget, QTabWidget, QHBoxLayout, QVBoxLayout, QLabel, QTextEdit, QPushButton
from PyQt5.QtCore import Qt, QSize, QTranslator, QCoreApplication, QLocale
from PyQt5.QtGui import QIcon, QFont
pyside6_is_installed = False
from persepolis.gui import resources
from persepolis.constants import VERSION
if pyside6_is_installed is True:
try:
from PySide6 import QtSvgWidgets
qtsvg_available = True
except ImportError:
qtsvg_available = False
else:
try:
from PyQt5 import QtSvg as QtSvgWidgets
qtsvg_available = True
except ImportError:
qtsvg_available = False
class AboutWindow_Ui(QWidget):
def __init__(self, persepolis_setting):
super().__init__()
self.persepolis_setting = persepolis_setting
# add support for other languages
locale = str(self.persepolis_setting.value('settings/locale'))
QLocale.setDefault(QLocale(locale))
self.translator = QTranslator()
if self.translator.load(':/translations/locales/ui_' + locale, 'ts'):
QCoreApplication.installTranslator(self.translator)
# set ui direction
ui_direction = self.persepolis_setting.value('ui_direction')
if ui_direction == 'rtl':
self.setLayoutDirection(Qt.RightToLeft)
elif ui_direction in 'ltr':
self.setLayoutDirection(Qt.LeftToRight)
icons = ':/' + \
str(self.persepolis_setting.value('settings/icons')) + '/'
self.setMinimumSize(QSize(545, 375))
self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/com.github.persepolisdm.persepolis.svg')))
verticalLayout = QVBoxLayout(self)
self.about_tabWidget = QTabWidget(self)
# about tab
self.about_tab = QWidget(self)
about_tab_horizontalLayout = QHBoxLayout(self.about_tab)
about_tab_verticalLayout = QVBoxLayout()
# persepolis icon
if qtsvg_available:
persepolis_icon_verticalLayout = QVBoxLayout()
self.persepolis_icon = QtSvgWidgets.QSvgWidget(':/com.github.persepolisdm.persepolis.svg')
self.persepolis_icon.setFixedSize(QSize(64, 64))
persepolis_icon_verticalLayout.addWidget(self.persepolis_icon)
persepolis_icon_verticalLayout.addStretch(1)
about_tab_horizontalLayout.addLayout(persepolis_icon_verticalLayout)
self.title_label = QLabel(self.about_tab)
font = QFont()
font.setBold(True)
font.setWeight(QFont.Weight.Bold)
self.title_label.setFont(font)
self.title_label.setAlignment(Qt.AlignCenter)
about_tab_verticalLayout.addWidget(self.title_label)
self.version_label = QLabel(self.about_tab)
self.version_label.setAlignment(Qt.AlignCenter)
self.version_label.setFont(font)
about_tab_verticalLayout.addWidget(self.version_label)
self.site2_label = QLabel(self.about_tab)
self.site2_label.setTextFormat(Qt.RichText)
self.site2_label.setAlignment(Qt.AlignCenter)
self.site2_label.setOpenExternalLinks(True)
self.site2_label.setTextInteractionFlags(
Qt.TextBrowserInteraction)
about_tab_verticalLayout.addWidget(self.site2_label)
self.telegram_label = QLabel(self.about_tab)
self.telegram_label.setTextFormat(Qt.RichText)
self.telegram_label.setAlignment(Qt.AlignCenter)
self.telegram_label.setOpenExternalLinks(True)
self.telegram_label.setTextInteractionFlags(
Qt.TextBrowserInteraction)
about_tab_verticalLayout.addWidget(self.telegram_label)
self.twitter_label = QLabel(self.about_tab)
self.twitter_label.setTextFormat(Qt.RichText)
self.twitter_label.setAlignment(Qt.AlignCenter)
self.twitter_label.setOpenExternalLinks(True)
self.twitter_label.setTextInteractionFlags(
Qt.TextBrowserInteraction)
about_tab_verticalLayout.addWidget(self.twitter_label)
about_tab_verticalLayout.addStretch(1)
about_tab_horizontalLayout.addLayout(about_tab_verticalLayout)
# developers_tab
# developers
self.developers_tab = QWidget(self)
developers_verticalLayout = QVBoxLayout(self.developers_tab)
self.developers_title_label = QLabel(self.developers_tab)
font.setBold(True)
font.setWeight(QFont.Weight.Bold)
self.developers_title_label.setFont(font)
self.developers_title_label.setAlignment(Qt.AlignCenter)
developers_verticalLayout.addWidget(self.developers_title_label)
self.name_label = QLabel(self.developers_tab)
self.name_label.setAlignment(Qt.AlignCenter)
developers_verticalLayout.addWidget(self.name_label)
# contributors
self.contributors_thank_label = QLabel(self.developers_tab)
self.contributors_thank_label.setFont(font)
self.contributors_thank_label.setAlignment(Qt.AlignCenter)
developers_verticalLayout.addWidget(self.contributors_thank_label)
self.contributors_link_label = QLabel(self.developers_tab)
self.contributors_link_label.setTextFormat(Qt.RichText)
self.contributors_link_label.setAlignment(Qt.AlignCenter)
self.contributors_link_label.setOpenExternalLinks(True)
self.contributors_link_label.setTextInteractionFlags(
Qt.TextBrowserInteraction)
developers_verticalLayout.addWidget(self.contributors_link_label)
developers_verticalLayout.addStretch(1)
# translators tab
self.translators_tab = QWidget(self)
translators_tab_verticalLayout = QVBoxLayout(self.translators_tab)
# translators
self.translators_textEdit = QTextEdit(self.translators_tab)
self.translators_textEdit.setReadOnly(True)
translators_tab_verticalLayout.addWidget(self.translators_textEdit)
# License tab
self.license_tab = QWidget(self)
license_tab_verticalLayout = QVBoxLayout(self.license_tab)
self.license_text = QTextEdit(self.license_tab)
self.license_text.setReadOnly(True)
license_tab_verticalLayout.addWidget(self.license_text)
verticalLayout.addWidget(self.about_tabWidget)
# Acknowledgments tab
self.acknowledgments_tab = QWidget(self)
acknowledgments_verticalLayout = QVBoxLayout(self.acknowledgments_tab)
self.acknowledgments_title_label = QLabel(self.acknowledgments_tab)
font.setBold(True)
font.setWeight(QFont.Weight.Bold)
self.acknowledgments_title_label.setFont(font)
self.acknowledgments_title_label.setAlignment(Qt.AlignCenter)
acknowledgments_verticalLayout.addWidget(self.acknowledgments_title_label)
self.acknowledgments_ffmpeg_label = QLabel(self.acknowledgments_tab)
self.acknowledgments_ffmpeg_label.setAlignment(Qt.AlignCenter)
self.acknowledgments_ytdlp_label = QLabel(self.acknowledgments_tab)
self.acknowledgments_ytdlp_label.setAlignment(Qt.AlignCenter)
self.acknowledgments_pyton_requests_label = QLabel(self.acknowledgments_tab)
self.acknowledgments_pyton_requests_label.setAlignment(Qt.AlignCenter)
self.acknowledgments_pyside_label = QLabel(self.acknowledgments_tab)
self.acknowledgments_pyside_label.setAlignment(Qt.AlignCenter)
self.acknowledgments_ffmpeg_label.setFont(font)
self.acknowledgments_ytdlp_label.setFont(font)
self.acknowledgments_pyside_label.setFont(font)
self.acknowledgments_pyton_requests_label.setFont(font)
acknowledgments_verticalLayout.addWidget(self.acknowledgments_ytdlp_label)
acknowledgments_verticalLayout.addWidget(self.acknowledgments_ffmpeg_label)
acknowledgments_verticalLayout.addWidget(self.acknowledgments_pyton_requests_label)
acknowledgments_verticalLayout.addWidget(self.acknowledgments_pyside_label)
acknowledgments_verticalLayout.addStretch(1)
# buttons
button_horizontalLayout = QHBoxLayout()
button_horizontalLayout.addStretch(1)
self.pushButton = QPushButton(self)
self.pushButton.setIcon(QIcon(icons + 'ok'))
self.pushButton.clicked.connect(self.close)
button_horizontalLayout.addWidget(self.pushButton)
verticalLayout.addLayout(button_horizontalLayout)
self.setWindowTitle(QCoreApplication.translate("about_ui_tr", "About Persepolis"))
# about_tab
self.title_label.setText(QCoreApplication.translate("about_ui_tr", "Persepolis Download Manager"))
self.version_label.setText(QCoreApplication.translate("about_ui_tr", "Version " + VERSION.version_str,
"TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!"))
self.site2_label.setText(QCoreApplication.translate("about_ui_tr",
"<a href=https://persepolisdm.github.io>https://persepolisdm.github.io</a>",
"TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!"))
self.telegram_label.setText(QCoreApplication.translate("about_ui_tr",
"<a href=https://telegram.me/persepolisdm>https://telegram.me/persepolisdm</a>",
"TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!"))
self.twitter_label.setText(QCoreApplication.translate("about_ui_tr",
"<a href=https://twitter.com/persepolisdm>https://twitter.com/persepolisdm</a>",
"TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!"))
# developers_tab
self.developers_title_label.setText(QCoreApplication.translate('about_ui_tr', 'Developers'))
self.name_label.setText(QCoreApplication.translate("about_ui_tr",
"\nAliReza AmirSamimi\nMohammadreza Abdollahzadeh\nSadegh Alirezaie\nMostafa Asadi\nJafar Akhondali\nKia Hamedi\nH.Rostami\nEhsan Titish\nMohammadAmin Vahedinia",
"TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!"))
self.contributors_thank_label.setText(QCoreApplication.translate('about_ui_tr', 'Special thanks to:'))
self.contributors_link_label.setText(
"<a href=https://github.com/persepolisdm/persepolis/graphs/contributors>our contributors</a>")
# Acknowledgments
self.acknowledgments_title_label.setText(QCoreApplication.translate('about_ui_tr', 'Acknowledgments:'))
self.acknowledgments_ytdlp_label.setText(QCoreApplication.translate("about_ui_tr",
"<a href=https://github.com/yt-dlp/yt-dlp>YT-DLP project</a>",
"TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!"))
self.acknowledgments_ffmpeg_label.setText(QCoreApplication.translate("about_ui_tr",
"<a href=https://github.com/ffmpeg/ffmpeg>FFmpeg project</a>",
"TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!"))
self.acknowledgments_pyside_label.setText(QCoreApplication.translate("about_ui_tr",
"<a href=https://wiki.qt.io/Qt_for_Python>Pyside project</a>",
"TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!"))
self.acknowledgments_pyton_requests_label.setText(QCoreApplication.translate("about_ui_tr",
"<a href=https://github.com/psf/requests>Requests project</a>",
"TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!"))
# License
self.license_text.setPlainText("""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
""")
# tabs
self.about_tabWidget.addTab(self.about_tab, QCoreApplication.translate("about_ui_tr", "About Persepolis"))
self.about_tabWidget.addTab(self.developers_tab, QCoreApplication.translate("about_ui_tr", "Developers"))
self.about_tabWidget.addTab(self.acknowledgments_tab, QCoreApplication.translate("about_ui_tr", "Acknowledgments"))
self.about_tabWidget.addTab(self.translators_tab, QCoreApplication.translate("about_ui_tr", "Translators"))
self.about_tabWidget.addTab(self.license_tab, QCoreApplication.translate("about_ui_tr", "License"))
# button
self.pushButton.setText(QCoreApplication.translate("about_ui_tr", "OK"))
================================================
FILE: persepolis/gui/addlink_ui.py
================================================
# -*- coding: utf-8 -*-
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
try:
from PySide6.QtWidgets import QTabWidget, QPushButton, QComboBox, QSpinBox, QVBoxLayout, QHBoxLayout, QLabel, QWidget, QGridLayout, QCheckBox, QFrame, QLineEdit, QRadioButton
from PySide6.QtCore import Qt, QTranslator, QCoreApplication, QLocale
from PySide6 import QtCore
from PySide6.QtGui import QIcon
except ImportError:
from PyQt5.QtWidgets import QTabWidget, QPushButton, QComboBox, QSpinBox, QVBoxLayout, QHBoxLayout, QLabel, QWidget, QGridLayout, QCheckBox, QFrame, QLineEdit, QRadioButton
from PyQt5.QtCore import Qt, QTranslator, QCoreApplication, QLocale
from PyQt5 import QtCore
from PyQt5.QtGui import QIcon
from persepolis.gui import resources
from persepolis.gui.customized_widgets import MyQDateTimeEdit
class AddLinkWindow_Ui(QWidget):
def __init__(self, persepolis_setting):
super().__init__()
self.persepolis_setting = persepolis_setting
# add support for other languages
locale = str(self.persepolis_setting.value('settings/locale'))
QLocale.setDefault(QLocale(locale))
self.translator = QTranslator()
if self.translator.load(':/translations/locales/ui_' + locale, 'ts'):
QCoreApplication.installTranslator(self.translator)
# set ui direction
ui_direction = self.persepolis_setting.value('ui_direction')
if ui_direction == 'rtl':
self.setLayoutDirection(Qt.RightToLeft)
elif ui_direction in 'ltr':
self.setLayoutDirection(Qt.LeftToRight)
# get icons name
icons = ':/' + \
str(self.persepolis_setting.value('settings/icons')) + '/'
self.setMinimumSize(QtCore.QSize(520, 425))
self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/com.github.persepolisdm.persepolis.svg')))
# main layout
window_verticalLayout = QVBoxLayout()
# add link tab widget
self.add_link_tabWidget = QTabWidget(self)
window_verticalLayout.addWidget(self.add_link_tabWidget)
# link tab
self.link_tab = QWidget()
link_tab_verticalLayout = QVBoxLayout(self.link_tab)
link_tab_verticalLayout.setContentsMargins(21, 21, 21, 81)
self.link_frame = QFrame(self.link_tab)
self.link_frame.setFrameShape(QFrame.StyledPanel)
self.link_frame.setFrameShadow(QFrame.Raised)
horizontalLayout_2 = QHBoxLayout(self.link_frame)
self.link_verticalLayout = QVBoxLayout()
# link ->
self.link_horizontalLayout = QHBoxLayout()
self.link_label = QLabel(self.link_frame)
self.link_horizontalLayout.addWidget(self.link_label)
self.link_lineEdit = QLineEdit(self.link_frame)
self.link_horizontalLayout.addWidget(self.link_lineEdit)
self.link_verticalLayout.addLayout(self.link_horizontalLayout)
horizontalLayout_2.addLayout(self.link_verticalLayout)
link_tab_verticalLayout.addWidget(self.link_frame)
# add change_name field ->
self.change_name_horizontalLayout = QHBoxLayout()
self.change_name_checkBox = QCheckBox(self.link_frame)
self.change_name_horizontalLayout.addWidget(self.change_name_checkBox)
self.change_name_lineEdit = QLineEdit(self.link_frame)
self.change_name_horizontalLayout.addWidget(self.change_name_lineEdit)
self.link_verticalLayout.addLayout(self.change_name_horizontalLayout)
# add_category ->
queue_horizontalLayout = QHBoxLayout()
self.queue_frame = QFrame(self)
self.queue_frame.setFrameShape(QFrame.StyledPanel)
self.queue_frame.setFrameShadow(QFrame.Raised)
add_queue_horizontalLayout = QHBoxLayout(self.queue_frame)
self.add_queue_label = QLabel(self.queue_frame)
add_queue_horizontalLayout.addWidget(self.add_queue_label)
self.add_queue_comboBox = QComboBox(self.queue_frame)
add_queue_horizontalLayout.addWidget(self.add_queue_comboBox)
queue_horizontalLayout.addWidget(self.queue_frame)
queue_horizontalLayout.addStretch(1)
self.size_label = QLabel(self)
queue_horizontalLayout.addWidget(self.size_label)
link_tab_verticalLayout.addLayout(queue_horizontalLayout)
link_tab_verticalLayout.addStretch(1)
self.add_link_tabWidget.addTab(self.link_tab, '')
# proxy tab
self.proxy_tab = QWidget(self)
proxy_verticalLayout = QVBoxLayout(self.proxy_tab)
proxy_verticalLayout.setContentsMargins(21, 21, 21, 171)
proxy_horizontalLayout = QHBoxLayout()
self.proxy_checkBox = QCheckBox(self.proxy_tab)
self.detect_proxy_pushButton = QPushButton(self.proxy_tab)
self.detect_proxy_label = QLabel(self.proxy_tab)
proxy_horizontalLayout.addWidget(self.proxy_checkBox)
proxy_horizontalLayout.addWidget(self.detect_proxy_label)
proxy_horizontalLayout.addWidget(self.detect_proxy_pushButton)
proxy_verticalLayout.addLayout(proxy_horizontalLayout)
self.proxy_frame = QFrame(self.proxy_tab)
self.proxy_frame.setFrameShape(QFrame.StyledPanel)
self.proxy_frame.setFrameShadow(QFrame.Raised)
gridLayout = QGridLayout(self.proxy_frame)
self.ip_label = QLabel(self.proxy_frame)
gridLayout.addWidget(self.ip_label, 0, 0, 1, 1)
self.ip_lineEdit = QLineEdit(self.proxy_frame)
self.ip_lineEdit.setInputMethodHints(QtCore.Qt.ImhNone)
gridLayout.addWidget(self.ip_lineEdit, 0, 1, 1, 1)
self.port_label = QLabel(self.proxy_frame)
gridLayout.addWidget(self.port_label, 0, 2, 1, 1)
self.port_spinBox = QSpinBox(self.proxy_frame)
self.port_spinBox.setMaximum(65535)
self.port_spinBox.setSingleStep(1)
gridLayout.addWidget(self.port_spinBox, 0, 3, 1, 1)
self.proxy_user_label = QLabel(self.proxy_frame)
gridLayout.addWidget(self.proxy_user_label, 2, 0, 1, 1)
self.proxy_user_lineEdit = QLineEdit(self.proxy_frame)
gridLayout.addWidget(self.proxy_user_lineEdit, 2, 1, 1, 1)
self.proxy_pass_label = QLabel(self.proxy_frame)
gridLayout.addWidget(self.proxy_pass_label, 2, 2, 1, 1)
self.proxy_pass_lineEdit = QLineEdit(self.proxy_frame)
self.proxy_pass_lineEdit.setEchoMode(QLineEdit.Password)
gridLayout.addWidget(self.proxy_pass_lineEdit, 2, 3, 1, 1)
proxy_verticalLayout.addWidget(self.proxy_frame)
# type of proxy
self.http_radioButton = QRadioButton(self.proxy_frame)
gridLayout.addWidget(self.http_radioButton, 4, 0, 1, 1)
self.https_radioButton = QRadioButton(self.proxy_frame)
gridLayout.addWidget(self.https_radioButton, 5, 0, 1, 1)
# hide this widget until https support
self.https_radioButton.hide()
self.socks5_radioButton = QRadioButton(self.proxy_frame)
gridLayout.addWidget(self.socks5_radioButton, 6, 0, 1, 1)
proxy_verticalLayout.addStretch(1)
self.add_link_tabWidget.addTab(self.proxy_tab, '')
# more options tab
self.more_options_tab = QWidget(self)
more_options_tab_verticalLayout = QVBoxLayout(self.more_options_tab)
# download Username & Password ->
download_horizontalLayout = QHBoxLayout()
download_horizontalLayout.setContentsMargins(-1, 10, -1, -1)
download_verticalLayout = QVBoxLayout()
self.download_checkBox = QCheckBox(self.more_options_tab)
download_verticalLayout.addWidget(self.download_checkBox)
self.download_frame = QFrame(self.more_options_tab)
self.download_frame.setFrameShape(QFrame.StyledPanel)
self.download_frame.setFrameShadow(QFrame.Raised)
gridLayout_2 = QGridLayout(self.download_frame)
self.download_user_lineEdit = QLineEdit(self.download_frame)
gridLayout_2.addWidget(self.download_user_lineEdit, 0, 1, 1, 1)
self.download_user_label = QLabel(self.download_frame)
gridLayout_2.addWidget(self.download_user_label, 0, 0, 1, 1)
self.download_pass_label = QLabel(self.download_frame)
gridLayout_2.addWidget(self.download_pass_label, 1, 0, 1, 1)
self.download_pass_lineEdit = QLineEdit(self.download_frame)
self.download_pass_lineEdit.setEchoMode(QLineEdit.Password)
gridLayout_2.addWidget(self.download_pass_lineEdit, 1, 1, 1, 1)
download_verticalLayout.addWidget(self.download_frame)
download_horizontalLayout.addLayout(download_verticalLayout)
# select folder ->
self.folder_frame = QFrame(self.more_options_tab)
self.folder_frame.setFrameShape(QFrame.StyledPanel)
self.folder_frame.setFrameShadow(QFrame.Raised)
gridLayout_3 = QGridLayout(self.folder_frame)
self.download_folder_lineEdit = QLineEdit(self.folder_frame)
gridLayout_3.addWidget(self.download_folder_lineEdit, 2, 0, 1, 1)
self.folder_pushButton = QPushButton(self.folder_frame)
gridLayout_3.addWidget(self.folder_pushButton, 3, 0, 1, 1)
self.folder_pushButton.setIcon(QIcon(icons + 'folder'))
self.folder_checkBox = QCheckBox(self.folder_frame)
gridLayout_3.addWidget(self.folder_checkBox)
self.folder_label = QLabel(self.folder_frame)
self.folder_label.setAlignment(QtCore.Qt.AlignCenter)
gridLayout_3.addWidget(self.folder_label, 1, 0, 1, 1)
download_horizontalLayout.addWidget(self.folder_frame)
more_options_tab_verticalLayout.addLayout(download_horizontalLayout)
# start time ->
time_limit_horizontalLayout = QHBoxLayout()
time_limit_horizontalLayout.setContentsMargins(-1, 10, -1, -1)
start_verticalLayout = QVBoxLayout()
self.start_checkBox = QCheckBox(self.more_options_tab)
start_verticalLayout.addWidget(self.start_checkBox)
self.start_frame = QFrame(self.more_options_tab)
self.start_frame.setFrameShape(QFrame.StyledPanel)
self.start_frame.setFrameShadow(QFrame.Raised)
horizontalLayout_5 = QHBoxLayout(self.start_frame)
self.start_time_qDataTimeEdit = MyQDateTimeEdit(self.start_frame)
self.start_time_qDataTimeEdit.setDisplayFormat('H:mm')
horizontalLayout_5.addWidget(self.start_time_qDataTimeEdit)
start_verticalLayout.addWidget(self.start_frame)
time_limit_horizontalLayout.addLayout(start_verticalLayout)
# end time ->
end_verticalLayout = QVBoxLayout()
self.end_checkBox = QCheckBox(self.more_options_tab)
end_verticalLayout.addWidget(self.end_checkBox)
self.end_frame = QFrame(self.more_options_tab)
self.end_frame.setFrameShape(QFrame.StyledPanel)
self.end_frame.setFrameShadow(QFrame.Raised)
horizontalLayout_6 = QHBoxLayout(self.end_frame)
self.end_time_qDateTimeEdit = MyQDateTimeEdit(self.end_frame)
self.end_time_qDateTimeEdit.setDisplayFormat('H:mm')
horizontalLayout_6.addWidget(self.end_time_qDateTimeEdit)
end_verticalLayout.addWidget(self.end_frame)
time_limit_horizontalLayout.addLayout(end_verticalLayout)
# limit Speed ->
limit_verticalLayout = QVBoxLayout()
self.limit_frame = QFrame(self.more_options_tab)
self.limit_frame.setFrameShape(QFrame.StyledPanel)
self.limit_frame.setFrameShadow(QFrame.Raised)
verticalLayout_4 = QVBoxLayout(self.limit_frame)
limit_verticalLayout.addWidget(self.limit_frame)
time_limit_horizontalLayout.addLayout(limit_verticalLayout)
more_options_tab_verticalLayout.addLayout(time_limit_horizontalLayout)
# number of connections ->
connections_horizontalLayout = QHBoxLayout()
connections_horizontalLayout.setContentsMargins(-1, 10, -1, -1)
self.connections_frame = QFrame(self.more_options_tab)
self.connections_frame.setFrameShape(QFrame.StyledPanel)
self.connections_frame.setFrameShadow(QFrame.Raised)
self.connections_label = QLabel(self.connections_frame)
verticalLayout_4.addWidget(self.connections_label)
self.connections_spinBox = QSpinBox(self.connections_frame)
self.connections_spinBox.setMinimum(1)
self.connections_spinBox.setMaximum(64)
self.connections_spinBox.setProperty("value", 64)
verticalLayout_4.addWidget(self.connections_spinBox)
connections_horizontalLayout.addWidget(self.connections_frame)
connections_horizontalLayout.addStretch(1)
more_options_tab_verticalLayout.addLayout(connections_horizontalLayout)
more_options_tab_verticalLayout.addStretch(1)
self.add_link_tabWidget.addTab(self.more_options_tab, '')
# advance options
self.advance_options_tab = QWidget(self)
advance_options_tab_verticalLayout = QVBoxLayout(self.advance_options_tab)
# referer
referer_horizontalLayout = QHBoxLayout()
self.referer_label = QLabel(self.advance_options_tab)
referer_horizontalLayout.addWidget(self.referer_label)
self.referer_lineEdit = QLineEdit(self.advance_options_tab)
referer_horizontalLayout.addWidget(self.referer_lineEdit)
advance_options_tab_verticalLayout.addLayout(referer_horizontalLayout)
# header
header_horizontalLayout = QHBoxLayout()
self.header_label = QLabel(self.advance_options_tab)
header_horizontalLayout.addWidget(self.header_label)
self.header_lineEdit = QLineEdit(self.advance_options_tab)
header_horizontalLayout.addWidget(self.header_lineEdit)
advance_options_tab_verticalLayout.addLayout(header_horizontalLayout)
# user_agent
user_agent_horizontalLayout = QHBoxLayout()
self.user_agent_label = QLabel(self.advance_options_tab)
user_agent_horizontalLayout.addWidget(self.user_agent_label)
self.user_agent_lineEdit = QLineEdit(self.advance_options_tab)
user_agent_horizontalLayout.addWidget(self.user_agent_lineEdit)
advance_options_tab_verticalLayout.addLayout(user_agent_horizontalLayout)
# load_cookies
load_cookies_horizontalLayout = QHBoxLayout()
self.load_cookies_label = QLabel(self.advance_options_tab)
load_cookies_horizontalLayout.addWidget(self.load_cookies_label)
self.load_cookies_lineEdit = QLineEdit(self.advance_options_tab)
load_cookies_horizontalLayout.addWidget(self.load_cookies_lineEdit)
advance_options_tab_verticalLayout.addLayout(load_cookies_horizontalLayout)
advance_options_tab_verticalLayout.addStretch(1)
self.add_link_tabWidget.addTab(self.advance_options_tab, '')
# ok cancel download_later buttons ->
buttons_horizontalLayout = QHBoxLayout()
buttons_horizontalLayout.addStretch(1)
self.download_later_pushButton = QPushButton(self)
self.download_later_pushButton.setIcon(QIcon(icons + 'stop'))
self.cancel_pushButton = QPushButton(self)
self.cancel_pushButton.setIcon(QIcon(icons + 'remove'))
self.ok_pushButton = QPushButton(self)
self.ok_pushButton.setIcon(QIcon(icons + 'ok'))
buttons_horizontalLayout.addWidget(self.download_later_pushButton)
buttons_horizontalLayout.addWidget(self.cancel_pushButton)
buttons_horizontalLayout.addWidget(self.ok_pushButton)
window_verticalLayout.addLayout(buttons_horizontalLayout)
self.setLayout(window_verticalLayout)
# labels ->
self.setWindowTitle(QCoreApplication.translate("addlink_ui_tr", "Add Download Link"))
self.link_label.setText(QCoreApplication.translate("addlink_ui_tr", "Download link: "))
self.add_queue_label.setText(QCoreApplication.translate("addlink_ui_tr", "Add to category: "))
self.change_name_checkBox.setText(QCoreApplication.translate("addlink_ui_tr", "Change file name: "))
self.detect_proxy_pushButton.setText(QCoreApplication.translate("addlink_ui_tr", "Detect System Proxy Settings"))
self.proxy_checkBox.setText(QCoreApplication.translate("addlink_ui_tr", "Proxy"))
self.proxy_pass_label.setText(QCoreApplication.translate("addlink_ui_tr", "Proxy password: "))
self.ip_label.setText(QCoreApplication.translate("addlink_ui_tr", "IP: "))
self.proxy_user_label.setText(QCoreApplication.translate("addlink_ui_tr", "Proxy username: "))
self.port_label.setText(QCoreApplication.translate("addlink_ui_tr", "Port:"))
self.http_radioButton.setText(QCoreApplication.translate("addlink_ui_tr", "HTTP"))
self.https_radioButton.setText(QCoreApplication.translate("addlink_ui_tr", "HTTPS"))
self.socks5_radioButton.setText(QCoreApplication.translate("addlink_ui_tr", "SOCKS5"))
self.download_checkBox.setText(QCoreApplication.translate("addlink_ui_tr", "Download username and password"))
self.download_user_label.setText(QCoreApplication.translate("addlink_ui_tr", "Download username: "))
self.download_pass_label.setText(QCoreApplication.translate("addlink_ui_tr", "Download password: "))
self.folder_pushButton.setText(QCoreApplication.translate("addlink_ui_tr", "Change Download Folder"))
self.folder_checkBox.setText(QCoreApplication.translate("addlink_ui_tr", "Remember this path"))
self.folder_label.setText(QCoreApplication.translate("addlink_ui_tr", "Download Folder: "))
self.start_checkBox.setText(QCoreApplication.translate("addlink_ui_tr", "Start time"))
self.end_checkBox.setText(QCoreApplication.translate("addlink_ui_tr", "End time"))
self.connections_label.setText(QCoreApplication.translate("addlink_ui_tr", "Number of connections:"))
self.cancel_pushButton.setText(QCoreApplication.translate("addlink_ui_tr", "Cancel"))
self.ok_pushButton.setText(QCoreApplication.translate("addlink_ui_tr", "OK"))
self.download_later_pushButton.setText(QCoreApplication.translate("addlink_ui_tr", "Download Later"))
self.add_link_tabWidget.setTabText(self.add_link_tabWidget.indexOf(
self.link_tab), QCoreApplication.translate("addlink_ui_tr", "Link"))
self.add_link_tabWidget.setTabText(self.add_link_tabWidget.indexOf(
self.proxy_tab), QCoreApplication.translate("addlink_ui_tr", "Proxy"))
self.add_link_tabWidget.setTabText(self.add_link_tabWidget.indexOf(
self.more_options_tab), QCoreApplication.translate("addlink_ui_tr", "More Options"))
self.add_link_tabWidget.setTabText(self.add_link_tabWidget.indexOf(
self.advance_options_tab), QCoreApplication.translate("addlink_ui_tr", "Advanced Options"))
self.referer_label.setText(QCoreApplication.translate("addlink_ui_tr", 'Referrer: '))
self.header_label.setText(QCoreApplication.translate("addlink_ui_tr", 'Header: '))
self.load_cookies_label.setText(QCoreApplication.translate("addlink_ui_tr", 'Load cookies: '))
self.user_agent_label.setText(QCoreApplication.translate("addlink_ui_tr", 'User agent: '))
================================================
FILE: persepolis/gui/after_download_ui.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
try:
from PySide6.QtWidgets import QCheckBox, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QLineEdit
from PySide6.QtCore import Qt, QTranslator, QCoreApplication, QLocale
from PySide6.QtGui import QIcon
except ImportError:
from PyQt5.QtWidgets import QCheckBox, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QLineEdit
from PyQt5.QtCore import Qt, QTranslator, QCoreApplication, QLocale
from PyQt5.QtGui import QIcon
from persepolis.gui import resources
class AfterDownloadWindow_Ui(QWidget):
def __init__(self, persepolis_setting):
super().__init__()
self.persepolis_setting = persepolis_setting
# add support for other languages
locale = str(self.persepolis_setting.value('settings/locale'))
QLocale.setDefault(QLocale(locale))
self.translator = QTranslator()
if self.translator.load(':/translations/locales/ui_' + locale, 'ts'):
QCoreApplication.installTranslator(self.translator)
# set ui direction
ui_direction = self.persepolis_setting.value('ui_direction')
if ui_direction == 'rtl':
self.setLayoutDirection(Qt.RightToLeft)
elif ui_direction in 'ltr':
self.setLayoutDirection(Qt.LeftToRight)
icons = ':/' + str(self.persepolis_setting.value('settings/icons')) + '/'
self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/com.github.persepolisdm.persepolis.svg')))
self.setWindowTitle(QCoreApplication.translate("after_download_ui_tr", "Persepolis Download Manager"))
# complete_label
window_verticalLayout = QVBoxLayout()
window_verticalLayout.setContentsMargins(21, 21, 21, 21)
self.complete_label = QLabel()
window_verticalLayout.addWidget(self.complete_label)
# file_name_label
self.file_name_label = QLabel()
window_verticalLayout.addWidget(self.file_name_label)
# size_label
self.size_label = QLabel()
window_verticalLayout.addWidget(self.size_label)
# link
self.link_label = QLabel()
window_verticalLayout.addWidget(self.link_label)
self.link_lineEdit = QLineEdit()
window_verticalLayout.addWidget(self.link_lineEdit)
# save_as
self.save_as_label = QLabel()
window_verticalLayout.addWidget(self.save_as_label)
self.save_as_lineEdit = QLineEdit()
window_verticalLayout.addWidget(self.save_as_lineEdit)
# open_pushButtun
button_horizontalLayout = QHBoxLayout()
button_horizontalLayout.setContentsMargins(10, 10, 10, 10)
button_horizontalLayout.addStretch(1)
self.open_pushButtun = QPushButton()
self.open_pushButtun.setIcon(QIcon(icons + 'file'))
button_horizontalLayout.addWidget(self.open_pushButtun)
# open_folder_pushButtun
self.open_folder_pushButtun = QPushButton()
self.open_folder_pushButtun.setIcon(QIcon(icons + 'folder'))
button_horizontalLayout.addWidget(self.open_folder_pushButtun)
# ok_pushButton
self.ok_pushButton = QPushButton()
self.ok_pushButton.setIcon(QIcon(icons + 'ok'))
button_horizontalLayout.addWidget(self.ok_pushButton)
window_verticalLayout.addLayout(button_horizontalLayout)
# dont_show_checkBox
self.dont_show_checkBox = QCheckBox()
window_verticalLayout.addWidget(self.dont_show_checkBox)
window_verticalLayout.addStretch(1)
self.setLayout(window_verticalLayout)
# labels
self.open_pushButtun.setText(QCoreApplication.translate("after_download_ui_tr", " Open File "))
self.open_folder_pushButtun.setText(QCoreApplication.translate("after_download_ui_tr", "Open Download Folder"))
self.ok_pushButton.setText(QCoreApplication.translate("after_download_ui_tr", " OK "))
self.dont_show_checkBox.setText(QCoreApplication.translate(
"after_download_ui_tr", "Don't show this message again."))
self.complete_label.setText(QCoreApplication.translate("after_download_ui_tr", "<b>Download Completed!</b>"))
self.save_as_label.setText(QCoreApplication.translate("after_download_ui_tr", "<b>Save as</b>: "))
self.link_label.setText(QCoreApplication.translate("after_download_ui_tr", "<b>Link</b>: "))
================================================
FILE: persepolis/gui/customized_widgets.py
================================================
# -*- coding: utf-8 -*-
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
try:
from PySide6.QtWidgets import QDateTimeEdit
from PySide6.QtCore import QSettings, Qt
except ImportError:
from PyQt5.QtWidgets import QDateTimeEdit
from PyQt5.QtCore import QSettings, Qt
# import persepolis_setting
persepolis_setting = QSettings('persepolis_download_manager', 'persepolis')
# check ui_direction RTL or LTR
ui_direction = persepolis_setting.value('ui_direction')
class MyQDateTimeEdit(QDateTimeEdit):
def __init__(self, parent=None):
super().__init__(parent)
# change ui direction from rtl to ltr
if ui_direction == 'rtl':
self.setLayoutDirection(Qt.LeftToRight)
================================================
FILE: persepolis/gui/log_window_ui.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
try:
from PySide6.QtWidgets import QWidget, QTextEdit, QVBoxLayout, QHBoxLayout, QPushButton, QTabWidget
from PySide6.QtCore import Qt, QTranslator, QCoreApplication, QLocale
from PySide6.QtGui import QIcon
from PySide6 import QtCore
except ImportError:
from PyQt5.QtWidgets import QWidget, QTextEdit, QVBoxLayout, QHBoxLayout, QPushButton, QTabWidget
from PyQt5.QtCore import Qt, QTranslator, QCoreApplication, QLocale
from PyQt5.QtGui import QIcon
from PyQt5 import QtCore
from persepolis.gui import resources
class LogWindow_Ui(QWidget):
def __init__(self, persepolis_setting):
super().__init__()
self.persepolis_setting = persepolis_setting
# add support for other languages
locale = str(self.persepolis_setting.value('settings/locale'))
QLocale.setDefault(QLocale(locale))
self.translator = QTranslator()
if self.translator.load(':/translations/locales/ui_' + locale, 'ts'):
QCoreApplication.installTranslator(self.translator)
# set ui direction
ui_direction = self.persepolis_setting.value('ui_direction')
if ui_direction == 'rtl':
self.setLayoutDirection(Qt.RightToLeft)
elif ui_direction in 'ltr':
self.setLayoutDirection(Qt.LeftToRight)
icons = ':/' + \
str(self.persepolis_setting.value('settings/icons')) + '/'
# finding windows_size
self.setMinimumSize(QtCore.QSize(620, 300))
self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/com.github.persepolisdm.persepolis.svg')))
verticalLayout = QVBoxLayout(self)
horizontalLayout = QHBoxLayout()
horizontalLayout.addStretch(1)
# Define tabwidget
self.log_tabWidget = QTabWidget(self)
verticalLayout.addWidget(self.log_tabWidget)
# Initialization tab
self.initialization_tab = QWidget()
initialization_tab_verticalLayout = QVBoxLayout(self.initialization_tab)
# text_edit
self.initialization_text_edit = QTextEdit(self.initialization_tab)
self.initialization_text_edit.setReadOnly(True)
initialization_tab_verticalLayout.addWidget(self.initialization_text_edit)
# downloads tab
self.downloads_tab = QWidget()
downloads_tab_verticalLayout = QVBoxLayout(self.downloads_tab)
# text_edit
self.downloads_text_edit = QTextEdit(self.downloads_tab)
self.downloads_text_edit.setReadOnly(True)
downloads_tab_verticalLayout.addWidget(self.downloads_text_edit)
# errors tab
self.errors_tab = QWidget()
errors_tab_verticalLayout = QVBoxLayout(self.errors_tab)
# text_edit
self.errors_text_edit = QTextEdit(self.errors_tab)
self.errors_text_edit.setReadOnly(True)
errors_tab_verticalLayout.addWidget(self.errors_text_edit)
self.log_tabWidget.addTab(self.initialization_tab, '')
self.log_tabWidget.addTab(self.downloads_tab, '')
self.log_tabWidget.addTab(self.errors_tab, '')
# clear_log_pushButton
self.clear_log_pushButton = QPushButton(self)
horizontalLayout.addWidget(self.clear_log_pushButton)
# refresh_log_pushButton
self.refresh_log_pushButton = QPushButton(self)
self.refresh_log_pushButton.setIcon(QIcon(icons + 'refresh'))
horizontalLayout.addWidget(self.refresh_log_pushButton)
# report_pushButton
self.report_pushButton = QPushButton(self)
self.report_pushButton.setIcon(QIcon(icons + 'about'))
horizontalLayout.addWidget(self.report_pushButton)
self.copy_log_pushButton = QPushButton(self)
# copy_log_pushButton
self.copy_log_pushButton.setIcon(QIcon(icons + 'clipboard'))
horizontalLayout.addWidget(self.copy_log_pushButton)
# close_pushButton
self.close_pushButton = QPushButton(self)
self.close_pushButton.setIcon(QIcon(icons + 'remove'))
horizontalLayout.addWidget(self.close_pushButton)
verticalLayout.addLayout(horizontalLayout)
# set labels
self.setWindowTitle(QCoreApplication.translate("log_window_ui_tr", 'Persepolis Log'))
self.close_pushButton.setText(QCoreApplication.translate("log_window_ui_tr", 'Close'))
self.copy_log_pushButton.setText(QCoreApplication.translate("log_window_ui_tr", 'Copy Selected to Clipboard'))
self.report_pushButton.setText(QCoreApplication.translate("log_window_ui_tr", "Report Issue"))
self.refresh_log_pushButton.setText(QCoreApplication.translate("log_window_ui_tr", 'Refresh Log Messages'))
self.clear_log_pushButton.setText(QCoreApplication.translate("log_window_ui_tr", 'Clear Log Messages'))
self.log_tabWidget.setTabText(self.log_tabWidget.indexOf(
self.initialization_tab), QCoreApplication.translate("log_window_ui_tr", "Initialization and information"))
self.log_tabWidget.setTabText(self.log_tabWidget.indexOf(
self.downloads_tab), QCoreApplication.translate("log_window_ui_tr", "Downloads"))
self.log_tabWidget.setTabText(self.log_tabWidget.indexOf(
self.errors_tab), QCoreApplication.translate("log_window_ui_tr", "Errors and warnings"))
================================================
FILE: persepolis/gui/mainwindow_ui.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
try:
from PySide6.QtWidgets import QDial, QHeaderView, QPushButton, QComboBox, QMenu, QTreeView, QSplitter, QHBoxLayout, QVBoxLayout, QTableWidgetItem, QAbstractItemView, QToolBar, QMenuBar, QStatusBar, QTableWidget, QMainWindow, QWidget, QFrame, QCheckBox, QLabel
from PySide6.QtGui import QShortcut, QAction, QCursor, QIcon, QStandardItemModel
from PySide6.QtCore import QCoreApplication, QRect, Qt, QTranslator, QLocale
except ImportError:
from PyQt5.QtWidgets import QDial, QHeaderView, QShortcut, QPushButton, QComboBox, QTreeView, QSplitter, QHBoxLayout, QVBoxLayout, QMenu, QTableWidgetItem, QAbstractItemView, QToolBar, QMenuBar, QStatusBar, QTableWidget, QAction, QMainWindow, QWidget, QFrame, QCheckBox, QLabel
from PyQt5.QtGui import QCursor, QIcon, QStandardItemModel
from PyQt5.QtCore import QCoreApplication, QRect, Qt, QTranslator, QLocale
from persepolis.gui import resources
from persepolis.gui.customized_widgets import MyQDateTimeEdit
# align center for items in download table
class QTableWidgetItem(QTableWidgetItem):
def __init__(self, input):
super().__init__(input)
self.setTextAlignment(0x0004 | 0x0080)
class MenuWidget(QPushButton):
def __init__(self, parent):
super().__init__()
self.parent = parent
icons = ':/' + \
str(self.parent.persepolis_setting.value('settings/icons')) + '/'
# add support for other languages
locale = str(self.parent.persepolis_setting.value('settings/locale'))
QLocale.setDefault(QLocale(locale))
self.translator = QTranslator()
if self.translator.load(':/translations/locales/ui_' + locale, 'ts'):
QCoreApplication.installTranslator(self.translator)
# set ui direction
ui_direction = self.parent.persepolis_setting.value('ui_direction')
if ui_direction == 'rtl':
self.setLayoutDirection(Qt.RightToLeft)
elif ui_direction in 'ltr':
self.setLayoutDirection(Qt.LeftToRight)
# creating context menu
self.menubar = QMenu(self)
self.setMenu(self.menubar)
self.setIcon(QIcon(icons + 'menu'))
self.setStyleSheet("""QPushButton{border: none; background-color: transparent; padding: 0px}""")
fileMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'File'))
editMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'Edit'))
viewMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'View'))
downloadMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'Download'))
queueMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'Queue'))
videoFinderMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'Video Finder'))
helpMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'Help'))
sortMenu = viewMenu.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'Sort by'))
videoFinderMenu.addAction(self.parent.videoFinderAddLinkAction)
downloadMenu.addAction(self.parent.stopAllAction)
sortMenu.addAction(self.parent.sort_file_name_Action)
sortMenu.addAction(self.parent.sort_file_size_Action)
sortMenu.addAction(self.parent.sort_first_try_date_Action)
sortMenu.addAction(self.parent.sort_last_try_date_Action)
sortMenu.addAction(self.parent.sort_download_status_Action)
viewMenu.addAction(self.parent.trayAction)
viewMenu.addAction(self.parent.showMenuBarAction)
viewMenu.addAction(self.parent.showSidePanelAction)
viewMenu.addAction(self.parent.minimizeAction)
fileMenu.addAction(self.parent.addlinkAction)
fileMenu.addAction(self.parent.addtextfileAction)
fileMenu.addAction(self.parent.addFromClipboardAction)
downloadMenu.addAction(self.parent.resumeAction)
downloadMenu.addAction(self.parent.pauseAction)
downloadMenu.addAction(self.parent.stopAction)
downloadMenu.addAction(self.parent.propertiesAction)
downloadMenu.addAction(self.parent.progressAction)
fileMenu.addAction(self.parent.openFileAction)
fileMenu.addAction(self.parent.openDownloadFolderAction)
fileMenu.addAction(self.parent.openDefaultDownloadFolderAction)
fileMenu.addAction(self.parent.exitAction)
editMenu.addAction(self.parent.clearAction)
editMenu.addAction(self.parent.removeSelectedAction)
editMenu.addAction(self.parent.deleteSelectedAction)
queueMenu.addAction(self.parent.createQueueAction)
queueMenu.addAction(self.parent.removeQueueAction)
queueMenu.addAction(self.parent.startQueueAction)
queueMenu.addAction(self.parent.stopQueueAction)
queueMenu.addAction(self.parent.moveUpSelectedAction)
queueMenu.addAction(self.parent.moveDownSelectedAction)
editMenu.addAction(self.parent.preferencesAction)
helpMenu.addAction(self.parent.aboutAction)
helpMenu.addAction(self.parent.issueAction)
helpMenu.addAction(self.parent.logAction)
helpMenu.addAction(self.parent.helpAction)
# viewMenu submenus
# DownloadTableWidget Class adds QMenu to QTableWidget Class
class DownloadTableWidget(QTableWidget):
def __init__(self, parent):
super().__init__()
# set ui direction
ui_direction = parent.persepolis_setting.value('ui_direction')
if ui_direction == 'rtl':
self.setLayoutDirection(Qt.RightToLeft)
elif ui_direction in 'ltr':
self.setLayoutDirection(Qt.LeftToRight)
# creating context menu
self.tablewidget_menu = QMenu(self)
self.sendMenu = self.tablewidget_menu.addMenu('')
# don't wrap items
self.setWordWrap(False)
def contextMenuEvent(self, event):
self.tablewidget_menu.popup(QCursor.pos())
# CategoryTreeView Class adds QMenu to QTreeView
class CategoryTreeView(QTreeView):
def __init__(self, parent):
super().__init__()
# set ui direction
ui_direction = parent.persepolis_setting.value('ui_direction')
if ui_direction == 'rtl':
self.setLayoutDirection(Qt.RightToLeft)
elif ui_direction in 'ltr':
self.setLayoutDirection(Qt.LeftToRight)
# creating context menu
self.category_tree_menu = QMenu(self)
# connecting activation event
self.activated.connect(parent.categoryTreeSelected)
self.pressed.connect(parent.categoryTreeSelected)
def contextMenuEvent(self, event):
self.category_tree_menu.popup(QCursor.pos())
class MainWindow_Ui(QMainWindow):
def __init__(self, persepolis_setting):
super().__init__()
# MainWindow
self.persepolis_setting = persepolis_setting
# add support for other languages
locale = str(self.persepolis_setting.value('settings/locale'))
QLocale.setDefault(QLocale(locale))
self.translator = QTranslator()
if self.translator.load(':/translations/locales/ui_' + locale, 'ts'):
QCoreApplication.installTranslator(self.translator)
# set ui direction
ui_direction = self.persepolis_setting.value('ui_direction')
if ui_direction == 'rtl':
self.setLayoutDirection(Qt.RightToLeft)
elif ui_direction in 'ltr':
self.setLayoutDirection(Qt.LeftToRight)
icons = ':/' + \
str(self.persepolis_setting.value('settings/icons')) + '/'
self.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", "Persepolis Download Manager"))
self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/com.github.persepolisdm.persepolis.svg')))
self.centralwidget = QWidget(self)
self.verticalLayout = QVBoxLayout(self.centralwidget)
# enable drag and drop
self.setAcceptDrops(True)
# frame
self.frame = QFrame(self.centralwidget)
# download_table_horizontalLayout
download_table_horizontalLayout = QHBoxLayout()
horizontal_splitter = QSplitter(Qt.Horizontal)
vertical_splitter = QSplitter(Qt.Vertical)
# category_tree
self.category_tree_qwidget = QWidget(self)
category_tree_verticalLayout = QVBoxLayout()
self.category_tree = CategoryTreeView(self)
category_tree_verticalLayout.addWidget(self.category_tree)
self.category_tree_model = QStandardItemModel()
self.category_tree.setModel(self.category_tree_model)
category_table_header = [QCoreApplication.translate("mainwindow_ui_tr", 'Category')]
self.category_tree_model.setHorizontalHeaderLabels(
category_table_header)
self.category_tree.header().setStretchLastSection(True)
self.category_tree.header().setDefaultAlignment(Qt.AlignCenter)
# queue_panel
self.queue_panel_widget = QWidget(self)
queue_panel_verticalLayout_main = QVBoxLayout(self.queue_panel_widget)
# queue_panel_show_button
self.queue_panel_show_button = QPushButton(self)
queue_panel_verticalLayout_main.addWidget(self.queue_panel_show_button)
# queue_panel_widget_frame
self.queue_panel_widget_frame = QFrame(self)
self.queue_panel_widget_frame.setFrameShape(QFrame.StyledPanel)
self.queue_panel_widget_frame.setFrameShadow(QFrame.Raised)
queue_panel_verticalLayout_main.addWidget(
self.queue_panel_widget_frame)
queue_panel_verticalLayout = QVBoxLayout(self.queue_panel_widget_frame)
queue_panel_verticalLayout_main.setContentsMargins(50, -1, 50, -1)
# start_end_frame
self.start_end_frame = QFrame(self)
# start time
start_verticalLayout = QVBoxLayout(self.start_end_frame)
self.start_checkBox = QCheckBox(self)
start_verticalLayout.addWidget(self.start_checkBox)
self.start_frame = QFrame(self)
self.start_frame.setFrameShape(QFrame.StyledPanel)
self.start_frame.setFrameShadow(QFrame.Raised)
start_frame_verticalLayout = QVBoxLayout(self.start_frame)
self.start_time_qDataTimeEdit = MyQDateTimeEdit(self.start_frame)
self.start_time_qDataTimeEdit.setDisplayFormat('H:mm')
start_frame_verticalLayout.addWidget(self.start_time_qDataTimeEdit)
start_verticalLayout.addWidget(self.start_frame)
# end time
self.end_checkBox = QCheckBox(self)
start_verticalLayout.addWidget(self.end_checkBox)
self.end_frame = QFrame(self)
self.end_frame.setFrameShape(QFrame.StyledPanel)
self.end_frame.setFrameShadow(QFrame.Raised)
end_frame_verticalLayout = QVBoxLayout(self.end_frame)
self.end_time_qDateTimeEdit = MyQDateTimeEdit(self.end_frame)
self.end_time_qDateTimeEdit.setDisplayFormat('H:mm')
end_frame_verticalLayout.addWidget(self.end_time_qDateTimeEdit)
start_verticalLayout.addWidget(self.end_frame)
self.reverse_checkBox = QCheckBox(self)
start_verticalLayout.addWidget(self.reverse_checkBox)
queue_panel_verticalLayout.addWidget(self.start_end_frame)
# limit_after_frame
self.limit_after_frame = QFrame(self)
# limit_checkBox
limit_verticalLayout = QVBoxLayout(self.limit_after_frame)
# limit_frame
self.limit_frame = QFrame(self)
self.limit_frame.setFrameShape(QFrame.StyledPanel)
self.limit_frame.setFrameShadow(QFrame.Raised)
limit_verticalLayout.addWidget(self.limit_frame)
limit_frame_verticalLayout = QVBoxLayout(self.limit_frame)
# limit_dial and limit_label
self.limit_dial = QDial(self.limit_frame)
self.limit_dial.setNotchesVisible(True)
self.limit_dial.setMaximum(10)
self.limit_dial.setMinimum(0)
limit_frame_verticalLayout.addWidget(self.limit_dial)
self.limit_label = QLabel(self.limit_frame)
limit_frame_verticalLayout.addWidget(self.limit_label)
# after_checkBox
self.after_checkBox = QCheckBox(self)
limit_verticalLayout.addWidget(self.after_checkBox)
# after_frame
self.after_frame = QFrame(self)
self.after_frame.setFrameShape(QFrame.StyledPanel)
self.after_frame.setFrameShadow(QFrame.Raised)
limit_verticalLayout.addWidget(self.after_frame)
after_frame_verticalLayout = QVBoxLayout(self.after_frame)
# after_comboBox
self.after_comboBox = QComboBox(self)
self.after_comboBox.addItem("")
after_frame_verticalLayout.addWidget(self.after_comboBox)
# after_pushButton
self.after_pushButton = QPushButton(self)
after_frame_verticalLayout.addWidget(self.after_pushButton)
queue_panel_verticalLayout.addWidget(self.limit_after_frame)
category_tree_verticalLayout.addWidget(self.queue_panel_widget)
# keep_awake_checkBox
self.keep_awake_checkBox = QCheckBox(self)
queue_panel_verticalLayout.addWidget(self.keep_awake_checkBox)
self.category_tree_qwidget.setLayout(category_tree_verticalLayout)
horizontal_splitter.addWidget(self.category_tree_qwidget)
# download table widget
self.download_table_content_widget = QWidget(self)
download_table_content_widget_verticalLayout = QVBoxLayout(
self.download_table_content_widget)
# download_table
self.download_table = DownloadTableWidget(self)
vertical_splitter.addWidget(self.download_table)
horizontal_splitter.addWidget(self.download_table_content_widget)
self.download_table.setColumnCount(13)
self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows)
self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.download_table.verticalHeader().hide()
# hide column of GID and column of link.
self.download_table.setColumnHidden(8, True)
self.download_table.setColumnHidden(9, True)
download_table_header = [QCoreApplication.translate("mainwindow_ui_tr", 'File Name'), QCoreApplication.translate("mainwindow_ui_tr", 'Status'), QCoreApplication.translate("mainwindow_ui_tr", 'Size'), QCoreApplication.translate("mainwindow_ui_tr", 'Downloaded'), QCoreApplication.translate("mainwindow_ui_tr", 'Percentage'), QCoreApplication.translate("mainwindow_ui_tr", 'Connections'),
QCoreApplication.translate("mainwindow_ui_tr", 'Transfer Rate'), QCoreApplication.translate("mainwindow_ui_tr", 'Estimated Time Left'), 'Gid', QCoreApplication.translate("mainwindow_ui_tr", 'Link'), QCoreApplication.translate("mainwindow_ui_tr", 'First Try Date'), QCoreApplication.translate("mainwindow_ui_tr", 'Last Try Date'), QCoreApplication.translate("mainwindow_ui_tr", 'Category')]
self.download_table.setHorizontalHeaderLabels(download_table_header)
# fixing the size of download_table when window is Maximized!
self.download_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Interactive)
self.download_table.horizontalHeader().setStretchLastSection(True)
horizontal_splitter.setStretchFactor(0, 3) # category_tree width
horizontal_splitter.setStretchFactor(1, 10) # ratio of tables's width
# video_finder_widget
self.video_finder_widget = QWidget(self)
video_finder_horizontalLayout = QHBoxLayout(self.video_finder_widget)
self.muxing_pushButton = QPushButton(self)
self.muxing_pushButton.setIcon(QIcon(icons + 'video_finder'))
video_finder_horizontalLayout.addWidget(self.muxing_pushButton)
video_finder_horizontalLayout.addSpacing(20)
video_audio_verticalLayout = QVBoxLayout()
self.video_label = QLabel(self)
video_audio_verticalLayout.addWidget(self.video_label)
self.audio_label = QLabel(self)
video_audio_verticalLayout.addWidget(self.audio_label)
video_finder_horizontalLayout.addLayout(video_audio_verticalLayout)
status_muxing_verticalLayout = QVBoxLayout()
self.video_finder_status_label = QLabel(self)
status_muxing_verticalLayout.addWidget(self.video_finder_status_label)
self.muxing_status_label = QLabel(self)
status_muxing_verticalLayout.addWidget(self.muxing_status_label)
video_finder_horizontalLayout.addLayout(status_muxing_verticalLayout)
vertical_splitter.addWidget(self.video_finder_widget)
download_table_content_widget_verticalLayout.addWidget(vertical_splitter)
download_table_horizontalLayout.addWidget(horizontal_splitter)
self.frame.setLayout(download_table_horizontalLayout)
self.verticalLayout.addWidget(self.frame)
self.setCentralWidget(self.centralwidget)
# menubar
self.menubar = QMenuBar(self)
self.menubar.setGeometry(QRect(0, 0, 600, 24))
self.setMenuBar(self.menubar)
fileMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&File'))
editMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Edit'))
viewMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&View'))
downloadMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Download'))
queueMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Queue'))
videoFinderMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'V&ideo Finder'))
helpMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Help'))
# viewMenu submenus
sortMenu = viewMenu.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'Sort by'))
# statusbar
self.statusbar = QStatusBar(self)
self.setStatusBar(self.statusbar)
self.statusbar.showMessage(QCoreApplication.translate("mainwindow_ui_tr", "Persepolis Download Manager"))
# toolBar
self.toolBar2 = QToolBar(self)
self.addToolBar(Qt.TopToolBarArea, self.toolBar2)
# self.toolBar2.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", 'Menu'))
self.toolBar2.setFloatable(False)
self.toolBar2.setMovable(False)
self.toolBar = QToolBar(self)
self.addToolBar(Qt.TopToolBarArea, self.toolBar)
# self.toolBar.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", 'Toolbar'))
self.toolBar.setFloatable(False)
self.toolBar.setMovable(False)
# toolBar and menubar and actions
self.persepolis_setting.beginGroup('settings/shortcuts')
# videoFinderAddLinkAction
self.videoFinderAddLinkAction = QAction(QIcon(icons + 'video_finder'), QCoreApplication.translate("mainwindow_ui_tr", 'Find Video Links...'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Download video or audio from Youtube, Vimeo, etc.'),
triggered=self.showVideoFinderAddLinkWindow)
self.videoFinderAddLinkAction_shortcut = QShortcut(self.persepolis_setting.value(
'video_finder_shortcut'), self, self.showVideoFinderAddLinkWindow)
videoFinderMenu.addAction(self.videoFinderAddLinkAction)
# stopAllAction
self.stopAllAction = QAction(QIcon(icons + 'stop_all'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop All Active Downloads'),
self, statusTip='Stop All Active Downloads', triggered=self.stopAllDownloads)
downloadMenu.addAction(self.stopAllAction)
# sort_file_name_Action
self.sort_file_name_Action = QAction(
QCoreApplication.translate("mainwindow_ui_tr", 'File Name'), self, triggered=self.sortByName)
sortMenu.addAction(self.sort_file_name_Action)
# sort_file_size_Action
self.sort_file_size_Action = QAction(
QCoreApplication.translate("mainwindow_ui_tr", 'File Size'), self, triggered=self.sortBySize)
sortMenu.addAction(self.sort_file_size_Action)
# sort_first_try_date_Action
self.sort_first_try_date_Action = QAction(
QCoreApplication.translate("mainwindow_ui_tr", 'First Try Date'), self, triggered=self.sortByFirstTry)
sortMenu.addAction(self.sort_first_try_date_Action)
# sort_last_try_date_Action
self.sort_last_try_date_Action = QAction(
QCoreApplication.translate("mainwindow_ui_tr", 'Last Try Date'), self, triggered=self.sortByLastTry)
sortMenu.addAction(self.sort_last_try_date_Action)
# sort_download_status_Action
self.sort_download_status_Action = QAction(
QCoreApplication.translate("mainwindow_ui_tr", 'Download Status'), self, triggered=self.sortByStatus)
sortMenu.addAction(self.sort_download_status_Action)
# trayAction
self.trayAction = QAction(QCoreApplication.translate("mainwindow_ui_tr", 'Show System Tray Icon'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Show/Hide system tray icon"), triggered=self.showTray)
self.trayAction.setCheckable(True)
viewMenu.addAction(self.trayAction)
# showMenuBarAction
self.showMenuBarAction = QAction(
QCoreApplication.translate("mainwindow_ui_tr", 'Show Menubar'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Show Menubar'), triggered=self.showMenuBar)
self.showMenuBarAction.setCheckable(True)
viewMenu.addAction(self.showMenuBarAction)
# showSidePanelAction
self.showSidePanelAction = QAction(
QCoreApplication.translate("mainwindow_ui_tr", 'Show Side Panel'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Show Side Panel'), triggered=self.showSidePanel)
self.showSidePanelAction.setCheckable(True)
viewMenu.addAction(self.showSidePanelAction)
# minimizeAction
self.minimizeAction = QAction(QIcon(icons + 'minimize'), QCoreApplication.translate("mainwindow_ui_tr", 'Minimize to System Tray'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Minimize to System Tray"), triggered=self.minMaxTray)
self.minimizeAction_shortcut = QShortcut(
self.persepolis_setting.value('hide_window_shortcut'), self, self.minMaxTray)
viewMenu.addAction(self.minimizeAction)
# addlinkAction
self.addlinkAction = QAction(QIcon(icons + 'add'), QCoreApplication.translate("mainwindow_ui_tr", 'Add New Download Link...'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Add New Download Link"), triggered=self.addLinkButtonPressed)
self.addlinkAction_shortcut = QShortcut(self.persepolis_setting.value(
'add_new_download_shortcut'), self, self.addLinkButtonPressed)
fileMenu.addAction(self.addlinkAction)
# importText
self.addtextfileAction = QAction(QIcon(icons + 'file'), QCoreApplication.translate("mainwindow_ui_tr", 'Import Links from Text File...'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Create a text file and put links in it, line by line!'), triggered=self.importText)
self.addtextfileAction_shortcut = QShortcut(
self.persepolis_setting.value('import_text_shortcut'), self, self.importText)
fileMenu.addAction(self.addtextfileAction)
# importText From Clipboard
self.addFromClipboardAction = QAction(QIcon(icons + 'clipboard'), QCoreApplication.translate("mainwindow_ui_tr", 'Import Links from Clipboard...'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Import Links From Clipboard'), triggered=self.importLinksFromClipboard)
fileMenu.addAction(self.addFromClipboardAction)
# resumeAction
self.resumeAction = QAction(QIcon(icons + 'play'), QCoreApplication.translate("mainwindow_ui_tr", 'Resume Download'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Resume Download"), triggered=self.resumeButtonPressed)
downloadMenu.addAction(self.resumeAction)
# pauseAction
self.pauseAction = QAction(QIcon(icons + 'pause'), QCoreApplication.translate("mainwindow_ui_tr", 'Pause Download'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Pause Download"), triggered=self.pauseButtonPressed)
downloadMenu.addAction(self.pauseAction)
# stopAction
self.stopAction = QAction(QIcon(icons + 'stop'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop Download'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Stop/Cancel Download"), triggered=self.stopButtonPressed)
downloadMenu.addAction(self.stopAction)
# propertiesAction
self.propertiesAction = QAction(QIcon(icons + 'setting'), QCoreApplication.translate("mainwindow_ui_tr", 'Properties'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Properties"), triggered=self.propertiesButtonPressed)
downloadMenu.addAction(self.propertiesAction)
# progressAction
self.progressAction = QAction(QIcon(icons + 'window'), QCoreApplication.translate("mainwindow_ui_tr", 'Progress'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Progress"), triggered=self.progressButtonPressed)
downloadMenu.addAction(self.progressAction)
# openFileAction
self.openFileAction = QAction(QIcon(
icons + 'file'), QCoreApplication.translate("mainwindow_ui_tr", 'Open File...'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open File...'), triggered=self.openFile)
fileMenu.addAction(self.openFileAction)
# openDownloadFolderAction
self.openDownloadFolderAction = QAction(QIcon(
icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Open Download Folder'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open Download Folder'), triggered=self.openDownloadFolder)
fileMenu.addAction(self.openDownloadFolderAction)
# openDefaultDownloadFolderAction
self.openDefaultDownloadFolderAction = QAction(QIcon(
icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Open Default Download Folder'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open Default Download Folder'), triggered=self.openDefaultDownloadFolder)
fileMenu.addAction(self.openDefaultDownloadFolderAction)
# exitAction
self.exitAction = QAction(QIcon(icons + 'exit'), QCoreApplication.translate("mainwindow_ui_tr", 'Exit'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Exit"), triggered=self.closeAction)
self.exitAction_shortcut = QShortcut(self.persepolis_setting.value('quit_shortcut'), self, self.closeAction)
fileMenu.addAction(self.exitAction)
# clearAction
self.clearAction = QAction(QIcon(icons + 'multi_remove'), QCoreApplication.translate("mainwindow_ui_tr", 'Clear Download List'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Clear all items in download list'), triggered=self.clearDownloadList)
editMenu.addAction(self.clearAction)
# removeSelectedAction
self.removeSelectedAction = QAction(QIcon(icons + 'remove'), QCoreApplication.translate("mainwindow_ui_tr", 'Remove Selected Downloads from List'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Remove Selected Downloads from List'), triggered=self.removeSelected)
self.removeSelectedAction_shortcut = QShortcut(
self.persepolis_setting.value('remove_shortcut'), self, self.removeSelected)
editMenu.addAction(self.removeSelectedAction)
self.removeSelectedAction.setEnabled(False)
# deleteSelectedAction
self.deleteSelectedAction = QAction(QIcon(icons + 'trash'), QCoreApplication.translate("mainwindow_ui_tr", 'Delete Selected Download Files'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Delete Selected Download Files'), triggered=self.deleteSelected)
self.deleteSelectedAction_shortcut = QShortcut(
self.persepolis_setting.value('delete_shortcut'), self, self.deleteSelected)
editMenu.addAction(self.deleteSelectedAction)
self.deleteSelectedAction.setEnabled(False)
# moveSelectedDownloadsAction
self.moveSelectedDownloadsAction = QAction(QIcon(icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Move Selected Download Files to Another Folder...'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Move Selected Download Files to Another Folder'), triggered=self.moveSelectedDownloads)
editMenu.addAction(self.moveSelectedDownloadsAction)
self.moveSelectedDownloadsAction.setEnabled(False)
# createQueueAction
self.createQueueAction = QAction(QIcon(icons + 'add_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Create New Queue...'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Create new download queue'), triggered=self.createQueue)
queueMenu.addAction(self.createQueueAction)
# removeQueueAction
self.removeQueueAction = QAction(QIcon(icons + 'remove_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Remove Queue'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Remove this queue'), triggered=self.removeQueue)
queueMenu.addAction(self.removeQueueAction)
# startQueueAction
self.startQueueAction = QAction(QIcon(
icons + 'start_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Start this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Start Queue'), triggered=self.startQueue)
queueMenu.addAction(self.startQueueAction)
# stopQueueAction
self.stopQueueAction = QAction(QIcon(
icons + 'stop_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Stop Queue'), triggered=self.stopQueue)
queueMenu.addAction(self.stopQueueAction)
# moveUpSelectedAction
self.moveUpSelectedAction = QAction(QIcon(icons + 'multi_up'), QCoreApplication.translate("mainwindow_ui_tr", 'Move Selected Items Up'), self,
statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Move currently selected items up by one row'), triggered=self.moveUpSelected)
self.moveUpSelectedAction_shortcut = QShortcut(self.persepolis_setting.value(
'move_up_selection_shortcut'), self, self.moveUpSelected)
queueMenu.addAction(self.moveUpSelectedAction)
# moveDownSelectedAction
self.moveDownSelectedAction = QAction(QIcon(icons + 'multi_down'), QCoreApplication.translate("mainwindow_ui_tr", 'Move Selected Items Down'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Move currently selected items down by one row'), triggered=self.moveDownSelected)
self.moveDownSelectedAction_shortcut = QShortcut(self.persepolis_setting.value(
'move_down_selection_shortcut'), self, self.moveDownSelected)
queueMenu.addAction(self.moveDownSelectedAction)
# preferencesAction
self.preferencesAction = QAction(QIcon(icons + 'preferences'), QCoreApplication.translate("mainwindow_ui_tr", 'Preferences'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Preferences'), triggered=self.openPreferences, menuRole=QAction.MenuRole.PreferencesRole)
editMenu.addAction(self.preferencesAction)
# aboutAction
self.aboutAction = QAction(QIcon(
icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'About'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'About'), triggered=self.openAbout, menuRole=QAction.MenuRole.AboutRole)
helpMenu.addAction(self.aboutAction)
# issueAction
self.issueAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Report an Issue'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Report an issue'), triggered=self.reportIssue)
helpMenu.addAction(self.issueAction)
# logAction
self.logAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Show Log File'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Help'), triggered=self.showLog)
helpMenu.addAction(self.logAction)
# helpAction
self.helpAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Help'),
self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Help'), triggered=self.persepolisHelp)
helpMenu.addAction(self.helpAction)
self.persepolis_setting.endGroup()
self.qmenu = MenuWidget(self)
self.toolBar2.addWidget(self.qmenu)
# labels
self.queue_panel_show_button.setText(QCoreApplication.translate("mainwindow_ui_tr", "Hide Options"))
self.start_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Start Time"))
self.end_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "End Time"))
self.reverse_checkBox.setText(QCoreApplication.translate(
"mainwindow_ui_tr", "Download bottom of\n the list first"))
self.after_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "After download"))
self.after_comboBox.setItemText(0, QCoreApplication.translate("mainwindow_ui_tr", "Shut Down"))
self.keep_awake_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Keep System Awake!"))
self.keep_awake_checkBox.setToolTip(
QCoreApplication.translate("mainwindow_ui_tr", "<html><head/><body><p>This option will prevent the system from going to sleep.\
It is necessary if your power manager is suspending the system automatically. </p></body></html>"))
self.after_pushButton.setText(QCoreApplication.translate("mainwindow_ui_tr", "Apply"))
self.muxing_pushButton.setText(QCoreApplication.translate("mainwindow_ui_tr", "Start Mixing"))
self.video_label.setText(QCoreApplication.translate("mainwindow_ui_tr", "<b>Video File Status: </b>"))
self.audio_label.setText(QCoreApplication.translate("mainwindow_ui_tr", "<b>Audio File Status: </b>"))
self.video_finder_status_label.setText(QCoreApplication.translate("mainwindow_ui_tr", "<b>Status: </b>"))
self.muxing_status_label.setText(QCoreApplication.translate("mainwindow_ui_tr", "<b>Mixing status: </b>"))
================================================
FILE: persepolis/gui/progress_ui.py
================================================
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
try:
from PySide6.QtWidgets import QDial, QCheckBox, QProgressBar, QFrame, QComboBox, QWidget, QTabWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel
from PySide6.QtCore import Qt, QTranslator, QCoreApplication, QLocale, QSize, QThread, Signal
from PySide6.QtGui import QIcon
except ImportError:
from PyQt5.QtWidgets import QDial, QCheckBox, QProgressBar, QFrame, QComboBox, QWidget, QTabWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel
from PyQt5.QtCore import Qt, QTranslator, QCoreApplication, QLocale, QSize, QThread
from PyQt5.QtCore import pyqtSignal as Signal
from PyQt5.QtGui import QIcon
from persepolis.gui import resources
import time
class UpdateProgressBarThread(QThread):
UPDATEPROGRESSBAR = Signal(int)
def __init__(self, parent, new_value):
QThread.__init__(self)
self.new_value = new_value
self.parent = parent
def run(self):
dif = self.new_value - self.parent.value()
while self.parent.value() != self.new_value:
if dif < 0:
self.UPDATEPROGRESSBAR.emit((self.parent.value() - 1))
time.sleep(0.1 / (dif * -1))
elif dif > 0:
self.UPDATEPROGRESSBAR.emit((self.parent.value() + 1))
time.sleep(0.1 / dif)
self.parent.update_lock = False
# This widget updated more smoothly than QProgressBar
class MyProgressBar(QProgressBar):
def __init__(self, main_window):
super().__init__()
self.setValue(0)
self.setMaximum(100)
self.update_lock = False
self.main_window = main_window
def showBusyIndicator(self):
# Show busy indicator
self.setMaximum(0)
self.setMinimum(0)
def setValueSmoothly(self, new_value):
# Show busy indicator
self.setMaximum(100)
self.setMinimum(0)
if new_value == 100:
self.setValue(100)
return
if self.update_lock:
return
self.update_lock = True
update_progress_bar = UpdateProgressBarThread(self, new_value)
update_progress_bar.UPDATEPROGRESSBAR.connect(self.setValueSmoothly2)
self.main_window.threadPool.append(update_progress_bar)
self.main_window.threadPool[-1].start()
def setValueSmoothly2(self, value):
self.setValue(value)
class ProgressWindow_Ui(QWidget):
def __init__(self, persepolis_setting, parent):
super().__init__()
self.persepolis_setting = persepolis_setting
icons = ':/' + str(persepolis_setting.value('settings/icons')) + '/'
# add support for other languages
locale = str(self.persepolis_setting.value('settings/locale'))
QLocale.setDefault(QLocale(locale))
self.translator = QTranslator()
if self.translator.load(':/translations/locales/ui_' + locale, 'ts'):
QCoreApplication.installTranslator(self.translator)
# set ui direction
ui_direction = self.persepolis_setting.value('ui_direction')
if ui_direction == 'rtl':
self.setLayoutDirection(Qt.RightToLeft)
elif ui_direction in 'ltr':
self.setLayoutDirection(Qt.LeftToRight)
# window
self.setMinimumSize(QSize(595, 284))
self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/com.github.persepolisdm.persepolis.svg')))
self.setWindowTitle(QCoreApplication.translate("progress_ui_tr", "Persepolis Download Manager"))
verticalLayout = QVBoxLayout(self)
# progress_tabWidget
self.progress_tabWidget = QTabWidget(self)
# information_tab
self.information_tab = QWidget()
information_verticalLayout = QVBoxLayout(self.information_tab)
# link_label
self.link_label = QLabel(self.information_tab)
information_verticalLayout.addWidget(self.link_label)
# status_label
self.status_label = QLabel(self.information_tab)
information_verticalLayout.addWidget(self.status_label)
# downloaded_label
self.downloaded_label = QLabel(self.information_tab)
information_verticalLayout.addWidget(self.downloaded_label)
# rate_label
self.rate_label = QLabel(self.information_tab)
information_verticalLayout.addWidget(self.rate_label)
# time_label
self.time_label = QLabel(self.information_tab)
information_verticalLayout.addWidget(self.time_label)
# connections_label
self.connections_label = QLabel(self.information_tab)
information_verticalLayout.addWidget(self.connections_label)
information_verticalLayout.addStretch(1)
# add information_tab to progress_tabWidget
self.progress_tabWidget.addTab(self.information_tab, "")
# options_tab
self.options_tab = QWidget()
options_tab_verticalLayout = QVBoxLayout(self.options_tab)
options_tab_horizontalLayout = QHBoxLayout()
# options_tab_horizontalLayout.setContentsMargins(11, 11, 11, 11)
# limit speed
limit_verticalLayout = QVBoxLayout()
# limit_frame
self.limit_frame = QFrame(self.options_tab)
self.limit_frame.setFrameShape(QFrame.StyledPanel)
self.limit_frame.setFrameShadow(QFrame.Raised)
limit_frame_verticalLayout = QVBoxLayout(self.limit_frame)
limit_frame_horizontalLayout = QHBoxLayout()
# limit dial and label
self.limit_dial = QDial(self.limit_frame)
self.limit_dial.setNotchesVisible(True)
self.limit_dial.setMaximum(10)
self.limit_dial.setMinimum(0)
self.limit_label = QLabel(self.limit_frame)
limit_frame_verticalLayout.addWidget(self.limit_dial)
limit_frame_verticalLayout.addWidget(self.limit_label)
limit_frame_verticalLayout.addLayout(limit_frame_horizontalLayout)
limit_verticalLayout.addWidget(self.limit_frame)
limit_verticalLayout.setContentsMargins(11, 11, 11, 11)
options_tab_horizontalLayout.addLayout(limit_verticalLayout)
options_tab_verticalLayout.addLayout(options_tab_horizontalLayout)
options_tab_verticalLayout.addStretch(1)
# after_checkBox
self.after_checkBox = QCheckBox(self.options_tab)
after_verticalLayout = QVBoxLayout()
after_verticalLayout.addWidget(self.after_checkBox)
# after_frame
self.after_frame = QFrame(self.options_tab)
self.after_frame.setFrameShape(QFrame.StyledPanel)
self.after_frame.setFrameShadow(QFrame.Raised)
after_frame_verticalLayout = QVBoxLayout(self.after_frame)
# after_comboBox
self.after_comboBox = QComboBox(self.options_tab)
self.after_comboBox.addItem("")
after_frame_verticalLayout.addWidget(self.after_comboBox)
# after_pushButton
self.after_pushButton = QPushButton(self.options_tab)
after_frame_verticalLayout.addWidget(self.after_pushButton)
after_verticalLayout.addWidget(self.after_frame)
after_verticalLayout.setContentsMargins(11, 11, 11, 11)
options_tab_horizontalLayout.addLayout(after_verticalLayout)
self.progress_tabWidget.addTab(self.options_tab, "")
verticalLayout.addWidget(self.progress_tabWidget)
# download_progressBar
self.download_progressBar = MyProgressBar(parent)
verticalLayout.addWidget(self.download_progressBar)
self.download_progressBar.setTextVisible(True)
# changing the alignment of progress bar
self.download_progressBar.setAlignment(Qt.AlignCenter)
self.download_progressBar.setFormat("%p%")
# buttons
button_horizontalLayout = QHBoxLayout()
button_horizontalLayout.addStretch(1)
# resume_pushButton
self.resume_pushButton = QPushButton(self)
self.resume_pushButton.setIcon(QIcon(icons + 'play'))
button_horizontalLayout.addWidget(self.resume_pushButton)
# pause_pushButton
self.pause_pushButton = QPushButton(self)
self.pause_pushButton.setIcon(QIcon(icons + 'pause'))
button_horizontalLayout.addWidget(self.pause_pushButton)
# stop_pushButton
self.stop_pushButton = QPushButton(self)
self.stop_pushButton.setIcon(QIcon(icons + 'stop'))
button_horizontalLayout.addWidget(self.stop_pushButton)
verticalLayout.addLayout(button_horizontalLayout)
self.progress_tabWidget.setCurrentIndex(0)
# labels
self.link_label.setText(QCoreApplication.translate("progress_ui_tr", "Link: "))
self.status_label.setText(QCoreApplication.translate("progress_ui_tr", "Status: "))
self.downloaded_label.setText(QCoreApplication.translate("progress_ui_tr", "Downloaded:"))
self.rate_label.setText(QCoreApplication.translate("progress_ui_tr", "Transfer rate: "))
self.time_label.setText(QCoreApplication.translate("progress_ui_tr", "Estimated time left:"))
self.connections_label.setText(QCoreApplication.translate("progress_ui_tr", "Number of connections: "))
self.progress_tabWidget.setTabText(self.progress_tabWidget.indexOf(
self.information_tab), QCoreApplication.translate("progress_ui_tr", "Download Information"))
self.after_checkBox.setText(QCoreApplication.translate("progress_ui_tr", "After download"))
self.after_comboBox.setItemText(0, QCoreApplication.translate("progress_ui_tr", "Shut Down"))
self.progress_tabWidget.setTabText(
self.progress_tabWidget.indexOf(self.options_tab), QCoreApplication.translate("progress_ui_tr", "Download Options"))
self.resume_pushButton.setText(QCoreApplication.translate("progress_ui_tr", "Resume"))
self.pause_pushButton.setText(QCoreApplication.translate("progress_ui_tr", "Pause"))
self.stop_pushButton.setText(QCoreApplication.translate("progress_ui_tr", "Stop"))
self.after_pushButton.setText(QCoreApplication.translate("progress_ui_tr", "Apply"))
================================================
FILE: persepolis/gui/resources.py
================================================
# Resource object code (Python 3)
# Created by: object code
# Created by: The Resource Compiler for Qt version 6.9.1
# WARNING! All changes made in this file will be lost!
try:
from PySide6 import QtCore
except ImportError:
from PyQt5 import QtCore
qt_resource_data = b"\
\x00\x00\x0d*\
A\
rabic:\x0d\x0aMajdi So\
bain MajdiSobain\
\x0d\x0aSaleh Alanazi \
Sal7_one\x0d\x0arayanm\
\x0d\x0aRex_sa rex07\x0d\x0a\
Simo simonetwork\
ing\x0d\x0a\xe6\x98\x8e \xe5\xbc\xa0 zhu\
angsha19740612 \x0d\
\x0a\x0d\x0a\x0d\x0aChinese (Ch\
ina): \x0d\x0a0day 0 0\
day\x0d\x0azyppe 210hc\
l\x0d\x0a\xe5\x93\xa5\xe5\x93\xa5 \xe5\xa5\xbd 48\
5250464\x0d\x0a\xe6\xb1\x9f \xe7\x8e\x8b\
664766245\x0d\x0ax x \
731515713\x0d\x0aCharl\
ey Yang CharleyY\
\x0d\x0aAlan Yee Choye\
e\x0d\x0aYonghui Chen \
ColoPaul\x0d\x0aSY C D\
arciaLee_066\x0d\x0aHi\
yool\x0d\x0aJ L JULIAN\
LEEEEE\x0d\x0aJack Su \
JackSu\x0d\x0a\xe5\xbf\xab\xe4\xb9\x90\xe7\x9a\
\x84\xe8\x80\x81\xe9\xbc\xa0\xe5\xae\x9d\xe5\xae\x9d La\
oShuBaby\x0d\x0ahaonan\
li Li_haonan\x0d\x0aL\
iro Liu Liro\x0d\x0a\xe6\x98\
\x8e\xe9\x98\xb3 \xe8\x92\x8b Lotumn\x0d\
\x0aAllure R Riseup\
\x0d\x0aVento Fang Ven\
to8866\x0d\x0a\xe5\xae\x89\xe5\xa1\x9e\xe6\x96\
\xaf\xe5\xa1\x94 \xe8\x96\x87\xe8\x96\x87\xe5\xae\x89 V\
ivianAncestor\x0d\x0aY\
e Wehchs WehchsY\
e\x0d\x0aK X X_K\x0d\x0aing \
YIn YIning\x0d\x0ayyy \
zzz ZZyyy\x0d\x0a\xe9\xb9\x8f \xe5\
\xbc\xa0 a5357663\x0d\x0ayon\
gkang yang acme9\
69290422\x0d\x0aAliRez\
a AmirSamimi ali\
reza_amirsamimi\x0d\
\x0aaltria morgan a\
ltria066\x0d\x0aanakin\
micheal anakinl\
t\x0d\x0aarthur \xe9\x9f\xa9 ar\
thurh\x0d\x0aLeon Chen\
bioleon\x0d\x0aGabrie\
lle Chou canonla\
yido\x0d\x0a\xe7\xa6\x85\xe5\x92\x8c \xe6\x9d\x8e\
cc379\x0d\x0aSheng Ch\
eng cs54ysm\x0d\x0aDav\
in davinma\x0d\x0adrhe\
nk Dai drhenkdss\
\x0d\x0aZHAN Dr dts008\
0\x0d\x0adan chin egg2\
33\x0d\x0achen chen fa\
lse\x0d\x0ayining fan \
fan211210\x0d\x0akoish\
i a ghostxt0\x0d\x0aZA\
RK LEE godiamgui\
lty\x0d\x0ajiangsheng \
hong hongjiangsh\
eng\x0d\x0adp h huangd\
p\x0d\x0aJackson Hu hu\
ming2207\x0d\x0aW Z ic\
waos\x0d\x0axiang wang\
ifoanle\x0d\x0a\xe6\xb5\xb7\xe9\xbe\x99\
\xe6\xb1\x9f jianghailon\
g\x0d\x0ahaha ha jiang\
weiyang336\x0d\x0a\xe5\xae\xb6\xe4\
\xbf\x8a \xe9\xbb\x84 jiayezhan\
g22\x0d\x0aliu li kuli\
erhao\x0d\x0ak y kyalt\
\x0d\x0aleo xxx leoxxx\
\x0d\x0a\xe6\xb9\x96\xe5\xb9\xbf \xe5\xbb\x96 lia\
ohuguang\x0d\x0alei li\
lilei9587\x0d\x0a\xe6\x97\xad\xe9\
\xba\x92 \xe5\x88\x98 liuxuqi\x0d\x0a\
\xe6\x88\x88\xe6\x89\xac \xe8\xb5\xb5 luciu\
s.z\x0d\x0aqihao mao m\
aoqihao\x0d\x0amonowol\
f Lucas monowolf\
\x0d\x0au muguo muguou\
\x0d\x0aeo L nbnatcom\x0d\
\x0aOra Prinzing pr\
inzingora\x0d\x0as k q\
qwwee\x0d\x0a\xe6\x96\x8c \xe7\x86\x8a q\
w71111520\x0d\x0aJane \
Yang qwe866zxc\x0d\x0a\
Minagawa Hifumi \
reeealin\x0d\x0a354 65\
48 richard954\x0d\x0ar\
ose tiffany rose\
_tiffany\x0d\x0aCUI SA\
N sanc163sa\x0d\x0a\xe4\xbd\xb3\
\xe4\xba\x8e sheena.ring\
o\x0d\x0aSin Qiu sino1\
641\x0d\x0agiga d togi\
ga\x0d\x0a\xe6\x80\x9d\xe6\x95\x8f \xe9\xb2\x8d t\
ulipasky\x0d\x0a\xe5\x88\x98 \xe4\xbf\
\x8a\xe5\x90\x9b tusks\x0d\x0awang\
yuehu wangyuehu\
\x0d\x0axinpu wei weix\
inpu\x0d\x0amike willi\
ams williamsguo\x0d\
\x0aT W wt118265734\
6\x0d\x0axiao wu wu121\
38\x0d\x0awwj402\x0d\x0acq n\
xiaolu\x0d\x0ayin xia\
o xiaoyinge\x0d\x0a\xe4\xb8\x80\
\xe5\xbc\x98 \xe9\x83\x91 yihong20\
18\x0d\x0ayoungcrazybo\
y\x0d\x0a\xe5\x8d\x93\xe7\x90\xaa \xe5\x88\x98 yo\
u\xe5\xbf\x97\xe8\x80\x85\x0d\x0aan mu z\
henlailu\x0d\x0along l\
ong zql00l\x0d\x0a\xe9\xaa\x8f\xe4\
\xb8\x80 \xe6\x88\x9a zsns1994\x0d\
\x0a\xe5\xbe\x90 \xe5\xa4\xa7\xe4\xbe\xa0 \xe4\xbc\x8f\xe5\
\x9f\x8e\x0d\x0a\xe4\xb9\xa6\xe7\xbd\x95 \xe5\x90\x91 \xe5\
\xa2\xa8\xe5\xa2\xa8\xe5\xa2\xa8\xe5\xa2\xa8\xe5\xa2\xa8\x0d\x0a\
chuantong xu \xe5\xbe\x90\
\xe4\xbc\xa0\xe7\xbb\x9f\x0d\x0a00 000 \xe6\
\x95\xb7\xe8\xa1\x8d\xe4\xbc\xa4\xe6\x83\x85\x0d\x0a\xe8\x8a\xb1\
\xe5\x8d\xb7 \xe6\x98\xa5 \xe6\x98\xa5\xe8\x8a\xb1\xe5\x8d\
\xb7 \x0d\x0a\x0d\x0a\x0d\x0aGerman (\
de):\x0d\x0aPatrick Me\
ier SonArc\x0d\x0aAndr\
eas Mueller anzb\
ert \x0d\x0a\x0d\x0a\x0d\x0aDutch \
(Netherlands): \x0d\
\x0aHeimen Stoffels\
Vistaus \x0d\x0a\x0d\x0a\x0d\x0aF\
rench (France):\x0d\
\x0aCwpute BipBoup \
cwpute \x0d\x0aSimon P\
orte sporte \x0d\x0a\x0d\x0a\
\x0d\x0aHungarian:\x0d\x0a- \
Totya Totya\x0d\x0a\x0d\x0a\x0d\
\x0aKorean:\x0d\x0aJungHe\
e Lee MarongHapp\
y\x0d\x0a\x0d\x0a\x0d\x0aPersian (\
Iran):\x0d\x0aAliReza \
AmirSamimi alire\
za_amirsamimi\x0d\x0ah\
_r 71 hayyan711\x0d\
\x0aMostafa Bodagh \
mosi2772\x0d\x0aMostaf\
a Asadi mostafaa\
sadi\x0d\x0a\x0d\x0a\x0d\x0aPolish\
(Poland): \x0d\x0aFad\
eMind\x0d\x0aMaurycy B\
\xc5\x82aszczak LuxF3r\
re\x0d\x0aArkadiusz Ro\
g\xc3\xb3\xc5\xbc arcio \x0d\x0a\x0d\x0a\
\x0d\x0aPortuguese:\x0d\x0aA\
ntonio Barbosa A\
lvoErrado2 \x0d\x0a\x0d\x0a\x0d\
\x0aPortuguese (Bra\
zil): \x0d\x0aCirnos G\
ersonzao \x0d\x0aCarlo\
s Henrique De Fr\
eitas Ferreira N\
eocazen\x0d\x0aThiago \
Schuch ThigSchuc\
h\x0d\x0aeltonfabricio\
10\x0d\x0aMarli Masa m\
arlimasa \x0d\x0a\x0d\x0a\x0d\x0aR\
ussian:\x0d\x0aVictor \
ViktorOnlin\x0d\x0a\xd0\x9c\xd0\
\xb8\xd1\x85\xd0\xb0\xd0\xb8\xd0\xbb \xd0\xa1\xd0\xbe\xd0\xbc\
\xd0\xbe\xd0\xb2 belliric300\
\x0d\x0aNikita Paseka \
deadman1987\x0d\x0aPav\
el irbinix\x0d\x0aSerg\
ey Suhih linuxma\
sterclub \x0d\x0aAbdol\
reza Taslimijali\
labadi rezaxx \x0d\x0a\
\x0d\x0a\x0d\x0aSpanish (Spa\
in):\x0d\x0aEdgardo Ca\
stro Castro eddy\
9305\x0d\x0aJose G. Ji\
menez S. josegji\
menez\x0d\x0aJuan Manu\
el ptero.4\x0d\x0aRub\xc3\
\xa9n Fern\xc3\xa1ndez ru\
benterco\x0d\x0aToni E\
st\xc3\xa9vez toniem \x0d\
\x0a\x0d\x0a\x0d\x0aTurkish (Tu\
rkey):\x0d\x0aO\xc4\x9fuzhan\
Aksoy OnePage\x0d\x0a\
abc Def abcmen\x0d\x0a\
Ya\xc5\x9far \xc3\x87iv yasa\
rciv67 \x0d\x0a\x0d\x0a\x0d\x0aTur\
kish:\x0d\x0aabc Def a\
bcmen\x0d\x0aKoray Bi\xc3\
\xa7er kbicer\x0d\x0aYa\xc5\x9f\
ar \xc3\x87iv yasarciv\
67\x0d\x0a\x0d\x0a\x0d\x0aChinese \
(Taiwan):\x0d\x0aEnfen\
g Tsao 5iderealA\
rt\x0d\x0aSr R sr32960\
01\x0d\x0aqge hao \xe9\xb8\x9f\xe8\
\xaf\xad\xe8\x8a\xb1\xe9\xa6\x99 \x0d\x0a\x0d\x0a\x0d\x0aP\
ortuguese:\x0d\x0aAnto\
nio Barbosa Alvo\
Errado2 \x0d\x0a\x0d\x0a\x0d\x0aSw\
edish:\x0d\x0aKristoff\
er Grundstr\xc3\xb6m U\
meaboy \x0d\x0a\
\x00\x00\x08\x86\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 ve\
rsion=\x221\x22>\x0a <rec\
t style=\x22fill:#e\
a4141\x22 width=\x2220\
\x22 height=\x2220\x22 x=\
\x22-22\x22 y=\x22-22\x22 rx\
=\x2210\x22 ry=\x2210\x22 tr\
ansform=\x22matrix(\
0,-1,-1,0,0,0)\x22/\
>\x0a <path style=\x22\
opacity:0.2;fill\
:#ffffff\x22 d=\x22M 1\
2,2 C 6.4604924,\
2 2.0008889,6.45\
99999 2.0008889,\
12 c 0,0.084 -0.\
002,0.1665 0,0.2\
5 C 2.1330771,6.\
8269999 6.544484\
9,2.5 12,2.5 c 5\
.455515,0 9.8671\
23,4.3269999 9.9\
99111,9.75 0.002\
,-0.0835 0,-0.16\
6 0,-0.25 C 21.9\
99111,6.4599999 \
17.539507,2 12,2\
Z\x22/>\x0a <path sty\
le=\x22opacity:0.2\x22\
d=\x22M 2.00585,12\
.25 C 2.0038,12.\
3335 2,12.416 2,\
12.5 c 0,5.54 4.\
4599999,10 10,10\
5.54,0 10,-4.46\
10,-10 0,-0.084\
-0.004,-0.1665 \
-0.006,-0.25 C 2\
1.862,17.673 17.\
456,22 12,22 6.5\
439999,22 2.138,\
17.673 2.006,12.\
25 Z\x22/>\x0a <g styl\
e=\x22opacity:0.2\x22 \
transform=\x22trans\
late(0,0.5)\x22>\x0a \
<path d=\x22M 11.5,\
14 C 9.9999998,1\
6 9.8725013,17.8\
73708 9.4999998,\
20 8.9995539,17.\
745224 8.9999999\
,16 7.4999999,14\
l 1.9999999,0.5\
z\x22/>\x0a <path d=\
\x22m 16.5,14 c -1.\
5,2 -1.627499,3.\
873708 -2,6 -0.5\
00446,-2.254776 \
-0.5,-4 -2,-6 l \
2,0.5 z\x22/>\x0a <pa\
th d=\x22M 8,9.4999\
998 C 9.9999999,\
11 14.873708,11.\
127498 17,11.5 1\
4.745224,12.0004\
46 9.9999999,12 \
8,13.5 l 0.5,-2 \
z\x22/>\x0a <path d=\x22\
m 8,4.4999999 c \
1.9999999,1.5 6.\
873708,1.6274985\
9,2 -2.254776,0\
.500446 -7.00000\
01,0.5 -9,1.9999\
999 L 8.5,6.4999\
999 Z\x22/>\x0a <path\
d=\x22m 9.5,6.9999\
999 c 2,1.499999\
9 3.373708,1.627\
4984 5.5,1.99999\
99 -2.254776,0.5\
00446 -3.5,0.5 -\
5.5,2.0000002 L \
9.9999999,8.9999\
998 Z\x22/>\x0a </g>\x0a \
<g>\x0a <path styl\
e=\x22fill:#ffffff\x22\
d=\x22M 11.5,14 C \
9.9999998,16 9.8\
725013,17.873708\
9.4999998,20 8.\
9995539,17.74522\
4 8.9999999,16 7\
.4999999,14 l 1.\
9999999,0.5 z\x22/>\
\x0a <path style=\x22\
fill:#ffffff\x22 d=\
\x22m 16.5,14 c -1.\
5,2 -1.627499,3.\
873708 -2,6 -0.5\
00446,-2.254776 \
-0.5,-4 -2,-6 l \
2,0.5 z\x22/>\x0a <pa\
th style=\x22fill:#\
ffffff\x22 d=\x22M 8,9\
.4999998 C 9.999\
9999,11 14.87370\
8,11.127498 17,1\
1.5 14.745224,12\
.000446 9.999999\
9,12 8,13.5 l 0.\
5,-2 z\x22/>\x0a <pat\
h style=\x22fill:#f\
fffff\x22 d=\x22m 8,4.\
4999999 c 1.9999\
999,1.5 6.873708\
,1.6274985 9,2 -\
2.254776,0.50044\
6 -7.0000001,0.5\
-9,1.9999999 L \
8.5,6.4999999 Z\x22\
/>\x0a <path style\
=\x22fill:#ffffff\x22 \
d=\x22m 9.5,6.99999\
99 c 2,1.4999999\
3.373708,1.6274\
984 5.5,1.999999\
9 -2.254776,0.50\
0446 -3.5,0.5 -5\
.5,2.0000002 L 9\
.9999999,8.99999\
98 Z\x22/>\x0a </g>\x0a</\
svg>\x0a\
\x00\x001U\
\x00\
\x00\xf8\xdax\xda\xed}ks\xdb8\xb2\xe8\xf7\xfc\x0a\
L\xf2a\x1e+\xc9o'\xa39{\xaa\x1c[I\x5c\
\xeb\xd8\x89\xa5L\xeeTj*\xa6$\xc8\xe2\x86\x225\
$\xe5\xc7l\xed\x7f\xbf\xfd\x00@\x90\x04\x1f\x92\x9d\xec\
\xec\xad\xeb\x9d\x99\xb5\x09\xa0\xd1\x00\x1a\x8dF\xa3\x1f[\
?=\x11?\x09\xf12\x96\xf2Oy\xe2\xc5_D\x92\
\xde\x072\x99K\x99\xf6\xa0\x88J\xfb\xde*\x9dGq\
_\x1cG\x81\x1f\x8a\x93\xd5\x1f+\x99\x84\xd1=\x17\xca\
\xa9\x9fb\xe1Q \xef\xc4\x9bU\xf2\xa7w=\xe7\x92\
\xc0\x9f\xc80\x91}\xf1\xf6t\xd4\x11\x89\x94\xe2\xec\xf4\
xp>\x1c\xf4\x16S\x0d{4\xf7\x13\x01\xffD\xb1\
\x7f\xed\x87^\x10\xdc\x0bO\xcc\x22@$\x9a\x89\xf7\x88\
\xd1\x10\x11\x1a\x22B\x1d\xe1\x85S\xac<\xf6\x129\x15\
Q\xa8\xf0\xde*\x8ea\x12\x05Q,\x92\xc9\x5c.d\
G\x8cW)6\x02\xcc\xc3H\xdcz\xd0\xc1l\xe6\x07\
\xbe\x97\x02\x8c[?\x9d\x8b\x7f\x9c\x0c\xf4X\xbb\x8f\xf1\
\xa3\x06&q\xdc\xe2\x8c'A\xfc\x00\x7f\xfc\xa8z9\
\x8e\x96\xf70\xdey*~\x98\xfc(\xfegw{g\
\xaf\x0b\xff\xd9\xff_\xf1?\x85)\xfe_w\xf5\x03\xa8\
\xbe\xbb\x03\xd5\xedI\xff_\x05\xfd\x9d\x8c\x17~\x92\xf8\
0?0\xec\xb9\x8c\xe5\xf8^\x5c\xc7^\x08\x03\xee\x88\
\x19L\x13\xce\xedd\xee\xc5\xd70;i\x04\xb3z/\
\x962N\xa0A4N=?\xf4\xc3k\x04\xe4\xc1D\
.\xef\xb1r\x8a\xab\x94D\xb3\xf4\xd6\x8b%\xad\x82\x97\
$\xd1\x84\xe7p\x1aMV\x0b\x19\xa6^\x8a]\xc2\xd4\
\xcaD\xfc\x90\xce%\x82x:T\x8d\x9e\xfeH]M\
\xa5\x17\xe0J@\xb1\xd0E\xb4\x08\x11,R,\x934\
\xf6'\x08\xa6\x03\x95&\xc1j\xaa0\xd15\x02\x7f\xe1\
\xab~\x10\x02MJ\x82pW\x09\x0c\x05\xb1\xed\x88E\
4\xf5g\xf8\xff\x92\xc6\xb7\x5c\x8d\x03?\x99w\x10\xcc\
\xd4\xc7\x0e\x80\x1e\xe0{\x82\xdfii\x88\xac\xb6\x90`\
d\x10 \x10\x1f\x06@\x83\xcepd\xd2K#\x84\xb2\
\xc4\xf9M\xd5\x8cQ\xef\xb7\xf3h\x91\x1f\x12L\xd7l\
\x15\x87\xd0\xb1\x9c\xd2\xb8#\x98>\xea\xf4\x9fr\x92*\
@\xd8b\x16\x05At\x0b\xc3\x84\x8eC\xd8I0\xb4\
\xa4\xaf\x16\x12I\xc8\x1bG7\x92F\xc6\x14\x10F)\
`\xcd\xd8\xe0\xa2,\xb3\xc5VE\xc9\x1cv\x91\x18K\
5\x83\xd0\xbf\x1f\xd2jZ\x83\x8b\x11\x93$\x05\x92\xf0\
a=\x96QL\xfd\x16\x07\xad7\xc5\xe8\xcd@\x0c/\
^\x8d>\x1e]\x0e\xc4\xe9P\xbc\xbb\xbc\xf8\xf5\xf4d\
p\x22\x9e\x1e\x0d\xe1\xef\xa7\x1d\xf1\xf1t\xf4\xe6\xe2\xc3\
H@\x8d\xcb\xa3\xf3\xd1o\xe2\xe2\x958:\xffM\xfc\
\xe3\xf4\xfc\xa4#\x06\xff\xe7\xdd\xe5`8DP\x17\x97\
\xe2\xf4\xed\xbb\xb3\xd3\x01|>=?>\xfbprz\
\xfeZ\xbc\x84\xa6\xe7\x17\xb0WNa\x93\x00\xdc\xd1\x05\
\xf5\xa9\xa0\x9d\x0e\x86\x00\x0f[\xbf\x1d\x5c\x1e\xbf\x81/\
G/O\xcfNG\xbfu\xc4\xab\xd3\xd19@\x16\xaf\
\x00\xee\x91xwt9:=\xfepvt)\xde}\
\xb8|w1\x1c\x00\x12'\x00\xf9\xfc\xf4\xfc\xd5%t\
4x;8\x1f\xe1\xa8\xa0o\xf8,\x06\xbf\xc2\xdfb\
\xf8\xe6\xe8\xec\x8c:<\xfa\x00\xc3\xb8\x1c\x22\x96\xc7\x17\
\xef~\xbb<}\xfdf$\xde\x5c\x9c\x9d\x0c\xe0\xe3\xcb\
\x01\xe0w\xf4\xf2l\xc0\xbd\x9d\xffF[\xf3\xec\xe8\xf4\
mG\x9c\x1c\xbd=z=\xa0\x86\x17\x00\xe8\x92j*\
\x1c?\xbe\x19\xd0'\xe8\xf2\x08\xfe9\x1e\x9d^\x9c\xe3\
\xfc\x1c_\x9c\x8f.\xe1O\xa2\xcc\xd1\xc5\xe5\xc8\xb4\xfe\
x:\x1ct\xc4\xd1\xe5\xe9\x10'\xe7\xd5\xe5\x05\xf4\x80\
\xb3\x0b\x8d.\x08\x0e4=\x1f0 \x9cy\xc4\x1d\x81\
\x985\x82Z8\x9c\x0f\xc3A\x86\xd1\xc9\xe0\xe8\x0c\xc0\
\x0d\xb1\xbd\xbd\xa0\xbd\xc7d{[O\x9el\xfd\xc4\x8c\
\xfd\xed\x11t4\x1c\xfdv6\x18\xbe\x19\x0cF\xf4\xcd\
\xd9\xe0\xfd(\x8a\x82\x91\xbf|\xf2\xaf'\x02~\xb6~\
\x12\xdb\xbd]\xe0j@\xdcH\x8c\xc9\x02\x08\x17\x18\x83\
\xb8\xf1\x82\x95\x84O^\xfa}\x82\xb4.\xfc\xeb0\x8a\
\xf9\x1c\xf8\xe8\x87\xd3\xe86\xe9!@\x042\x8e\xe2\xa9\
\x843i\xbb\xb7\xbd/\x17\xb0\xf5\x02\x7f*\x9e\xc9\xd9\
l{\xb6\xf3\x0b\xd7\xf0&_\xae\xe3h\x15N\xbb\xfe\
\xc2\xbb\x86C*\x8cBY*\xa3\x93\xa4/\x9e\xed\xed\
\xec\x1d\xee\x8d\xb9\xd8\x0bR\x19\x87\xc0\xfa\xba\x0d\x15\xf5\
7\xbb\xdf\xa57E\xa6\x86\xa8\xed\xc8\x05\x7f\x8b\x96\xde\
\xc4O\xef\xfbbw{\xfb\x97'\xff\x86)\xf9\xe8O\
\xafe\xaaf\xc4\x05\xa6\xa1g\xe0d\x92\xf8\xa8\x0b\xc5\
\xf1\x8b\xbd\xdd\xbd\xddb\xc5\xa6^\x02\x7f\xd9W\xf3\xfa\
\x8b5\xc7\xf9\xd9\xd3+\xf8\xfe\x04\xf8Jt\xfdr\x95\
\xa6Q\xf82\x82\xc5\x9c \x7fQ\xab3\xa5\xc2\xee\xc4\
\x0b'2\xe8bQ_\xac\xe2\xe0\x87\xfe\xd6\x14O\xef\
\xd9\x0a\xd9\xd9\x16\xd7\xfa\xcc\xb5z\xc9\xcd\xf5\x8f\xbf\xe4\
Z\x07Q\x22\x1b\x1bc\xa5r\xdb\xe8KS\xc3\xe8\x8b\
\xa3\xd5R\x86\x8d\xed\xa0N\xb9%\x1cl2mjJ\
\x95\xcam\x13\xef\xa6q\x98X\xa7\xdc\xf2^&\x9b\x0c\
s.\x83eS;\xacSn\x19FM\xed\xc2\xa8\xdc\
\xca[.\x83\xfbM\x10\x85\xd3|\xe2\xc5\xd3\xa6\xa6\xaa\
\x9aj\xaf)\xf4\x15\x88)y\xaaD\xc1EAF\xba\
\xbf\xad\x03\x1d\xc8Y\xfa\xd9\x8b\xe3\xe8\xd6B\xcb\x02\x00\
\xcdR\x90\x88\x92\x1b_\xdeV\x02\xc1\xfa\x9f5\xa1\xaa\
\x06npS\x09R\x19\xfc\xd5\x1a\x9cn\xe0\x06'\xc3\
i+(P\xcf\x0d\xc0\x0fgQk\x5c\xb0\xb2\x1b\x0c\
\xc8eik0X\xd9\x0d&\x04\x08S?\x06>\x16\
\xc5\xd5\x84\x04\x82\x16\xb0+7\x84%\x08;a\xda\x02\
\xc8jY\xb7\xea P\xc5i\xab\xc1P\xcd\x1cE\xeb\
\x9e\x89cM\xdb\x8fb\x83\x81gM\xe0\xaa\xf1\xa5\xa1\
\xddg\xac\xe3l\x5c\xcb\x0eU\xe3\x02;\xc4)\xa8\x9d\
\x9fb\xddz\x04qB\x0b\xe8\x81 ^\xdd\x03\x16~\
6\x03(0\x84\xf7oe\x92\xc0QV:\xad\x16\xfc\
}\x1c\xddu'1\x08\xe8\x13\xaf\xfa\xccRu?\xeb\
\x8a\x16f\x16\x18\xdc\x11\xf1\x82\xae1\x8d\x90\xac\xban\
`xQl\x05IWt\x83\x01v\x87\xd7\xbeF(\
\xaa^a\xf2\x8e\xa3\xc5\x12nUq~\xe6&\xeak\
%P]\xc1\xa6/\x99|I\xa3\x9a\x03\x88\xcb\xad\x16\
\x93\xba\x13 \x99|\x9e\xc6~\xfet\xbcY\xb3\xc1,\
\x88\x96\xcb\x9a\xfdE\xc5\xa5Vp\xbd\x06I/\xa9&\
_\xacPj\x15\xca\xf46\x8a\xab\x1b\xa9\xf2R\xbb4\
\xf6\x92ye+*-,\xd9\x11\xf2\xb1\xfcz\xad\x96\
\xc4\xdc\xd6\xe1~ u\x87\xf5\x8d\xb0F\xa9\x19\x9e\x9f\
\xf5\xcd\x9c',]\x81\xeb\xdbQ\x95R\xc3\x0d\x0f\xf4\
(\xaemT\xeeKO\xee\xc8O\x039\xf6\x0a\xfb!\
U_\x1bd\xd7[\xba\xcc\x94d\xd7\xac5\xca\x0aw\
i\xad\x9cV\x10\xd0L\xdb\x85w\xe7/\xfc?\xab;\
\xd7\x15\x9c\x8de\xb8\xaaa\x10\xe1\xca\xd9\xc8\x0f\x1bz\
T\x15\x5c\x8dC\xe4}\xd5\xec\x16\x15Fp\x05t\xb5\
L\xe6\xde\xb4\xbaO*u5[\x85\xf5\x0dUya\
\xb9/`1\x0ak=\x8d\x80\xe2\xe8\x16\xd7\xb0\xda\xc5\
e\xa6\xfb3\xfe\xc0}\xf9\x22Du\xe8\x0d\x88r\xde\
\x18\xc5\xd5P\xbcO\x0fY\x155\xf1V\x09jr\xb8\
\xe7$\x01\xe6\xde\x13C)\xc5\xb3\xc3\xdd\x9e\x01\x00\xa7\
\xa3D\xfd,\xe0 atc\xba\x8f\xd5\xa0\x02\x95>\
#mY\xf8\xe0\x80\xb2+i\x1fX\x1a\xe22-\xdc\
M\xf7\x0f\xf0\x7f\x8dwS\x04t<\x97\x93/p\xca\
*\x08\x09^~\xf9B\xbc\xbbgn\xc4\xab\x14Q\xb7\
/\xe5\xae\xfb\xe9\xc2\x8b\xaf}\xb8\xe3F0\xac\x05\xdd\
\xf6\x7f\xae\xbeS\xeb~\xab\x860\xde\xc6\xffq\xdd\xd7\
\x80\xfe2\xc3\x11\x96\xf8\x5c\xb2\x22o\xe1}\x91\x22Y\
\xc5\x92\x94\x138\xcc%\x1c\x9f\xb0\xdc2\x09\xbfO\xe9\
\xc8\x03\xaaL\xc4X\x06\xc0^\xb1\x0e\xd1\x96\xd1L\x00\
\xb5\xc3\x0d\x0b\x19G_\xec\xf4v5\xban\x85\xc5\xf3\
\xc3\xe7??\x9f\xe4\xae\xdb\xb17\xf5WI~\xac\x16\
\xc9\x90:\xfd\x1a\xce\x86D\xac\x12!\xc3hu=\xa7\
)\x96\xc2K\x19\x9dh\x89\xe3\x90!\x0d\xe2V\x02%\
\x85b\x81JFR\xd92\x18\xc2\x19\xab\x91\x1a1\xf1\
\xa7j\xb8+\xf8\x0d\x17&Q\xfaP\xf8\xa6\x14\x1a\x16\
x\x0d\x84\xbbH\xb0\x8f9\x5cP\x15\x1a\xc5\x891D\
f-(\x00\xc1\x11\x1e\xe8\x01\xaa>\xf8;\xa9M\xec\
E\xea\xcf\xa2\xc9*QK\xb5\xf1D\xe6 \xf6\x09\xb7\
l\xf5?J\x11j\x02\xc0\xa9\xda\xee\x1d\x02\xf0\xd5\xb2\
<Ejv\xfe\x06X\xe2\xf9\xa1Q7\xebOC\xe8\
\xee`{\xa5\x81Y\x8d\x91\xa1\xc7Q\xd0\xe57\x90\xbe\
P\x97\xc1R\xf92JHA\xdc\xa7E\x9c@\x15\xa3\
\x8b1[\xae\xa0\x08\xd23\x87\xe7\x1bm\xb1\xe2\x94\xc6\
L\x8a\xaa$?\xad\x81\x97\xe6fU\xaf\x8b=\xb3\x87\
\xbb\x87\x07\x87/r3\xab\xfb\xa2j z\x84\x09\xdf\
\xaf\xdc\xcb\xa0\xfboU\xdb\xda\xe9\x95\xd5s{\xbd\x0f\
g)\x08\xe2pJt\x9e\xbc\x1f\xc5R\xfe\x0a\xf7\xcd\
\xc2Wd\x06\x8a\xbb\xe5\x0a2j0_\xd5t\x00c\
O\xe7\x8a\x12I\xd6\xd3\x1b\xbaLH\xa6i\x7f\x15N\
\x10+9\xed4\x943=w\x9c\xa3\xc8A\xa9-7\
P\x1c\xa3\xceA\xa9-w\xec-\xad\xf1s\x9c\x1f\xd8\
\x06\xb8\xe1g\xd3\xfc\xb3\xe6\xb5\xea@i37\xf5\xa3\
\x9a\xc3\xf6\x8b\x1bk\x11\x0fn1:\x0d\xad\xbeV\x06\
\xad~\xdd4\xb4\xfaZ\x0aZ\x81_Y\xda\xe7\xb5g\
\xd9\x9a\x5c\xd7\xb4\xd4/u=Q\xaa\xd2u\x09`-\
\xc4j\xd7\xb4\xcd\x9eh\xb7\xeam\xd6\xbc\xcd\xdeiG\
\x15mh\xa2\xd8[]\x9dG\xa3\x9avK\x03\xbf\xc9\
\x14\x9f\x16\xf1\x9d\xa3b\x22ru\xd6\xa5\x90\x5c\xe3u\
\x90\xa9\xa5\x84|\xcd:\xba\xca\xd7\xac\xa7\x1cw\xff\xcd\
5\xeb(\xcd\xd9\xff\xb7\x9bD\xcd\x97[aW\x10\x98\
7C\xcfu\x14\xd4m\xe6\x06\x0c\x1d\xd5\xea\xb6\xcf\xa6\
C\xa89\xc7\xeaO\xa0\x06\xf4\x9d\x15\xeb\xcf\x8dM\x87\
P{\x18_\x82\x14\x1c\xf13\xdd\xd7\xbb\x8f\x15:\xaa\
\xba\x80\xd9\x02\x9c]}}\xf1\xcb\xdd:'e4U\
YK\xf0\xc1\xbbD\xd4z\xa2\xeb\x85\x87\xc6\x8aM'\
\x81c\xad\xd6\xc4\xbf\x19m\x97X\xf0(8\xac\x8bA\
\xd3\xb4\x15\x8f\xd8\x86j_mn\xd7\x1eWa\x8f<\
\xb4\xe3\x8dHrM\x8e\xd3b\x17\xbc\x95\xe1\xea\xa5\xa7\
\xf7\xf1\x9a\xe6\x13\x16\x00\xc07\x95\x8b\x12\x98\xbe}#\
t4\xe8\xb3\xb9C6\xa2\xaa\x96\xd5\x9a\x04m<Q\
\x86\xdd\x82\xab\xe5\x1b\x14\x88\xad\xdeP\xa3\x05\xbb\xed\xda\
:!}\xbfw\xf1bD\xa3\xc6\xb6\x84\xc1\x96\x9b\x00\
\xda\x13sLd\x95\xf8\x94\xb0*e+\x83\xcf\x0c\xd3\
\xa9\x90w0\xb9FQd\xdb\xee\x91\x8a\x04\xff\xa2\xb6\
\x82T\xe9ZSbY\xca`\x17b\x07\xf5A\xd9\x1f\
{\x0e\xd5\xd9\xcff\x9d\xca\xab\xd9D$n\x0aii\
{S\xa4\x8a\x02\xb0\xd2N\xaa\xd7\x90Z\x10Z\x12U\
\xe5\x19\xb9\xdd{Q<%\xadO\xf8R\x11\x09/\xf0\
\xafC\xb6\x84\xb5\xd6\xb9#n\xe7\xfed.\xe6^\x22\
<=\xed\xbc\xea\xbd\x82\xbaN+|\xf6\x1c:\xadL\
g\xc5\xfa*z\xfaq\x22\xde\x07\xd6\xd6\x95w\x93\x00\
\xb8\xc9\x8d\xcc\xd8\xd0\xa3\xca;-\xfb,1\x8ao\xd0\
\xf9\xa3]\xb5[u\xb3\xf1\x08\x9b\xfb\xdb|\x0d[\x9e\
\x0d\x9d\xad;\xb4\x07\xf5\xba\xc9\x00\xd7\x99\xc2\x07\x8d\
\xa9\xaa#\xe2\xbd]\xe2\xb6\x15\xec\xbcU\x1f\xce\xa7V\
\xc3x\x0e*\x18\x8f\x13\x8d\xb5e\x8d\xaco\xd7z\x1d\
\x8d\x13`\xf2\x93\xf4\x14x(^\xbd\x14\xd4\x07Yn\
:\xcf\x99\x5c\xab\x9a\x97\x85\x917V*\xe6\x92\xfa\xc2\
%\x9a\xeaoC\xe8\x03\xfat=p\xb0 \x88\xb0\xcf\
@0\x1cL\xfd\xb4\xfap\xd9\x99\xeen\xef\xee\xfd\xe2\
:Vs\x98\x93\xefG\x9f\x87\xf6\x08\xefR.\x01N\
\xaf\xccp\x02\xa7Cp\x14K/\xbf\xe2.8\xee\x99\
\xcf!Q\x1as\xf1\x8c\xd7f\xc9\xda\xdf\x04\x85\x8e\xac\
\x95\x91C\xf0-O\xb9'\xb0\xe4\xc4\x0f\x140\x948\
\x941A\xb8\x9d\xcb\x90J\xe7\x22\xa1A\x8c\xbd\x18\x8e\
H\xf4\x8b\x98\xa4h\x95Af\xcd\x8e\x81\xf6\xfb\x0a\xca\
\xbf\xaa\xdfl,L\x8f=|P\x9cF\x84\xcc?N\
\x06\xec\x99\x836\xfa\xb7\xe8\xd3\xc1\xc6\xd1\x1a\x018\xa6\
\xc3i@.\x17b,'\xd1B&\x22 \xcc\x95\xb8\
\xc5\xf7$z\xb5\x8b\xf0U\x19G\xc1\x05YC\xf4\x16\
\xc1j\xe4\xd3\x01\x00\xfcT\xc1\xa2\xae\xfd?a\x8b\x99\
\xf9\x83\x02|\x81\xe6\x0eq.2X\xe6i\xd0\x9a_\
y\x83\xd6\x8d4K)L\x0522l\x99F\xb0%\
`4j\xcex\xaePB\x9eG\xb1\xff'\x88\x10^\
\xd0\x8e\xaa3\x1esh\xf8N\xc6\xd3v\xf6Hr<\
d\x01\xd2\xfa\xcbI\xe4\xb9W%\xbb\x93\x12\x89\xee<\
\xd7\xfb\xdb\x859\xdfM\xab\xf1\xb7\x85\xb8\xac}\x9f'\
\xb1\xd5\x0c\xd8\x17\x84\xfa\xeb\x8a~z.s\xe7V\x83\
*#\xd54\xb8\xf6\xa8\x15z\x02\xf6\xd4\xa5\xabni\
\x02\xcczZ\xabh~mwdYK\xeb:\xb2\xf6\
w\xcagV\xf6\xcd)\xd5\x12{\xa8|\xc9e\x94K\
c\x84\x9a\xffMcd\x91}\xbd!:\x96\xd1\xe8j\
\x1a\xaa\x99;\xe6\x7f\xefj\xba\x86\xea\xaa\xf6\x1f\x1c\xea\
&\x8b\xbaZ*i-\x1bB~\x8ch\xecW\xaa\xe2\
8\xef2\xe1\xa5@\x0bK\x1c\x7f\x15t\x9c\xc1B\x85\
\x96\xb0a1\xc8\x1e\xb7\xddab\xa6\xd5u\x96\x94\x0f\
\x11\xc7\xee|\xa4\xb3D\xa3\xfd\xb0\x93\xa4y\xf0\xeb\x9f\
#\x19\x99mv\x90\xb4\x1d\xd9\xc6\xc7\x88\xd9m\x85\xd1\
\x17\x85\x82\x1c\x9f}\x08\x83um<\xc7\xfe\xac2\xe7\
\xd9\x98\xbf\xfe7\x8c\x8fE\xe9\x8d\xf9j\x9eX:\x0d\
\x95\x1e\xc8S\xff\xd3\xebX{J\xfe\x15\x06\xb9\xd9b\
\x9a\xa3C\x0f\xa1\xf2\xe0\xa8dWM\xc7\x86\x1b\xb29\
4Z\xc1\x1d\xc9\xbb\xb4\xfd]\xbaAM\xe0\xb81c\
\x1f\xef\x02\xcf\x0f\x1f\xab\xa3\xa6\x0bs\x05\x0eC\xb8\xcd\
\xbd\x8e\x8d\xd3m\x13\x15%P\xfd\x1a\xaa\xb7\xd4\xf3\x1c\
(\xc6\xaf\xaf\xb2C\xc9\xc6\xa1\x89\x04JD\x05\x97\xb2\
\x9b\xb4\x88\xb3#\x12?\x9c\xf0\xad\x16m\xa7\x95\xde\x99\
\x11#\x1feq\x11\x8aw\xf7d\x00\x1dJ\x9f\xec\x9e\
\xf9\x9a\x8e5`\x09\xe3\xe2\x9d3\x91x\x00SG\xb1\
L\x96\xa4>S\x17\xcd\xb7\xb0\x02\xec3\x0c\x04\xa2\x91\
*[\x90\xfe\x5ck\x92\xd8\xfc\xa2P\x04\x9d\xcd\x90\xb5\
V\xd5\xc7y\xad\x01g\xdeT\xb6\xf89{\xf6)\x96\
h@\xd9.W\x05q\x9e%\xe0(^\xc5\xdeB~\
\x9a\xe1\x7f\x87so)\xff\xfet\xf7\xe9\xef\x1d\xf2\x96\
\xa2\xa2~\xff\x9d\x17\xca@\xfc\xfd\xefb\xfbn{{\
{\x8f&\xb7\xdcj\xaf\xd0\x0a\xa6\xbe]\xc3\xfdB\xc3\
7\xa8\xeb2\xad\xf6+Z\x1d\x14Z\xfd\x9akuP\
\xd1\xea\xf0\xe9\xef\xc2nEqG\xa6y<\x0f\xb1m\
n\xcb\x98m\x80;\xad\xa4a+n\xc9J\x0d\x9bS\
\x0b\xd9@\x1a%\x06`^\xe2`\x14\xef\xe2\xe8\x06m\
\x92\xe7\xb0\xaa\xa4\x08\xc2\xa77\xd4r\xd1\x90EDq\
(\xd8a\xde\xbd\xcc\xe6\x1cr.gM\xe9~m\xe9\
Am\xe9\xa1.\xad\xb5\xe6\xb6D>\x18\xe9I\x84z\
\xb2\xa5\x1a\xaf\x17\xea\xb7r\xe1\xcf\x8c\xe9\xb9'\xd8\x17\
\x83\xc2\x07\x88\xd4\xfb\x82\xf6\xf1K\xe6Ih\x95\xee\x9e\
\x87\xdfEI\x91\xec\xc6\xce\xa06\x0e`\xc9r\xac\xef\
<Ja\xbdO\xd1\xca\xfe{\x8cpB\x11n& \
\x05_\xcb\x22\xbfR\xd17\xd2(\x22\x95\x22\xab\xe4\xc2\
\xa9\x5cJ\xf8O\x98\x06\xf7\x9aG\xa22\x90\xa3\xdd\x10\
\x97\x9c\xfa\xb3\x99$\xfeDT\x92he&k+\x89\
\xcb\x09T\x11j\xb5\x1cz\xcd\xe8\xce>\x9c\xf6(\xcc\
\x08{\x05P\xc7\x18K\x85;\xc7\x0a\xaa=\xd1m'\
\x0f\x02\xea\xd1\x1f\xe8\xc0\x8d\xef\x16\x18\x83\x84\xeb)=\
)>\x1f\xb2\x83\x01)2\x15\xef\xc5p\x0f\x99\x0d\xc0\
\x0c\xc4\x87\xee\xad\xe2\x8b\xe3(\x98\xaas\x98+\xd5\xdf\
\xf4\xdc\x9ax\xbby\xcd\x99\xdf\xdc\xb8Z\x13\xd7pZ\
\xce\xd1G@\xcd\xa6\xf5(Q\x84[D\xae\x01\xeaM\
\x03Ts\xd8l\x800\xb4m\x05y]\x94\xeb\xe0\x0a\
\xfe\xc5\xb6=s\x10C\xc3\x9dZm\xb8\xf5\x5c\x1d\x8c\
\xc1\x82\x03\x93\xf5\xd8\x8f\x13\x82\xdb\x88\xa8\xfa>\xbd\xc5\
\x91~\xb4}\x84v%\xf2C\x10q\xfc\x14\x18v\xb4\
\x10W\xae\x9e\xae\x80!D\x22\x90\xc8\xe1|l\xd0+\
\xd8N\xac1\x17FT\x039\x09c\x02\xc5+\x0c\xe3\
\x84\x9c\xc4\x83\x13\xd1\x0f$G\xf401\xc1NV\xe4\
\x1f\xc4,\x02Yk\xd2\xc1\xbd\x8e<6\xf6\x0d/[\
\xf8\xc0\x12@v\xa4(I^\xa0<\x7f\x16J\xf7\x0f\
\xd8\x80\xa0G\x0ep\xb1y\x0a`&\x93\xb9'\x11\xff\
V\x8eLz\x8a\x00-\xc3\xa0\xa6q\xb4\xec\xe2\xf5A\
\xa0\x07\xa2~\xbcYF\xcb\xd5R1\x1c\xc6\x5c\xb8f\
\xf0\x13\xd5{\x1bM\xe1\xec\xd9\x06\xa9\xa1u\xe5\x9d\xa7\
\xbf\xab\xf5-N\xf5N\xe5T\x1b\xb1\xaae\x1f\xbb\x1b\
\xf4aT.\xefV\xc9<\xb7\xb76\x88\x22\xd3\xfc\xf8\
W\xf7\x98\xe8\xba\x988\xcc\xd8\xf2\x0eq;e\xfc\xc9\
\x0f\xa9S\xfaR\xb7Q\xab\xfd\x82\xa2\xc58\xc2GW\
\x0cL\x90\x87\x89_\x1aE\xbb\x82\xb0\xe6\x04\xcd\x11\x1c\
\xf2\xc0\xf9\xdbC\xc0[\xc0\xda\x1b\x13m\xd4[\xad\xb4\
\x9a\xf3\xc4\xb3\x17\xbdloV.c\xf2\xdd\x91wN\
\xe25\xdf\xcb\xf4\xb3_|Q\xd6\xee\xa6EJ\xb1\xde\
\xc9]\x8f\xcfV\xd5F\xe3;\xe8\xc0\xdb\x9f9F\xdd\
\xb5\xf5\xc2\xc5aC\xe1\xf3\xfd\xba\xf7oM&\x0fu\
W\xac\xdc}\xd6+\xdf\xae\xb9\x88g\xd4\x89\xde\xc0H\
=\xcdz\x87\xc2\x84\x15\x0c]\xca\xed\xca\x9e\x80u\xc3\
jX\x9e\x06\xb5p3\x97\xaa\xb3\x9dt\x8f\xac\xa9\xcf\
\xe6\xf15\xf5i\x16\xc18\xa6\xe8\x0f\xda\xde\xc3\x18\x0d\
,\xfd\xd0\xaeX\xfc\xae\xebk\xd3\x0fS\xd1|0^\
*J\xcf\x949\xa3\xe8\x0f\xbaFN\x1de\xaa\xe5\xbf\
\x16\xf1\xcb\xaeB\xb6\x7fC\xe9C\xb3c\xeezS\xa6\
wm\xff;M\xc6\x9d2\xd5X\xce<\xce\xe9\xb4\xca\
\xf3\xd3g{\x01\xe5\xa6\xc3*pL\x96\xa3\xbfl6\
\x5c\x9eE\xb9\x82v\x16\xa1\xc7Q\xb0Z\x84\x96%S\
\xdd\x81\xe7n\xb8\xb9\xb6\x8f\xaf\xd9\x03\x0fns\x13\x02\
\xa7\x85,\x8c\xdd\x84\xb6 ^\xf9\x9e\xcc\x17\xea\xacw\
Qe\x92U7\x90\xdc=\x9f\xc5\xceS\xb8\xde\x93\xbe\
\x0f\xa4\xc7D\xe2\x8d7L\xfc$\x95\xe1\xe4^\x8ce\
z+%\xc6H8 \x19\x92T\x85\xb7\xec\xb9\xad%\
N%W\x92\x1a\xe0Vj\xeb\x9a,\x08'\x80ZR\
\xfcM\xf2J\x07\x81\x84t\x97^\xd6O*\xae\x16\xde\
\x9d\x92X\xae\xf4L\xa0\xadnO\x1c\x85\xf7\xe9\x5cE\
,\xd5?\xec\xee~E\xb6oW *c\x10N4\
\x9c\x11\x18P\x0f\xc8\xf2\x9ad\xf8D\xab&(\xc8\xa1\
\xdd\xde\xc6\x99\x03\x96\xc1\x8c\xe3\xf5 \xc0\xf0\xadJ3\
\x8a?\xbb\x8c\xaa\x16\x91\x0b\xed\x00?\x5c\xa9%\x08\xcb\
2\x0e\xee\xa9\x1akC\xb9\xf5\x1e\xb7\xbe\xa2\xab\xc2\x95\
R\x09&\xdax\x08\xb5\x038\xa3|\xcai\xe1\x9e\xd4\
\xf5I\xc7\xc6\x16+]\x91|z\xa5\xdb\xe2\xa1O\xdf\
\xd9\x90*\x8f\x17\x83\xc8A\x80\x92\x02\x96\xd4\x9a\xae\x01\
\xa4\xafA\xf5\x15Rh/\x0b!\xcc\x1fr\xc4\xc0F\
NQ\xfc%A=\x90\xb1P\xbab\xbb\xea+\xeb\xe5\
\x82`\xe4\x16Uk9\xa0\xf2O\xfc(a\xd7\xc7\xba\
8;W8\xa1\x09\x87In\xa0\xf5\x9cQ\xbc\xfb\xd4\
\x86\xee\xcb\x1a\xf5\x0c\xa9\x9c\xf5d}We\xe3\xce5\
-8-[P~=d\xb3{\xfd\xfb\x9a8\x18\xcb\
\xd5\xce:\x8d\xec\xb3\xb8\x95\x11(5\xb0\xbd\xf3j\xbb\
B\xa2l7E\xce\xc0@\x8f0C\x19\x06\xed'\xc8\
j\xd3j~2\xdc\x1d\xd3\xe3<W\xd7\x93\x0e5\x90\
J\xe6\xbe\xa5\x02\x92\xcc\xbd%\xdc\xae\x8cb\xb2xg\
\xf7\x82[\xef\x1e\xf5\x07s\xd2\x00\x08\x8d\x05\xc6)\x0e\
\xa3\xb4\xa7\x83\xba\xd6\xbf\x91\xd5\xc6<\xfd\xf9\xf9\xeex\
w\x9c\xbb\x84\xea\xb2\xed\x86{kn\xba\xfa\x06u\xed\
.Y~\x01U\x1b\xbc!|\x87ejT\xb07)\
\xc6\xd20\x8c\xa1\x80(\x95U>(`\x105\xdeQ\
\x96EF\xf1\x8en\xdb\xb8\x96\xea\x15\x06n^h[\
J\x11Y\xe0\xaf\xa2\x85v\x93\x7f\xcaA\xf3\xcb\x94\x0b\
\xaf~\x14v*JJ\x02\xb7]\xb8\x8e\xa7\xa73\x9a\
\xd9\x03\xc7R\x90R\xeb\x8e\x89M,\xa1\x1f\xf2\x90l\
]&s\x17\xcc\x92\xc7\xadS\xd2v?\xa8:\xb4\xa8\
\xc5\xd6\xab\xa5\x0aU\xd5\xa9)k\xb8\xaf\x95<\xc06\
\xda\xa9\xcai\xc9\xda\xacn\xb5^+2p\x0d\x95\xe8\
\xb0r\xb0V\xe9\xb7\x1cnf\x1bX\xa9yl3X\
-\xb4\xbf\x5c]\x8b\x99\x7f\xa7\xf4\xc9 \x10\x87\xd7\x94\
8\x00\x85\x22\xca\xcb\xf0^\x8dW&,\x91\xbe\xbc\x17\
S9\xf3VA\xda1\xe2+\x1b\x8f\x8fq\xcc\xd0t\
|/\xae\xac\xc9\xb9\xa2f$}\x1a\xfa`\xed8\x05\
\xc9\xd7*u\x98\xd9\x15\xa7\x98\x98\xcd(\x0c\xff\x5c\x99\
\xb6\x87\xd7\xbd\x5cB\x0a2\x7f\x9fG\xb7\x12\xa6\x5cW\
N\xd0\x10\x1e8\x05J\xc0\xaa\x91\x00\xa6\xa0\xc4\xfd\xf7\
\xf4\x5c\xdc;>\xfe\xacy\x8cv\xa0\xe3\xe6\x09&\xb3\
H\xe9\xb6\xa9\x8c\xe8'^\x08\x87\x9b\xb2\xd8\x17Z\x08\
`\x90Ye\xfd\xe6\xe7\xd3{\x1b\xde\xb5\xae\x83h\xec\
\x05\xfc\xd2\xd6\xcbPNpf00z\x98\xc0QK\
v0\xdaH_XX\xa9\xdb\x83'\x12\x98rtw\
`\xf9\x1dsd\xa4\xf3\x98\xb4\xeci\x8c\x0f\x00\xa4\x85\
\x07F\x17wx\x0e9\x83\xc6\xccS\xd36\xf1\x92L\
\x02?RC|\xb6\xbf]\xf4~P\x84l\xec\x7f:\
5ev,\x84\xeaJ\xd1lV[\xfe\x1dT\xe8\x7f\
\xa7AU\xaaP\xac\x13\xa0\xbe\xb4\x16+\xfb\xf4q\xe3\
e\xd5pa\xe6<w2\xed\xf8F<\xc5\xccE\x93\
\x80X\x08\xe8Y\x0b\xab\xf5\xe2\xb4\xed\xb4\xceo\xab\x0c\
\xb8\x95\xc0k@\x17\xc5\xdd\x9aUi\x82Y:\xf1\x1b\
\xe0\xadA.\xed\xbbn5W\xed(\xadMo\xc5\xe9\
;\x89V\x00'/\x9fX\xa2\xc1~\x81\xdf_\xbd?\
\xf6\x02\x19\x02p\xf6ys\xdcedH\x98]\xe1\x05\
\x9a\x9d\xb1\xe8\x1c\xebX'\x1b\x81R_=2\xe7R\
\xf2\xbdJ\xefCo\x93\xe4q%\xa6\xc0,\x13[+\
\xd5\xdb\x1c\x0f=i\x0cT_\xee[\xc2\xa9yk\xab\
\xcf\xb4\xd0*a\x03+\xe2>\x92\xbd\x0b\xda\xb0\xb0\xb7\
\x96\xf2\xadb\x8d\xdb\xbbX\xde\x9c\xcb\xbb\x14\x10\xce\xbd\
\xfe\xe5|\x7f^8E\xb9\xec\x91\xf8\x0fV\xc0\xa4\x1c\
\xf3\x18M\x05\xa1\xd5\xf2\x0e\xffU\xca\xf3b/\xcf\xfe\
H?O\xd4\x1c}\x0e\xa1d\x01\xa2\xc5\xbc\x89\xe2r\
-,r\xab\x07\x0fw\xd5\x9b\xf5\xc0c\x0b?Z%\
\xb6>\xd3\x18&\x1a\xc3(z\xafF\xb8Dm\xf7\xd2\
\x8b\x91\x16\x96\x01\x5cM\xe9K\xe1\xd2j\x1b\xd9p3\
^\xc3\x1e\x06\x8bdW=\xce\x9a\xc4\xc6\x132\xb87\
\xc7\xf1-\xfc\xe3\x85x\x08g\xb7Ie\xec\xc3\xfe\xbf\
y\x17D\x96>;b\x15\x06\xfe\x17V\x82q\x5c\x5c\
\xfb\xe1\xb8\x82PK&\x16-$\xc7\x07\xbdI\xb9\x1c\
\x89\x9dW\x99\xc2Kb\xd5\x93\xb6E\x96\x15/\xc5\xd5\
C^\xd3\x96\xa3\x06\x90\x15\x9d\xb0\xba\xd2Z\xf1<j\
\xe7\xa4i\xecUq\x99r~\xaeR\x14\x91E\x92%\
\xc1r\xe4/H\xb8$\x13Y\xb2\xcd\xf0\x17Z\xe9J\
\xad5\xfdJ\xde\x07\xd6(sa!BeG(B\
o\xc1;\xe1\x0av*2\xce\x14z\x80\x0e\xcc\xaee\
a<\xb3\xea\xe0\x0e\x00\x03\x0f\xe3\xc3\x06A#\xf9\xf6\
\xfb\x1c}:\x8b\xcf\xf9\xac\xa2+\xb1\x06\x94\x06\xe9\xeb\
+\xa8\x01\xf4\x13\xf2s\xfd\xda\xcd7+g\xec\x16E\
\x06] \xf6\x9d\x07\x85\x8b\xb5\xf9H#\xad\xf3\x14)\
\xc1\xf8\x01\x93\x5c\xad+\xfa\xaa\x13\x5c\xba\x9fg\xf3\xfa\
8sWuv\xd0N\xe1\xabgO\xbc\xd4\x0f\x0e\xf6\
\xd1`\x1e\x16\xb0*\xef3\xf5\x1d6\x855\x81*\xba\
2=Z\x90_\xf9*\x8d\x80\xd9\xfa\x09;`[\xed\
\xb9;sS\xc5Mi\xac\x9f0\x11\x9e\xe4\x97\xa5H\
\x5c\x9dH8\xc8\xe4\xf4\x1d\x96\x5c5\xee\xb6O\xd8\xe5\
%\xf6\xf8\xf7\xa7i\xbc\x92O\x7f/XJU)\xa9\
\x5c\xb4U\x90\x1b\xad7\x8d\x1dK=fi\x9aze\
\xb7\xbb\x06\xab\xf7\x0c\x8f\x12g\xdcv[\xa1X\xd7\xa7\
3o,\x83V&\xbd\xe2\xe5\xc5%\xe5\x82#;V\
\x13\xd2\xa1\xbf\xf4BY\xff\xbac\x22*\xed\x97#B\
P\xf3>\x06\xcenk\x13\xa2\x99H54\xa6\xda5\
\x8cL\xb2\x10R\x950q\xe2ZC\xcc\xd8Z%<\
\xdaR\xad\x01jfX\x80\x98Y\x12gR\xeb4\xf6\
n_z\x98xt\xdbF\xa6\xd6F-S\x8d\xdb\x01\
\xf8\xd9z;\xb5bF\xa0\xfa)&\xf3r\xd2e\xe1\
\xa3x\xea\x8du\x90\xf7S\x95\x9b\xce\x00\xd0\xb911\
\xf3\xa6\xc9\xd9\x98F\xd1\x17lN{\x16\x8d(c\xb4\
\x83D\x96\xd7\x13G)\x1at&\x19\x84\x9dm\xd8\xde\
\xab8\xe1\x17\xd01>p\xdfB9\x06#\x8f\xef\xd5\
Ko\xba\x8a\xe1(\x9e\xa9<\x9d\x88]\xc7\xc2\x80\x92\
\xe5M\x81\xd3P#R=E\x0bD*\x1f{\xbdt\
A)9\xb5\xf0t\xbb\xad:\xdcv\xb9V+\xb6\x81\
S\xba\xb9\xec}\xe8D\xa9\xe6\xc8Y\x07\xb8n\xe2\x8f\
9\xf2<\x08S\xf8\xa6\x0bs\x0e\x123\xb7J\xf2\xe9\
\xfd\xd6uz\xab\xbe(\x14R0\xd4z\xf6\xb8\x86\xd3\
\xee\x82M-Jwk'\xbc\xbc(\xd9\x00QU\xce\
Yk\x8c.\xde\x89\xd1\xd1K\xc3\xa9\xa8\x0b Td\
3\x9d\xd2\x97~\x00\x14\xe5\xf8\x8c\x8f\xe8\xdd\xc8\xf0\xb6\
\x16\xeen\x15\xb6\xd9\xae\xc8\xf05\xf7\x8a\x5cL\xf8\xea\
z:\x1c\xfd\xcfn{\xa2\x06\xbb\xb1&\xeb\xb9\x03\xba\
\xee\xb6\xf2\xb4\xd3\xefh\xf4\x22g\xaa\xb5zk\xcb\xb3\
\xb2l\xeag~\xdcfI\x0aN]E\xd6\xb8\xee\x0a\
\x17\x1f\xa9\xaa\xe1}\xb7Y\xa0\xbc\xdd\xc9\xde\xf6\xde\xfe\
\x06\xa4\xd3\x96&\x0a\x19\x02\xd6\xbb\xbc~\xb5\xd5D\x05\
G\xd7\x1d\xc2\xab&\x01By\xb2\xbe\x02jf!\x1b\
\x1e\x98\xe2\xeb\xb1\xf7\xc3\xee\xc1AGlw\xc4.\xfc\
\x0bg\xe6\x8f\xff\xb9\x19\xcd\xd0\xa6\x9d\xf2\x97F\x9e\x04\
\xc7\xd1\xe8\xe2\xad\x9b%s\xdb\x8e\xeb\xa3k\xdb\xaa\x92\
\xbf8o\xce\xc7\x1d\xfd\x0f\xb3g\xb4\x85\xa8]>\x87\
\xb1\x84\x8b\xf0\xd4\xa0\x5c\xbc\xd9\xbd*E\xf6\xfc\xa2\x06\
j\xeb\xa5.1\xe9:\xa8\xdf\x9aO;R\xc4<\x80\
\x8a\xbe\xdd\x9a>\x1a\x87~d\xbc\xbe\x09{\xfej8\
\x7fu\xde\xfc\x00\xcc\x81+\x9f\x0d^\x8d\xdc<\x19a\
v\xca\x9f\x5c\x9b\x94\xbe?67n\x12m\xd7\x14v\
\x1a\x99\xfb\x86\xbcX+r\xd6e\xc6\x8e\x15\xd9H\x12\
\xa0q\xb9\xd8\xb1kQ\xf2\xba#7\xd7\x5cg\x91\xcb\
\xd9\x0e\xaaA\xfe?\xcd\x86\x1fu5\xf5c]\x053\
\xb6\x07\xd6\x86\x15?*n\xdf\x8c\x19\x7f%\xac\xbf\x09\
;~\x00\xee\xc0\x92/O_\xbf\xa9\xe0\xc9\xfc\x0c\xea\
\xf8\xe6\xda\xb0\x5c\xf0\x17g\xcb\xcd\xfb\xef\x1b\xf3\xe56\
w\x9cr\x9d\x22\xd5\xf1\xb0\x5cl\xd9\xb9*m\xf8\xf2\
z\xeb\xdc\x923s\xdb\xbf&kn{\x1d\xfbv\xeb\
\xf9\xc8\x8c\xf91Q\xfbk\x08\xc9\x1b#\xfd\x9f\x97\x92\
\xebP/F\x86\xa0\xa7{\xe5\xcb\x11\xfb^x\xbd\x0a\
\xc8D@\xbf\xee$\xda(\x15\x15\xf7\xfeu\x18)_\
/\x15\xa8\xcbK\xa1\xd5x\x95\xda9du\x912\xfa\
\xc2\x0c\xc4\xca\xc8\xcb\x18(\x8c\xf9)\xf3\xc6\xf7\xd85\
\xcb\x9e\xd0+\xaeLm\xf5#\x902\xb2\xc5\xf6\xc0!\
1\xe6\x0e\x99\xdb\x22\x1c\x8e\xbe3\xcd\xf9\x8f\xc5\xca\xae\
8\xc1\xb8?lj\xbc\xdd\xdd\xcb0\xb4F\x0al\x86\
+\xecw\x9f\xe7`(\x94L\xfc!mu\xac\x82\x8f\
\xa1C\x5c\x8e\x0c\x8c\xdb\x9b\xed\x88o>\xe6\xbcT\x9e\
X\x87\xe1\xa7$\x8b\xb3\x84p:\xc5\x82\x83\xaa\x82\xc3\
\xaa\x82\xe7U\x05\xba\x8f<\xe7-v\xe4.=\xac-\
}^[j\xfa\xd5\x8c\xbd\xba\xef\xca\x1a\x87\x8d5\x9e\
\x17k\x14\xd2={\x82\x1e[\x98\x121?\x0a\xac\x89\
\xf0\x82\xe5\xdc#\x1a\xc2\xc0`\xc68[[y\x13\xb1\
\xa09\x9b~\xabrF2]\xf3X\xcf\x18\xc8\xe6\x8b\
\xff\x90\xa5\xdc`9\xcav\x87\x07\xc6|\xf0\xa1T\xf9\
\x10\xca\xda\x9c*\xcarU\xf5\xb2d\xcc\xbdz\xa6\xaa\
\xab\x1c6Wy^\xaa\xb2\x99\xf4\x92s\xad\x9e\xc4\xd2\
Kd1QS\xb4$c\x18\xf4\xb1\x9dJ\xed\xfbK\
\x8e\xc8\x18\xd3\xe7&\xc2lK\xc4\xb0\x95C\xb3\xe1\x89\
/?\xbc\xee\xe7\x22\x1b\xb1;.\x1e\x1c\xe7Q\x9c\xce\
;\xe2\xa3\x84\x15\x22\x1e;\x80\xb5\xe2\xfc\xf6p\xc2\x0d\
a\x9f\xcd\xd9\x07C{H`\xd3\x9e8\x0a\x02zm\
\xd7\xd69\x09}/\x1eEP\x83\xbdJ\xd2\xc3^\x05\
\xe3\xfc\x84u\x8e\x83\x88L}\xb5\x89K\xe5\x86\xaa\xae\
]\x11\x9f\xe7\xc0\xbdi\x0f\xd7\x00\x95\xc9\xae\x15\xc0\x9e\
\xaf\x01\xcc\xce\xa7\xaeV\x1cO\x99\x0f\xa1\xf2\x7f\xb7\xe2\
*1\x03\xf3\xc6\xbd'\x5cg\x10\xae\x162&w\x1d\
\xf2M\xe7\xa3O\xad\x1f-\x94^F\xbd\x84\xe4\xc7N\
'Z\x87 P\xfc*:+\x19\xe2\xf9\xc5h\xd0G\
_y\x8aM(\xe3\x8c<\xc89\x1e\xa8\xc8P\x184\
q\x1f{\xf6c\xb9{\x879\xac\x0d\xf2\xab\xd4\x05\x01\
j\xb7r\x9dj\x01X\xd62;/*W\xa7\x16\x84\
\xb6\xe0\xc9\xda\x9fD\x93/,@\xd5\xe5\x07)\x1a\xa8\
\x9c\xa6F\xcc(YP\xd8Q\x06Y\xc0\xe2\xcdk\x1a\
[}\x9a\xe3\x8d\x1a\x91Y\x09\xd9\xe4\x93u\x9c\x0e\x07\
\x90\xb7\x17\xb1\xd1\xd0YA<1f_/\xb4\xf6\xe4\
\xd0\x7f:)\x88J@\xa2\xe3ap&\x12v\xf7e\
\xfbu\x03\xecRR8\xc3\x89\xec\x8by\x9a.\x93\xfe\
\xd6V\x92\xc2d \x80Y\x10\xdd\xf6&\xd1b\xeb\x0f\
Eb\x01[{\xbb;\xfb\x07\xdb/\xb6\xb7\xfe\xc0\
\xb8\xb1\x1c\x8c\xac\x0b\xf5\xbc\xb4k/@\x97\x10`\x9b\
\x91$7\x10\xb2\xdd\x19{\xb1\xaa\x8e\x84\xd7\xde\xa8\xc4\
4f\x93\xec5Z[\xac\x97CXfF\xb7\x04\xd4\
\xf2\xfc\xba\xf6o\xc8\xf5\xebV\xfa1L\xdd\xc2O\xc8\
I\x8cW\x95]\xdf8\x84d1\xbc#E\xd2\xe5)\
\xd1\x86\xbb\x5ce\xe1\xf9a\x01D& C1\xccU\
N@\x86=o\x96\x17\xf68\xa6\x14S\x11(\xf9:\
\xd0\xb1\x92\xd2\xe0\x140\x9bH`F\x02\xb4\x8az\xc2\
\x96HL\xa8\x8a.9<'\xda\xc3_\xd1\xa2`0\
\x8d$\x95\x1e\x05\x8f\xbb\xb2M|\xae:\x14\xde\xd7\x9f\
\xf1Q\xa0\x1a\xe5\xbd\x14\xa0\x8eL'l\x1eI\x87\x93\
\x15\xfdw\xee\x05<\x1dhQD0\xa0\x87h\x15\x8b\
\xa9L\xfc\xd8p6\x1d.\xcel\x8a\x12\x9f\xb1\x8b\x98\
\xc2r\x9b\xdbi\xc4Va^\xef\xbe\xae\xd5\xe5\xa3\x04\
\xa9\xf4\xadw\xe7/V\x0b5@4\x8fB\x8e]0\
\x8e\xc2\xc2nBN\x1b;\xfbZLi\x85\xf9\xa3\x19\
T\xc1\x00\xa0\xbf\x9c\x03\x91\xbb\xfb\x96n]\x04\xaeh\
9\xa5\xc2&j[)\x9dbh\x1a\xf1\x9d\xeb\x1a#\
\x81\x00\xc3\xb1o\x90\x1e\xc8\x04H\xc2\xbd\xd2B\xe7\x90\
ji}\xe5F\xab\x92~\xbe\xceT\xdb\xb6ku\xbd\
?\xc0D\xedQ'\xfa\x11\xcd\xdcLD%\x8a\xe4\x94\
\xa4vT\xa1z/\xf8:+\xdf,N\x93-|\xeb\
o\xb6D\xae\xfb\xec\xbb\xbe}\xe7\xd4\x925u\xd9\x1f\
\xc3\xeaO\xe6\xfd\xb9\x97t\xf1\x1c\x07\x16\xdd62\xc1\
\x0dj\x0b\xca\x14c9\x86(\x95\x0cw\x919\x1b\xe9\
\x95L\xd0\xb6\x9f\xc5\xe5\x22:\xdf5\xe2S2\xe9\xb7\
B\xea\xd7\x0d\xae\xefM\xff\x19\x01\xdf\xef\xda\xf9|\x1b\
F\xca`>/\xa2X:\x88!\x8f\xf4d\xee\x07S\
\xd8K\xf9!<\xa0W\x19N\xeb:\xad\xe9\xd3\xc4\x85\
,5\xe2\x92|[\xc7\x8c7\xa1\xc6`\x1e\x84]9\
\x84[[\x1c\xdb\xf1\x97\x1c\xa6eS\xd8G\x99M\x0c\
\xe4Y\xd3r\xed\xe5.9\xff\xae=7\xed\xb0\xdc\x1c\
I\xdc\x09\xcdX6\xcc\xcb\xc6H6a\x87@\x1e\x80\
W5I\xd6c\xb7\x16A\x22\xa8\x129\x16\xce\x14`\
\xa0\xaf\xd1\xd9\x98\x02\xc6\xabH\x16r\xc1i\x0d1\x83\
2\x9c\x8c\x14\xeb,R\xe1Bz\xaeD\xd6\xd6m1\
\x90Yh0\xfb\xe4\xd0\x1f\xb2\xf1\xba\x83\x87e\x1e\x0b\
\xae\xc0\x89\xce\xd69\xd7\x06\xd4p\xa6:\xf4\x5c.\x10\
=+<Y\x83\xd2\x114\xd0$\xbb5R\xban\x0d\
\xde>Ft<x\xbe\xc7\xa8\x00\x1eI\xe6\x89\xe0a\
\xe0\x0f\xce3\xadSm\xa2\x8bR\xa0o& \xb7\xce\
\x02\x1f\x95\xa8T\x07\x04t\xbb\xcf\x85\x14?\xc8\xbb\x89\
\x5c\xf2]\x95\xef\x93[\xe4\x8b\xb0e\x82g,\x13\xb9\
\x9aFp[Le\xf2\xa3\xbeQ\x1a(:L\x05\x5c\
\x9fVR<;\xd8\xc9_h\x1b\x84\x86\xcc\xa3\xc8\xb9\
\x84\xc5G\xa8\xd2\x92:*\xe4\x17\xe91\x9e\xb1l$\
\xab\xd4\x81%\x1are\xcce\x94D)\xb9l\xbd\xbf\
\x07\x13\x99\xa5\x16\xa0\xd8\x81[\xca\x87N+z\xc8\x0b\
\x9aU\xe5&\xd4\x97\xce\xcf\x10!\x19L\xa4\x17\xb0\x16\
\xdd\x80\xd2\x9a\x80kX\xfb\xd5\x98T\x00G\x81\xbc\x9b\
\xaf\x92?\xbd\xeb\xf9\x16_F)\x06\xcbp.e\x9a\
l\xd1\x22'[\x87?\xe7\xd68\xef(F\x99p8\
\xc5n9\xd8\x7f\xa7TV\x93M\xc0-^\xe6^o\
\xed\xf8\xb1\xc6\x93\xf1y\xd9\x93\xf1y\xa5\x8f\xd2\xdeA\
\x01\xe9R\xa0\x7f\x0de\xb7P\xb1\x80\xb9\x8e\x0f\xdc8\
\x07\x85\xa4b]\x95\x06~\xdb\xd9\xac*\x13\x99n\x96\
o\x043\x07D\xee\x9eoUV7\xdf\xce\xe7\xf7\x96\
i\x99w~nD\xa6\x94\xb0g\xbf\xa2\x89{f\x1d\
\xf5+2\xa8v\xeaj\x14\xd2@\xbb\x93\xe7\xd5\x94\xb7\
\x8f\xbf[\x8f\xe9w\x04\x08\xce\xe5\x86\xfer\xf5j\xfb\
\xd5\x9b\xc1\xee\xd7\x91\xde\xd1\xea\xab\x94\xe6\xcbE\x15\x0e\
c\x9c\xbae\xaf\xc88Y\xc4\xa7\xae\xc7rThW\
\x8f\x98V(\xf3\xaeEf\xa4U\x7f\xd6\xe7\xef\x13\xd6\
\x9d\xab\x8c5\xcbU2\xd7\x0e\xbe\xa1:\xac\xc7\xeat\
\x9dfI_\x82{\x8e\xe0\xc4yb\xd4\xbb\x8d\x8e\xa4\
\x98\x92RN\xe7\xa6F%\xd1\x0f\x1e\x85\xaf\xf8Qx\
I\x12M|R\xec\xd3y\xea\xa7\xbd\x5c\x82\xec\x04D\
\x1a/\xe0P[V\xa0\x0a\x0e\xd9\xaa\xdf\x868\xa6\xab\
R6Z\x083\xa8\x0f!HI\xe9*\xa4\xe8\x17\x1d\
F\x86\xfc#\xc5u\x14M\xcdS=\x0el*S\x19\
/\xf0\xd5\x1c\x1d\x14Y\x8d\xa7\xcb\xb5\xd6\x8f&\x010\
\xbbz\xaf\x95\x09jPW\x1d\xed\x01\xdd\x81a|\x8f\
z\xca\x05\x8c?\xe2\xc8\xb1\xa8\xd4\xf4\xf2\xb6\x01\xe8\xd6\
\xa9R\x0192H\xd0\xabS~\xfc\xe1\xbd\xd1\x9d\xff\
$\xb2p\xc1\xd9\x13\xbe\xf1\x8e\xeeSe\xf8\xb3\xab=\
\xb0\xf5;\x96\x1dt\x8c\xe7\x8d\xa7\xd2\x0a\xe4\xc5\x01p\
\xe1\xe3\xe8~\x09\x90(\x86m,\x97p\xb6\xaa\xe3\x92\
\x1fEt\xd5\xd4\x90\xce\x90\xa3@jGU/X\x80\
\x10\xa4\xe2jj\x17pR\x1a\x22\xc8\x0eip\x94 \
\xc6\x87\xac\x06\x08\x7f\xf5\x95\xd2\x9eh\xb005,\x97\
eo\xe1\xba\xb5\xcet\x04'\xf9\xbd\x09\xb9l\x85\xfa\
\xa5H\xcb\x94\xa5\xc9\x9b\xda)Ct\x9c\x133\xa1J\
\x11\x0d\xd2A.\x06\xf3\xe9LI\x9d\xd9\x16\xc2QZ\
n\xf1v\x08a&a\xd8\xdb\x09y\xeb\xb2\x8aW\xcb\
\x1e~xe\xa53\xb9\xea)\xa5\x88B(\x07\x86C\
\x0e\xc3\x10\xd5\x84\xe1\x98\xaf\xe7H\xbe\xf4\xde\x09}\xdc\
\xf8\xf4\xd8\x92eE\xc7e\xd6T\xa2\x7fL$\xbb$\
B]\xfe-M\x84\xa2\x05Z\xa6\xc4OW\x94=)\
\xc9Esv\x0c\xda\x90\x92A-?\xf0sz\x83\xa0\
\xbd\x86\xee\x0c\x81L\x12\xa3\x1dV~\xc0jaq9\
3\x8f\xe4\x1c\x10\x18F,\xffX\xd1\xac\xe1-\xe7\xd9\
\xfes;9\x9f\x9eH\xdb\xe0\x81\xd3\xd0\xe7\xa0`\x22\
)~\x08\xf0\x8d\xd9\x8b\x09|G\xe2\xdf\xc2\xfb'\xde\
2HLS\x84\x90\x83\xf0\xe1\x94\xa6L\xc5c\xca\xf5\
=6\xf1\x01s\x068\x99|\x19\xda\x9b\x8d\xf6\x0f^\
\xd4p\x0f\xab\xc7\x09\xf3\xf8D\x01\xbbu\xae-z\xe1\
69\xb8XG\x09\xb4\xec\xa9\xe0@\x18\xd5B1d\
\x1cTFF\x1d\x93\x8df\x12Pm\xa2\x0f\x8e\xd5\x8d\
\xaf5\x84\xc1T\xe8s\x04\x17h\xe1}!rL\x09\
\xbe\x0a\xbb\xe2\x07\x81\xbc&\x8a\xd2\xc3\xfa(Mf\xb3\
\xa4l\x7f\xe5\xa9x\x84\x1d1\xbd\x0f\xbd\x85?\xb1y\
*?t@\x9f\xb1\x1e\x95\xc90\x04\x80\x12~>/\
lh&\x0cu\x10D\xd8\xc7\xc4DH\xc4P-\xfe\
L\x1d)~b\x88H_ \xaf\xe0\xf6\x8di\x0f\xaf\
\xf2\x8c\x9b\xfc\xdbW\xb2g\xe2ed\xf5\xa0h\xe6\x05\
\xb4\xfb\x025\xaeb'\xb0\xd92\x8c~\x8bV\xb4\xb6\
\xf4\xfcc\x0e\x01\xe8\xff\x9d\xea\xf0*\xbb\xd0\x9a`\xe7\
0\x17jrp\xe2s\xf4\xc24B\x87J\xa2_\xb6\
\x9f\xed\xeev\xe0?/:H\xf7\xd9\xee\xda\xf4\xfa\xb1\
\xbb\xfbp\x10/\x1e\x0cb\xff9=m\x19\xa1\xe3C\
\xc2\x89\xf2n(\xca:\x11\xd6\x0c\x88\x87\xaf\x9f@\x0e\
\xfc\x94g\xd87.\x02\xbf\x003\xa1\xab\xe0ktv\
\xf26\xccE\xa2B\xa2]\x00]2\xaf\xb9\xb2B\x89\
\xd0j?\xb5\x82u\xe2F\xa1E\xa3\xaa\x8a>i\xdb\
\xff\x13\x01\xc0\xdf@f\x9a`L{M\xdc\xab\xa2\xfd\
\x82\xb6>\xa0\xe0\x94\xe2(\x008\x08B\x8f+Q\x11\
\x90h\xcf\xf2\x86\x9b)2FZ\x93w\x98\xc7\xce\x07\
\x89\x0a\xeb\x8d\xfd\xe9T\x86v\xce:cm\x90\x85I\
)`\xf6\xfb\xa7\xd2`\x7f\xff\x84cl\xca,U\x82\
\xb3V^\xaa\xba\xd6;\x0fj\x9d\xa5\xa0*Eb)\
\xdf\xa4\xdd\xe1c\x14\xd4\x87\xe4ria\xf7\x5c\xdd?\
[\xc5<\xa0\xfbb\x04\x08\x90\xe5\x8fJDE'\xb5\
\x9a\xe5*\xa2\xc2SUb\xe4\x8e^\x81\xa6\xb2%`\
d;\x0ds\xb9\x1eI9\xe3\xf7l\xdex\xe7!\x8d\
\x1d\xf4\xf4\xb8q\xe2\xf2t\xb0I2\xbfb\xc0\xb7\x07\
$\xf6\xab\x0f\xe5\x98\x8b\x98e\xe5>\xc8\xf7i\x05\xfd\
/\x14X\x11u\xed\xcf\xa5\xc8\xa6\xb6\xd2\xf7\x84\x85@\
}d\xf3\x05\x84t\x16[\xac\xea \xd6\x8f\x16\x1bJ\
J3-\xc9\x94\xc3\x92\xe8P3LQ\x11uh\xe5\
RDe\xd3\x94\xcd\xfaTL\xac\x00c\xdf\x80@\x02\
\x82\x8c\x16:\x16^\xc8Q\x99\xd5A\x84f\xd8\x983\
\xb0\x10\x9ef\x93\xe0]\x1c\xcf\xfa\x97\xf59X>\x1b\
E>\xba\xe7\x1a\xe94\x8a@\xad\x0c\x0e-a\x96\xf2\
O\x14A\x9a\x08\xb9-\x01:b\xfe\xba\xc9\xa7-@\
g\x80\xdc\xaa\x99,\xe4\xaek\x95\xda\xc3\x11\xfb\xb6b\
N\xdbB\xb7\x12c4\x00/E?~Ht\xe3\x8a\
yn\x0b\xba>\x1c\xf0_)\xc8\xa1#\xa6!\x9c\x9a\
]\xe2\xd1\xe2o\xda\x81\xae\x90\xab\xd4\x15\xed\xd0\xe6]\
VZ'\xa5\xfdR7\x852kP\x99yHN\xb4\
^\xad\xccM\xfc\xe8\x1fG\x1d\xddov1\xf1S\x9d\
\xd1T1\x96\xec\xe9\xca\xe42\xf6\xa6$\x98\xdaBg\
\x1a\xd1m\x0e/\xb1)\x88\xa4>\x88\x03\x0b\x9d\x8b\xca\
\x00\xc0X~\x8f\xc0\xcf\x1cQ\x08\xad|\xad\x8e\xfc*\
\xb9\x90\xb2\xa5L\xaet\xbf\xa4P\xb4\x1cf\x8b5\x8c\
\xf8\x9c\x8c!\xc2\x96\xde\x04\xe6j.\xf5\xcd\x9f\x8e\x80\
\xcc^w\xbd\xec\xaa\x98Q\xdcM\x97\xc5\xf5\xb7\x92\x98\
\xfew\xc5\x94t-Sy\x08.c0W\xae\x96\x83\
v\xa9Z\x0e\xac\x0d\xb6#\xefx<\xb4\xc7\xf6\xe1/\
2\x0fd\xdb\xdf\xbf\x19\xc5\xd5\xdf\xc5.\x14a6\xde\
\x09\xa9\x7f\xbd1HI\x9a,\xd5|X1f\x9dR\
Y9\xf0l\xd5H\x1d+\xe7`\x0f\x1bN\xe3:I\
1\xea\xc04\x85\xee-\x19c\xb6\x9e\x14\xfdH\xdcd\
\x06\x86\x85\xd7\xb1?\xb53\x13\xe5\xef&\xf5\xb9\x98\xb2\
\xd7\xe8\x82\xd3H\x907fke\x8e\xe6D\xba\xec\xd3\
X\x9b\xe6\xcce\x94\xe0nP9\xfb\x85\xbcMk@\
4\x0f\xe9\xdfq\x84x\x07\xe8\x8aGt\xbe\xe0\xa1\x82\
\xc42\x88 5\xd9\x1f\xb84 C\xe24\xa02\xd1\
x\xbf\xac\xd0\xbdP[\xd8\x87J\x95\xdc\xcb\xa5\xc1\xa8\
B\xaf\x12\xbbBg?<\xd1Z\xd1\xbb\x1d\xda\xf5\x1d\
q\xcf\xbfd\x05\xbb\xba\x00~\xd9\xe9\x98\xef\x09_\x9c\
\xf4T\x16\x0bvt\x01}\xffq\xf3\x99v\xef\xc4\xaf\
3\x92\x17;\xb3\x9d\x99k$T\xd04\x927\xd2\x83\
\xa5\xaa\xb7\x16\xad\xd1\x0a4\x1atW\x06\xaf-_8\
2TP\x8fI\xafY\x8f\xa5(i\x93\xe9\xc9\x85\x98\
\xd0o\xfc\xe6W\xe5\xe8\x80/\x0ad\xe8\x94]\xab*\
\x86\xd0\xcf^\x84M\x14\x80\x86j\x05_\xbbfW\xf9\
\xc6\xae\x1d\x90J\xc7\x81\x13\x80\xf5\xee]\x8f\xbd]\xd1\
\x8d\x7f\x9d\x13\x7f\x8b\xfe]\xc0j\xc6\xf0)\x99G\xb7\
\xc3(NO\xb5\x84\x95\xf9\x84UC\x07n7\xc4\x94\
\x9a*t4\xcb\x0fv\x86O\xeblN8\x9di\xaf\
Bt\xb7RT\xbaF\x96\xcf \xad\xe9sF?\x95\
g\xdc\xe1\x8b\xdd\xe7\xbb\xcf5_\xb6\x1fn\xad\xbcN\
\xc6\x0b0\xb3K[\x85\xf4\xfa\x85\xa3\x98\x13.x'\
\x98\x04\xfe\xe4\x0b\xbd&!sv\xe1\xa8-\x1c\xdaQ\
F\xfb\xea\x9a>\xea[\x14\xb6M\xdb\xcay\xe0\xad\xd5\
]\xed(\xe7\x01\x99r\xfe\xff\x0d\xaeMB\xb9V7\
\x90\xaai\xa4w\x13c\x0bB\x8a\xb5\xc4\xd8ch?\
\xde\xbc\xd7_iS\xf7U\xce\xb1+\xdbA\xf2\xaa\x90\
-9\xb7\x0c\xcc$|z_\x8f0\x146%w+\
\xf7i\x1c\x08\xc7\xf7Y\xf7\xa1\x80\x93$\xf6LNd\
\xadM\xc4\x14d\x05m\x22\xaa\x0d]\xe6{\xae\x8bX\
\xc9\xbb\xd3\xc1\x8b\xea\xe8|\xc3\x9cY\xdf\x9a\x106\x9a\
\x01#\xd0\x0b\xfe\xf58\x8aC\x19\xeb\x8b\xd0C\x04\x8f\
\x5c\xa4\x97\x9a\x10\xcd\x8f\x1b\xec&\xb3\xaa:\x8f\xec$\
H\xda\xd9\xbbz\xb05\x1c\xd29\x94\xd6\xb3\xb7\xfe\xe3\
@\xc5\xa5\x8a\xae\xa8ke\x01\xad\x8a\xbb\xce\x80l\x7f\
\xf0\xda\xd8\xac\xf6\x84\xe7\xe2\x96\xeeX.\xe8\x16\xcc\x9c\
\x7f\x94\xfd\xdd\x91\xd7\xae>\x1a,\x99\xe4-\x03?M\
3\xa3\xc2\xda\xdc\xa19\xe3O\xeb\xae\xd1\xa5\x8d\xe2\xaa\
e\xe7\xd7vf\xd7.\x04\xbb\xd1\x81\xfcs\x0e\xd5h\
\xa0\x9cx\xa9\x9f`\x16\xc4(\xbe7Qc\x18\xcb\x84\
\x1fO\xb8\xfdL\xdcG\xab\xcc\xb8\xde$\xad\x1f\xa3q\
\xd4\xb5\x87\xd7>\xb2{\x0f\xf4\x89\xa4|\xae\xd9\xd8\x0d\
1M:\x04\x02;E{\x96\xe4~\xb1\x90i\x8c'\
\xbe\x98\xacb`\xfb|\xa4-\xe3h\xbaB\xfb0/\
T\x8f\xe2\x98l\xd9\x0b2\xef^\xa5\xa8{\x17G\xd7\
H\xa3\x18\x7f&g\xefh\x17T\x9a:f\x02Y\xc9\
\xe0\x11W\xe7\xe7\xb6\xa6\xb7{\xd5\x97!7\x82%K\
\xdc]G0\xe0C\xd7-\xc5\x91\xb45\xd3<U\xe5\
\x5c\xca\x95Ud\x1b)\x85\x17\xdbu'\xf9UJ\xb4\
\xe2\xd8\xaaL\x86\x9d\xc9\x9e\x9c#\xe3\x9e\x7fqF\x14\
(\x8f\xccN\xeeQ\x1c\x9a\xc9\x8cQ\x95\xa6\xb8z\xd0\
Y\x02c{p \xe5\xaf\xc2/\xd5\x04\xa6\xca\x9b\xe9\
\xac\xcc+5\x9d\xb5\xf0\xa86'\xdf\x90,\xd3\x8eb\
\xe9u\xec?2\xcb\xea\xec\x93\xf3hp\xa7\x819=\
\xbe8\x1f\xe6\xacx\x91]\x8cW~\x90vQv\xa5\
WR\xb4T\xa2\xd7N8\x19\xd2\xf4\x1e\xc685\xe2\
\xee}\x82\xce\x15\xe4\xd5\xc2v(hN\x95\x89q\xec\
\x80\x03b\x17\x9bG\xc2v\xa7\xcf j\xf5\xc4+\xf4\
\xc7\xb9\xf3\x16\xcb\x80\x18\x88T\xbb\x9e$8\x15\xb0\x88\
\xe0vXk\xe5\x89\x80\xdeu\xd1\x9a\x8e\xac\xb4.\xbe\
\x5ci\xabb\xe8\x15\xd6\xe5^r\xd4-|\x8a%\xa3\
\xb2\x105\xc2(\x8c\x99w\x02\x1e#k\xfa\xf9\xdc\xc3\
L\xb2d\xb5\x05\xcc\x86\xedeP\xa1,\x92\xd4\xc3\xcc\
?Scu\x88\xaf\x0e\xd6w\xcd\xdd\xd0\xd6\xb2\x03r\
\x11\xa6\xc
gitextract_m5nz38oz/
├── .github/
│ ├── ISSUE_TEMPLATE
│ └── contributing.md
├── .gitignore
├── .pep8
├── .travis.yml
├── .tx/
│ └── config
├── LICENSE
├── README.md
├── check_dependencies.py
├── clear.py
├── man/
│ ├── meson.build
│ └── persepolis.1
├── meson.build
├── persepolis/
│ ├── .pep8
│ ├── Persepolis Download Manager.py
│ ├── __init__.py
│ ├── __main__.py
│ ├── constants/
│ │ ├── Browser.py
│ │ ├── Os.py
│ │ ├── Version.py
│ │ └── __init__.py
│ ├── gui/
│ │ ├── .pep8
│ │ ├── __init__.py
│ │ ├── about_ui.py
│ │ ├── addlink_ui.py
│ │ ├── after_download_ui.py
│ │ ├── customized_widgets.py
│ │ ├── log_window_ui.py
│ │ ├── mainwindow_ui.py
│ │ ├── progress_ui.py
│ │ ├── resources.py
│ │ ├── setting_ui.py
│ │ ├── text_queue_ui.py
│ │ └── video_finder_progress_ui.py
│ ├── meson.build
│ ├── persepolis.py
│ └── scripts/
│ ├── .pep8
│ ├── __init__.py
│ ├── about.py
│ ├── addlink.py
│ ├── after_download.py
│ ├── browser_integration.py
│ ├── browser_plugin_queue.py
│ ├── bubble.py
│ ├── check_proxy.py
│ ├── compatibility.py
│ ├── data_base.py
│ ├── download_link.py
│ ├── error_window.py
│ ├── initialization.py
│ ├── log_window.py
│ ├── logger.py
│ ├── mainwindow.py
│ ├── newopen.py
│ ├── osCommands.py
│ ├── persepolis.py
│ ├── persepolis_lib_prime.py
│ ├── play.py
│ ├── progress.py
│ ├── properties.py
│ ├── queue.py
│ ├── queue_prime.py
│ ├── setting.py
│ ├── shutdown.py
│ ├── spider.py
│ ├── startup.py
│ ├── text_queue.py
│ ├── useful_tools.py
│ ├── video_finder.py
│ ├── video_finder_addlink.py
│ ├── video_finder_progress.py
│ └── ytdlp_downloader.py
├── requirements.md
├── requirements.txt
├── resources/
│ ├── PersepolisBI.py
│ ├── dark_style.qss
│ ├── light_style.qss
│ ├── locales/
│ │ ├── ui.qm
│ │ ├── ui.ts
│ │ ├── ui_ar.qm
│ │ ├── ui_ar.ts
│ │ ├── ui_de.qm
│ │ ├── ui_de.ts
│ │ ├── ui_es_ES.qm
│ │ ├── ui_es_ES.ts
│ │ ├── ui_fa_IR.qm
│ │ ├── ui_fa_IR.ts
│ │ ├── ui_fr_FR.qm
│ │ ├── ui_fr_FR.ts
│ │ ├── ui_hu.qm
│ │ ├── ui_hu.ts
│ │ ├── ui_ko.qm
│ │ ├── ui_ko.ts
│ │ ├── ui_nl_NL.qm
│ │ ├── ui_nl_NL.ts
│ │ ├── ui_pl_PL.qm
│ │ ├── ui_pl_PL.ts
│ │ ├── ui_pt.qm
│ │ ├── ui_pt.ts
│ │ ├── ui_pt_BR.qm
│ │ ├── ui_pt_BR.ts
│ │ ├── ui_ru.qm
│ │ ├── ui_ru.ts
│ │ ├── ui_sv.qm
│ │ ├── ui_sv.ts
│ │ ├── ui_tr.qm
│ │ ├── ui_tr.ts
│ │ ├── ui_tr_TR.qm
│ │ ├── ui_tr_TR.ts
│ │ ├── ui_zh_CN.qm
│ │ ├── ui_zh_CN.ts
│ │ ├── ui_zh_TW.qm
│ │ └── ui_zh_TW.ts
│ ├── meson.build
│ ├── resources.qrc
│ ├── resources_generator.sh
│ ├── translation_files.pro
│ └── translators.txt
├── test/
│ ├── .pep8
│ └── test.py
├── uninstall.py
└── xdg/
├── com.github.persepolisdm.persepolis.appdata.xml
├── com.github.persepolisdm.persepolis.desktop.in
└── meson.build
SYMBOL INDEX (572 symbols across 48 files)
FILE: persepolis/constants/Browser.py
class BROWSER (line 17) | class BROWSER:
FILE: persepolis/constants/Os.py
class OS (line 16) | class OS:
FILE: persepolis/constants/Version.py
class VERSION (line 16) | class VERSION:
FILE: persepolis/gui/about_ui.py
class AboutWindow_Ui (line 43) | class AboutWindow_Ui(QWidget):
method __init__ (line 44) | def __init__(self, persepolis_setting):
FILE: persepolis/gui/addlink_ui.py
class AddLinkWindow_Ui (line 33) | class AddLinkWindow_Ui(QWidget):
method __init__ (line 34) | def __init__(self, persepolis_setting):
FILE: persepolis/gui/after_download_ui.py
class AfterDownloadWindow_Ui (line 28) | class AfterDownloadWindow_Ui(QWidget):
method __init__ (line 29) | def __init__(self, persepolis_setting):
FILE: persepolis/gui/customized_widgets.py
class MyQDateTimeEdit (line 30) | class MyQDateTimeEdit(QDateTimeEdit):
method __init__ (line 31) | def __init__(self, parent=None):
FILE: persepolis/gui/log_window_ui.py
class LogWindow_Ui (line 30) | class LogWindow_Ui(QWidget):
method __init__ (line 31) | def __init__(self, persepolis_setting):
FILE: persepolis/gui/mainwindow_ui.py
class QTableWidgetItem (line 30) | class QTableWidgetItem(QTableWidgetItem):
method __init__ (line 31) | def __init__(self, input):
class MenuWidget (line 36) | class MenuWidget(QPushButton):
method __init__ (line 37) | def __init__(self, parent):
class DownloadTableWidget (line 154) | class DownloadTableWidget(QTableWidget):
method __init__ (line 155) | def __init__(self, parent):
method contextMenuEvent (line 174) | def contextMenuEvent(self, event):
class CategoryTreeView (line 179) | class CategoryTreeView(QTreeView):
method __init__ (line 180) | def __init__(self, parent):
method contextMenuEvent (line 199) | def contextMenuEvent(self, event):
class MainWindow_Ui (line 203) | class MainWindow_Ui(QMainWindow):
method __init__ (line 204) | def __init__(self, persepolis_setting):
FILE: persepolis/gui/progress_ui.py
class UpdateProgressBarThread (line 32) | class UpdateProgressBarThread(QThread):
method __init__ (line 35) | def __init__(self, parent, new_value):
method run (line 40) | def run(self):
class MyProgressBar (line 55) | class MyProgressBar(QProgressBar):
method __init__ (line 56) | def __init__(self, main_window):
method showBusyIndicator (line 63) | def showBusyIndicator(self):
method setValueSmoothly (line 68) | def setValueSmoothly(self, new_value):
method setValueSmoothly2 (line 86) | def setValueSmoothly2(self, value):
class ProgressWindow_Ui (line 90) | class ProgressWindow_Ui(QWidget):
method __init__ (line 91) | def __init__(self, persepolis_setting, parent):
FILE: persepolis/gui/resources.py
function qInitResources (line 35451) | def qInitResources():
function qCleanupResources (line 35454) | def qCleanupResources():
FILE: persepolis/gui/setting_ui.py
class KeyCapturingWindow_Ui (line 29) | class KeyCapturingWindow_Ui(QWidget):
method __init__ (line 30) | def __init__(self, persepolis_setting):
class Setting_Ui (line 85) | class Setting_Ui(QWidget):
method __init__ (line 86) | def __init__(self, persepolis_setting):
FILE: persepolis/gui/text_queue_ui.py
class TextQueue_Ui (line 29) | class TextQueue_Ui(QWidget):
method __init__ (line 30) | def __init__(self, persepolis_setting):
FILE: persepolis/gui/video_finder_progress_ui.py
class VideoFinderProgressWindow_Ui (line 27) | class VideoFinderProgressWindow_Ui(ProgressWindow_Ui):
method __init__ (line 28) | def __init__(self, persepolis_setting, parent):
FILE: persepolis/scripts/about.py
class AboutWindow (line 27) | class AboutWindow(AboutWindow_Ui):
method __init__ (line 28) | def __init__(self, persepolis_setting):
method keyPressEvent (line 52) | def keyPressEvent(self, event):
method changeIcon (line 56) | def changeIcon(self, icons):
method closeEvent (line 60) | def closeEvent(self, event):
FILE: persepolis/scripts/addlink.py
class AddLinkSpiderThread (line 37) | class AddLinkSpiderThread(QThread):
method __init__ (line 40) | def __init__(self, add_link_dictionary):
method run (line 44) | def run(self):
class AddLinkWindow (line 68) | class AddLinkWindow(AddLinkWindow_Ui):
method __init__ (line 69) | def __init__(self, parent, callback, persepolis_setting, plugin_add_li...
method currentTabChanged (line 228) | def currentTabChanged(self, index):
method detectProxy (line 233) | def detectProxy(self, button):
method proxyFrame (line 258) | def proxyFrame(self, checkBox):
method downloadFrame (line 265) | def downloadFrame(self, checkBox):
method startFrame (line 272) | def startFrame(self, checkBox):
method endFrame (line 279) | def endFrame(self, checkBox):
method changeFolder (line 286) | def changeFolder(self, button):
method linkLineChanged (line 304) | def linkLineChanged(self, lineEdit):
method changeName (line 342) | def changeName(self, checkBoxes):
method queueChanged (line 348) | def queueChanged(self, combo):
method getProxyInformation (line 363) | def getProxyInformation(self):
method getUserPass (line 403) | def getUserPass(self):
method getAdditionalInformation (line 418) | def getAdditionalInformation(self):
method okButtonPressed (line 445) | def okButtonPressed(self, download_later, button=None):
method keyPressEvent (line 517) | def keyPressEvent(self, event):
method closeEvent (line 523) | def closeEvent(self, event):
method changeIcon (line 529) | def changeIcon(self, icons):
FILE: persepolis/scripts/after_download.py
class AfterDownloadWindow (line 30) | class AfterDownloadWindow(AfterDownloadWindow_Ui):
method __init__ (line 31) | def __init__(self, parent, dict, persepolis_setting):
method openFile (line 100) | def openFile(self):
method openFolder (line 110) | def openFolder(self):
method okButtonPressed (line 128) | def okButtonPressed(self):
method keyPressEvent (line 137) | def keyPressEvent(self, event):
method closeEvent (line 141) | def closeEvent(self, event):
method changeIcon (line 150) | def changeIcon(self, icons):
FILE: persepolis/scripts/browser_integration.py
function removeRegistryKey (line 34) | def removeRegistryKey(browser):
function installIntermidiary (line 73) | def installIntermidiary(intermediary):
function uninstallNativeMessageHost (line 115) | def uninstallNativeMessageHost(browser, native_message_folder):
function installNativeMessageHost (line 131) | def installNativeMessageHost(browser, native_message_folder, webextensio...
function nativeMessageHostFile (line 199) | def nativeMessageHostFile(browser, intermediary):
function getIntermediaryPath (line 222) | def getIntermediaryPath():
function getNativeMessageFolder (line 234) | def getNativeMessageFolder(browser):
function browserIntegration (line 278) | def browserIntegration(browser):
function browserIsolation (line 288) | def browserIsolation(browser):
FILE: persepolis/scripts/browser_plugin_queue.py
class QueueSpiderThread (line 36) | class QueueSpiderThread(QThread):
method __init__ (line 39) | def __init__(self, dict_):
method run (line 43) | def run(self):
class BrowserPluginQueue (line 60) | class BrowserPluginQueue(TextQueue_Ui):
method __init__ (line 61) | def __init__(self, parent, list_of_links, callback, persepolis_setting):
method currentTabChanged (line 212) | def currentTabChanged(self, index):
method selectAll (line 249) | def selectAll(self, button):
method deselectAll (line 255) | def deselectAll(self, button):
method queueChanged (line 261) | def queueChanged(self, combo):
method proxyFrame (line 287) | def proxyFrame(self, checkBox):
method downloadFrame (line 294) | def downloadFrame(self, checkBox):
method changeFolder (line 301) | def changeFolder(self, button):
method getProxyInformation (line 315) | def getProxyInformation(self):
method getUserPass (line 355) | def getUserPass(self):
method okButtonPressed (line 370) | def okButtonPressed(self, button):
method keyPressEvent (line 456) | def keyPressEvent(self, event):
method closeEvent (line 460) | def closeEvent(self, event):
method changeIcon (line 467) | def changeIcon(self, icons):
FILE: persepolis/scripts/bubble.py
function checkNotificationSounds (line 57) | def checkNotificationSounds():
function createNotificationSounds (line 85) | def createNotificationSounds(main_window):
function getSoundPath (line 118) | def getSoundPath(name):
function notifySend (line 143) | def notifySend(message1, message2, time, sound, parent=None):
FILE: persepolis/scripts/check_proxy.py
function getProxy (line 26) | def getProxy():
FILE: persepolis/scripts/compatibility.py
function compatibility (line 52) | def compatibility():
FILE: persepolis/scripts/data_base.py
class TempDB (line 33) | class TempDB():
method __init__ (line 34) | def __init__(self):
method lockCursor (line 48) | def lockCursor(self):
method createTables (line 57) | def createTables(self):
method insertInSingleTable (line 77) | def insertInSingleTable(self, gid):
method insertInQueueTable (line 90) | def insertInQueueTable(self, category):
method updateSingleTable (line 102) | def updateSingleTable(self, dict_):
method updateQueueTable (line 126) | def updateQueueTable(self, dict_):
method returnActiveGids (line 147) | def returnActiveGids(self):
method returnGid (line 165) | def returnGid(self, gid):
method returnCategory (line 183) | def returnCategory(self, category):
method resetDataBase (line 198) | def resetDataBase(self):
method closeConnections (line 211) | def closeConnections(self):
class PluginsDB (line 221) | class PluginsDB():
method __init__ (line 222) | def __init__(self):
method lockCursor (line 237) | def lockCursor(self):
method createTables (line 246) | def createTables(self):
method insertInPluginsTable (line 266) | def insertInPluginsTable(self, list_):
method returnNewLinks (line 287) | def returnNewLinks(self):
method deleteOldLinks (line 328) | def deleteOldLinks(self):
method closeConnections (line 340) | def closeConnections(self):
class PersepolisDB (line 353) | class PersepolisDB():
method __init__ (line 354) | def __init__(self):
method lockCursor (line 372) | def lockCursor(self):
method createTables (line 381) | def createTables(self):
method insertInCategoryTable (line 532) | def insertInCategoryTable(self, dict_):
method insertInDownloadTable (line 555) | def insertInDownloadTable(self, list_):
method insertInAddLinkTable (line 611) | def insertInAddLinkTable(self, list_):
method insertInVideoFinderTable (line 644) | def insertInVideoFinderTable(self, list_):
method searchGidInVideoFinderTable (line 664) | def searchGidInVideoFinderTable(self, gid):
method insertInVideoFinderTable2 (line 691) | def insertInVideoFinderTable2(self, list_):
method searchGidInVideoFinderTable2 (line 711) | def searchGidInVideoFinderTable2(self, gid):
method searchGidInDownloadTable (line 742) | def searchGidInDownloadTable(self, gid):
method returnItemsInDownloadTable (line 777) | def returnItemsInDownloadTable(self, category=None):
method searchLinkInAddLinkTable (line 818) | def searchLinkInAddLinkTable(self, link):
method searchGidInAddLinkTable (line 835) | def searchGidInAddLinkTable(self, gid):
method returnItemsInAddLinkTable (line 877) | def returnItemsInAddLinkTable(self, category=None):
method updateDownloadTable (line 924) | def updateDownloadTable(self, list_):
method updateCategoryTable (line 972) | def updateCategoryTable(self, list_):
method updateAddLinkTable (line 1018) | def updateAddLinkTable(self, list_):
method updateVideoFinderTable (line 1062) | def updateVideoFinderTable(self, list_):
method updateVideoFinderTable2 (line 1104) | def updateVideoFinderTable2(self, dict_):
method setDefaultGidInAddlinkTable (line 1137) | def setDefaultGidInAddlinkTable(self, gid, start_time=False, end_time=...
method searchCategoryInCategoryTable (line 1159) | def searchCategoryInCategoryTable(self, category):
method categoriesList (line 1195) | def categoriesList(self):
method setDBTablesToDefaultValue (line 1214) | def setDBTablesToDefaultValue(self):
method findActiveDownloads (line 1242) | def findActiveDownloads(self, category=None):
method returnDownloadingItems (line 1267) | def returnDownloadingItems(self):
method returnPausedItems (line 1288) | def returnPausedItems(self):
method returnVideoFinderGids (line 1308) | def returnVideoFinderGids(self):
method deleteCategory (line 1335) | def deleteCategory(self, category):
method resetDataBase (line 1366) | def resetDataBase(self):
method deleteItemInDownloadTable (line 1390) | def deleteItemInDownloadTable(self, gid, category):
method correctDataBase (line 1434) | def correctDataBase(self):
method correctDataBaseForVersion410 (line 1455) | def correctDataBaseForVersion410(self):
method correctDataBaseForVersion411 (line 1481) | def correctDataBaseForVersion411(self):
method closeConnections (line 1543) | def closeConnections(self):
FILE: persepolis/scripts/download_link.py
class DownloadLink (line 27) | class DownloadLink(QThread):
method __init__ (line 28) | def __init__(self, gid, download_session, main_window):
method run (line 34) | def run(self):
class DownloadSingleLink (line 48) | class DownloadSingleLink(QThread):
method __init__ (line 51) | def __init__(self, download_link, file_path):
method run (line 56) | def run(self):
FILE: persepolis/scripts/error_window.py
class ErrorWindow (line 30) | class ErrorWindow(QWidget):
method __init__ (line 31) | def __init__(self, text):
method reportPushButtonPressed (line 71) | def reportPushButtonPressed(self, button):
method keyPressEvent (line 75) | def keyPressEvent(self, event):
method closePushButtonPressed (line 79) | def closePushButtonPressed(self, button):
method resetPushButtonPressed (line 82) | def resetPushButtonPressed(self, button):
FILE: persepolis/scripts/log_window.py
class LogWindow (line 33) | class LogWindow(LogWindow_Ui):
method __init__ (line 35) | def __init__(self, persepolis_setting):
method clearLogPushButtonPressed (line 97) | def clearLogPushButtonPressed(self, button):
method reportPushButtonPressed (line 108) | def reportPushButtonPressed(self, button):
method closePushButtonPressed (line 111) | def closePushButtonPressed(self, button):
method copyAvailableSignalHandler (line 114) | def copyAvailableSignalHandler(self, signal):
method copyPushButtonPressed (line 120) | def copyPushButtonPressed(self, button):
method refreshLogPushButtonPressed (line 129) | def refreshLogPushButtonPressed(self, button):
method keyPressEvent (line 145) | def keyPressEvent(self, event):
method closeEvent (line 149) | def closeEvent(self, event):
method changeIcon (line 159) | def changeIcon(self, icons):
FILE: persepolis/scripts/logger.py
function setUpLogger (line 22) | def setUpLogger(logger_name, log_file, level):
function sendToLog (line 65) | def sendToLog(text="", type="INFO"):
FILE: persepolis/scripts/mainwindow.py
class DeleteThingsThatAreNoLongerNeededThread (line 129) | class DeleteThingsThatAreNoLongerNeededThread(QThread):
method __init__ (line 132) | def __init__(self, gid, file_name, status, category, delete_download_f...
method run (line 142) | def run(self):
class InitializationThread (line 185) | class InitializationThread(QThread):
method __init__ (line 187) | def __init__(self, parent):
method run (line 191) | def run(self):
class CheckClipBoardThread (line 233) | class CheckClipBoardThread(QThread):
method __init__ (line 237) | def __init__(self, parent):
method run (line 240) | def run(self):
class CheckClipboardStateThread (line 258) | class CheckClipboardStateThread(QThread):
method __init__ (line 262) | def __init__(self):
method run (line 265) | def run(self):
class CheckNewerVersionThread (line 273) | class CheckNewerVersionThread(QThread):
method __init__ (line 277) | def __init__(self, parent):
method run (line 283) | def run(self):
class CheckSelectedRowThread (line 305) | class CheckSelectedRowThread(QThread):
method __init__ (line 308) | def __init__(self):
method run (line 311) | def run(self):
class CheckDownloadInfoThread (line 318) | class CheckDownloadInfoThread(QThread):
method __init__ (line 321) | def __init__(self, parent):
method run (line 325) | def run(self):
class SpiderThread (line 392) | class SpiderThread(QThread):
method __init__ (line 395) | def __init__(self, add_link_dictionary, parent):
method run (line 400) | def run(self):
class CheckingThread (line 422) | class CheckingThread(QThread):
method __init__ (line 426) | def __init__(self):
method run (line 429) | def run(self):
class WaitThread (line 465) | class WaitThread(QThread):
method __init__ (line 468) | def __init__(self):
method run (line 471) | def run(self):
class ButtonPressedThread (line 483) | class ButtonPressedThread(QThread):
method __init__ (line 484) | def __init__(self):
method run (line 487) | def run(self):
class ShutDownThread (line 497) | class ShutDownThread(QThread):
method __init__ (line 498) | def __init__(self, parent, category, password=None):
method run (line 505) | def run(self):
class KeepAwakeThread (line 513) | class KeepAwakeThread(QThread):
method __init__ (line 517) | def __init__(self):
method run (line 520) | def run(self):
class MoveThread (line 554) | class MoveThread(QThread):
method __init__ (line 557) | def __init__(self, parent, gid_list, new_folder_path):
method run (line 563) | def run(self):
class MainWindow (line 598) | class MainWindow(MainWindow_Ui):
method __init__ (line 599) | def __init__(self, start_in_tray, persepolis_main, persepolis_setting):
method changeShutdownValue (line 1032) | def changeShutdownValue(self, value):
method returnShutDownValue (line 1037) | def returnShutDownValue(self):
method notifySendFromThread (line 1045) | def notifySendFromThread(self, signal_list):
method keepAwake (line 1049) | def keepAwake(self, add):
method newVersionIsAvailable (line 1065) | def newVersionIsAvailable(self, message):
method keepAwakeCheckBoxToggled (line 1076) | def keepAwakeCheckBoxToggled(self, checkbox):
method checkDownloadInfo (line 1091) | def checkDownloadInfo(self, list):
method dragEnterEvent (line 1552) | def dragEnterEvent(self, droplink):
method dropEvent (line 1561) | def dropEvent(self, droplink):
method gidGenerator (line 1575) | def gidGenerator(self):
method userSelectedRows (line 1595) | def userSelectedRows(self):
method selectedRow (line 1612) | def selectedRow(self):
method checkSelectedRow (line 1620) | def checkSelectedRow(self):
method checkVideoFinderSupportedSites (line 1900) | def checkVideoFinderSupportedSites(self, link):
method checkPluginCall (line 1920) | def checkPluginCall(self):
method pluginAddLink (line 1977) | def pluginAddLink(self, add_link_dictionary):
method addLinkButtonPressed (line 1988) | def addLinkButtonPressed(self, button=None):
method callBack (line 1994) | def callBack(self, add_link_dictionary, download_later, category, sing...
method resumeButtonPressed (line 2185) | def resumeButtonPressed(self, button=None):
method stopButtonPressed (line 2300) | def stopButtonPressed(self, button=None):
method pauseButtonPressed (line 2349) | def pauseButtonPressed(self, button=None):
method propertiesButtonPressed (line 2379) | def propertiesButtonPressed(self, button=None):
method propertiesCallback (line 2418) | def propertiesCallback(self, add_link_dictionary, gid, category,
method propertiesCallback2 (line 2435) | def propertiesCallback2(self, add_link_dictionary, gid, category,
method progressButtonPressed (line 2463) | def progressButtonPressed(self, button=None):
method progressBarOpen (line 2493) | def progressBarOpen(self, gid):
method keyPressEvent (line 2540) | def keyPressEvent(self, event):
method cleanTempFolder (line 2544) | def cleanTempFolder(self):
method closeEvent (line 2552) | def closeEvent(self, event=None):
method closeAction (line 2566) | def closeAction(self, event=None):
method showTray (line 2639) | def showTray(self, menu=None):
method showMenuBar (line 2664) | def showMenuBar(self, menu=None):
method showSidePanel (line 2690) | def showSidePanel(self, menu=None):
method systemTrayPressed (line 2706) | def systemTrayPressed(self, click):
method minMaxTray (line 2711) | def minMaxTray(self, menu=None):
method showMainWindow (line 2724) | def showMainWindow(self):
method stopAllDownloads (line 2730) | def stopAllDownloads(self, menu=None):
method openPreferences (line 2750) | def openPreferences(self, menu=None):
method openAbout (line 2759) | def openAbout(self, menu=None):
method openDefaultDownloadFolder (line 2766) | def openDefaultDownloadFolder(self, menu=None):
method openDownloadFolder (line 2781) | def openDownloadFolder(self, menu=None):
method openFile (line 2822) | def openFile(self, menu=None):
method selectDownloads (line 2863) | def selectDownloads(self):
method removeSelected (line 2885) | def removeSelected(self, menu=None):
method removeSelected2 (line 2898) | def removeSelected2(self):
method deleteSelected (line 3020) | def deleteSelected(self, menu=None):
method deleteSelected2 (line 3059) | def deleteSelected2(self):
method sortByName (line 3180) | def sortByName(self, menu=None):
method sortByName2 (line 3193) | def sortByName2(self):
method sortBySize (line 3264) | def sortBySize(self, menu=None):
method sortBySize2 (line 3277) | def sortBySize2(self):
method sortByStatus (line 3368) | def sortByStatus(self, menu=None):
method sortByStatus2 (line 3381) | def sortByStatus2(self):
method sortByFirstTry (line 3468) | def sortByFirstTry(self, menu=None):
method sortByFirstTry2 (line 3481) | def sortByFirstTry2(self):
method sortByLastTry (line 3568) | def sortByLastTry(self, menu=None):
method sortByLastTry2 (line 3580) | def sortByLastTry2(self):
method createQueue (line 3671) | def createQueue(self, menu=None):
method pluginQueue (line 3733) | def pluginQueue(self, list_of_links):
method importText (line 3747) | def importText(self, menu=None):
method importLinksFromClipboard (line 3764) | def importLinksFromClipboard(self, menu=None):
method importLinksFromClipboard2 (line 3775) | def importLinksFromClipboard2(self):
method queueCallback (line 3814) | def queueCallback(self, add_link_dictionary_list, category):
method categoryTreeSelected (line 3935) | def categoryTreeSelected(self, item):
method categoryTreeSelected2 (line 3951) | def categoryTreeSelected2(self, new_selection):
method toolBarAndContextMenuItems (line 4059) | def toolBarAndContextMenuItems(self, category):
method removeQueue (line 4221) | def removeQueue(self, menu=None):
method startQueue (line 4277) | def startQueue(self, menu=None):
method stopQueue (line 4335) | def stopQueue(self, menu=None):
method addToQueue (line 4350) | def addToQueue(self, data, menu=None):
method addToQueue2 (line 4363) | def addToQueue2(self, data):
method startFrame (line 4484) | def startFrame(self, checkBox):
method endFrame (line 4492) | def endFrame(self, checkBox):
method showQueuePanelOptions (line 4502) | def showQueuePanelOptions(self, button):
method limitDialIsReleased (line 4512) | def limitDialIsReleased(self):
method limitDialIsChanged (line 4519) | def limitDialIsChanged(self, button):
method afterPushButtonPressed (line 4528) | def afterPushButtonPressed(self, button):
method afterFrame (line 4599) | def afterFrame(self, checkBox):
method queuePanelWidget (line 4625) | def queuePanelWidget(self, category):
method reportIssue (line 4691) | def reportIssue(self, menu=None):
method persepolisHelp (line 4695) | def persepolisHelp(self, menu=None):
method showLog (line 4700) | def showLog(self, menu=None):
method moveUpSelected (line 4708) | def moveUpSelected(self, menu=None):
method moveUpSelected2 (line 4729) | def moveUpSelected2(self):
method moveDownSelected (line 4799) | def moveDownSelected(self, menu=None):
method moveDownSelected2 (line 4819) | def moveDownSelected2(self):
method moveSelectedDownloads (line 4896) | def moveSelectedDownloads(self, menu=None):
method queueSpiderCallBack (line 4955) | def queueSpiderCallBack(self, filename, child, row_number):
method addLinkSpiderCallBack (line 4968) | def addLinkSpiderCallBack(self, spider_dict, child):
method spiderUpdate (line 4985) | def spiderUpdate(self, dict):
method clearDownloadList (line 5018) | def clearDownloadList(self, item):
method clearDownloadList2 (line 5031) | def clearDownloadList2(self):
method showVideoFinderAddLinkWindow (line 5059) | def showVideoFinderAddLinkWindow(self, input_dict=None, menu=None):
method videoFinderCallBack (line 5090) | def videoFinderCallBack(self, add_link_dictionary_list, download_later...
method videoFinderCompleted (line 5259) | def videoFinderCompleted(self, complete_dictionary):
method videoFinderCompleted2 (line 5272) | def videoFinderCompleted2(self, complete_dictionary):
method muxingPushButtonPressed (line 5409) | def muxingPushButtonPressed(self, button):
method changeIcon (line 5445) | def changeIcon(self, new_icons):
FILE: persepolis/scripts/newopen.py
function writeList (line 20) | def writeList(file_path, list):
function readList (line 29) | def readList(file_path, mode='dictionary'):
function readDict (line 45) | def readDict(file_path):
FILE: persepolis/scripts/osCommands.py
function findFileManager (line 28) | def findFileManager():
function touch (line 38) | def touch(file_path):
function xdgOpen (line 46) | def xdgOpen(file_path, f_type='file', path='file'):
function remove (line 204) | def remove(file_path):
function removeDir (line 221) | def removeDir(folder_path):
function makeDirs (line 239) | def makeDirs(folder_path, hidden=False):
function findMountPoint (line 272) | def findMountPoint(path):
function moveFile (line 281) | def moveFile(old_file_path, new_path, new_path_type='folder'):
function copyFile (line 318) | def copyFile(old_path, new_path):
FILE: persepolis/scripts/persepolis.py
class PersepolisApplication (line 117) | class PersepolisApplication(QtWidgets.QApplication):
method __init__ (line 118) | def __init__(self, argv):
method setPersepolisStyle (line 122) | def setPersepolisStyle(self, style):
method setPersepolisFont (line 127) | def setPersepolisFont(self, font, font_size, custom_font):
method setPersepolisColorScheme (line 135) | def setPersepolisColorScheme(self, color_scheme):
function main (line 356) | def main():
FILE: persepolis/scripts/persepolis_lib_prime.py
class Download (line 32) | class Download():
method __init__ (line 33) | def __init__(self, add_link_dictionary, main_window, gid):
method createSession (line 95) | def createSession(self):
method setRetry (line 149) | def setRetry(self):
method getFileSize (line 164) | def getFileSize(self):
method getFileName (line 200) | def getFileName(self):
method getFileTag (line 225) | def getFileTag(self):
method resumingSupport (line 232) | def resumingSupport(self):
method createControlFile (line 243) | def createControlFile(self):
method definePartSizes (line 444) | def definePartSizes(self):
method downloadSpeed (line 513) | def downloadSpeed(self):
method runProgressBar (line 541) | def runProgressBar(self):
method askForNewPart (line 550) | def askForNewPart(self):
method threadHandler (line 576) | def threadHandler(self, thread_number):
method saveInfo (line 829) | def saveInfo(self):
method runDownloadThreads (line 844) | def runDownloadThreads(self):
method checkDownloadProgress (line 872) | def checkDownloadProgress(self):
method nowDate (line 924) | def nowDate(self):
method sigmaTime (line 928) | def sigmaTime(self, time):
method nowTime (line 933) | def nowTime(self):
method startTime (line 938) | def startTime(self):
method endTime (line 954) | def endTime(self):
method runEndTimeThread (line 978) | def runEndTimeThread(self):
method start (line 986) | def start(self):
method downloadPause (line 1059) | def downloadPause(self):
method downloadUnpause (line 1062) | def downloadUnpause(self):
method downloadStop (line 1065) | def downloadStop(self):
method close (line 1069) | def close(self):
method tellStatus (line 1119) | def tellStatus(self):
method limitSpeed (line 1148) | def limitSpeed(self, limit_value):
method downloadCompleteAction (line 1155) | def downloadCompleteAction(self, new_download_path):
method findDownloadPath (line 1172) | def findDownloadPath(self, file_name, download_path, subfolder):
FILE: persepolis/scripts/play.py
function playNotification (line 34) | def playNotification(file):
FILE: persepolis/scripts/progress.py
class ShutDownThread (line 35) | class ShutDownThread(QThread):
method __init__ (line 36) | def __init__(self, parent, gid, password=None):
method run (line 42) | def run(self):
class ProgressWindow (line 46) | class ProgressWindow(ProgressWindow_Ui):
method __init__ (line 47) | def __init__(self, parent, gid, persepolis_setting, single_video_link=...
method keyPressEvent (line 95) | def keyPressEvent(self, event):
method closeEvent (line 99) | def closeEvent(self, event):
method resumePushButtonPressed (line 107) | def resumePushButtonPressed(self, button):
method pausePushButtonPressed (line 117) | def pausePushButtonPressed(self, button):
method stopPushButtonPressed (line 127) | def stopPushButtonPressed(self, button):
method afterComboBoxChanged (line 142) | def afterComboBoxChanged(self, connect):
method afterCheckBoxToggled (line 145) | def afterCheckBoxToggled(self, checkBoxes):
method afterPushButtonPressed (line 159) | def afterPushButtonPressed(self, button):
method limitDialIsReleased (line 226) | def limitDialIsReleased(self):
method limitDialIsChanged (line 236) | def limitDialIsChanged(self, button):
method changeIcon (line 244) | def changeIcon(self, icons):
FILE: persepolis/scripts/properties.py
class PropertiesWindow (line 31) | class PropertiesWindow(AddLinkWindow_Ui):
method __init__ (line 32) | def __init__(self, parent, callback, gid, persepolis_setting, video_fi...
method detectProxy (line 249) | def detectProxy(self, button):
method proxyFrame (line 275) | def proxyFrame(self, checkBox):
method downloadFrame (line 282) | def downloadFrame(self, checkBox):
method startFrame (line 289) | def startFrame(self, checkBox):
method endFrame (line 296) | def endFrame(self, checkBox):
method changeFolder (line 303) | def changeFolder(self, button):
method linkLineChanged (line 315) | def linkLineChanged(self, lineEdit):
method queueChanged (line 321) | def queueChanged(self, combo):
method getProxyInformation (line 335) | def getProxyInformation(self):
method getUserPass (line 375) | def getUserPass(self):
method getAdditionalInformation (line 390) | def getAdditionalInformation(self):
method okButtonPressed (line 417) | def okButtonPressed(self, button):
method keyPressEvent (line 570) | def keyPressEvent(self, event):
method closeEvent (line 574) | def closeEvent(self, event):
method changeIcon (line 583) | def changeIcon(self, icons):
FILE: persepolis/scripts/queue.py
class Queue (line 37) | class Queue(QThread):
method __init__ (line 42) | def __init__(self, category, start_time, end_time, parent):
method run (line 49) | def run(self):
FILE: persepolis/scripts/queue_prime.py
class Queue (line 36) | class Queue():
method __init__ (line 37) | def __init__(self, queue_dict, main_window):
method start (line 50) | def start(self):...
FILE: persepolis/scripts/setting.py
class KeyCapturingWindow (line 39) | class KeyCapturingWindow(KeyCapturingWindow_Ui):
method __init__ (line 40) | def __init__(self, callback, persepolis_setting):
method eventFilter (line 50) | def eventFilter(self, source, event):
method okPushButtonPressed (line 57) | def okPushButtonPressed(self, button):
method closeEvent (line 62) | def closeEvent(self, event):
class PreferencesWindow (line 66) | class PreferencesWindow(Setting_Ui):
method __init__ (line 67) | def __init__(self, parent, persepolis_setting):
method showCaptureKeyboardWindow (line 442) | def showCaptureKeyboardWindow(self):
method callBack (line 450) | def callBack(self, keys):
method styleComboBoxChanged (line 478) | def styleComboBoxChanged(self, index=None):
method setDarkLightIcon (line 521) | def setDarkLightIcon(self, index=None):
method fontCheckBoxState (line 602) | def fontCheckBoxState(self, checkBox):
method keyPressEvent (line 613) | def keyPressEvent(self, event):
method closeEvent (line 617) | def closeEvent(self, event):
method browserIntegrationSettings (line 629) | def browserIntegrationSettings(self):
method soundFrame (line 674) | def soundFrame(self, checkBox):
method downloadFolderPushButtonClicked (line 681) | def downloadFolderPushButtonClicked(self, button):
method dialChanged (line 697) | def dialChanged(self, dial):
method defaultsPushButtonPressed (line 701) | def defaultsPushButtonPressed(self, button):
method okPushButtonPressed (line 852) | def okPushButtonPressed(self, button):
FILE: persepolis/scripts/shutdown.py
function shutDown (line 25) | def shutDown(parent, gid=None, category=None, password=None):
FILE: persepolis/scripts/spider.py
function spider (line 39) | def spider(add_link_dictionary):
function queueSpider (line 158) | def queueSpider(add_link_dictionary):
function addLinkSpider (line 164) | def addLinkSpider(add_link_dictionary):
FILE: persepolis/scripts/startup.py
function checkStartUp (line 31) | def checkStartUp():
function addStartUp (line 71) | def addStartUp(parent):
function removeStartUp (line 148) | def removeStartUp():
FILE: persepolis/scripts/text_queue.py
class QueueSpiderThread (line 35) | class QueueSpiderThread(QThread):
method __init__ (line 38) | def __init__(self, dict_):
method run (line 42) | def run(self):
class TextQueue (line 59) | class TextQueue(TextQueue_Ui):
method __init__ (line 60) | def __init__(self, parent, file_path, callback, persepolis_setting):
method currentTabChanged (line 215) | def currentTabChanged(self, index):
method selectAll (line 250) | def selectAll(self, button):
method deselectAll (line 256) | def deselectAll(self, button):
method queueChanged (line 262) | def queueChanged(self, combo):
method proxyFrame (line 288) | def proxyFrame(self, checkBox):
method downloadFrame (line 295) | def downloadFrame(self, checkBox):
method changeFolder (line 302) | def changeFolder(self, button):
method getProxyInformation (line 318) | def getProxyInformation(self):
method getUserPass (line 358) | def getUserPass(self):
method okButtonPressed (line 373) | def okButtonPressed(self, button):
method keyPressEvent (line 452) | def keyPressEvent(self, event):
method closeEvent (line 456) | def closeEvent(self, event):
method changeIcon (line 463) | def changeIcon(self, icons):
FILE: persepolis/scripts/useful_tools.py
class RunApplicationThread (line 52) | class RunApplicationThread(QThread):
method __init__ (line 55) | def __init__(self, command_argument, call_back=False):
method run (line 60) | def run(self):
function determineConfigFolder (line 69) | def determineConfigFolder():
function osAndDesktopEnvironment (line 85) | def osAndDesktopEnvironment():
function humanReadableSize (line 102) | def humanReadableSize(size, input_type='file_size'):
function convertTime (line 122) | def convertTime(time):
function convertToByte (line 135) | def convertToByte(file_size):
function freeSpace (line 172) | def freeSpace(dir):
function returnDefaultSettings (line 194) | def returnDefaultSettings():
function muxer (line 266) | def muxer(parent, video_finder_dictionary):
function ffmpegVersion (line 368) | def ffmpegVersion():
function qRunApplication (line 402) | def qRunApplication(command: str, command_argument: list, parent=None):
function runApplication (line 411) | def runApplication(command_argument):
function findExternalAppPath (line 436) | def findExternalAppPath(app_name):
function getExecPath (line 515) | def getExecPath():
function nowDate (line 594) | def nowDate():
function fold (line 599) | def fold(header):
function dictToHeader (line 617) | def dictToHeader(data):
function headerToDict (line 622) | def headerToDict(headers):
function readCookieJar (line 633) | def readCookieJar(load_cookies):
function getFileNameFromLink (line 654) | def getFileNameFromLink(link):
function returnNewFileName (line 663) | def returnNewFileName(folder_path, file_name):
FILE: persepolis/scripts/video_finder.py
class VideoFinder (line 47) | class VideoFinder(QThread):
method __init__ (line 50) | def __init__(self, video_finder_dictionary, main_window):
method run (line 58) | def run(self):
FILE: persepolis/scripts/video_finder_addlink.py
class MediaListFetcherThread (line 63) | class MediaListFetcherThread(QThread):
method __init__ (line 69) | def __init__(self, receiver_slot, video_dict, main_window):
method run (line 151) | def run(self):
method makeHttpCookie (line 209) | def makeHttpCookie(self, raw_cookie, host_name='.youtube.com'):
class FileSizeFetcherThread (line 225) | class FileSizeFetcherThread(QThread):
method __init__ (line 228) | def __init__(self, dictionary, text, combobox_type, index):
method run (line 235) | def run(self):
class VideoFinderAddLink (line 243) | class VideoFinderAddLink(AddLinkWindow):
method __init__ (line 247) | def __init__(self, parent, receiver_slot, settings, video_dict={}):
method advancedFormatFrame (line 389) | def advancedFormatFrame(self, button):
method getReadableSize (line 401) | def getReadableSize(self, size):
method getReadableDuration (line 407) | def getReadableDuration(self, seconds):
method urlChanged (line 420) | def urlChanged(self, value):
method submitClicked (line 429) | def submitClicked(self, button=None):
method showThumbnail (line 466) | def showThumbnail(self, thumbnail_path):
method setLoadCookie (line 474) | def setLoadCookie(self, str):
method fileNameChanged (line 479) | def fileNameChanged(self, value):
method mediaSelectionChanged (line 483) | def mediaSelectionChanged(self, combobox, index):
method getFileExtension (line 532) | def getFileExtension(self, url):
method fetchedResult (line 537) | def fetchedResult(self, media_dict):
method findFileSize (line 724) | def findFileSize(self, result):
method linkLineChangedHere (line 740) | def linkLineChangedHere(self, lineEdit):
method closeEvent (line 746) | def closeEvent(self, event):
method collectMoreOptions (line 754) | def collectMoreOptions(self):
method okButtonPressed (line 797) | def okButtonPressed(self, download_later, button=None): # noqa
FILE: persepolis/scripts/video_finder_progress.py
class ShutDownThread (line 34) | class ShutDownThread(QThread):
method __init__ (line 35) | def __init__(self, parent, category, password=None):
method run (line 41) | def run(self):
class VideoFinderProgressWindow (line 45) | class VideoFinderProgressWindow(VideoFinderProgressWindow_Ui):
method __init__ (line 46) | def __init__(self, parent, gid_list, persepolis_setting):
method keyPressEvent (line 96) | def keyPressEvent(self, event):
method closeEvent (line 100) | def closeEvent(self, event):
method resumePushButtonPressed (line 109) | def resumePushButtonPressed(self, button):
method pausePushButtonPressed (line 118) | def pausePushButtonPressed(self, button):
method stopPushButtonPressed (line 128) | def stopPushButtonPressed(self, button):
method afterComboBoxChanged (line 144) | def afterComboBoxChanged(self, connect):
method afterCheckBoxToggled (line 148) | def afterCheckBoxToggled(self, checkBoxes):
method afterPushButtonPressed (line 164) | def afterPushButtonPressed(self, button):
method limitDialIsReleased (line 237) | def limitDialIsReleased(self):
method limitDialIsChanged (line 247) | def limitDialIsChanged(self, button):
method changeIcon (line 255) | def changeIcon(self, icons):
FILE: persepolis/scripts/ytdlp_downloader.py
class Ytdp_Logger (line 30) | class Ytdp_Logger():
method debug (line 31) | def debug(self, msg):
method info (line 40) | def info(self, msg):
method warning (line 43) | def warning(self, msg):
method error (line 46) | def error(self, msg):
class Ytdp_Download (line 51) | class Ytdp_Download():
method __init__ (line 52) | def __init__(self, add_link_dictionary, main_window, gid, single_video...
method getFileName (line 119) | def getFileName(self):
method createSession (line 134) | def createSession(self):
method nowDate (line 194) | def nowDate(self):
method sigmaTime (line 198) | def sigmaTime(self, time):
method nowTime (line 203) | def nowTime(self):
method startTime (line 208) | def startTime(self):
method endTime (line 224) | def endTime(self):
method runEndTimeThread (line 249) | def runEndTimeThread(self):
method getStatus (line 256) | def getStatus(self, data):
method tellStatus (line 327) | def tellStatus(self):
method checkDownloadProgress (line 379) | def checkDownloadProgress(self):
method download (line 399) | def download(self):
method start (line 415) | def start(self):
method close (line 474) | def close(self):
method downloadCompleteAction (line 518) | def downloadCompleteAction(self, new_download_path):
method downloadPause (line 537) | def downloadPause(self):
method downloadUnpause (line 540) | def downloadUnpause(self):
method downloadStop (line 543) | def downloadStop(self):
method limitSpeed (line 553) | def limitSpeed(self, limit_value):
FILE: resources/PersepolisBI.py
class PluginsDB (line 56) | class PluginsDB():
method __init__ (line 57) | def __init__(self):
method lockCursor (line 72) | def lockCursor(self):
method insertInPluginsTable (line 82) | def insertInPluginsTable(self, list_):
method closeConnections (line 103) | def closeConnections(self):
function sendToLog (line 142) | def sendToLog(text="", type="INFO"):
function findExternalAppPath (line 153) | def findExternalAppPath(app_name):
Condensed preview — 124 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,351K chars).
[
{
"path": ".github/ISSUE_TEMPLATE",
"chars": 574,
"preview": "**System Details:**\n* Operating System: ?\n* Distro(For GNU/Linux and BSD users): ?\n* Desktop Environment(For GNU/Linux a"
},
{
"path": ".github/contributing.md",
"chars": 120,
"preview": "Please read our [contribution instruction](https://github.com/persepolisdm/persepolis/wiki/Home-en#contributers-guide).\n"
},
{
"path": ".gitignore",
"chars": 317,
"preview": "__pycache__/\n*.pyc\n.env\n*.orig\nroot/\nbuild/\nbuilddir/\npersepolis.egg-info/\nman/persepolis.1.gz\n.idea/\n.mypy_cache\npersep"
},
{
"path": ".pep8",
"chars": 60,
"preview": "[pycodestyle]\nmax_line_length = 120\nignore = E501,E722,W503\n"
},
{
"path": ".travis.yml",
"chars": 821,
"preview": "language: python\ndist: bionic\nsudo: required\npython:\n - \"3.6\"\nvirtualenv:\n system_site_packages: true\n\naddons:\n apt:\n"
},
{
"path": ".tx/config",
"chars": 198,
"preview": "[main]\nhost = https://www.transifex.com\n\n[persepolis-translations.ui]\nfile_filter = resources/locales/ui_<lang>.ts\nminim"
},
{
"path": "LICENSE",
"chars": 35141,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
},
{
"path": "README.md",
"chars": 5507,
"preview": "<p align=\"center\">\n <img src=\"https://persepolisdm.github.io/img/screen/persepolisـreadme.png\" width=\"128px\"/>\n</p>\n<h1"
},
{
"path": "check_dependencies.py",
"chars": 3361,
"preview": "#!/usr/bin/env python3\n# coding: utf-8\n# This program is free software: you can redistribute it and/or modify\n# it"
},
{
"path": "clear.py",
"chars": 2763,
"preview": "#!/usr/bin/env python3\n# coding: utf-8\n# This program is free software: you can redistribute it and/or modify\n# it"
},
{
"path": "man/meson.build",
"chars": 97,
"preview": "# creating man page file\npersepolis_man_page='persepolis.1'\n\ninstall_man(persepolis_man_page)\n\n\n\n"
},
{
"path": "man/persepolis.1",
"chars": 2772,
"preview": ".TH \"Persepolis\" \"1\" \"July 14, 2025\" \"5.2.0\" \"persepolis\"\n.SH NAME\npersepolis \\- Persepolis Download Manager\n.\n.nr rst2m"
},
{
"path": "meson.build",
"chars": 901,
"preview": "project('persepolis',\n version: '5.2.0', \n meson_version: '>=0.61.2')\n\npython = import('python')\npython3 = python.find"
},
{
"path": "persepolis/.pep8",
"chars": 36,
"preview": "[pycodestyle]\nmax_line_length = 120\n"
},
{
"path": "persepolis/Persepolis Download Manager.py",
"chars": 818,
"preview": "# -*- coding: utf-8 -*-\n\n\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "persepolis/__init__.py",
"chars": 731,
"preview": "# -*- coding: utf-8 -*-\n\n\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "persepolis/__main__.py",
"chars": 753,
"preview": "# -*- coding: utf-8 -*-\n\n\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "persepolis/constants/Browser.py",
"chars": 1037,
"preview": "# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it under the term"
},
{
"path": "persepolis/constants/Os.py",
"chars": 958,
"preview": "# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it under the term"
},
{
"path": "persepolis/constants/Version.py",
"chars": 732,
"preview": "# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it under the term"
},
{
"path": "persepolis/constants/__init__.py",
"chars": 809,
"preview": "# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it under the term"
},
{
"path": "persepolis/gui/.pep8",
"chars": 36,
"preview": "[pycodestyle]\nmax_line_length = 120\n"
},
{
"path": "persepolis/gui/__init__.py",
"chars": 731,
"preview": "# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it under the term"
},
{
"path": "persepolis/gui/about_ui.py",
"chars": 14933,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\n This program is free software: you can redistribute it and/or modify\n it under the te"
},
{
"path": "persepolis/gui/addlink_ui.py",
"chars": 19889,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\n This program is free software: you can redistribute it and/or modify\n it under the te"
},
{
"path": "persepolis/gui/after_download_ui.py",
"chars": 5064,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/gui/customized_widgets.py",
"chars": 1328,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\n This program is free software: you can redistribute it and/or modify\n it under the te"
},
{
"path": "persepolis/gui/log_window_ui.py",
"chars": 5994,
"preview": "# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it under the term"
},
{
"path": "persepolis/gui/mainwindow_ui.py",
"chars": 36613,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/gui/progress_ui.py",
"chars": 10764,
"preview": "\n# -*- coding: utf-8 -*-\n\n\n# This program is free software: you can redistribute it and/or modify\n# it under the t"
},
{
"path": "persepolis/gui/resources.py",
"chars": 1065596,
"preview": "# Resource object code (Python 3)\n# Created by: object code\n# Created by: The Resource Compiler for Qt version 6.9.1\n# W"
},
{
"path": "persepolis/gui/setting_ui.py",
"chars": 32529,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/gui/text_queue_ui.py",
"chars": 13780,
"preview": "# -*- coding: utf-8 -*-\n\n\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "persepolis/gui/video_finder_progress_ui.py",
"chars": 2742,
"preview": "# -*- coding: utf-8 -*-\n\n\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "persepolis/meson.build",
"chars": 2157,
"preview": "shell_sources = [\n '__init__.py',\n '__main__.py'\n ]\nconstants_sources = [\n 'constants/Browser.py',\n 'constants/__in"
},
{
"path": "persepolis/persepolis.py",
"chars": 982,
"preview": "#!@PYTHON@\n\n\n# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it u"
},
{
"path": "persepolis/scripts/.pep8",
"chars": 36,
"preview": "[pycodestyle]\nmax_line_length = 120\n"
},
{
"path": "persepolis/scripts/__init__.py",
"chars": 702,
"preview": "\"\"\"\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General P"
},
{
"path": "persepolis/scripts/about.py",
"chars": 2315,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\n This program is free software: you can redistribute it and/or modify\n it under the te"
},
{
"path": "persepolis/scripts/addlink.py",
"chars": 20378,
"preview": "# -*- coding: utf-8 -*-\n\n\"\"\"\n This program is free software: you can redistribute it and/or modify\n it under the t"
},
{
"path": "persepolis/scripts/after_download.py",
"chars": 5343,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/browser_integration.py",
"chars": 12483,
"preview": "# -*- coding: utf-8 -*-\r\n# This program is free software: you can redistribute it and/or modify\r\n# it under the te"
},
{
"path": "persepolis/scripts/browser_plugin_queue.py",
"chars": 17054,
"preview": "# -*- coding: utf-8 -*-\n\n\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "persepolis/scripts/bubble.py",
"chars": 6767,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/check_proxy.py",
"chars": 9884,
"preview": "# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it under the term"
},
{
"path": "persepolis/scripts/compatibility.py",
"chars": 6625,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/data_base.py",
"chars": 68511,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\n This program is free software: you can redistribute it and/or modify\n it under the te"
},
{
"path": "persepolis/scripts/download_link.py",
"chars": 2569,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\n This program is free software: you can redistribute it and/or modify\n it under the te"
},
{
"path": "persepolis/scripts/error_window.py",
"chars": 3907,
"preview": "# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it under the term"
},
{
"path": "persepolis/scripts/initialization.py",
"chars": 10701,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/log_window.py",
"chars": 5896,
"preview": "# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it under the term"
},
{
"path": "persepolis/scripts/logger.py",
"chars": 2604,
"preview": "# -*- coding: utf-8 -*-\n# This program is free software: you can redistribute it and/or modify\n# it under the term"
},
{
"path": "persepolis/scripts/mainwindow.py",
"chars": 227997,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/newopen.py",
"chars": 1563,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/osCommands.py",
"chars": 10592,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/persepolis.py",
"chars": 18701,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/persepolis_lib_prime.py",
"chars": 55846,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/play.py",
"chars": 2427,
"preview": "\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Pu"
},
{
"path": "persepolis/scripts/progress.py",
"chars": 9889,
"preview": "\n# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "persepolis/scripts/properties.py",
"chars": 23517,
"preview": "# -*- coding: utf-8 -*-\n\n\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "persepolis/scripts/queue.py",
"chars": 17919,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/queue_prime.py",
"chars": 2022,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/setting.py",
"chars": 48707,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/shutdown.py",
"chars": 4155,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/spider.py",
"chars": 5917,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/startup.py",
"chars": 5846,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/text_queue.py",
"chars": 16782,
"preview": "# -*- coding: utf-8 -*-\n\n\n# This program is free software: you can redistribute it and/or modify\n# it under the te"
},
{
"path": "persepolis/scripts/useful_tools.py",
"chars": 23959,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/video_finder.py",
"chars": 11296,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\n This program is free software: you can redistribute it and/or modify\n it under the te"
},
{
"path": "persepolis/scripts/video_finder_addlink.py",
"chars": 44705,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\n This program is free software: you can redistribute it and/or modify\n it under the te"
},
{
"path": "persepolis/scripts/video_finder_progress.py",
"chars": 10257,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "persepolis/scripts/ytdlp_downloader.py",
"chars": 22821,
"preview": "# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modify\n# it under the ter"
},
{
"path": "requirements.md",
"chars": 158,
"preview": "## You can find requirements and installation instructions in [Persepolis Wiki](https://github.com/persepolisdm/persepol"
},
{
"path": "requirements.txt",
"chars": 69,
"preview": "PySide6_Essentials;\nrequests;\nurllib3;\nsetproctitle;\npsutil;\nyt-dlp;\n"
},
{
"path": "resources/PersepolisBI.py",
"chars": 11005,
"preview": "# -*- coding: utf-8 -*-\r\n# This program is free software: you can redistribute it and/or modify\r\n# it under the te"
},
{
"path": "resources/dark_style.qss",
"chars": 63706,
"preview": "/*\n * BreezeDark stylesheet.\n *\n * :author: Colin Duquesnoy\n * :editor: Alex Huszagh\n * :license: MIT, see LICENSE.m"
},
{
"path": "resources/light_style.qss",
"chars": 64608,
"preview": "/*\n * BreezeDark stylesheet.\n *\n * :author: Colin Duquesnoy\n * :editor: Alex Huszagh\n * :license: MIT, see LICENSE.m"
},
{
"path": "resources/locales/ui.qm",
"chars": 7,
"preview": "<d\u0018!\u001c`"
},
{
"path": "resources/locales/ui.ts",
"chars": 44336,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\">\n<context>\n <name>about_ui_tr</name>\n <mess"
},
{
"path": "resources/locales/ui_ar.ts",
"chars": 44038,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"ar\">\n<context>\n <name>about_ui_tr</name>\n <message>"
},
{
"path": "resources/locales/ui_de.ts",
"chars": 44096,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"de\">\n<context>\n <name>about_ui_tr</name>\n <message>"
},
{
"path": "resources/locales/ui_es_ES.ts",
"chars": 44554,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"es_ES\">\n<context>\n <name>about_ui_tr</name>\n <messa"
},
{
"path": "resources/locales/ui_fa_IR.ts",
"chars": 46218,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"fa_IR\">\n<context>\n <name>about_ui_tr</name>\n <messa"
},
{
"path": "resources/locales/ui_fr_FR.ts",
"chars": 46892,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"fr_FR\">\n<context>\n <name>about_ui_tr</name>\n <messa"
},
{
"path": "resources/locales/ui_hu.ts",
"chars": 44253,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"hu\">\n<context>\n <name>about_ui_tr</name>\n <message>"
},
{
"path": "resources/locales/ui_ko.ts",
"chars": 45138,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"ko\">\n<context>\n <name>about_ui_tr</name>\n <message>"
},
{
"path": "resources/locales/ui_nl_NL.ts",
"chars": 47299,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"nl_NL\">\n<context>\n <name>about_ui_tr</name>\n <messa"
},
{
"path": "resources/locales/ui_pl_PL.ts",
"chars": 44059,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"pl_PL\">\n<context>\n <name>about_ui_tr</name>\n <messa"
},
{
"path": "resources/locales/ui_pt.ts",
"chars": 74437,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"pt\">\n<context>\n <name>about_ui_tr</name>\n <message>"
},
{
"path": "resources/locales/ui_pt_BR.ts",
"chars": 44386,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"pt_BR\">\n<context>\n <name>about_ui_tr</name>\n <messa"
},
{
"path": "resources/locales/ui_ru.ts",
"chars": 45139,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"ru\">\n<context>\n <name>about_ui_tr</name>\n <message>"
},
{
"path": "resources/locales/ui_sv.ts",
"chars": 72968,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"sv\">\n<context>\n <name>about_ui_tr</name>\n <message>"
},
{
"path": "resources/locales/ui_tr.ts",
"chars": 44275,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"tr\">\n<context>\n <name>about_ui_tr</name>\n <message>"
},
{
"path": "resources/locales/ui_tr_TR.ts",
"chars": 44329,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"tr_TR\">\n<context>\n <name>about_ui_tr</name>\n <messa"
},
{
"path": "resources/locales/ui_zh_CN.ts",
"chars": 44186,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"zh_CN\">\n<context>\n <name>about_ui_tr</name>\n <messa"
},
{
"path": "resources/locales/ui_zh_TW.ts",
"chars": 42900,
"preview": "<?xml version=\"1.0\" ?><!DOCTYPE TS><TS version=\"2.1\" language=\"zh_TW\">\n<context>\n <name>about_ui_tr</name>\n <messa"
},
{
"path": "resources/meson.build",
"chars": 132,
"preview": "icon_files = [\n 'com.github.persepolisdm.persepolis.svg',\n 'persepolis-tray.svg']\n\ninstall_data(icon_files, install_di"
},
{
"path": "resources/resources.qrc",
"chars": 20347,
"preview": "<!DOCTYPE RCC><RCC version=\"1.0\">\n\t<qresource prefix=\"/\">\n\n <file>translators.txt</file>\n <file>com.github"
},
{
"path": "resources/resources_generator.sh",
"chars": 1851,
"preview": "#!/bin/bash\n\nwhile getopts \"trqh\" arg;do\n case $arg in\n t)\n translate=\"1\";;\n r)\n "
},
{
"path": "resources/translation_files.pro",
"chars": 762,
"preview": "TEMPLATE = app\nTARGET = ts\nINCLUDEPATH += persepolis\n\n\n# Input\nSOURCES += ../persepolis/gui/about_ui.py \\\n ."
},
{
"path": "resources/translators.txt",
"chars": 3154,
"preview": "Arabic:\r\nMajdi Sobain MajdiSobain\r\nSaleh Alanazi Sal7_one\r\nrayanm\r\nRex_sa rex07\r\nSimo simonetworking\r\n明 张 zhuangsha19740"
},
{
"path": "test/.pep8",
"chars": 36,
"preview": "[pycodestyle]\nmax_line_length = 120\n"
},
{
"path": "test/test.py",
"chars": 1286,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n# This program is free software: you can redistribute it and/or modif"
},
{
"path": "uninstall.py",
"chars": 3477,
"preview": "#!/usr/bin/env python3\n# coding: utf-8\n# This program is free software: you can redistribute it and/or modify\n# it"
},
{
"path": "xdg/com.github.persepolisdm.persepolis.appdata.xml",
"chars": 2266,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<component type=\"desktop-application\">\n <id>com.github.persepolisdm.persepolis</"
},
{
"path": "xdg/com.github.persepolisdm.persepolis.desktop.in",
"chars": 1191,
"preview": "[Desktop Entry]\nActions=Open;Tray;\nCategories=Qt;Network;\nComment[en_US]=A download manager written in Python\nComment=A "
},
{
"path": "xdg/meson.build",
"chars": 456,
"preview": "desktop_file='com.github.persepolisdm.persepolis.desktop'\nxml_file='com.github.persepolisdm.persepolis.appdata.xml'\n\ncon"
}
]
// ... and 17 more files (download for full content)
About this extraction
This page contains the full source code of the persepolisdm/persepolis GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 124 files (2.9 MB), approximately 767.5k tokens, and a symbol index with 572 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.