From bb12fc73e2acef2e351439ffe25ddd1a126321e2 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Tue, 25 Jun 2024 18:29:47 +0200 Subject: [PATCH 01/39] - added changelog information when checking for updates - partially refactored the code - removed a lot of useless functions - fixed some parts of the layout (still a lot to do) - started with the ideas for the Android layout --- README/CHANGELOG.md | 36 +- README/CREDITS.md | 2 +- README/Changelogs/1.0/Changelog.md | 2 + README/Changelogs/1.1/Changelog.md | 7 + README/Changelogs/1.2/Changelog.md | 3 + README/Changelogs/1.3/Changelog.md | 4 + README/Changelogs/1.4/Changelog.md | 2 + README/Changelogs/1.5/Changelog.md | 3 + README/Changelogs/1.6/Changelog.md | 9 + README/Changelogs/1.7/Changelog.md | 13 + README/Changelogs/1.8/Changelog.md | 10 + README/Changelogs/1.9/Changelog.md | 3 + README/Changelogs/2.0/Changelog.md | 2 + README/Changelogs/2.1/Changelog.md | 18 + README/Changelogs/2.2/Changelog.md | 8 + README/Changelogs/2.3/Changelog.md | 2 + README/Changelogs/2.4/Changelog.md | 12 + README/Changelogs/2.5/Changelog.md | 9 + README/Changelogs/2.6/Changelog.md | 5 + README/Changelogs/2.7/Changelog.md | 5 + README/Changelogs/2.8/Changelog.md | 47 ++ README/Changelogs/2.9/Changelog.md | 6 + README/Changelogs/3.0/Changelog.md | 95 +++ README/Changelogs/3.1/Changelog.md | 43 + README/Changelogs/3.2/Changelog.md | 24 + README/Changelogs/3.3/Changelog.md | 27 + README/Changelogs/Note.txt | 4 + main.py | 318 +++---- requirements.txt | 3 +- src/frontend/form_desktop.ui | 972 ++++++++++++---------- src/frontend/graphics/progressbars.svg | 1 + src/frontend/qressource_file.qrc | 1 + src/frontend/resources.py | 1060 ++++++++++++------------ src/frontend/ui_form_desktop.py | 778 ++++++++--------- 34 files changed, 1959 insertions(+), 1575 deletions(-) create mode 100644 README/Changelogs/1.0/Changelog.md create mode 100644 README/Changelogs/1.1/Changelog.md create mode 100644 README/Changelogs/1.2/Changelog.md create mode 100644 README/Changelogs/1.3/Changelog.md create mode 100644 README/Changelogs/1.4/Changelog.md create mode 100644 README/Changelogs/1.5/Changelog.md create mode 100644 README/Changelogs/1.6/Changelog.md create mode 100644 README/Changelogs/1.7/Changelog.md create mode 100644 README/Changelogs/1.8/Changelog.md create mode 100644 README/Changelogs/1.9/Changelog.md create mode 100644 README/Changelogs/2.0/Changelog.md create mode 100644 README/Changelogs/2.1/Changelog.md create mode 100644 README/Changelogs/2.2/Changelog.md create mode 100644 README/Changelogs/2.3/Changelog.md create mode 100644 README/Changelogs/2.4/Changelog.md create mode 100644 README/Changelogs/2.5/Changelog.md create mode 100644 README/Changelogs/2.6/Changelog.md create mode 100644 README/Changelogs/2.7/Changelog.md create mode 100644 README/Changelogs/2.8/Changelog.md create mode 100644 README/Changelogs/2.9/Changelog.md create mode 100644 README/Changelogs/3.0/Changelog.md create mode 100644 README/Changelogs/3.1/Changelog.md create mode 100644 README/Changelogs/3.2/Changelog.md create mode 100644 README/Changelogs/3.3/Changelog.md create mode 100644 README/Changelogs/Note.txt create mode 100644 src/frontend/graphics/progressbars.svg diff --git a/README/CHANGELOG.md b/README/CHANGELOG.md index d5c6317..9546582 100644 --- a/README/CHANGELOG.md +++ b/README/CHANGELOG.md @@ -8,6 +8,7 @@ Initial Release - Fixed typo issues - Fixed the output path issue - Changed License to LGPLv3 (The reason for this is, that I am stupid and I used the wrong license. Creative Commons is not valid to be used for developing with Qt. I didn't know that, I am sorry...) + # 1.2 - Added additional stuff to the metadata function (Likes, Image URL, Tags) - Added border colours for input fields @@ -15,20 +16,16 @@ Initial Release # 1.3 - Added Threading Modes - Single: Downloads will be executed within the main thread, and the GUI won't respond to your actions if the download isn't finished. - - Multiple: Download(s) will be executed with separate Threads (QThreads). This is mostly intended for single downloads. You can use that function also for multiple downloads, but that will ruin the progress bar, because it will jump between the different videos. # 1.4 - - Changed UI (stackedWidget) -# 1.5 - +# 1.5 - Added CI - Made Readme.md and Build process simpler to understand # 1.6 - - Fixed 7 Bugs - CLI is more stable - Code refactoring @@ -40,7 +37,6 @@ Initial Release # 1.7 - - Implemented an automated fix for the IndexError exception - Improved overall code quality - Split the code into multiple files, to be better readable @@ -56,7 +52,6 @@ Initial Release # 1.8 - - Implemented final License agreement - Persistent settings (untested) - Added Ubuntu to Install script @@ -68,16 +63,13 @@ Initial Release - Added some basic exceptions # 1.9 - - Fixed OS Error issue - Added function to strip out special symbols in title, to prevent path issues # 2.0 - This release exists, but I don't remember the changes anymore. # 2.1 - - A complete new UI design - UI is more fluent / flexible - API updated to v3.1 @@ -97,7 +89,6 @@ This release exists, but I don't remember the changes anymore. - added more filters, to prevent OS Error # 2.2 - - You can now log in with your PornHub Account - You can now fetch your watched, liked, and recommended videos for your PornHub Account - updated the CLI a little bit (not finished. It's my priority for the next release) @@ -106,16 +97,13 @@ This release exists, but I don't remember the changes anymore. - removed Security.md, because it was useless, and I don't really remember why I even added it - added all files to the release page (thanks to Egsagon for telling me that I should do that :) -# 2.3 - +# 2.3 - fixed some issues... # 2.4 - - If you use the file / model - user - channel functionality, then the TreeWidget will be used to let you select the videos that you want to download instead of downloading everything - - fixed an issue in the termux build script - API updated to v3.1-4 - You can now select if you want to have a delay or not (enabling it is recommended!) @@ -127,7 +115,6 @@ The next update will focus more on features / compatibility to other systems. I hope that most issues are now fixed. # 2.5 - - Added search filters - Move settings to a new page of stacked Widget - Added keyboard shortcut and some buttons for it @@ -138,14 +125,12 @@ I hope that most issues are now fixed. - Recoded CLI # 2.6 - - API Updated to v3.2.1 - Redesign of the settings widget - removed some things from the roadmap - added a connection error exception # 2.7 - - API Updated to v4 - Huge stability and performance boost - fixed setting Delay not working issue @@ -200,7 +185,6 @@ I hope that most issues are now fixed. - improved visual look and progressbar # 2.9 - - API updated to 4.1.3 - Added Enhancement request from #11 (Skips already downloaded videos...) - huge Performance increase when downloading (thanks to Egsagon's threaded preset) @@ -399,4 +383,16 @@ I tested it on Android 12 & 13 on two devices. - Improved visual appearance and startup time ## Deprecations -- removed all metadata functionality from Porn Fetch, because it's useless and hard to maintain. \ No newline at end of file +- removed all metadata functionality from Porn Fetch, because it's useless and hard to maintain. + +# 3.4 + +## Design +- switched the sidebar to a top bar (looks better) +- removed the progressbars at the bottom, but added a second widget for it (more space) +- added a new button into the menu which can switch to the previous mentioned widget + +## Deprecations +- removed internet checks, because it triggers AV +- removed status bar at the top, because it's useless +- removed discord rich presence. i don't even remember why I added it :skull: \ No newline at end of file diff --git a/README/CREDITS.md b/README/CREDITS.md index e971817..c7561c5 100644 --- a/README/CREDITS.md +++ b/README/CREDITS.md @@ -29,7 +29,7 @@ Copyright (C) 2023-2024 Johannes Habel (EchterAlsFake) - Free [Settings Icon](https://iconscout.com/free-icon/settings-2856913) in Gradient Style By [Haca Studio](https://iconscout.com/contributors/boosticon) - Done by Google Inc. on IconScout - +- Progressbar by Vaadin Icons on IconScout Logo was generated by DALL-E (ChatGPT)
Some assets aren't used anymore because I have decided to use new icons, diff --git a/README/Changelogs/1.0/Changelog.md b/README/Changelogs/1.0/Changelog.md new file mode 100644 index 0000000..f84a5e7 --- /dev/null +++ b/README/Changelogs/1.0/Changelog.md @@ -0,0 +1,2 @@ +# 1.0 +Initial Release diff --git a/README/Changelogs/1.1/Changelog.md b/README/Changelogs/1.1/Changelog.md new file mode 100644 index 0000000..d101421 --- /dev/null +++ b/README/Changelogs/1.1/Changelog.md @@ -0,0 +1,7 @@ +# 1.1 +- Code refactoring +- Added Support for downloading a whole channel / user +- Fixed an Issue with the progress bar +- Fixed typo issues +- Fixed the output path issue +- Changed License to LGPLv3 (The reason for this is, that I am stupid and I used the wrong license. Creative Commons is not valid to be used for developing with Qt. I didn't know that, I am sorry...) diff --git a/README/Changelogs/1.2/Changelog.md b/README/Changelogs/1.2/Changelog.md new file mode 100644 index 0000000..bcd0f41 --- /dev/null +++ b/README/Changelogs/1.2/Changelog.md @@ -0,0 +1,3 @@ +# 1.2 +- Added additional stuff to the metadata function (Likes, Image URL, Tags) +- Added border colours for input fields diff --git a/README/Changelogs/1.3/Changelog.md b/README/Changelogs/1.3/Changelog.md new file mode 100644 index 0000000..3fad464 --- /dev/null +++ b/README/Changelogs/1.3/Changelog.md @@ -0,0 +1,4 @@ +# 1.3 +- Added Threading Modes +- Single: Downloads will be executed within the main thread, and the GUI won't respond to your actions if the download isn't finished. +- Multiple: Download(s) will be executed with separate Threads (QThreads). This is mostly intended for single downloads. You can use that function also for multiple downloads, but that will ruin the progress bar, because it will jump between the different videos. diff --git a/README/Changelogs/1.4/Changelog.md b/README/Changelogs/1.4/Changelog.md new file mode 100644 index 0000000..cc9aa6a --- /dev/null +++ b/README/Changelogs/1.4/Changelog.md @@ -0,0 +1,2 @@ +# 1.4 +- Changed UI (stackedWidget) diff --git a/README/Changelogs/1.5/Changelog.md b/README/Changelogs/1.5/Changelog.md new file mode 100644 index 0000000..0cbb1d4 --- /dev/null +++ b/README/Changelogs/1.5/Changelog.md @@ -0,0 +1,3 @@ +# 1.5 +- Added CI +- Made Readme.md and Build process simpler to understand diff --git a/README/Changelogs/1.6/Changelog.md b/README/Changelogs/1.6/Changelog.md new file mode 100644 index 0000000..72cb9fe --- /dev/null +++ b/README/Changelogs/1.6/Changelog.md @@ -0,0 +1,9 @@ +# 1.6 +- Fixed 7 Bugs +- CLI is more stable +- Code refactoring +- Handling API timeout in Search function +- Created Security.md +- Created ROADMAP.md +- Created ISSUES.md +- Compiled Versions now compiled with Python 3.11.4 diff --git a/README/Changelogs/1.7/Changelog.md b/README/Changelogs/1.7/Changelog.md new file mode 100644 index 0000000..b0ed6d7 --- /dev/null +++ b/README/Changelogs/1.7/Changelog.md @@ -0,0 +1,13 @@ +# 1.7 +- Implemented an automated fix for the IndexError exception +- Improved overall code quality +- Split the code into multiple files, to be better readable +- A lot of grammar fixes +- Added native support for Termux (See building from source : Android) +- Changed Qt Version from 6.5.1 to 6.5.2 +- Changed Python version from 3.11.3 to 3.11.4 +- Added automatic error reporting with Sentry.io +- Changed License to GPL 3 +- Added CI/CD Actions for build and security checks +- Made the Readme.md A LOT more readable and more professionally +- Added license agreement script (implemented in 1.8) diff --git a/README/Changelogs/1.8/Changelog.md b/README/Changelogs/1.8/Changelog.md new file mode 100644 index 0000000..9835453 --- /dev/null +++ b/README/Changelogs/1.8/Changelog.md @@ -0,0 +1,10 @@ +# 1.8 +- Implemented final License agreement +- Persistent settings (untested) +- Added Ubuntu to Install script +- Added installation script +- Added arch linux to install script +- Typo and grammar fixes +- Added Icons and images +- UI redesign +- Added some basic exceptions diff --git a/README/Changelogs/1.9/Changelog.md b/README/Changelogs/1.9/Changelog.md new file mode 100644 index 0000000..060e336 --- /dev/null +++ b/README/Changelogs/1.9/Changelog.md @@ -0,0 +1,3 @@ +# 1.9 +- Fixed OS Error issue +- Added function to strip out special symbols in title, to prevent path issues diff --git a/README/Changelogs/2.0/Changelog.md b/README/Changelogs/2.0/Changelog.md new file mode 100644 index 0000000..d938016 --- /dev/null +++ b/README/Changelogs/2.0/Changelog.md @@ -0,0 +1,2 @@ +# 2.0 +This release exists, but I don't remember the changes anymore. diff --git a/README/Changelogs/2.1/Changelog.md b/README/Changelogs/2.1/Changelog.md new file mode 100644 index 0000000..2918379 --- /dev/null +++ b/README/Changelogs/2.1/Changelog.md @@ -0,0 +1,18 @@ +# 2.1 +- A complete new UI design +- UI is more fluent / flexible +- API updated to v3.1 +- Thanks to Egsagons Update, most errors are fixed now +- Fixed Connection Error +- You can change the API language +- You can change the UI language (only english supported now, see contribution for more) +- Added Keyboard shortcuts +- UI is much smaller now +- removed icons +- added more dependencies +- little bit code refactoring +- removed borders +- better windows support +- better automatic error handling +- included sentry reporting to more sections of the code +- added more filters, to prevent OS Error diff --git a/README/Changelogs/2.2/Changelog.md b/README/Changelogs/2.2/Changelog.md new file mode 100644 index 0000000..bf95346 --- /dev/null +++ b/README/Changelogs/2.2/Changelog.md @@ -0,0 +1,8 @@ +# 2.2 +- You can now log in with your PornHub Account +- You can now fetch your watched, liked, and recommended videos for your PornHub Account +- updated the CLI a little bit (not finished. It's my priority for the next release) +- API updated to v3.1-1 +- a lot of typo fixes +- removed Security.md, because it was useless, and I don't really remember why I even added it +- added all files to the release page (thanks to Egsagon for telling me that I should do that :) diff --git a/README/Changelogs/2.3/Changelog.md b/README/Changelogs/2.3/Changelog.md new file mode 100644 index 0000000..5e17302 --- /dev/null +++ b/README/Changelogs/2.3/Changelog.md @@ -0,0 +1,2 @@ +# 2.3 +- fixed some issues... diff --git a/README/Changelogs/2.4/Changelog.md b/README/Changelogs/2.4/Changelog.md new file mode 100644 index 0000000..cf278d8 --- /dev/null +++ b/README/Changelogs/2.4/Changelog.md @@ -0,0 +1,12 @@ +# 2.4 +- If you use the file / model - user - channel functionality, then the TreeWidget will be used + to let you select the videos that you want to download instead of downloading everything +- fixed an issue in the termux build script +- API updated to v3.1-4 +- You can now select if you want to have a delay or not (enabling it is recommended!) +- OS error is fixed (FOR REAL!) +- Sentry strips out sensitive information and now only the exception, lines of code, server name is reported + (Although I need to still test that.) + +The next update will focus more on features / compatibility to other systems. +I hope that most issues are now fixed. diff --git a/README/Changelogs/2.5/Changelog.md b/README/Changelogs/2.5/Changelog.md new file mode 100644 index 0000000..1bbf6ba --- /dev/null +++ b/README/Changelogs/2.5/Changelog.md @@ -0,0 +1,9 @@ +# 2.5 +- Added search filters +- Move settings to a new page of stacked Widget +- Added keyboard shortcut and some buttons for it +- API Updated to v3.2 +- Added function for downloading the thumbnail +- Fixed an error with the metadata function +- Removed file logging +- Recoded CLI diff --git a/README/Changelogs/2.6/Changelog.md b/README/Changelogs/2.6/Changelog.md new file mode 100644 index 0000000..27ce8f8 --- /dev/null +++ b/README/Changelogs/2.6/Changelog.md @@ -0,0 +1,5 @@ +# 2.6 +- API Updated to v3.2.1 +- Redesign of the settings widget +- removed some things from the roadmap +- added a connection error exception diff --git a/README/Changelogs/2.7/Changelog.md b/README/Changelogs/2.7/Changelog.md new file mode 100644 index 0000000..f880c1e --- /dev/null +++ b/README/Changelogs/2.7/Changelog.md @@ -0,0 +1,5 @@ +# 2.7 +- API Updated to v4 +- Huge stability and performance boost +- fixed setting Delay not working issue +- fixed #4 connection error / model error diff --git a/README/Changelogs/2.8/Changelog.md b/README/Changelogs/2.8/Changelog.md new file mode 100644 index 0000000..5e882e9 --- /dev/null +++ b/README/Changelogs/2.8/Changelog.md @@ -0,0 +1,47 @@ +# Version 2.8 Update Notes + +### New Features: +- Added support for HQPorner.com. +- Introduced dynamic colors for CLI. +- Created STATUS.md for tracking upcoming releases. +- Implemented help buttons for threading and "high speed" (previously known as Delay). +- Added user metadata and info functionality. +- Included a new logo. + +#### Interface & Design: +- Rolled out the final app design. +- Integrated qt resource file for better icon handling. +- Improved stylesheet logic in the GUI (reduces code by approx. 1500 lines). +- Unified to a single tree widget for all functionalities. + +#### Performance & Efficiency: +- Removed 'get_graphics' function, enhancing UI start speed and eliminating setup requirement. +- Adjusted "Delay" to "High Speed" for clearer understanding. +- Defaulting to maximum api requests possible for faster downloads +- API updated to v4.1 + +#### CLI Updates: +- Updated CLI to version 4.1. +- Entirely refactored CLI. +- Fixed issues with Termux CLI build. + +#### Build & Integration: +- Improved dependency handling in the build script. +- Added support for iSH in the build script. +- Integrated kivy build with CI/CD. + +#### Removals & Deprecations: +- Eliminated Sentry from the project. +- Deleted unnecessary files: DOWNLOADS.md, ISSUES.md. +- Discontinued transparency support. +- Modified several minor elements in various files. + +#### Miscellaneous: +- Updated thumbnail download to align with PHUB v4. +- Note: This Readme has been crafted with assistance from ChatGPT for professionalism. + +#### Android: +- API Update to PHUB v4.1 from py-3.9 branch using custom fork +- You can now just paste the URL from the clipboard +- You can now choose the output folder without needing to enter it in to the input line +- improved visual look and progressbar diff --git a/README/Changelogs/2.9/Changelog.md b/README/Changelogs/2.9/Changelog.md new file mode 100644 index 0000000..b8bf61a --- /dev/null +++ b/README/Changelogs/2.9/Changelog.md @@ -0,0 +1,6 @@ +# 2.9 +- API updated to 4.1.3 +- Added Enhancement request from #11 (Skips already downloaded videos...) +- huge Performance increase when downloading (thanks to Egsagon's threaded preset) +- Added a Semaphore (only 4 threads at once -- less overload and less CPU burning) +- Added Avatar downloading diff --git a/README/Changelogs/3.0/Changelog.md b/README/Changelogs/3.0/Changelog.md new file mode 100644 index 0000000..deb2378 --- /dev/null +++ b/README/Changelogs/3.0/Changelog.md @@ -0,0 +1,95 @@ +# 3.0 +#### Entire rewrite of Porn Fetch, the CLI, the Android App and the HQPorner API. + + +## GUI +- Entire rewrite of the Porn Fetch GUI (Graphical User Interface) +- The GUI is now fully resizeable and works on all screen sizes +- The GUI now supports translations in German, Chinese and French +- The GUI now has a sidebar which is simpler than v2.9 +- There's a third progressbar which tracks the total progress of all PornHub videos being downloaded +- The Tree Widget can now provide more information over the videos. Author, title and duration +- The Progressbars now have a dark design +- The License widget has now a dark design too +- The header of the QTreeWidget now supports Dark Mode. +- Updated to new improved icons. +- Global usage of the tree Widget. + + +## Performance +- There are three threading modes for different use cases +- The semaphore has been fixed, and you can now decide how many videos can be downloaded simultaneously (1-6) +- Implemented a Threading class for listing model videos. +- Transitioned all Metadata methods to use threading. +- Optimized the 'check_if_video_exists' function for greater efficiency. +- Strengthened the robustness of the config file integrity checking logic. +- Porn Fetch is now built with Python 3.12 (Android still 3.10) + +## GitHub Repository +- A lot better project structure +- The Readme now has a translation guide +- Optimized all readmes + +## Code Optimization +- Removed unnecessary signals and completed slots +- Improved threading classes +- Refactored the user settings functions +- Enhanced structure of the Q Resource file. +- Stylesheets have been reorganized and divided into multiple sections for better management. +- Changed the strip title function to allow non UTF-8 characters to support other language alphabets +- Comprehensive rewrite of the Command Line Interface (CLI). + +## Translations +- Added German +- Added French +- Added Chinese + +## Scripts +- Removed iOS build script (Porn Fetch isn't working on iOS sadly) +- Added support for macOS in the build script +- Added support for Windows (separate build script) + +## Issues / Bug Fixes +- Fixed an issue with the config file location creation + +# Deprecations +- Threading is now ALWAYS on. You can't disable it, because I see no reason for it. +- Removed Searching Filters + +## Features +- Added support for Eporner.com +- Added support for xnxx.com +- Added support for xvideos.com +- New directory system to organize videos by model in separate folders. +- Videos can now be shown in reverse order [#17](https://github.com/EchterAlsFake/Porn_Fetch/issues/17) +- You can now also download by model on HQPorner +- You can now download by category on HQPorner +- You can now download by Top Porn on HQPorner +- You can now download a random video on HQPorner +- You can now search for videos on HQPorner +- FFMPEG will now be automatically downloaded and installed if checked as threading mode + +# Android +- The Android App is now exactly the same as Porn Fetch desktop +- The Android app is now based on PySide6 +- The Android app now supports all* features as the Desktop App + +* except the QFileDialog, but this is an Issue from Qt itself. + +## Contributors + +- [Egsagon](https://github.com/Egsagon) French translations +- [Joshua-auhsoj](https://github.com/Joshua-auhsoj) Chinese translations & Enhancement [#17](https://github.com/EchterAlsFake/Porn_Fetch/issues/17) + +# IMPORTANT FOR ANDROID USERS + +Since Android changed a lot on their storage permission system, apps must nowadays ask for read / write permissions +at runtime. +
I can't do this for some [reason](). You can ONLY use Porn Fetch on Android if you have the shared Download folder. It would be in +
`/storage/emulated/0/Download` Porn Fetch will automatically check this and notify you if it doesn't work. + +This is also the reason why Porn Fetch uses an older Android SDK, because with a lower SDK level I can get around the +
Permission system, but there's no guarantee that this works. + +I tested it on Android 12 & 13 on two devices. + diff --git a/README/Changelogs/3.1/Changelog.md b/README/Changelogs/3.1/Changelog.md new file mode 100644 index 0000000..8590ad6 --- /dev/null +++ b/README/Changelogs/3.1/Changelog.md @@ -0,0 +1,43 @@ +# 3.1 + +# Features / Improvements +- Added playlist support #20 +- Added model for EPorner +- Error handling if wrong URL was entered +- Added Disclaimer to the License agreement +- Added more ui popups into the translations +- Updated **ALL** Stylesheets. The GUI now looks a LOT better +- implemented logic, so that user can't log in to PornHub without entering actual credentials +- Added searching support for EPorner +- Implemented update mechanism +- Implemented a factory reset for the settings +- Reimplemented back the client delay (optional) +- Redesigned settings widget +- Added get_by_category for EPorner +- Added a setting for specifying the workers and timeout in the threaded preset + + +# Bug Fixes / Issues +- Fixed an issue, where the settings were displayed, instead of the download tab +- Fixed total progress callback for processed videos in file mode +- Fixed the issue that the downloaded ffmpeg .zip wasn't deleted on windows +- Fixed callback progress for HQPorner +- Fixed the total progress for FFMPEG +- Fixed the FFMPEG type error #21 +- Fixed individual progress for FFMPEG +- Fixed searching (result) limit +- Fixed total progress for loading objects and stuff +- Handling `Client.call failed after 4 attempts` +- Fixed an issue that video reversing is not working +- Fixed overflow error +- Progress now gets only updated all 0.5 seconds +- Some issues in the CLI + +# Code related +- Renamed UI widgets so that they make more sense +- Improved the load style function +- Added code comments +- Code refactoring (refactored all Signals) + +# Android +- [x] Fixed the threaded presets for Android (may or may not work...) diff --git a/README/Changelogs/3.2/Changelog.md b/README/Changelogs/3.2/Changelog.md new file mode 100644 index 0000000..8f3e071 --- /dev/null +++ b/README/Changelogs/3.2/Changelog.md @@ -0,0 +1,24 @@ +# 3.2 + +## New Features +- Disabled limits in the settings e.g., the search limit +- You can now apply your own values for the timeout, max workers, delay and other network settings +- You can now export Video URLs from the tree widget directly into a file +- You can now stop loading video objects by clicking the button +- Porn Fetch is now able to install ffmpeg automatically for you. Go to the settings to do this. +- Added Searching support for xnxx +- Added Model support for xnxx +- Porn Fetch will now automatically write some metadata to the files and convert the .ts files into a valid .mp4 header file. + (This requires FFmpeg. If it is not installed, it will be skipped.) + +## Bug Fixes +- Fixed the Overflow Error +- Fixed logger debug / error connections (only relevant for local development with Android) +- Fixed several typo issues, e.g., #34 +- Fixed some PHUB errors related to #33 #30 #27 #12 #4 + + +## Other +- Rewrite of the README +- Rewrite of the CLI of Porn Fetch +- A lot of code optimizations diff --git a/README/Changelogs/3.3/Changelog.md b/README/Changelogs/3.3/Changelog.md new file mode 100644 index 0000000..0f90db1 --- /dev/null +++ b/README/Changelogs/3.3/Changelog.md @@ -0,0 +1,27 @@ +# 3.3 + +## New Features +- Porn Fetch supports discord rich presence (although it's optional and disabled by default) +- Porn Fetch now checks connection to all sites and lets you know if there was an error +- Untested support for macOS +- Added model support for xvideos +- You can now select a range of videos +- Added sorting to the tree widget +- Added searching support for files + +## Bug fixes +- Fixed application tabbing +- Fixed the total progressbar showing no percent value after it is finished + +## Other +- Huge code refactoring +- Added CI/CD build actions for all platforms +- Switched to Qt 6.7.0 +- Improved terminal debug messages +- Reduced file size by over 70% on Windows and Linux +- Improved the tree widget +- Switched building to pyside6-deploy (nuitka) +- Improved visual appearance and startup time + +## Deprecations +- removed all metadata functionality from Porn Fetch, because it's useless and hard to maintain. diff --git a/README/Changelogs/Note.txt b/README/Changelogs/Note.txt new file mode 100644 index 0000000..41daf6d --- /dev/null +++ b/README/Changelogs/Note.txt @@ -0,0 +1,4 @@ +These structure exists, because I can now check for updates within Porn Fetch and directly show the +changelog with it. I don't have a server, so I need to do it this way :) + +The "CHANGELOG.md" file will still be used to keep everything in one place. \ No newline at end of file diff --git a/main.py b/main.py index 3e687fc..40d8c6c 100644 --- a/main.py +++ b/main.py @@ -11,7 +11,6 @@ from itertools import islice from threading import Event from pathlib import Path -from pypresence import Presence, exceptions from hqporner_api.api import Sort as hq_Sort from phub import consts @@ -27,8 +26,7 @@ from PySide6.QtCore import (QFile, QTextStream, Signal, QRunnable, QThreadPool, QObject, QSemaphore, Qt, QLocale, QTranslator, QCoreApplication) -from PySide6.QtWidgets import (QWidget, QApplication, QInputDialog, QTreeWidgetItem, QButtonGroup, QFileDialog, - QPushButton) +from PySide6.QtWidgets import QWidget, QApplication, QInputDialog, QTreeWidgetItem, QButtonGroup, QFileDialog from PySide6.QtGui import QIcon, QFont """ @@ -58,8 +56,6 @@ __build__ = "desktop" # android or desktop __author__ = "Johannes Habel" __next_release__ = "3.5" -discord_id = "1224629014032023563" # Used for rich presence -discord_image = "logo_transparent" total_segments = 0 downloaded_segments = 0 last_index = 0 @@ -75,6 +71,7 @@ ffmpeg_linux = "ffmpeg-6.1-amd64-static" ffmpeg_windows = "ffmpeg-7.0-essentials_build" android_arch = None +session_urls = [] # This list saves all URls used in the current session. Used for the URL export function class Signals(QObject): @@ -172,26 +169,6 @@ def run(self): self.signals.result.emit(False) -class CheckInternet(QRunnable): - def __init__(self): - super(CheckInternet, self).__init__() - self.signals = Signals() - - def run(self): - try: - for url in urls: - if not requests.get(url).status_code == 200: - self.signals.result.emit(False) - return - - except (requests.exceptions.SSLError, requests.exceptions.ConnectionError, ConnectionResetError, - ConnectionError, requests.exceptions.HTTPError): - self.signals.result.emit(False) - - else: - self.signals.result.emit(True) - - class AddToTreeWidget(QRunnable): def __init__(self, iterator, search_limit, data_mode, reverse, stop_flag, is_checked): super(AddToTreeWidget, self).__init__() @@ -205,7 +182,7 @@ def __init__(self, iterator, search_limit, data_mode, reverse, stop_flag, is_che def process_video(self, video, index): title = video.title - disabled = QCoreApplication.tr("Disabled", None) + disabled = QCoreApplication().tr("Disabled", None) duration = disabled author = disabled @@ -282,8 +259,9 @@ def run(self): try: text_data = self.process_video(video, i) except errors.RegexError as e: - logger_error(f"Warning: a Regex Error occurred. This must not be an error, but could be one!" - f" -->: {e}") + logger_error( + f"Warning: a Regex Error occurred. This must not be an error, but could be one!" + f" -->: {e}") text_data = [str(video.title), str("Unknown"), str("Unknown"), str(i), video] @@ -643,34 +621,6 @@ def run(self): self.signals.finished.emit() -class Discord(QRunnable): - """ - The Discord class handles the Pypresence, which is a feature that allows to show your current activity in Discord. - If enabled, discord will show on your profile, that you are 'playing' Porn Fetch. - """ - - def __init__(self): - super(Discord, self).__init__() - - def run(self): - while True: - try: - presence = Presence(discord_id) - presence.connect() - presence.update(details=f"Porn Fetch (v{__version__})", large_image=discord_image, buttons= - [{"label": "Visit Project", "url": "https://github.com/EchterAlsFake/Porn_Fetch"}]) - time.sleep(60) # Delay of 60 seconds, so that the Discord API doesn't get spammed - - except exceptions.DiscordNotFound: - logger_error("Discord was not found... Pypresence won't be started!") - - except exceptions.InvalidID: - logger_error("Invalid Discord Application ID. Please report this error, as it shouldn't happen!") - - except exceptions.PyPresenceException as e: - logger_error(f"Pypresence exception... {e}") - - class AddUrls(QRunnable): """ This class is used to add the URLs from the 'open file' function, because the UI doesn't respond until @@ -707,7 +657,7 @@ def run(self): elif line.startswith("search#"): query = line.split("#")[1] site = line.split("#")[2] - search_iterators.append({"website" : site, + search_iterators.append({"website": site, "query": query}) else: @@ -727,10 +677,8 @@ def run(self): class Porn_Fetch(QWidget): def __init__(self, parent=None): super().__init__(parent) - # Variable initialization: self.gui_language_map = None - self.discord_map = None self.max_retries = None self.workers = None self.timeout = None @@ -770,26 +718,13 @@ def __init__(self, parent=None): self.load_user_settings() # Loads the user settings and applies selected values to the UI logger_debug("Startup: [4/5] Loaded the user settings") self.switch_to_home() # Switches Porn Fetch to the home widget - self.check_for_updates() # Checks if a new version is out, by using the GitHub release tags - self.check_internet() # Checks if Porn Fetch can reach all websites + self.check_for_updates() self.check_ffmpeg() # Checks and sets up FFmpeg - self.discord_() # Discord Rich Presence logger_debug("Startup: [5/5] ✔") if __build__ == "android": self.setup_android() # Sets up Android, if build mode is Android (handles some UI stuff and things) - @classmethod - def load_stylesheet(cls, path): - """Load stylesheet from a given path with explicit open and close.""" - file = QFile(path) - if not file.open(QFile.ReadOnly | QFile.Text): - logger_debug(f"Failed to open {path}") - return "" - stylesheet = QTextStream(file).readAll() - file.close() - return stylesheet - def load_style(self): """Refactored function to load icons and stylesheets.""" # Setting icons with a loop if applicable @@ -808,7 +743,7 @@ def load_style(self): self.ui.button_result_limit_help: "faq.svg", self.ui.button_timeout_maximal_retries_help: "faq.svg", self.ui.button_help_file: "faq.svg", - self.ui.discord_rich_presence_help: "faq.svg", + self.ui.button_view_progress_bars: "progressbars.svg" } for button, icon_name in icons.items(): button.setIcon(QIcon(f":/images/graphics/{icon_name}")) @@ -831,7 +766,7 @@ def load_style(self): "button_reset": ":/style/stylesheets/stylesheet_button_reset.qss" } - stylesheets = {key: self.load_stylesheet(path) for key, path in stylesheet_paths.items()} + stylesheets = {key: load_stylesheet(path) for key, path in stylesheet_paths.items()} # Applying stylesheets to specific buttons # Simplify this part based on actual UI structure and naming @@ -843,7 +778,6 @@ def load_style(self): self.ui.progressbar_hqporner.setStyleSheet(stylesheets["progressbar_hqporner"]) self.ui.progressbar_xvideos.setStyleSheet(stylesheets["progressbar_xvideos"]) self.ui.progressbar_converting.setStyleSheet(stylesheets["progressbar_converting"]) - self.ui.button_model.setStyleSheet(stylesheets["button_purple"]) self.ui.button_search.setStyleSheet(stylesheets["button_purple"]) self.ui.button_download.setStyleSheet(stylesheets["button_purple"]) @@ -872,7 +806,6 @@ def load_style(self): self.ui.button_result_limit_help.setStyleSheet(stylesheets["button_green"]) self.ui.button_settings_reset.setStyleSheet(stylesheets["button_reset"]) self.ui.button_playlist_get_videos.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_view_all_progress_bars.setStyleSheet(stylesheets["button_blue"]) self.ui.button_tree_stop.setStyleSheet(stylesheets["button_reset"]) self.ui.button_tree_export_video_urls.setStyleSheet(stylesheets["button_purple"]) self.ui.button_timeout_maximal_retries_help.setStyleSheet(stylesheets["button_green"]) @@ -897,32 +830,23 @@ def check_for_updates_result(self, value): """Receives the Update result from the thread""" if value: logger_debug(f"Next release v{__next_release__} found!") - ui_popup(QCoreApplication.tr(f""" - Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. - Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__}""", None)) - self.ui.lineedit_status_update.setText(f"✔, V{__next_release__} is out!") - - else: - logger_debug("No updates found...") - self.ui.lineedit_status_update.setText("❌") + try: + changelog = (requests.get(f"https://github.com/EchterAlsFake/Porn_Fetch/tree/master/README/Changelog/" + f"{__next_release__}/Changelog.md").text) - def check_internet(self): - """Checks the internet access for all sites""" - self.internet_thread = CheckInternet() - self.internet_thread.signals.result.connect(self.check_internet_result) - self.threadpool.start(self.internet_thread) + except Exception as e: + logger_error(f"Couldn't fetch changelog of version: {__next_release__}") + changelog = f"Unknown Error: {e}" - def check_internet_result(self, value): - if value: - logger_debug("All Internet connection tests passed: ✔") - self.ui.lineedit_status_internet.setText("✔") + ui_popup(QCoreApplication().tr(f""" + Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. + Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} + + Changelog: + {markdown.markdown(changelog)} + + """, None)) - else: - logger_error(""" -Couldn't access one of the supported websites, make sure you have a stable internet connection and you are outside of -a firewall. If you are at a public place or using your universities WiFi, your IT-Administrator may have forbidden -access to specific sites. In this case you can use a VPN / Proxy.""") - self.ui.lineedit_status_internet.setText("❌, please check your Internet connection!") def check_ffmpeg(self): # Check if ffmpeg is available in the system PATH @@ -937,7 +861,7 @@ def check_ffmpeg(self): if ffmpeg_binary is None: # If ffmpeg binaries are not found in the current directory, display warning and disable features if self.conf.get("Performance", "ffmpeg_warning") == "true": - ffmpeg_warning_message = QCoreApplication.tr( + ffmpeg_warning_message = QCoreApplication().tr( """ FFmpeg isn't installed on your system... Some features won't be available: @@ -961,17 +885,14 @@ def check_ffmpeg(self): global ffmpeg_features ffmpeg_features = False logger_error("FFMPEG features have been disabled, because ffmpeg wasn't found on your system.") - self.ui.lineedit_status_ffmpeg.setText("❌, FFmpeg features won't be available!") else: # If ffmpeg binary is found in the current directory, set it as the ffmpeg path ffmpeg_path = os.path.abspath(ffmpeg_binary) - self.ui.lineedit_status_ffmpeg.setText(f"✔ -->: {ffmpeg_path}") else: # If ffmpeg is found in system PATH, use it directly ffmpeg_path = shutil.which("ffmpeg") consts.FFMPEG_EXECUTABLE = ffmpeg_path bs_consts.FFMPEG_PATH = ffmpeg_path - self.ui.lineedit_status_ffmpeg.setText(f"✔ -->: {ffmpeg_path}") logger_debug(f"FFMPEG: {ffmpeg_path}") def download_ffmpeg(self): @@ -989,16 +910,7 @@ def download_ffmpeg(self): @classmethod def ffmpeg_finished(cls): - ui_popup(QCoreApplication.tr("FFmpeg has been installed. Please restart Porn Fetch :)")) - - def discord_(self): - """ - I don't force anyone to use this. It's disabled by default :) - """ - if self.discord: - self.discord_thread = Discord() - self.threadpool.start(self.discord_thread) - logger_debug("Started Discord thread") + ui_popup(QCoreApplication().tr("FFmpeg has been installed. Please restart Porn Fetch :)", None)) def button_groups(self): """ @@ -1054,51 +966,25 @@ def setup_android(self): def handle_no_output_path(self): ui_popup( - QCoreApplication.tr("The output path does not exist or is not writable.", None)) + QCoreApplication().tr("The output path does not exist or is not writable.", None)) text, ok = QInputDialog.getText(self, "Enter custom Path", - QCoreApplication.tr("Enter custom Path:", None)) + QCoreApplication().tr("Enter custom Path:", None)) if ok and get_output_path(text): ui_popup( - QCoreApplication.tr(f"Success: {text} will be used for this session!", None)) + QCoreApplication().tr(f"Success: {text} will be used for this session!", None)) self.configure_ui_for_android(text) else: ui_popup( - QCoreApplication.tr("Invalid path. The application will now exit.", None)) + QCoreApplication().tr("Invalid path. The application will now exit.", None)) sys.exit() def configure_ui_for_android(self, path): - """Disables some things on Android which just don't work yet""" - self.output_path = path - self.ui.lineedit_output_path.setText(self.output_path) - self.ui.lineedit_output_path.setReadOnly(True) - self.ui.button_open_file.setDisabled(True) - self.ui.lineedit_file.setText(QCoreApplication.tr("Not supported on Android", None)) - self.ui.radio_threading_mode_ffmpeg.setDisabled(True) - self.warn_about_high_performance_threading() - - self.ui.gridlayout_progressbar.addWidget(self.ui.label_progress_pornhub) - self.ui.gridlayout_progressbar.addWidget(self.ui.progressbar_pornhub) - self.ui.gridlayout_progressbar.addWidget(self.ui.label_total_progress) - self.ui.gridlayout_progressbar.addWidget(self.ui.progressbar_total) - self.ui.gridlayout_progressbar.addWidget(self.ui.label_progress_converting) - self.ui.gridlayout_progressbar.addWidget(self.ui.progressbar_converting) - - self.progress_button = QPushButton("Show Progress") - self.ui.verticallayout_sidebar.addWidget(self.progress_button) - self.progress_button.clicked.connect(self.switch_to_all_progress_bars) - self.ui.scrollarea_status.deleteLater() + "" def warn_about_high_performance_threading(self): if self.ui.radio_threading_mode_high_performance.isChecked(): ui_popup( - QCoreApplication.tr("High Performance threading may cause issues on Android devices.", None)) - - @staticmethod - def reset_pornfetch(): - ui_popup( - QCoreApplication.tr("Porn Fetch will now reset to its default settings...", None)) - setup_config_file(force=True) - ui_popup(QCoreApplication.tr("Done! Please restart.", None)) + QCoreApplication().tr("High Performance threading may cause issues on Android devices.", None)) def toggle_sorting(self): if self.ui.checkbox_tree_allow_sorting.isChecked(): @@ -1117,7 +1003,7 @@ def button_connectors(self): self.ui.button_switch_credits.clicked.connect(self.switch_to_credits) self.ui.button_switch_account.clicked.connect(self.switch_to_account) self.ui.button_switch_supported_websites.clicked.connect(self.switch_to_supported_websites) - self.ui.button_view_all_progress_bars.clicked.connect(self.switch_to_all_progress_bars) + self.ui.button_view_progress_bars.clicked.connect(self.switch_to_all_progress_bars) # Video Download Button Connections self.ui.button_download.clicked.connect(self.start_single_video) @@ -1136,11 +1022,10 @@ def button_connectors(self): self.ui.button_result_limit_help.clicked.connect(result_limit_help) self.ui.button_help_file.clicked.connect(open_file_help) self.ui.button_timeout_maximal_retries_help.clicked.connect(max_retries_help) - self.ui.discord_rich_presence_help.clicked.connect(discord_rich_presence_help) # Settings self.ui.button_settings_apply.clicked.connect(self.save_user_settings) - self.ui.button_settings_reset.clicked.connect(self.reset_pornfetch) + self.ui.button_settings_reset.clicked.connect(reset_pornfetch) # Account self.ui.button_login.clicked.connect(self.login) @@ -1170,8 +1055,8 @@ def button_connectors(self): # Other stuff idk self.ui.checkbox_tree_allow_sorting.checkStateChanged.connect(self.toggle_sorting) self.ui.button_tree_select_range.clicked.connect(self.select_range_of_items) - self.ui.button_tree_stop.clicked.connect(self.switch_stop_state) - self.ui.button_tree_export_video_urls.clicked.connect(self.export_urls) + self.ui.button_tree_stop.clicked.connect(switch_stop_state) + self.ui.button_tree_export_video_urls.clicked.connect(export_urls) self.ui.button_download_ffmpeg.clicked.connect(self.download_ffmpeg) def switch_login_button_state(self): @@ -1185,11 +1070,6 @@ def switch_login_button_state(self): self.ui.button_get_watched_videos.setStyleSheet(stylesheet) self.ui.button_get_recommended_videos.setStyleSheet(stylesheet) - @classmethod - def switch_stop_state_2(cls): - global stop_flag - stop_flag = Event() - def switch_to_home(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(0) @@ -1229,11 +1109,6 @@ def settings_maps_initialization(self): "0": self.ui.radio_directory_system_no } - self.discord_map = { - "false": self.ui.radio_discord_no, - "true": self.ui.radio_discord_yes - } - self.gui_language_map = { "en": self.ui.radio_ui_language_english, "de_DE": self.ui.radio_ui_language_german, @@ -1250,7 +1125,6 @@ def load_user_settings(self): self.threading_mode_map.get(self.conf.get("Performance", "threading_mode")).setChecked(True) self.directory_system_map.get(self.conf.get("Video", "directory_system")).setChecked(True) self.language_map.get(self.conf.get("Video", "language")).setChecked(True) - self.discord_map.get(self.conf.get("UI", "discord")).setChecked(True) self.gui_language_map.get(self.conf.get("UI", "language")).setChecked(True) self.ui.spinbox_semaphore.setValue(int(self.conf.get("Performance", "semaphore"))) self.ui.spinbox_treewidget_limit.setValue(int(self.conf.get("Video", "search_limit"))) @@ -1270,7 +1144,6 @@ def load_user_settings(self): self.workers = int(self.conf["Performance"]["workers"]) self.max_retries = int(self.conf["Performance"]["retries"]) - self.discord = True if self.conf["UI"]["discord"] == "yes" else False self.ui.spinbox_maximal_timeout.setValue(int(self.timeout)) self.ui.spinbox_maximal_workers.setValue(int(self.workers)) self.ui.spinbox_pornhub_delay.setValue(int(self.delay)) @@ -1306,10 +1179,6 @@ def save_user_settings(self): if radio_button.isChecked(): self.conf.set("UI", "language", language) - for mode, radio_button in self.discord_map.items(): - if radio_button.isChecked(): - self.conf.set("UI", "discord", mode) - # Save other settings self.conf.set("Performance", "semaphore", str(self.ui.spinbox_semaphore.value())) self.conf.set("Video", "search_limit", str(self.ui.spinbox_treewidget_limit.value())) @@ -1322,7 +1191,7 @@ def save_user_settings(self): with open("config.ini", "w") as config_file: self.conf.write(config_file) - ui_popup(QCoreApplication.tr("Saved User Settings, please restart Porn Fetch!", None)) + ui_popup(QCoreApplication().tr("Saved User Settings, please restart Porn Fetch!", None)) logger_debug("Saved User Settings, please restart Porn Fetch.") """ @@ -1357,11 +1226,7 @@ def switch_to_supported_websites(self): def switch_to_all_progress_bars(self): self.ui.stacked_widget_top.setCurrentIndex(2) - - def switch_stop_state(self): - stop_flag.set() - time.sleep(1) - self.switch_stop_state_2() + self.ui.stacked_widget_main.setCurrentIndex(0) """ The following functions are related to the tree widget @@ -1458,30 +1323,6 @@ def reindex(self): original_title = current_text.split(') ', 1)[1] if ') ' in current_text else current_text item.setText(0, f"{new_index}) {original_title}") - def export_urls(self): - video_urls = [] - - for i in range(self.ui.treeWidget.topLevelItemCount()): - item = self.ui.treeWidget.topLevelItem(i) - video_object = item.data(0, Qt.UserRole) - video_urls.append(video_object.url) - - if len(video_urls) == 0: - ui_popup(QCoreApplication.tr("No video URLs found. Are there videos in the tree widget?", None)) - return - - file, mode = QFileDialog().getSaveFileName(self) - - try: - with open(file, "a") as file: - for url in video_urls: - file.write(f"{url}\n") - - except PermissionError: - ui_popup(QCoreApplication.tr(f"Permission Error, please select a file from your user space," - f"or run Porn Fetch with admin permissions (not recommended!)", - None)) - def progress_tree_widget(self, total, current): """This tracks the progress of the tree widget data""" self.ui.progressbar_total.setMaximum(total) @@ -1646,8 +1487,8 @@ def on_video_loaded(self, video, author, stripped_title, output_file_path, threa def on_video_load_error(self, error_message): # Handle errors, possibly show message to user logger_debug(f"Error loading video: {error_message}") - ui_popup(QCoreApplication.tr(f"Some error occurred in loading a video. Please report this: {error_message}", - None)) + ui_popup(QCoreApplication().tr(f"Some error occurred in loading a video. Please report this: {error_message}", + None)) def process_video_thread(self, output_path, video, threading_mode, quality): """Checks which of the three types of threading the user selected and handles them.""" @@ -1718,10 +1559,10 @@ def start_undefined_range(self): def stop_undefined_range(self): """This stops the undefined range (loading animation) of the total progressbar""" - logger_debug("Repainting the total progressbar") self.ui.progressbar_total.setMinimum(0) self.ui.progressbar_total.setMaximum(100) self.ui.progressbar_total.setValue(0) + """ The following functions are used for opening files / directories with the QFileDialog """ @@ -1797,20 +1638,20 @@ def login(self): password = self.ui.lineedit_password.text() if len(username) <= 2 or len(password) <= 2: ui_popup( - QCoreApplication.tr("Those credentials don't seem to be valid...", None)) + QCoreApplication().tr("Those credentials don't seem to be valid...", None)) return try: self.client = Client(username, password, language=self.api_language, delay=self.delay) logger_debug("Login Successful!") - ui_popup(QCoreApplication.tr("Login Successful!", None)) + ui_popup(QCoreApplication().tr("Login Successful!", None)) self.switch_login_button_state() except errors.LoginFailed: - ui_popup(QCoreApplication.tr("Login Failed, please check your credentials and try again!", None)) + ui_popup(QCoreApplication().tr("Login Failed, please check your credentials and try again!", None)) except errors.ClientAlreadyLogged: - ui_popup(QCoreApplication.tr("You are already logged in!", None)) + ui_popup(QCoreApplication().tr("You are already logged in!", None)) def check_login(self): """Checks if the user is logged in, so that no errors are threw if not""" @@ -1820,8 +1661,9 @@ def check_login(self): elif not self.client.logged: self.login() if not self.client.logged: - text = QCoreApplication.tr("There's a problem with the login. Please make sure you login first " - "and then you try to get videos based on your account.", None) + text = (QCoreApplication().tr( + "There's a problem with the login. Please make sure you login first and then you try to " + "get videos based on your account.", None)) ui_popup(text) return False @@ -1893,8 +1735,8 @@ def get_top_porn_hqporner(self): def get_by_category_hqporner(self): """Returns video by category from HQPorner. I want to add support for EPorner""" # TODO - self.list_all_categories_string = QCoreApplication.tr( - "Invalid Category. Press 'list categories' to see all possible ones.", None) + self.list_all_categories_string = (QCoreApplication().tr( + "Invalid Category. Press 'list categories' to see all possible ones.", None)) category_name = self.ui.lineedit_hqporner_category.text() all_categories = hq_Client().get_all_categories() search_limit = self.search_limit @@ -2021,6 +1863,54 @@ def main(): if __name__ == "__main__": + + """ + These functions are static functions which I won't need while coding. + These just exist for some reason, but I don't want to scroll through endless lines of code, + which is why I placed them here. + """ + + + def load_stylesheet(path): + """Load stylesheet from a given path with explicit open and close.""" + file = QFile(path) + if not file.open(QFile.ReadOnly | QFile.Text): + logger_debug(f"Failed to open {path}") + return "" + stylesheet = QTextStream(file).readAll() + file.close() + return stylesheet + + + def reset_pornfetch(): + setup_config_file(force=True) + ui_popup(QCoreApplication().tr("Done! Please restart.", None)) + + + def switch_stop_state_2(): + global stop_flag + stop_flag = Event() + + + def switch_stop_state(): + stop_flag.set() + time.sleep(1) + switch_stop_state_2() + + + def export_urls(): + if not len(session_urls) == 0: + file, type = QFileDialog().getOpenFileName() + with open(file, "w") as url_export_file: + for url in session_urls: + url_export_file.write(f"{url}\n") + + ui_popup(f"Success! Saved: {len(session_urls)} URLs") + + else: + ui_popup(QCoreApplication().tr("No URLs in the current session...", None)) + + parser = argparse.ArgumentParser() parser.add_argument("-v", "--version", help="Shows the version information", action="store_true") args = parser.parse_args() @@ -2029,14 +1919,4 @@ def main(): print(__version__) setup_config_file() - try: - main() - - except FileNotFoundError as e: - ui_popup(f"a File Not Found Error occured. This shouldn't happenn. If you see this error, please report it: {e}") - - except PermissionError as e: - ui_popup(f"Permission Error: {e}, please report this error.") - - except OverflowError: - ui_popup("OverFlow Error, please report this immediately, as it's supposed to be fixed!") + main() diff --git a/requirements.txt b/requirements.txt index 16066a0..45ea471 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,5 +12,4 @@ Markdown rich tqdm ffmpeg-progress-yield -mutagen -pypresence \ No newline at end of file +mutagen \ No newline at end of file diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 03eef47..63a85b7 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -44,9 +44,9 @@ - + - + @@ -74,7 +74,7 @@ - + @@ -96,8 +96,8 @@ 0 0 - 1512 - 291 + 1570 + 277 @@ -119,7 +119,7 @@ b - 2 + 0 @@ -131,7 +131,7 @@ 0 - + @@ -147,59 +147,26 @@ - - - - Playlist URL: - - - - - - - Search Website - - - - - - - - 0 - 0 - - - - - 100 - 2 - - - - File: - - - - - + + - + 0 0 - 100 - 2 + 300 + 4 - - Model URL: + + Enter video URL - + @@ -224,27 +191,40 @@ - - + + + + Search Website + + + + + - + 0 0 - 100 + 60 2 + + PointingHandCursor + + + + - URL: + Get Videos - - + + 0 @@ -264,28 +244,40 @@ - Get Videos + Download - - - - PointingHandCursor + + + + + 0 + 0 + - - See Supported Websites + + + 300 + 2 + + + + Enter Model / Channel / Actress URL - + - 0 + 4 5 + + 5 + @@ -339,7 +331,7 @@ - + @@ -364,53 +356,73 @@ - + + + + + 0 + 0 + + + + + 100 + 2 + + + + URL: + + + + + + + Enter a PornHub Playlist URL + + + + Search Query: - - + + - Get Videos + Playlist URL: - - + + - + 0 0 - 60 + 100 2 - - PointingHandCursor - - - - - Download + Model URL: - - + + - Help + Get Videos - + @@ -432,48 +444,57 @@ - - + + - + 0 0 - 300 + 100 2 - - Enter Model / Channel / Actress URL + + File: - - - - Enter a PornHub Playlist URL + + + + Help - + - + 0 0 - 300 - 4 + 0 + 25 - - Enter video URL + + + 16777215 + 20 + + + + PointingHandCursor + + + See Supported Websites @@ -642,61 +663,55 @@ 0 0 - 1474 - 253 + 1532 + 239 - + - - - - - 0 - 0 - - - - - 300 - 0 - - + + 0 - - - - 0 + + + + + 0 + 0 + - - - - - - 0 + + PornHub: - - + + - Eporner + XVideos - + XNXX - + + + + 0 + + + + @@ -709,21 +724,45 @@ - - - - XVideos + + + + + 0 + 0 + + + + + 300 + 0 + + + + 0 - - + + + + + 0 + 0 + + + + + 300 + 0 + + 0 - + Qt::Vertical @@ -736,6 +775,37 @@ + + + + 0 + + + + + + + Eporner + + + + + + + Info: + + + + + + + + + + true + + + @@ -1070,7 +1140,7 @@ - + @@ -1082,8 +1152,8 @@ 0 0 - 1510 - 326 + 1568 + 336 @@ -1238,6 +1308,18 @@ + + + 0 + 0 + + + + + 0 + 30 + + PointingHandCursor @@ -1254,6 +1336,18 @@ + + + 0 + 0 + + + + + 0 + 30 + + Does not stop downloading videos @@ -1264,6 +1358,18 @@ + + + 0 + 0 + + + + + 0 + 30 + + PointingHandCursor @@ -1280,6 +1386,18 @@ + + + 0 + 0 + + + + + 0 + 30 + + PointingHandCursor @@ -1295,40 +1413,6 @@ - - - - - - Internet: - - - - - - - - - - FFmpeg: - - - - - - - - - - Update available: - - - - - - - - @@ -1343,8 +1427,8 @@ 0 0 - 846 - 762 + 721 + 720 @@ -2075,46 +2159,46 @@ QPushButton:pressed { <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Supported Websites:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Downloading:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com (supports total progress)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Eporner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com (supports total progress)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XVideos.com (supports total progress)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">All sites support *threaded* downloads and selectable quality!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">downloaded, therefore threading in a segment isn't needed.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Model / Channel Downloads</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- EPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XVideos.com</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Searching:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Xvideos.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Eporner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">I am constantly working to support more websites.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Supported Websites:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Downloading:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com (supports total progress)</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All sites support *threaded* downloads and selectable quality!</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">downloaded, therefore threading in a segment isn't needed.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Model / Channel Downloads</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- EPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Searching:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Xvideos.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I am constantly working to support more websites.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> @@ -2145,15 +2229,18 @@ p, li { white-space: pre-wrap; } 0 0 - 1530 - 171 + 1588 + 161 - - + + 0 + + + 0 @@ -2161,52 +2248,26 @@ p, li { white-space: pre-wrap; } - PornHub: + Total: - - - - - 0 - 0 - - - - - 300 - 0 - - + + 0 - + Converting: - - - - 0 - - - - - - - View all other progress bars - - - - - + + 0 @@ -2214,11 +2275,11 @@ p, li { white-space: pre-wrap; } - Total: + Information: The total progressbar does not count for Eporner and HQPorner, because they are using different mechanisms for downloading. - + @@ -2237,19 +2298,6 @@ p, li { white-space: pre-wrap; } - - - - - 0 - 0 - - - - Information: The total progressbar does not count for Eporner and HQPorner, because they are using different mechanisms for downloading. - - - @@ -2259,152 +2307,239 @@ p, li { white-space: pre-wrap; } - - - - - - - 50 - 50 - - - - PointingHandCursor - - - border: none - - - - - - - 32 - 32 - - - - - - - - - 50 - 50 - - - - PointingHandCursor - - - border: none - - - - - - - 32 - 32 - - - - - - - - - 50 - 50 - - - - - 9 - - - - PointingHandCursor - - - border: none - - - - - - - 32 - 32 - - - - - - - - - 50 - 50 - - - - PointingHandCursor - - - border: none; - - - - - - - 32 - 32 - - - - - - - - - 50 - 50 - - - - PointingHandCursor - - - border: none; - - - - - - - 32 - 32 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + + + + + + 0 + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + PointingHandCursor + + + border: none + + + + + + + 32 + 32 + + + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + PointingHandCursor + + + border: none + + + + + + + 32 + 32 + + + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + + 9 + + + + PointingHandCursor + + + border: none + + + + + + + 32 + 32 + + + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + PointingHandCursor + + + border: none; + + + + + + + 32 + 32 + + + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + PointingHandCursor + + + border: none; + + + + + + + 32 + 32 + + + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + PointingHandCursor + + + border: none; + + + + + + + 32 + 32 + + + @@ -2415,15 +2550,8 @@ p, li { white-space: pre-wrap; } - button_switch_home - button_switch_account - button_switch_tools - button_switch_settings - button_switch_credits scrollarea_status - button_view_all_progress_bars scrollarea_stacked_top - button_switch_supported_websites lineedit_url button_download lineedit_playlist_url diff --git a/src/frontend/graphics/progressbars.svg b/src/frontend/graphics/progressbars.svg new file mode 100644 index 0000000..1fec2e0 --- /dev/null +++ b/src/frontend/graphics/progressbars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/qressource_file.qrc b/src/frontend/qressource_file.qrc index 401528f..fc3dd36 100644 --- a/src/frontend/qressource_file.qrc +++ b/src/frontend/qressource_file.qrc @@ -12,6 +12,7 @@ graphics/tools.svg graphics/faq.svg graphics/done.svg + graphics/progressbars.svg stylesheets/stylesheet.qss diff --git a/src/frontend/resources.py b/src/frontend/resources.py index 8050409..8d8432e 100644 --- a/src/frontend/resources.py +++ b/src/frontend/resources.py @@ -1,6 +1,6 @@ # Resource object code (Python 3) # Created by: object code -# Created by: The Resource Compiler for Qt version 6.7.0 +# Created by: The Resource Compiler for Qt version 6.7.2 # WARNING! All changes made in this file will be lost! from PySide6 import QtCore @@ -389,6 +389,24 @@ ass=\x22color000000\ svgShape\x22>\ +\x00\x00\x00\xf9\ +<\ +svg xmlns=\x22http:\ +//www.w3.org/200\ +0/svg\x22 viewBox=\x22\ +0 0 16 16\x22 id=\x22P\ +rogressbar\x22>\ +\ \x00\x00\x09\xdf\ \x00\ \x00\x01\x00\x01\x00\x00\x00\x00\x00\x01\x00 \x00\xc9\x09\x00\ @@ -8804,489 +8822,479 @@ .26,0,0,0,12,2.7\ 5Z\x22><\ /svg>\ -\x00\x00\x03\xe6\ +\x00\x00\x03\xde\ \x00\ -\x00\x0fOx\xda\xbdW\xc9n\xdb0\x10\xbd\x07\xc8?\ -\x10\xe8\xa1\x0b\xa2\xda\xb1,\xdbRNr\x96\xf6\xd0\x02\ -u\xd73-1\x12\x1b\x85\x14H*N\x1b\xf4\xdf;\ -\x14eY\xbb\xdc\x16\xa8\x8d \xf0\x88\x9cy\xf3f\xd5\ -\xe6\x1b\x0d#\xa2\xd0\xd3\xe9\x09\x82O\xc0\x13.<\xf4\ -\xec\xfaR\x7f/\x10\x9a\xbcBkA\xa3X\x11FB\ -t\xcb\x05\xda\x12\xa5\x88\x80\x93L\x09,\x15z51\ -W\xb78\xb8\x8b\x04\xcfXh\xed\xb5\xcc\x16\xfa{\xa1\ -\x95\x5caq7\xae\x82\x8b\x90\xc0E\xc6\x19\xb90\xa2\ -[8cI\xfa\x93x\xe8|\x96>\x82\xf4\xd7\xe9\xc9\ -\xe9\xc9\xe6\x1de\xe4:\xa4%\xf0\xfdU8\x83$O\ -h\x88\x9e9\x8ec\x1c\xf0\xc3\xef\x99Tu\xdb\x0fT\ -\xd2-M\xa8\xfa\xd1\xb0n\x09\x1c\xd2Lzh\x9e[\ -\xab<(\xbc\x12\xd1\x16\xbfX\xcc\xcff3\xf8\x9b\xae\ -\xce\x90;}Y\x1cLq\x18R\x16y\xc89\xdcm\ -\xb3b\xdb\xb6\xc1\xf5)\xd1\xc4&?P\xfe\x1f@i\ -|!\x95\x8a\xb2@Q\xceJd\x8d\xa849\xf0n\ -y\x90\xc9A&\x5c\xf7\xe6\xa6\x1aM\xb4M2\x82\x14\ -G\x94\x854\xc0\x8a \xa3C[4\xca?\x02\x0d|\ -\x9d)\x058\x9ez`h\xa1LqP\xf1\xb9u\xd9\ -\xf3\x0a\x13\xe0[\xa1gGC\x15C<\xed\x92\xa5\x98\ -hP5Q#\x1a\xcbQ\xed^\xc6\x82\x98\x04w\x10\ -\xe7\xa7^\xeeuN\xd4i:?\xd0\xb4\x5c.\xc7l\ -\x8c[X\xfaK\x1f\xb8\xee5\xe2\xf8\x8ey>h'\ -\xe6\x0fD\xd4#ZZp}\xb7\xaa\x01\xb2H\xdb\xf0\ -\x00\x07\x5c\x82\x9b\x82\xfe\x84\xa2\xc1I3!j f\ -\xfejf\x12\xe2C&\xd2\x84\x14\xa7FJd\x1f\xa7\ -UG~\x17\x99=PKu\xbc1fa\xd2\x89\xb7\ -\xaa\xb2@:\xe6I=\xb1\x0e\xf0\xee\xb1\x88(\xf3\x90\ -\xb5\x80+\xd3npn\x078\x99m\xad\x14G\xc7\xc3\ -3\xd7?\x0bB\xea\x0d\xb5\xbf+\xf6\xbad\xfb\xee\xd5\ -\xach\x11o@!\xab\xc6\x86\xdc\xa71\x96T\xf6u\ -\xadj\x15V\xd0l\xde\x12\x0c\xc7\xbeR\xb2\x03\xe7\x88\ -i/O\x83-j\x9c\xf2\x83\x15\xa3\xb7\xb7\xd0\x9dv\ -\xa1;\x8dB\xaf[hTi-\x8fP\xaf\xd9C\x07\ -h\xd4O_\x1f\xf8\xd5\xa3\xa7Q\xe5\xf4^g\x02\xca\ -D\xf2\xe2\xb97\xc9\x7f\xc9I$p\x1a\xd3@NB\ -\x18V\xaf\xe5C\xf4\xfceI\xc9\x1b0\x96\xae\xf9\xe3\ -@K\x9e_\xfa7\xce\xd4\x04\xf9=\x17\x04\xaa\xed\x01\ -\xe4Q\x1e\xef\xe3\x03}\xc8qK\xf1\x14H\x9c\x96\xe2\ -\xc60\xaa#\xf3!O\xb9\xf0\ +\xd1\x9b\xbb\x1b\xfd\xdd\x224\xfd\x80v\x82\xc6\x89\x22\x8c\ +D\xe8\x81\x0bt J\x11\x017\x99\x12X*\xf4a\ +j$\x0f8|\x8c\x05\xcfY\xe4T \xf3\x95\xfen\ +5\xc6-\x16\x8fg\x11\xb8\x88\x08\xc81\xce\xc8\xd6\x9c\ +<\xc0\x0dG\xd2\x9f\xc4G\xd7\xf3\xec\xfbv\xf2:\x99\ +\xec\x7f\xa7\x8c\xdcE\xb4b\x5cI\xc1s$yJ#\ +\xf4\xc6u\xdd\x82y\x10\xfd\x93Kek}\xa6\x92\x1e\ +hJ\xd5\x0f[\xaf#pDs\xe9\xa3\xa5V\xd48\ +/\xad\x11\xf1\x01\xbf[-\xaf\xe6s\xf8\x9bm\xae\x90\ +7{_\xdc\xcbp\x14Q\x16\xfb\xc8\xad%\xbb\xbeX\ +,\x16\x05\xa7/\xa9\xf6f\xfa\x03\x99\xff@Hs\x8b\ +\xa8T\x94\x85\x8arV\xb1jE\xc22\xdd\x7f\xe0a\ +.\xc7\x1c\xe0y\xf7\xf7\xcd\xe8\xa1C\x9a\x13\xa48\xa2\ +,\xa2!V\x04\x15\x10\xa0L\x03\xff\x09\xb6\xf3]\xae\ +\x14\xe8\xefM\x04s&3\x1c\x9e\x0cm\xc9\xf9~\x09\ +\x0d\xe6\x14\x10G\x1a\xa9\x04\x22\xb7\xa8\xdc\x92\x10M\xa5\ +y\xd2r\xfdz\x1c\xd7\xcfY\x98\x90\xf0\x11\x02\xfa2\ +\xe4g\x1d{\xcb-\xd7'\xb7\xac\xd7\xebQ\xf8\xb3\xe0\ +\xeb`\x1d\x80_\x87\xf0\xdd\xc05\x8fGT$\xfc\x99\ +\x08+p5\xb8\x17x\xb54$\x89\x06\xf7A?\x08\ +\x80\x94\xa0?\xa1\x16p\xda\x8a\xb9\xa5|\x1el\xe6E\ +\xcc?\xe7\x22KIyk<\xf9\xab\x98l\xba\xb9[\ +f\xed`\x8d4\x89&\x98Ei\x1f\xd1&ZI\xf1\ +\x8c\x05V\xee\xd4\xb4\x9e\xb0\x88)\xf3\x91\xb3\x02\x81Y\ +/)\xafMJ\xe6\x07'\xc3\xf1\xa5\xb4\xb4\xe8WA\ +\x88\xd5\x10\x87\xdb\xda\x90\x19\x8b\xc0\xbb\x9d\x97\xc5\xfe\x09\ +\xe0X3\x0e\xe4)K\xb0\xa4r\xa0\xf7\xd4\x85\xd5\xe0\ +\xb1\xff\x8d`\xb8\xf3\x8d\x92#\x98D\x8a&\xf12\xd6\ +g\xce9\xb8RP@\x0e\x95\xad\xdb)[\xd7.[\ +\x1b\xdb\xae;+S\xd0\x80\xc2S=\xdbu1P\xd5\ +\xaf\xfd v\xd5\xd2'\x1dp\x94\x8b\xf4\xdd[\x7fj\ +~\xc9i,p\x96\xd0PN#\x18-\x1f\xe5s\xfc\ +\xf6}\xe1\x85O\xa0&\xdb\xf1\xef\xc3\xadty\x13\xdc\ +\xbb\xb3\x22\x9a\x7fpA\xa0\x84\x9e\xe1<6\x81\xbd4\ +\xa2\xa7\x04v\x14\xcf\xc0o\xb3\xea\xd4\x9e\x1dMJ\xbe\ +\xaf\xa8\x82\x22.\x98A*\x9bq\xc9S\x07r\xd9T\ +B\x01\xb8m?\xce\xb8\xa4:E|\xe8\xf6\x19\x0a\x09\ +\x83\xba\x1f\x9cJ\xa5uV\xc7\xbf7\x1f3\xb5\xef\x98\ +\xcc\x05\xb8\xf6\x98P\x98\x18\xe6\x82\xb1yhr_w\ +\xfcf{y\xff9\x97\x895f\xcep\x1a\x01\xee\xf1\ +\xf5\xa2\xcf\xab\xa5\xb3\x87x\x9c\xcb\xbc\xd5j\xb7[\x05\ +#\xf2\x99 R\x8e\x0d\x8d\xc5fs\xb7\xa8\x068>\ +\x90td\xc2\xd6\xc4\xe7\x95)\x9d\x15\xa8\xbb)i\xe0\ +\x13\xa1+\xb4\xbf\xd1\x15q\xca\xeaQE\xee\xc0(^\ +^T\xeb\x03\xfd\xc7ft\xe9\xd0k\xd1\xeen\x1b\xd5\ +\x85\xff\xa3gi\x85\xbd\x1a\xffK\xbf\xe9\x07\xfc\xd5.\ +\x08\x03.\xa3\xac\xd1\xb5~q\x0aTVw{O\x89\ +\xeb\xfby\xe6\x1c\xaal\xaa\x0f#~d\xe5\xf1\x05\xfb\ +\xd7\xb8c\xb0\x10\xfc\xf8\x91\x86\x1c<\xa3;\xcd_\x8c\ +>Pp\xaaJ\x08\x82SVo\xa6]J\x85\x97\x06\ +\x88\x9d/\xe7\x95m\xeae\x9bt!\x12B\x7fM\x03\ +A\xb0Vn~\xec\xb0\x18\xd9\xc8n\xafgK\xaf~\ +\xfdAY\xb1\x95\xe9\x06\xda\xf3\x122RJ\xb5\xaej\ +\xcf\xea\xdbb\xbc\xc0uo\x17F\xdb73\xa2\x1a\xea\ +\xca\xed\xaf\xf5\x96\xd1\x82\x86lpRx\xc1h\x1aW\ +\xecP\xfatDe\x1b\x08\x22e\xc2k\x03\x99 \x99\ +\xf3\xde\x1d\xac\xf0\xd5\xe4\xf5_\xff\xe0\x81\x89\ +\x00\x00\x01\x02\ Q\ -ProgressBar {\x0d\x0a \ - color: #E0E0E\ -0;\x0d\x0a border: \ -2px solid #5A2A8\ -2;\x0d\x0a border-r\ -adius: 5px;\x0d\x0a \ - text-align: cen\ -ter;\x0d\x0a backgr\ -ound-color: #3C3\ -C3C;\x0d\x0a}\x0d\x0a\x0d\x0aQProg\ -ressBar::chunk {\ -\x0d\x0a background\ --color: #4800FF;\ - /* Adjusted to \ -a consistent pur\ -ple */\x0d\x0a widt\ -h: 10px;\x0d\x0a}\x0d\x0a\ -\x00\x00\x01\x14\ +ProgressBar {\x0a \ + color: #E0E0E0\ +;\x0a border: 2p\ +x solid #5A2A82;\ +\x0a border-radi\ +us: 5px;\x0a tex\ +t-align: center;\ +\x0a background-\ +color: #3C3C3C;\x0a\ +}\x0a\x0aQProgressBar:\ +:chunk {\x0a bac\ +kground-color: #\ +4800FF; /* Adjus\ +ted to a consist\ +ent purple */\x0a \ + width: 10px;\x0a}\ +\x0a\ +\x00\x00\x01\x06\ Q\ -PushButton {\x0d\x0a \ - background-col\ -or: #FFA500; /* \ -Orange */\x0d\x0a f\ -ont: bold 12px;\x0d\ -\x0a color: whit\ -e;\x0d\x0a border-r\ -adius: 8px;\x0d\x0a}\x0d\x0a\ -\x0d\x0aQPushButton:ho\ -ver {\x0d\x0a backg\ -round-color: #40\ -E0D0; /* Turquoi\ -se */\x0d\x0a}\x0d\x0a\x0d\x0aQPus\ -hButton:pressed \ -{\x0d\x0a backgroun\ -d-color: #FF6347\ -; /* Tomato */\x0d\x0a\ -}\x0d\x0a\ -\x00\x00\x01\x0e\ +PushButton {\x0a \ + background-colo\ +r: #FFA500; /* O\ +range */\x0a fon\ +t: bold 12px;\x0a \ + color: white;\x0a\ + border-radiu\ +s: 8px;\x0a}\x0a\x0aQPush\ +Button:hover {\x0a \ + background-co\ +lor: #40E0D0; /*\ + Turquoise */\x0a}\x0a\ +\x0aQPushButton:pre\ +ssed {\x0a backg\ +round-color: #FF\ +6347; /* Tomato \ +*/\x0a}\x0a\ +\x00\x00\x01\x02\ Q\ -ProgressBar {\x0d\x0a \ - color: #E0E0E\ -0;\x0d\x0a border: \ -2px solid #5A2A8\ -2;\x0d\x0a border-r\ -adius: 5px;\x0d\x0a \ - text-align: cen\ -ter;\x0d\x0a backgr\ -ound-color: #3C3\ -C3C;\x0d\x0a}\x0d\x0a\x0d\x0aQProg\ -ressBar::chunk {\ -\x0d\x0a background\ --color: #FF8C00;\ - /* Adjusted to \ -a consistent ora\ -nge */\x0d\x0a widt\ -h: 10px;\x0d\x0a}\x0d\x0a\ -\x00\x00\x01\x0c\ +ProgressBar {\x0a \ + color: #E0E0E0\ +;\x0a border: 2p\ +x solid #5A2A82;\ +\x0a border-radi\ +us: 5px;\x0a tex\ +t-align: center;\ +\x0a background-\ +color: #3C3C3C;\x0a\ +}\x0a\x0aQProgressBar:\ +:chunk {\x0a bac\ +kground-color: #\ +FF8C00; /* Adjus\ +ted to a consist\ +ent orange */\x0a \ + width: 10px;\x0a}\ +\x0a\ +\x00\x00\x01\x00\ Q\ -ProgressBar {\x0d\x0a \ - color: #E0E0E\ -0;\x0d\x0a border: \ -2px solid #5A2A8\ -2;\x0d\x0a border-r\ -adius: 5px;\x0d\x0a \ - text-align: cen\ -ter;\x0d\x0a backgr\ -ound-color: #3C3\ -C3C;\x0d\x0a}\x0d\x0a\x0d\x0aQProg\ -ressBar::chunk {\ -\x0d\x0a background\ --color: #FF0088;\ - /* Adjusted to \ -a consistent pin\ -k */\x0d\x0a width:\ - 20px;\x0d\x0a}\x0d\x0a\ -\x00\x00\x01\xc2\ +ProgressBar {\x0a \ + color: #E0E0E0\ +;\x0a border: 2p\ +x solid #5A2A82;\ +\x0a border-radi\ +us: 5px;\x0a tex\ +t-align: center;\ +\x0a background-\ +color: #3C3C3C;\x0a\ +}\x0a\x0aQProgressBar:\ +:chunk {\x0a bac\ +kground-color: #\ +FF0088; /* Adjus\ +ted to a consist\ +ent pink */\x0a \ +width: 20px;\x0a}\x0a\ +\x00\x00\x01\xb2\ Q\ -PushButton {\x0d\x0a \ - padding: 5px;\x0d\ -\x0a color: #DDD\ -;\x0d\x0a font-weig\ -ht: bold;\x0d\x0a f\ -ont-size: 14px;\x0d\ -\x0a background:\ - qlineargradient\ -(x1:0, y1:0, x2:\ -1, y2:0, stop:0 \ -#78909C, stop:1 \ -#90A4AE);\x0d\x0a b\ -order-radius: 4p\ -x;\x0d\x0a}\x0d\x0a\x0d\x0aQPushBu\ -tton:hover {\x0d\x0a \ - background: ql\ -ineargradient(x1\ -:0, y1:0, x2:1, \ -y2:0, stop:0 #90\ -A4AE, stop:1 #B0\ -BEC5);\x0d\x0a}\x0d\x0a\x0d\x0aQPu\ -shButton:pressed\ - {\x0d\x0a backgrou\ +PushButton {\x0a \ + padding: 5px;\x0a \ + color: #DDD;\x0a\ + font-weight:\ + bold;\x0a font-\ +size: 14px;\x0a \ +background: qlin\ +eargradient(x1:0\ +, y1:0, x2:1, y2\ +:0, stop:0 #7890\ +9C, stop:1 #90A4\ +AE);\x0a border-\ +radius: 4px;\x0a}\x0a\x0a\ +QPushButton:hove\ +r {\x0a backgrou\ nd: qlineargradi\ ent(x1:0, y1:0, \ x2:1, y2:0, stop\ -:0 #607D8B, stop\ -:1 #78909C);\x0d\x0a}\x0d\ +:0 #90A4AE, stop\ +:1 #B0BEC5);\x0a}\x0a\x0a\ +QPushButton:pres\ +sed {\x0a backgr\ +ound: qlineargra\ +dient(x1:0, y1:0\ +, x2:1, y2:0, st\ +op:0 #607D8B, st\ +op:1 #78909C);\x0a}\ \x0a\ -\x00\x00\x01\xc7\ +\x00\x00\x01\xbb\ Q\ -ProgressBar {\x0d\x0a \ - color: #E0E0E\ -0; /* Text color\ - adjusted for vi\ -sibility */\x0d\x0a \ - border: 2px sol\ -id #5A2A82; /* P\ -urple border for\ - consistency */\x0d\ -\x0a border-radi\ -us: 5px; /* Roun\ -ded corners */\x0d\x0a\ - text-align: \ -center; /* Cente\ -red text */\x0d\x0a \ +ProgressBar {\x0a \ + color: #E0E0E0\ +; /* Text color \ +adjusted for vis\ +ibility */\x0a b\ +order: 2px solid\ + #5A2A82; /* Pur\ +ple border for c\ +onsistency */\x0a \ + border-radius:\ + 5px; /* Rounded\ + corners */\x0a \ +text-align: cent\ +er; /* Centered \ +text */\x0a back\ +ground-color: #3\ +C3C3C; /* Dark b\ +ackground for th\ +e progress bar *\ +/\x0a}\x0a\x0aQProgressBa\ +r::chunk {\x0a b\ +ackground-color:\ + #7A7AFF; /* Adj\ +usted chunk colo\ +r for consistenc\ +y */\x0a width: \ +20px; /* Chunk w\ +idth */\x0a}\x0a\ +\x00\x00\x01\x0e\ +Q\ +PushButton {\x0a \ background-colo\ -r: #3C3C3C; /* D\ -ark background f\ -or the progress \ -bar */\x0d\x0a}\x0d\x0a\x0d\x0aQPr\ -ogressBar::chunk\ - {\x0d\x0a backgrou\ -nd-color: #7A7AF\ -F; /* Adjusted c\ -hunk color for c\ -onsistency */\x0d\x0a \ - width: 20px; \ -/* Chunk width *\ -/\x0d\x0a}\x0d\x0a\ -\x00\x00\x01\x1c\ +r: #4CAF50; /* G\ +reen */\x0a font\ +: bold 14px;\x0a \ + color: white;\x0a \ + border-radius\ +: 10px;\x0a}\x0a\x0aQPush\ +Button:hover {\x0a \ + background-co\ +lor: #66BB6A; /*\ + Lighter green *\ +/\x0a}\x0a\x0aQPushButton\ +:pressed {\x0a b\ +ackground-color:\ + #388E3C; /* Dar\ +k green */\x0a}\x0a\ +\x00\x00\x01\x16\ Q\ -PushButton {\x0d\x0a \ - background-col\ -or: #4CAF50; /* \ -Green */\x0d\x0a fo\ -nt: bold 14px;\x0d\x0a\ - color: white\ -;\x0d\x0a border-ra\ -dius: 10px;\x0d\x0a}\x0d\x0a\ -\x0d\x0aQPushButton:ho\ -ver {\x0d\x0a backg\ -round-color: #66\ -BB6A; /* Lighter\ - green */\x0d\x0a}\x0d\x0a\x0d\x0a\ -QPushButton:pres\ -sed {\x0d\x0a backg\ -round-color: #38\ -8E3C; /* Dark gr\ -een */\x0d\x0a}\x0d\x0a\ -\x00\x00\x01$\ +PushButton {\x0a \ + background-colo\ +r: #FFA200; /* S\ +olid orange */\x0a \ + font: bold 12\ +px;\x0a color: w\ +hite;\x0a border\ +-radius: 8px;\x0a}\x0a\ +\x0aQPushButton:hov\ +er {\x0a backgro\ +und-color: #FFB7\ +4D; /* Lighter o\ +range */\x0a}\x0a\x0aQPus\ +hButton:pressed \ +{\x0a background\ +-color: #F57C00;\ + /* Dark orange \ +*/\x0a}\x0a\ +\x00\x00\x01\x10\ Q\ -PushButton {\x0d\x0a \ - background-col\ -or: #FFA200; /* \ -Solid orange */\x0d\ -\x0a font: bold \ -12px;\x0d\x0a color\ -: white;\x0d\x0a bo\ -rder-radius: 8px\ -;\x0d\x0a}\x0d\x0a\x0d\x0aQPushBut\ -ton:hover {\x0d\x0a \ +PushButton {\x0a \ background-colo\ -r: #FFB74D; /* L\ -ighter orange */\ -\x0d\x0a}\x0d\x0a\x0d\x0aQPushButt\ -on:pressed {\x0d\x0a \ - background-col\ -or: #F57C00; /* \ -Dark orange */\x0d\x0a\ -}\x0d\x0a\ -\x00\x00\x01\x1e\ +r: #7B1FA2; /* P\ +urple */\x0a fon\ +t: bold 12px;\x0a \ + color: white;\x0a\ + border-radiu\ +s: 8px;\x0a}\x0a\x0aQPush\ +Button:hover {\x0a \ + background-co\ +lor: #9575CD; /*\ + Lighter violet \ +*/\x0a}\x0a\x0aQPushButto\ +n:pressed {\x0a \ +background-color\ +: #6A1B9A; /* Da\ +rk purple */\x0a}\x0a\ +\x00\x00\x01(\ Q\ -PushButton {\x0d\x0a \ - background-col\ -or: #7B1FA2; /* \ -Purple */\x0d\x0a f\ -ont: bold 12px;\x0d\ -\x0a color: whit\ -e;\x0d\x0a border-r\ -adius: 8px;\x0d\x0a}\x0d\x0a\ -\x0d\x0aQPushButton:ho\ -ver {\x0d\x0a backg\ -round-color: #95\ -75CD; /* Lighter\ - violet */\x0d\x0a}\x0d\x0a\x0d\ -\x0aQPushButton:pre\ -ssed {\x0d\x0a back\ -ground-color: #6\ -A1B9A; /* Dark p\ -urple */\x0d\x0a}\x0d\x0a\ -\x00\x00\x016\ +PushButton {\x0a \ + background-colo\ +r: rgb(128, 0, 0\ +); /* Dark red *\ +/\x0a font: bold\ + 14px;\x0a color\ +: white;\x0a bor\ +der-radius: 10px\ +;\x0a}\x0a\x0aQPushButton\ +:hover {\x0a bac\ +kground-color: r\ +gb(255, 0, 0); /\ +* Bright red */\x0a\ +}\x0a\x0aQPushButton:p\ +ressed {\x0a bac\ +kground-color: r\ +gb(153, 0, 0); /\ +* Deeper dark re\ +d */\x0a}\x0a\ +\x00\x00\x01\x03\ Q\ -PushButton {\x0d\x0a \ - background-col\ -or: rgb(128, 0, \ -0); /* Dark red \ -*/\x0d\x0a font: bo\ -ld 14px;\x0d\x0a co\ -lor: white;\x0d\x0a \ - border-radius: \ -10px;\x0d\x0a}\x0d\x0a\x0d\x0aQPus\ -hButton:hover {\x0d\ +ProgressBar {\x0a \ + color: #E0E0E0\ +;\x0a border: 2p\ +x solid #5A2A82;\ +\x0a border-radi\ +us: 5px;\x0a tex\ +t-align: center;\ \x0a background-\ -color: rgb(255, \ -0, 0); /* Bright\ - red */\x0d\x0a}\x0d\x0a\x0d\x0aQP\ -ushButton:presse\ -d {\x0d\x0a backgro\ -und-color: rgb(1\ -53, 0, 0); /* De\ -eper dark red */\ -\x0d\x0a}\x0d\x0a\ -\x00\x00\x01\x0f\ +color: #3C3C3C;\x0a\ +}\x0a\x0aQProgressBar:\ +:chunk {\x0a bac\ +kground-color: #\ +D500FF; /* Adjus\ +ted to a consist\ +ent magenta */\x0a \ + width: 20px;\x0a\ +}\x0a\ +\x00\x00\x01\xc2\ Q\ -ProgressBar {\x0d\x0a \ - color: #E0E0E\ -0;\x0d\x0a border: \ -2px solid #5A2A8\ -2;\x0d\x0a border-r\ -adius: 5px;\x0d\x0a \ - text-align: cen\ -ter;\x0d\x0a backgr\ -ound-color: #3C3\ -C3C;\x0d\x0a}\x0d\x0a\x0d\x0aQProg\ -ressBar::chunk {\ -\x0d\x0a background\ --color: #D500FF;\ - /* Adjusted to \ -a consistent mag\ -enta */\x0d\x0a wid\ -th: 20px;\x0d\x0a}\x0d\x0a\ -\x00\x00\x01\xce\ +ProgressBar {\x0a \ + color: #E0E0E0\ +; /* Text color \ +adjusted for vis\ +ibility */\x0a b\ +order: 2px solid\ + #5A2A82; /* Pur\ +ple border for c\ +onsistency */\x0a \ + border-radius:\ + 5px; /* Rounded\ + corners */\x0a \ +text-align: cent\ +er; /* Centered \ +text */\x0a back\ +ground-color: #3\ +C3C3C; /* Dark b\ +ackground for th\ +e progress bar *\ +/\x0a}\x0a\x0aQProgressBa\ +r::chunk {\x0a b\ +ackground-color:\ + rgb(255, 0, 0);\ + /* Adjusted chu\ +nk color for con\ +sistency */\x0a \ +width: 20px; /* \ +Chunk width */\x0a}\ +\x0a\ +\x00\x00\x01\x00\ Q\ -ProgressBar {\x0d\x0a \ - color: #E0E0E\ -0; /* Text color\ - adjusted for vi\ -sibility */\x0d\x0a \ - border: 2px sol\ -id #5A2A82; /* P\ -urple border for\ - consistency */\x0d\ +ProgressBar {\x0a \ + color: #E0E0E0\ +;\x0a border: 2p\ +x solid #5A2A82;\ \x0a border-radi\ -us: 5px; /* Roun\ -ded corners */\x0d\x0a\ - text-align: \ -center; /* Cente\ -red text */\x0d\x0a \ - background-colo\ -r: #3C3C3C; /* D\ -ark background f\ -or the progress \ -bar */\x0d\x0a}\x0d\x0a\x0d\x0aQPr\ -ogressBar::chunk\ - {\x0d\x0a backgrou\ -nd-color: rgb(25\ -5, 0, 0); /* Adj\ -usted chunk colo\ -r for consistenc\ -y */\x0d\x0a width:\ - 20px; /* Chunk \ -width */\x0d\x0a}\x0d\x0a\ -\x00\x00\x01\x0c\ -Q\ -ProgressBar {\x0d\x0a \ - color: #E0E0E\ -0;\x0d\x0a border: \ -2px solid #5A2A8\ -2;\x0d\x0a border-r\ -adius: 5px;\x0d\x0a \ - text-align: cen\ -ter;\x0d\x0a backgr\ -ound-color: #3C3\ -C3C;\x0d\x0a}\x0d\x0a\x0d\x0aQProg\ -ressBar::chunk {\ -\x0d\x0a background\ --color: #00AA7F;\ - /* Adjusted to \ -a consistent tea\ -l */\x0d\x0a width:\ - 10px;\x0d\x0a}\x0d\x0a\ -\x00\x00\x01\x86\ +us: 5px;\x0a tex\ +t-align: center;\ +\x0a background-\ +color: #3C3C3C;\x0a\ +}\x0a\x0aQProgressBar:\ +:chunk {\x0a bac\ +kground-color: #\ +00AA7F; /* Adjus\ +ted to a consist\ +ent teal */\x0a \ +width: 10px;\x0a}\x0a\ +\x00\x00\x01u\ Q\ -PushButton {\x0d\x0a \ - background-col\ -or: #2196F3; /* \ -Vivid blue */\x0d\x0a \ - color: white;\ -\x0d\x0a font-size:\ - 14px;\x0d\x0a bord\ -er-radius: 4px;\x0d\ -\x0a border: non\ -e;\x0d\x0a padding:\ - 6px 12px;\x0d\x0a}\x0d\x0a\x0d\ -\x0aQPushButton:hov\ -er {\x0d\x0a backgr\ -ound-color: #64B\ -5F6; /* Lighter \ -blue */\x0d\x0a bor\ -der-color: #BBDE\ -FB; /* Even ligh\ -ter blue border \ -*/\x0d\x0a}\x0d\x0a\x0d\x0aQPushBu\ -tton:pressed {\x0d\x0a\ - background-c\ -olor: #1976D2; /\ -* Darker blue */\ -\x0d\x0a}\x0d\x0a\ -\x00\x00\x06\x19\ +PushButton {\x0a \ + background-colo\ +r: #2196F3; /* V\ +ivid blue */\x0a \ + color: white;\x0a \ + font-size: 14\ +px;\x0a border-r\ +adius: 4px;\x0a \ +border: none;\x0a \ + padding: 6px 1\ +2px;\x0a}\x0a\x0aQPushBut\ +ton:hover {\x0a \ +background-color\ +: #64B5F6; /* Li\ +ghter blue */\x0a \ + border-color: \ +#BBDEFB; /* Even\ + lighter blue bo\ +rder */\x0a}\x0a\x0aQPush\ +Button:pressed {\ +\x0a background-\ +color: #1976D2; \ +/* Darker blue *\ +/\x0a}\x0a\ +\x00\x00\x06&\ \x00\ -\x00\x17,x\xda\xddXmo\xdb6\x10\xfe\x1e \xff\ -\xe1\x96\x00k\x5cTVcom\x17\xb4\x05\x1c;/\ -N\x9d\xce\xab\xd3\xa2@0\x04\x94t\x96\x18K\xa4L\ -Rq\xdc_\xbf#e7\x8e\xab\xb4\x8e\x86\x01\xc5\x10\ -\xc0\xb1\xc5\xe7y\xee\x85\xe4\x91\xa7]\x18J%\xe0\x18\ -M\x98\xc0\xa7v\xb3\xbd\xbd\xb5\xbd\xd5\x95\xf9\x5c\xf18\ -1\xb0\xd7m@\xeby\xab\xed\xd1\xc7op&\x13&\ -\x04j8e\x01\xa6\xb0w\x14&\x06U'\xd5\xc7l\ -\x82\x0d\xcb\xdc\xde\xda\xdd\xdd\x85\x8b\x84k\x18*y\x8d\ -\xa1\x01\xfa*E:\x87\x5cj\xcd\x83\x14\xc1\x90\xc8D\ -\x83\x91p\x14k\x16K\xf1D\xc3\xe5\xf0\xf4\xe3\xe1\xdf\ -{\x891\xb9>\xf0\xfd\x98\x9b\xa4\x08\x9a\xa1\xcc\xfc{\ -6|\x0bk@g\xd8/M\xc10E\xa6\x11\xc2\x04\ -\xc3\x09\xc8\xc2\x80\xb5\x9c/,3\x11A\xcco\x108\ -}\x07m\x98\xfa\xc5\xd1\xa0\x877\x98\xca\x0f-\xbe\x14\ -\x1b\xa6\xcc\x8c\xa5\xca\xc8\xf6\x097\xa7EP\x95\x04\x87\ -{\x0b\xc1\ -\xfcG\xa6\xe8\x87Q<(\x8cT\xda\xe7s>\x91\xa2\ -\x9e\xcd\xbe\xe3B\xb3\xd9\xb4\x967\x0e\x92\x0b;Y\xcc\ -\xf0\xdav\xef\x04\xea\x84\x9c\xa3a\xdc\xbbf\xf4\x88\xe5\ -rC'\xde\x0e-\x0b\xce\xbe\xb2\x9ce\x8a\xfe\xfb\x96\ -7\xd3\xee\x13ed)\x8f\xcac!\x14\xb2\xa8^\x0a\ -Kn\x9d\xec\x05\xb4\xef\x98\xf1\x1cb\xb3\xe8\x0e\x1d\x83\ -\x0a\x86\xe6\xf1O\x906#s\x8f)%g\xf52w\ -!s\xe8Xz\x9d\xe4\x85\x94uC\xd5\xd4\xd3\xa6\x88\ -\xb8\xac\xe7\xc19g\x02F\x8c\x05\x8f\x0a;\x923\xf1\ -o\xe2\xee\x11\xbf~\xe0,b\xd9#\x96L\x87\xe0\xd0\ -s\x84\x9f`\xc1\xf0pRs\xad\x10\xb3N\xb6&2\ -\x95^\xe4\xf6K=\xc3\xef\x18\x91\x92GE\xc9Bz\ - j\x9e>\x0br\xad\x95!\xe2\x98\xeaC^P]\ -\xddpq\x94\x0c\x18Z\xca\xcfPOd\xaa\xeb\xd6\x12\ -\xa2\xd6\xdbN\x99v%\xb8\x9e\xddN\xef|\x04\xfd\xe5\ -\xee\xda8\xd21\x9b\xd6\xb3w\xcc\xa6\xff\xd3\x83\xdaV\ -\xc5T\xb2\xc8e\xd3\xc6wyQ\x98b\x22\xc7wW\ -\xc2\xef\x048F\xa5\x0b\xcd\x94Y\xdc)\x11\xe1r\x84\ -\xc6p\x11k\xa7\xf8\x90\xca\x98\xa0n\xfe}\xbd\x80{\ -\xadW\xbf\xbf\xf8c\xbf\xdd\x00.\xec\xbd3\xe2t1\ -\x87\x91\x99\xa7\xb8\xbduH~\x9d\xb2\x90\xd1o{\xec\ -l\xe4[ \xa56v\xbc\xf1\x88#F`\xdd\xc3E\ -`\x9d\x15\x12K\x19\xa7\x94\x09\x11n6\x7f'\x0eO\ -\xf7\xfe\xb0\xf9\x1f.\x0b\xfb7\x90\xb1\x84\x19\xd3\x10\xa3\ -@\xba\xfe`dc\xebu\x06\x03\xef\x88:\xc2\x84\x99\ -\x93\xe1\x05\xa5\xf6u\xa0\xde\x8ed\x86@V\xd0h`\ -\x0a\xc5\x13\x03\x85&\x02\x13\xf3L*|\x06\x01\x86\x8c\ -\x9e@\x1f\x12F\xadX\x84!\xb5*\x91\xed\xfe\xecS\ -\x813pN?\xdb\xde\xa2\xbc\x10*\xe2\x91\x15\x99\xd1\ -\x1e\xb0 \x85\x99\xbc\xb1=#f\xcdE\xcf\xd7]\xc9\ -\xa2\x9d\xdf\xcbE\x1bY\xdd>\x96c\x0d\xb0\x9d\xa3m\ -\x1c\xe1W\xbbX\x05u\xbb\x17\x8a\x09\x9d\xba\xabx\xa9\ -\xf3a\xd4\xeb\x1e\x9f|:=<{\xff\xee|P)\ -w\x1f\xd2\x80\x038\x12\xd4\xce\x86h{I\xb8\xdc\xdd\ -\xdf\xdf\xa4\x89\xa5\x8e\xfb\xcau\xdc>\xd7\xba@\xed\xef\ -\xef\xbb\x95\xdaMh~(+{\xed\xe6\xf3\x06u\xd1\ -\x8b>\x99\xfa\xb43\xa9\x93\x82y\xacH\xb4\xbc\xae4\ -q\x0f\xd1\xa0(\xd7\x1c{Y\xcf\xb1\x97\x8d25R\ -\x0c\x98\xda\xdfo\xb7\xaa\xd3\xf2u\xb8\xb1f\xb7\xf5\xbc\ -\x96\xdd\x16\xc5\xbfG\xbd\xf1\xdcv\x950*\xf2\x5cR\ -\xa5y\xb6.\xfe\xaa\x9e\xf8+\x12\xef\x16\xda\xc8\x8c\xd6\ -\x97QsHy\xc6\xcbBvy{\xdb\x17\x11W\x18\ -\x9aJ\xed\xbb\xe1\xf5H\x1fH\xcd\x8f\x9c\xa1\x949\xbb\ -8V\xecVWJ\x94C\xdf\xd8\xab7\xa3\xed\x97\x14\ -\xfc\x07\xba\xb9 hL)\x0e\xaa\xc0\xeeM\x89\xe1\xb4\ -\x935\xa5\xd9\x96\xe4F\xf9\x12`\xc0\x03\xc5\x14\xc7r\ -\x7f<\xea\x1d\xcd\xde\xc9pp\xd3.cS8%\xd3\ -\xa6:\xba\x5c\x8f\xfd%\x80h\x9d\x9c\x85\x09B\x8bv\ -\x80\xe3&S\x9az*CW,\xe7\x1b\x18_\x85\x93\ -\xda`\xc5\x8b\xa4\xc0+\x9d\xf0\xb1\xd9Df\x89]\xd3\ -\xd8\xfcM\x8bK\x00\xf8`\xd9%7\xa4\x9b\xb1b\x19\ -\xab4O\xa7\x8aIq\xee/A\xc4?\x1c\xf5\xa0\x0d\ -\xdd\xd4\x96\xcfR!cjb{\xa1J\x85\xf2\xd5\x95\ -w\xbe\xc0\xf8Kp\xa5\x92\xe2aR\xa9rAgE\ -\xc1R:\x1d|\x8b!\xf2y\xff\xa2\xe4\x98i\x94U\ -\xfbN\x03\xeec\x15}4t\xf3`K\xee\x06\xf9\xc6\ -\x07g\xed\xf3\xfb\xcf\x9f7\x14\xb9\x15\xb7\xb7U\x0a\x9f\ -h\xca\xa4\xbe\xdaP\xe4\xa6D\x7f\xab\x83l|\x150\ -\x8d\x0f\xaeDtB,\xd5c\x17\xd2\x0a|M)\x9f\ -\xe7\x8a\xea<\xed\xe5J\x9d\xe9\x0c\x95\x99\xd3\x8e\xa0O\ -\xff\x0e\xbb\x9a\xdd\xf18\xcb1\xf6r%c\x1a\xd5\xde\ -\x9cc\x1aU\x8a\xe94\x09'~%~U\xf0\xbc0\ -\x8c\x8e\xfbj\x7f\x0a\x19\xa5<@\xe3g%j\xb1\xbb\ -[\x8b;@\xe7}\xef\xc3\x9f\xfd\xde\x81\x13:,x\ -\x1a\xc9/\xa8*\xa5&\xfcf\xee\x07K\xc8\xaa\x03\xdd\ -\xb57\xaf+\xa4\xd0\x0d-\xfe\xad\x97\x08[\xa6:y\ -\x9e\xf2p\xe5$?>>\x1f\x1e\x9d\xdc\x89\x95\xe1\x97\ -\xafp\x9d\xef\x8e\xf8\xf4)t\xd2\x14$].\x14\x1d\ -\x01\x8bRg\xaf1`]4\xf6:JW\x90rc\ -\xd1\xed\xe3\x1f\xaa\xa1\xfdr\ +\x00\x18\x22x\xda\xddXko\xdb6\x14\xfd\xee_q\ +\x97\x00[\x5cTVcom\x17\xb4\x01\x1c;\x0f\xa7\ +N\xe7\xd5iP \x18\x02J\xba\x96\x18S\xa4BR\ +q\xdc_\xbfK:\xae\x93Ti\x1d\x0dC\x87}\xf1\ +C:\xe7\xdc\x07\xc9K^n\xc2Hi\x09\x07h\xe3\ +\x0c\xce:\xadN\xa3\xd1S\xc5\x5c\xf34\xb3\xb0\xd5k\ +B\xfbE\xbb\x13\xd0\xc7\xafp\xac2&%\x1a8b\ +\x11\x0a\xd8\xda\x8f3\x8b\xba+\xcc\x01\x9bb\xb3\xd1h\ +lnn\xc2i\xc6\x0d\x8c\xb4\xba\xc4\xd8\x02\xfdTR\ +\xcc\xa1P\xc6\xf0H XR\x98\x1a\xb0\x0a\xf6S\xc3\ +R%\x7f1p>:\xfa\xb8\xf7\xd7Vfmav\ +\xc20\xe56+\xa3V\xac\xf2\xf0\x9e\x81\xd0\xc1\x9a\xd0\ +\x1d\x0d\x9c!\x18\x09d\x06!\xce0\x9e\x82*-8\ +\xbb\xc5\xad]&\x13H\xf95\x02\xa7\xdf`,\xd3?\ +\x11\x09\xfax\x8dB\x159J\xdb\x08`\xc8dZ\xb2\ +\x14w\xc8\x83\xb9\xcd\x94\x5c\xf90\x9b\xcdZ\x85\x7f\xd6\ +R:\x0d\x9b\x84\x1e\xf4\xf7w\xe0\x18m\xa4\x19\x97\xce\ +\xe9y/c:w\xa1N\x90\xa2S\x92\x89\xfb\x02\x97\ +K\xb0\x8f\xa5\x98\xc7\x0e\xef\xb5F\x82\xd9\x89\xd29Y\ +>\xe4\xf6\xa8\x8c\xaa\xa2w\xc0C\xcd\x8a\x8c\xc7L\xc0\ +G\x83\x1a\x06\x92\xd21a\xf1\xc2\xe51O\xf0\xe5\x8a\ +\x99\xa8\xb8ue[\x5c\x85WN|\xe1~\xf0\xd2\x1b\ +<\xd0,\xc7\x99\xd2S\x22\xfeiW\x1c\x8f\xf7#\xb7\ +4e\x08\xfd\x86A\xa6q\xf2vc\x09\xe3\xb1\x92&\ +\xa6$\xfbH\xfc\xbfPpc7 \x16\xcc\x98\xb7\x1b\ +\x16olP\xca\x04\xb5\xe0\x12a\xa2\xa4\x0d\x0c\xff\x8c\ +\x81\xc97\x80\xb2\x9f\xa2}\xbbq\x11\x09\x1a\xfc\x8d\xdd\ +!1\xdf\x84l\x17\xa2\xf9\xf7L\xd1\x1f\xabyTZ\ +\xa5M\xc8\xe7|\xaad=\x9b\x03\xcf\x85V\xab\xe5,\ +\xaf\x1b#\x97n\x94\x98\xe5\xb5\xcd\xae\x04\xeaD\x5c\xa0\ +e<\xb8d\xf4\x88\x15jM'vG\x8e\x05\xc7_\ +X\xde2\x05\xffm\xcb\xebi\x0f\x882v\x94\xa7\xa4\ +\xb1\x94\x1aYR/\x83\x0bn\x9d\xe4E\xb4\xdc\x98\x0d\ +Fk\xb9L\x8d\x17|LdB\ +P?\xf8\xa1\xb9\x85\x07\xed\xd7\xbf\xbd\xfc}\xbb\xd3\x04\ +.\xdda3\xe1t\x0a\x87\xb1\x9d\x0bl\xec\x91WG\ +,f\xf4\xd7m7ky\x16)e\xac{\xdf\x5c\x7f\ +k\x91XwS\x91Xgv\xa4J\xa5\x82\xf2 \xe3\ +\xf5\xc6\xee\xd0\xe3\xe9\x98\x1f\xb7~x\xc9\xa0V*\xd5\ +\xd4\xd8DL\xd7K\xdah%P'w\xd7\x8c\xa6\x88\ +|\xca\xf1\xed\xcc3V5\xe3\xdfI_c\xa8R\x05\ +3f E\x89t^\xc4\xc4\x85\xd6\xef\x0e\x87\xc1>\ +5\xcc\x19\xb3\x87\xa3\xd3f\xe3M\xa4w\xc7*G \ +\x03h\x0d0\x8d\xf2\x17\x0b\xa5!<\x93\xf3\x5ci\x84\ +\x08cF\x0f`\x00\x19\xa3f5\xc1\x98Z\xba\xc4u\ +\xc7\xee\xa9\xc4\x19xw\x9f7('\x04Jx\xe2$\ +fT7\x1cFc\xae\xae]K\x8dy\xcb\xb7\xc4\xbd\ +;\xf9\xa3a>\xbfm\xb1\xab[\xeb\xc5\xbb&\xb8\xae\ +\xda5\xd5\xf0\xb3[\xdf2\xce\xe0T3i\x84oZ\ +\xbc\xcc\x87q\xbfwpxv\xb4w\xfc\xfe\xdd\xc9\xb0\ +R\xed>\xa4\x09;\xb0/\xa9\xd3\x8f\xd1\xb5\xdap\xbe\ +\xb9\xbd\xbdN\x7f\xaf\xb4\xbc\xf0\xf7\x10!7\xa6D\x13\ +no\xbb\xc5\xdd\xcbhL(\x1f[\x9d\xd6\x8b&\x9c\ +.o\x10\xa8\x95=V&+Y\xc0\xca\xcc\xa8\xcbJ\ +\x0b\xf7\x10M\x8a\xf1\x81_\xaf\xea\xf9\xf5\xaa\xe9\x13\xa3\ +\xe4\x90\xe9\xed\xedN\xbb:)_^7\x1f\x98m\xbf\ +\xa8e\xb6M\xe1o\x8d\x04\x9b\xbb\xde\x1b\xc6eQ(\ +*\xcc\xcf\x1f\x8a\xbf\xae'\xfe\x9a\xc4{\xa5\xb1*\xa7\ +\x99e\xf5\x1c\x04\xcf\xb9\xaf\xfb\xe777\x03\x99p\x8d\ +\xb1\xad\x94^\xbd~\x18\xe8#\x99\xf9\x9e/\x941g\ +\x16'\x9a\xdd\x98J\x85\xc5\xab\xaf\xcc\xd5\x1b\xce\xce+\ +\x0a\xfd\x03\x9d\xf1\x10\x0c\x0a\x0a\x83\xf6+\x7f\x85d9\ +\xad_CI\xa6\x07MwI2\xe4\x91f\x9a\xa3_\ +\x17O\xba\xb6\xda:\x1c\x0d\xaf;>,\x8dWd\xd5\ +V\x07V\x98I\xb8\x04\x10\xab[\xb08Ch\xd3\xcc\ +w\xd4\xec\x8a\x86\x9c\xaa\xce\x05+\xf8\x1a\xa6\xef\xc2I\ +l\xb8\xf2!+\xf1\xc2d|b\xd7QYb\xefK\ +\xac\x7f\x01\xe5\x83\x87\x10\x1c\xd9Sc\xea\x1c4\xcbY\ +\xa5q\xdaG\xac\xc0y\xb8\x04\x11}o\xdc\x87\x0e\xf4\ +\x84+\x96^ gz\xea:\xc5J\x81\xc5e^p\ +r\x8b\x09\x97\xe0*!\xcd\xe3\xacR\xe4\x94v\x84\x92\ +\x09\xda\x03B\x87!\xee\xc9\xe0\xd4S\xecU\x92W;\ +N/\xfc\xc7\x1d\xf0\xfe\xc8\x0f\x80+\xb0kd\x1a\x1f\ +\x1b\xaeO\xef?}ZS\xe3F\xde\xdcT\x08\x9c\xd1\ +X)s\xb1\xa6\xc6\xf5\x02\xfd\x95\x0c\xb2\xc9E\xc4\x0c\ +>:\xff\xd0\xeb0a&>\x9e;\xf0\xfbB\xc5\xbc\ +\xa0\xb3\x01m7X)s5Cm\xe7\xb4\x0a\xe83\ +\x5ca\xef$v2\xc9\x0bL\x83\xe5)%\x98s\x14\ +I\xa5\x96\x11Y<\x0d+\xf1w\xf4NJ\xcbhC\ +\xaf\xf6\xa6T\x89\xe0\x11\xda0_\xa0n\x97s{\xb1\ +\xcbw\xdf\xf7?\xfc1\xe8\xef8\x99\xbd\x92\x8bD}\ +F])4\xe5\xd7\xf30ZB\xeeX\xef=\xb8\x7f\ +\xbe\xc3\x89\xfd\xab\xdb\xaf\x07\x15\x81*R\xb7(\x04\x8f\ +W\x9b\xf5\xc1\xc1\xc9h\xffp\xa5\xb4\x88{q\x8b\xed\ +\xbd&\xd6\xb3g\xd0\x15\x02\x14\x9d\x1c4U\xf9\xdb\x92\ +\xe6N(\xe0\x9c\xb3\xee\x84N\xe7\x8b\xc5:j5\xfe\ +\x06u,k\xc3\ \x00\x00\x1a\xfc\ <\ \xb8d\x18\xca\xef\x9c\x95\xcd!\x1c\xbf`\xa1\xbd\xdd\xa7\ @@ -10636,6 +10644,10 @@ \x06HW\xa7\ \x00d\ \x00o\x00n\x00e\x00.\x00s\x00v\x00g\ +\x00\x10\ +\x05\x92\xec\xa7\ +\x00p\ +\x00r\x00o\x00g\x00r\x00e\x00s\x00s\x00b\x00a\x00r\x00s\x00.\x00s\x00v\x00g\ \x00\x0d\ \x0f\xb0?_\ \x00t\ @@ -10773,7 +10785,7 @@ qt_resource_struct = b"\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x002\x00\x02\x00\x00\x00\x01\x00\x00\x00\x18\ +\x00\x00\x002\x00\x02\x00\x00\x00\x01\x00\x00\x00\x19\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00B\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0b\ \x00\x00\x00\x00\x00\x00\x00\x00\ @@ -10783,74 +10795,76 @@ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x06\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x05`\x00\x00\x00\x00\x00\x01\x00\x02@;\ -\x00\x00\x01\x8f \xf3\xf9\x8e\ -\x00\x00\x05p\x00\x01\x00\x00\x00\x01\x00\x02[;\ -\x00\x00\x01\x8f \xf7\xc5C\ -\x00\x00\x05\x86\x00\x00\x00\x00\x00\x01\x00\x02z\xf2\ -\x00\x00\x01\x8f \xf3\xf9\x8e\ -\x00\x00\x054\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0a\ +\x00\x00\x05\x86\x00\x00\x00\x00\x00\x01\x00\x02@\x82\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x05\x96\x00\x01\x00\x00\x00\x01\x00\x02[\x82\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x05\xac\x00\x00\x00\x00\x00\x01\x00\x02{9\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x05Z\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0a\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x05F\x00\x01\x00\x00\x00\x01\x00\x02:\x1e\ -\x00\x00\x01\x8f \xf3\xf9~\ -\x00\x00\x00T\x00\x02\x00\x00\x00\x0c\x00\x00\x00\x0c\ +\x00\x00\x05l\x00\x01\x00\x00\x00\x01\x00\x02:X\ +\x00\x00\x01\x90O\xe2\x09u\ +\x00\x00\x00T\x00\x02\x00\x00\x00\x0d\x00\x00\x00\x0c\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x01\x96\x00\x01\x00\x00\x00\x01\x00\x02\x1c\x8d\ -\x00\x00\x01\x8e\x9c:z\x09\ -\x00\x00\x01<\x00\x00\x00\x00\x00\x01\x00\x01\xben\ -\x00\x00\x01\x8e\x9c:z\x07\ +\x00\x00\x01\xbc\x00\x01\x00\x00\x00\x01\x00\x02\x1d\x8a\ +\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01b\x00\x00\x00\x00\x00\x01\x00\x01\xbfk\ +\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x00\xca\x00\x00\x00\x00\x00\x01\x00\x00\x17S\ +\x00\x00\x01\x90O\xe1+5\ \x00\x00\x00j\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x8e\x9c:z\x0f\ +\x00\x00\x01\x90O\xb8\x19R\ \x00\x00\x00\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x16f\ -\x00\x00\x01\x8f\x0f\xf0)\x9e\ -\x00\x00\x00\xea\x00\x00\x00\x00\x00\x01\x00\x00!6\ -\x00\x00\x01\x8e\x9c:z\x09\ -\x00\x00\x01\x0e\x00\x00\x00\x00\x00\x01\x00\x00%P\ -\x00\x00\x01\x8e\x9c:z\x0a\ -\x00\x00\x01x\x00\x01\x00\x00\x00\x01\x00\x01\xd0M\ -\x00\x00\x01\x8e\x9c:z\x08\ -\x00\x00\x01^\x00\x00\x00\x00\x00\x01\x00\x01\xcd1\ -\x00\x00\x01\x8e\x9c:z\x0f\ +\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01\x10\x00\x00\x00\x00\x00\x01\x00\x00\x223\ +\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x014\x00\x00\x00\x00\x00\x01\x00\x00&M\ +\x00\x00\x01\x90O\xb8\x19O\ +\x00\x00\x01\x9e\x00\x01\x00\x00\x00\x01\x00\x01\xd1J\ +\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01\x84\x00\x00\x00\x00\x00\x01\x00\x01\xce.\ +\x00\x00\x01\x90O\xb8\x19R\ \x00\x00\x00\x82\x00\x00\x00\x00\x00\x01\x00\x00\x06\xea\ -\x00\x00\x01\x8e\x9c:z\x0f\ +\x00\x00\x01\x90O\xb8\x19R\ \x00\x00\x00\xa0\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xf0\ -\x00\x00\x01\x8e\x9c:z\x09\ -\x00\x00\x01\xac\x00\x00\x00\x00\x00\x01\x00\x02!Z\ -\x00\x00\x01\x8e\x9c:z\x06\ -\x00\x00\x00\xca\x00\x00\x00\x00\x00\x01\x00\x00\x17S\ -\x00\x00\x01\x8e\x9c:z\x0f\ -\x00\x00\x01\xc8\x00\x02\x00\x00\x00\x0f\x00\x00\x00\x19\ +\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01\xd2\x00\x00\x00\x00\x00\x01\x00\x02\x22W\ +\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x01\x00\x00\x18P\ +\x00\x00\x01\x90O\xb8\x19R\ +\x00\x00\x01\xee\x00\x02\x00\x00\x00\x0f\x00\x00\x00\x1a\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x02\xc8\x00\x00\x00\x00\x00\x01\x00\x02+Z\ -\x00\x00\x01\x8e\x9c:z\x1b\ -\x00\x00\x01\xe4\x00\x01\x00\x00\x00\x01\x00\x02$4\ -\x00\x00\x01\x8f\x0f\xf0)\xbe\ -\x00\x00\x034\x00\x00\x00\x00\x00\x01\x00\x02.0\ -\x00\x00\x01\x8e\x9c:z\x1a\ -\x00\x00\x02\xf6\x00\x00\x00\x00\x00\x01\x00\x02,j\ -\x00\x00\x01\x8f\x0f\xf0)\xca\ -\x00\x00\x02\x92\x00\x00\x00\x00\x00\x01\x00\x02*H\ -\x00\x00\x01\x8e\x9c:z\x1a\ -\x00\x00\x04\x90\x00\x00\x00\x00\x00\x01\x00\x025\xb2\ -\x00\x00\x01\x8e\x9c:z\x19\ -\x00\x00\x04\xfa\x00\x00\x00\x00\x00\x01\x00\x028\x94\ -\x00\x00\x01\x8f\x0f\xf0)\xc6\ -\x00\x00\x04\x5c\x00\x00\x00\x00\x00\x01\x00\x024\x9f\ -\x00\x00\x01\x8e\x9c:z\x1b\ -\x00\x00\x04 \x00\x00\x00\x00\x00\x01\x00\x023e\ -\x00\x00\x01\x8e\x9c:z\x1d\ -\x00\x00\x03\xe2\x00\x00\x00\x00\x00\x01\x00\x022C\ -\x00\x00\x01\x8f\x0f\xf0)\xc9\ -\x00\x00\x04\xca\x00\x00\x00\x00\x00\x01\x00\x027\x84\ -\x00\x00\x01\x8e\x9c:z\x1a\ -\x00\x00\x03h\x00\x00\x00\x00\x00\x01\x00\x02/\xfb\ -\x00\x00\x01\x8e\x9c:z\x1d\ -\x00\x00\x02:\x00\x00\x00\x00\x00\x01\x00\x02)0\ -\x00\x00\x01\x8e\x9c:z\x1e\ -\x00\x00\x03\xa4\x00\x00\x00\x00\x00\x01\x00\x021\x1b\ -\x00\x00\x01\x8f\x0f\xf0)\xc7\ -\x00\x00\x02\x06\x00\x00\x00\x00\x00\x01\x00\x02(\x1e\ -\x00\x00\x01\x8e\x9c:z\x1a\ +\x00\x00\x02\xee\x00\x00\x00\x00\x00\x01\x00\x02,)\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x02\x0a\x00\x01\x00\x00\x00\x01\x00\x02%1\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x03Z\x00\x00\x00\x00\x00\x01\x00\x02.\xe3\ +\x00\x00\x01\x90O\xb8\x19U\ +\x00\x00\x03\x1c\x00\x00\x00\x00\x00\x01\x00\x02--\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x02\xb8\x00\x00\x00\x00\x00\x01\x00\x02+#\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x04\xb6\x00\x00\x00\x00\x00\x01\x00\x026\x15\ +\x00\x00\x01\x90O\xb8\x19U\ +\x00\x00\x05 \x00\x00\x00\x00\x00\x01\x00\x028\xdf\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x04\x82\x00\x00\x00\x00\x00\x01\x00\x025\x0e\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x04F\x00\x00\x00\x00\x00\x01\x00\x023\xe2\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x04\x08\x00\x00\x00\x00\x00\x01\x00\x022\xce\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x04\xf0\x00\x00\x00\x00\x00\x01\x00\x027\xdb\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x03\x8e\x00\x00\x00\x00\x00\x01\x00\x020\xa2\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x02`\x00\x00\x00\x00\x00\x01\x00\x02*\x19\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x03\xca\x00\x00\x00\x00\x00\x01\x00\x021\xb4\ +\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x02,\x00\x00\x00\x00\x00\x01\x00\x02)\x13\ +\x00\x00\x01\x90O\xb8\x19Y\ " def qInitResources(): diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index 1b775ef..a32128b 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'form_desktop.ui' ## -## Created by: Qt User Interface Compiler version 6.7.0 +## Created by: Qt User Interface Compiler version 6.7.2 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -69,7 +69,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_stacked_top.setWidgetResizable(True) self.scrollAreaWidgetContents_7 = QWidget() self.scrollAreaWidgetContents_7.setObjectName(u"scrollAreaWidgetContents_7") - self.scrollAreaWidgetContents_7.setGeometry(QRect(0, 0, 1512, 291)) + self.scrollAreaWidgetContents_7.setGeometry(QRect(0, 0, 1570, 277)) self.gridLayout_14 = QGridLayout(self.scrollAreaWidgetContents_7) self.gridLayout_14.setObjectName(u"gridLayout_14") self.stacked_widget_top = QStackedWidget(self.scrollAreaWidgetContents_7) @@ -96,77 +96,65 @@ def setupUi(self, Porn_Fetch_Widget): sizePolicy3.setVerticalStretch(0) sizePolicy3.setHeightForWidth(self.button_search.sizePolicy().hasHeightForWidth()) self.button_search.setSizePolicy(sizePolicy3) - self.button_search.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_search.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridlayout_downloading.addWidget(self.button_search, 6, 3, 1, 1) + self.gridlayout_downloading.addWidget(self.button_search, 7, 3, 1, 1) - self.label_playlist_url = QLabel(self.page_download) - self.label_playlist_url.setObjectName(u"label_playlist_url") - - self.gridlayout_downloading.addWidget(self.label_playlist_url, 3, 0, 1, 1) - - self.label_search_website = QLabel(self.page_download) - self.label_search_website.setObjectName(u"label_search_website") - - self.gridlayout_downloading.addWidget(self.label_search_website, 8, 0, 1, 1) - - self.label_file = QLabel(self.page_download) - self.label_file.setObjectName(u"label_file") - sizePolicy4 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) - sizePolicy4.setHorizontalStretch(0) - sizePolicy4.setVerticalStretch(0) - sizePolicy4.setHeightForWidth(self.label_file.sizePolicy().hasHeightForWidth()) - self.label_file.setSizePolicy(sizePolicy4) - self.label_file.setMinimumSize(QSize(100, 2)) - - self.gridlayout_downloading.addWidget(self.label_file, 5, 0, 1, 1) - - self.label_model_url = QLabel(self.page_download) - self.label_model_url.setObjectName(u"label_model_url") - sizePolicy4.setHeightForWidth(self.label_model_url.sizePolicy().hasHeightForWidth()) - self.label_model_url.setSizePolicy(sizePolicy4) - self.label_model_url.setMinimumSize(QSize(100, 2)) + self.lineedit_url = QLineEdit(self.page_download) + self.lineedit_url.setObjectName(u"lineedit_url") + sizePolicy2.setHeightForWidth(self.lineedit_url.sizePolicy().hasHeightForWidth()) + self.lineedit_url.setSizePolicy(sizePolicy2) + self.lineedit_url.setMinimumSize(QSize(300, 4)) - self.gridlayout_downloading.addWidget(self.label_model_url, 4, 0, 1, 1) + self.gridlayout_downloading.addWidget(self.lineedit_url, 2, 1, 1, 2) self.button_open_file = QPushButton(self.page_download) self.button_open_file.setObjectName(u"button_open_file") sizePolicy3.setHeightForWidth(self.button_open_file.sizePolicy().hasHeightForWidth()) self.button_open_file.setSizePolicy(sizePolicy3) self.button_open_file.setMinimumSize(QSize(60, 2)) - self.button_open_file.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_open_file.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_open_file.setStyleSheet(u"") - self.gridlayout_downloading.addWidget(self.button_open_file, 5, 3, 1, 1) + self.gridlayout_downloading.addWidget(self.button_open_file, 6, 3, 1, 1) - self.label_url = QLabel(self.page_download) - self.label_url.setObjectName(u"label_url") - sizePolicy4.setHeightForWidth(self.label_url.sizePolicy().hasHeightForWidth()) - self.label_url.setSizePolicy(sizePolicy4) - self.label_url.setMinimumSize(QSize(100, 2)) + self.label_search_website = QLabel(self.page_download) + self.label_search_website.setObjectName(u"label_search_website") - self.gridlayout_downloading.addWidget(self.label_url, 1, 0, 1, 1) + self.gridlayout_downloading.addWidget(self.label_search_website, 9, 0, 1, 1) self.button_model = QPushButton(self.page_download) self.button_model.setObjectName(u"button_model") sizePolicy3.setHeightForWidth(self.button_model.sizePolicy().hasHeightForWidth()) self.button_model.setSizePolicy(sizePolicy3) self.button_model.setMinimumSize(QSize(60, 2)) - self.button_model.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_model.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_model.setStyleSheet(u"") - self.gridlayout_downloading.addWidget(self.button_model, 4, 3, 1, 1) + self.gridlayout_downloading.addWidget(self.button_model, 5, 3, 1, 1) - self.button_switch_supported_websites = QPushButton(self.page_download) - self.button_switch_supported_websites.setObjectName(u"button_switch_supported_websites") - self.button_switch_supported_websites.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_download = QPushButton(self.page_download) + self.button_download.setObjectName(u"button_download") + sizePolicy3.setHeightForWidth(self.button_download.sizePolicy().hasHeightForWidth()) + self.button_download.setSizePolicy(sizePolicy3) + self.button_download.setMinimumSize(QSize(60, 2)) + self.button_download.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + self.button_download.setStyleSheet(u"") - self.gridlayout_downloading.addWidget(self.button_switch_supported_websites, 0, 0, 1, 4) + self.gridlayout_downloading.addWidget(self.button_download, 2, 3, 1, 1) + + self.lineedit_model_url = QLineEdit(self.page_download) + self.lineedit_model_url.setObjectName(u"lineedit_model_url") + sizePolicy2.setHeightForWidth(self.lineedit_model_url.sizePolicy().hasHeightForWidth()) + self.lineedit_model_url.setSizePolicy(sizePolicy2) + self.lineedit_model_url.setMinimumSize(QSize(300, 2)) + + self.gridlayout_downloading.addWidget(self.lineedit_model_url, 5, 1, 1, 2) self.horizontallayout_searching_websites = QHBoxLayout() - self.horizontallayout_searching_websites.setSpacing(0) + self.horizontallayout_searching_websites.setSpacing(4) self.horizontallayout_searching_websites.setObjectName(u"horizontallayout_searching_websites") - self.horizontallayout_searching_websites.setContentsMargins(-1, 5, -1, -1) + self.horizontallayout_searching_websites.setContentsMargins(-1, 5, 5, -1) self.radio_search_website_pornhub = QRadioButton(self.page_download) self.radio_search_website_pornhub.setObjectName(u"radio_search_website_pornhub") self.radio_search_website_pornhub.setChecked(True) @@ -198,7 +186,7 @@ def setupUi(self, Porn_Fetch_Widget): self.horizontallayout_searching_websites.addItem(self.horizontal_spacer_searching) - self.gridlayout_downloading.addLayout(self.horizontallayout_searching_websites, 8, 1, 1, 3) + self.gridlayout_downloading.addLayout(self.horizontallayout_searching_websites, 9, 1, 1, 3) self.lineedit_file = QLineEdit(self.page_download) self.lineedit_file.setObjectName(u"lineedit_file") @@ -207,32 +195,46 @@ def setupUi(self, Porn_Fetch_Widget): self.lineedit_file.setMinimumSize(QSize(300, 2)) self.lineedit_file.setReadOnly(True) - self.gridlayout_downloading.addWidget(self.lineedit_file, 5, 1, 1, 1) + self.gridlayout_downloading.addWidget(self.lineedit_file, 6, 1, 1, 1) + + self.label_url = QLabel(self.page_download) + self.label_url.setObjectName(u"label_url") + sizePolicy4 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) + sizePolicy4.setHorizontalStretch(0) + sizePolicy4.setVerticalStretch(0) + sizePolicy4.setHeightForWidth(self.label_url.sizePolicy().hasHeightForWidth()) + self.label_url.setSizePolicy(sizePolicy4) + self.label_url.setMinimumSize(QSize(100, 2)) + + self.gridlayout_downloading.addWidget(self.label_url, 2, 0, 1, 1) + + self.lineedit_playlist_url = QLineEdit(self.page_download) + self.lineedit_playlist_url.setObjectName(u"lineedit_playlist_url") + + self.gridlayout_downloading.addWidget(self.lineedit_playlist_url, 4, 1, 1, 2) self.labell_search = QLabel(self.page_download) self.labell_search.setObjectName(u"labell_search") - self.gridlayout_downloading.addWidget(self.labell_search, 6, 0, 1, 1) + self.gridlayout_downloading.addWidget(self.labell_search, 7, 0, 1, 1) - self.button_playlist_get_videos = QPushButton(self.page_download) - self.button_playlist_get_videos.setObjectName(u"button_playlist_get_videos") + self.label_playlist_url = QLabel(self.page_download) + self.label_playlist_url.setObjectName(u"label_playlist_url") - self.gridlayout_downloading.addWidget(self.button_playlist_get_videos, 3, 3, 1, 1) + self.gridlayout_downloading.addWidget(self.label_playlist_url, 4, 0, 1, 1) - self.button_download = QPushButton(self.page_download) - self.button_download.setObjectName(u"button_download") - sizePolicy3.setHeightForWidth(self.button_download.sizePolicy().hasHeightForWidth()) - self.button_download.setSizePolicy(sizePolicy3) - self.button_download.setMinimumSize(QSize(60, 2)) - self.button_download.setCursor(QCursor(Qt.PointingHandCursor)) - self.button_download.setStyleSheet(u"") + self.label_model_url = QLabel(self.page_download) + self.label_model_url.setObjectName(u"label_model_url") + sizePolicy4.setHeightForWidth(self.label_model_url.sizePolicy().hasHeightForWidth()) + self.label_model_url.setSizePolicy(sizePolicy4) + self.label_model_url.setMinimumSize(QSize(100, 2)) - self.gridlayout_downloading.addWidget(self.button_download, 1, 3, 1, 1) + self.gridlayout_downloading.addWidget(self.label_model_url, 5, 0, 1, 1) - self.button_help_file = QPushButton(self.page_download) - self.button_help_file.setObjectName(u"button_help_file") + self.button_playlist_get_videos = QPushButton(self.page_download) + self.button_playlist_get_videos.setObjectName(u"button_playlist_get_videos") - self.gridlayout_downloading.addWidget(self.button_help_file, 5, 2, 1, 1) + self.gridlayout_downloading.addWidget(self.button_playlist_get_videos, 4, 3, 1, 1) self.lineedit_search_query = QLineEdit(self.page_download) self.lineedit_search_query.setObjectName(u"lineedit_search_query") @@ -240,28 +242,33 @@ def setupUi(self, Porn_Fetch_Widget): self.lineedit_search_query.setSizePolicy(sizePolicy2) self.lineedit_search_query.setMinimumSize(QSize(300, 0)) - self.gridlayout_downloading.addWidget(self.lineedit_search_query, 6, 1, 1, 2) + self.gridlayout_downloading.addWidget(self.lineedit_search_query, 7, 1, 1, 2) - self.lineedit_model_url = QLineEdit(self.page_download) - self.lineedit_model_url.setObjectName(u"lineedit_model_url") - sizePolicy2.setHeightForWidth(self.lineedit_model_url.sizePolicy().hasHeightForWidth()) - self.lineedit_model_url.setSizePolicy(sizePolicy2) - self.lineedit_model_url.setMinimumSize(QSize(300, 2)) + self.label_file = QLabel(self.page_download) + self.label_file.setObjectName(u"label_file") + sizePolicy4.setHeightForWidth(self.label_file.sizePolicy().hasHeightForWidth()) + self.label_file.setSizePolicy(sizePolicy4) + self.label_file.setMinimumSize(QSize(100, 2)) - self.gridlayout_downloading.addWidget(self.lineedit_model_url, 4, 1, 1, 2) + self.gridlayout_downloading.addWidget(self.label_file, 6, 0, 1, 1) - self.lineedit_playlist_url = QLineEdit(self.page_download) - self.lineedit_playlist_url.setObjectName(u"lineedit_playlist_url") + self.button_help_file = QPushButton(self.page_download) + self.button_help_file.setObjectName(u"button_help_file") - self.gridlayout_downloading.addWidget(self.lineedit_playlist_url, 3, 1, 1, 2) + self.gridlayout_downloading.addWidget(self.button_help_file, 6, 2, 1, 1) - self.lineedit_url = QLineEdit(self.page_download) - self.lineedit_url.setObjectName(u"lineedit_url") - sizePolicy2.setHeightForWidth(self.lineedit_url.sizePolicy().hasHeightForWidth()) - self.lineedit_url.setSizePolicy(sizePolicy2) - self.lineedit_url.setMinimumSize(QSize(300, 4)) + self.button_switch_supported_websites = QPushButton(self.page_download) + self.button_switch_supported_websites.setObjectName(u"button_switch_supported_websites") + sizePolicy5 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Maximum) + sizePolicy5.setHorizontalStretch(0) + sizePolicy5.setVerticalStretch(0) + sizePolicy5.setHeightForWidth(self.button_switch_supported_websites.sizePolicy().hasHeightForWidth()) + self.button_switch_supported_websites.setSizePolicy(sizePolicy5) + self.button_switch_supported_websites.setMinimumSize(QSize(0, 25)) + self.button_switch_supported_websites.setMaximumSize(QSize(16777215, 20)) + self.button_switch_supported_websites.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridlayout_downloading.addWidget(self.lineedit_url, 1, 1, 1, 2) + self.gridlayout_downloading.addWidget(self.button_switch_supported_websites, 1, 1, 1, 2) self.gridLayout_5.addLayout(self.gridlayout_downloading, 1, 0, 1, 1) @@ -276,32 +283,32 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_login_box.setObjectName(u"gridlayout_login_box") self.button_get_liked_videos = QPushButton(self.page_login) self.button_get_liked_videos.setObjectName(u"button_get_liked_videos") - self.button_get_liked_videos.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_get_liked_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_get_liked_videos.setStyleSheet(u"") self.gridlayout_login_box.addWidget(self.button_get_liked_videos, 3, 0, 1, 1) self.button_get_watched_videos = QPushButton(self.page_login) self.button_get_watched_videos.setObjectName(u"button_get_watched_videos") - self.button_get_watched_videos.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_get_watched_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_get_watched_videos.setStyleSheet(u"") self.gridlayout_login_box.addWidget(self.button_get_watched_videos, 3, 1, 1, 1) self.label_username = QLabel(self.page_login) self.label_username.setObjectName(u"label_username") - sizePolicy5 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) - sizePolicy5.setHorizontalStretch(0) - sizePolicy5.setVerticalStretch(0) - sizePolicy5.setHeightForWidth(self.label_username.sizePolicy().hasHeightForWidth()) - self.label_username.setSizePolicy(sizePolicy5) + sizePolicy6 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) + sizePolicy6.setHorizontalStretch(0) + sizePolicy6.setVerticalStretch(0) + sizePolicy6.setHeightForWidth(self.label_username.sizePolicy().hasHeightForWidth()) + self.label_username.setSizePolicy(sizePolicy6) self.gridlayout_login_box.addWidget(self.label_username, 0, 0, 1, 1) self.button_login = QPushButton(self.page_login) self.button_login.setObjectName(u"button_login") self.button_login.setMinimumSize(QSize(0, 0)) - self.button_login.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_login.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_login.setStyleSheet(u"") self.gridlayout_login_box.addWidget(self.button_login, 2, 0, 1, 4) @@ -316,15 +323,15 @@ def setupUi(self, Porn_Fetch_Widget): self.button_get_recommended_videos = QPushButton(self.page_login) self.button_get_recommended_videos.setObjectName(u"button_get_recommended_videos") - self.button_get_recommended_videos.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_get_recommended_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_get_recommended_videos.setStyleSheet(u"") self.gridlayout_login_box.addWidget(self.button_get_recommended_videos, 3, 2, 1, 1) self.label_password = QLabel(self.page_login) self.label_password.setObjectName(u"label_password") - sizePolicy5.setHeightForWidth(self.label_password.sizePolicy().hasHeightForWidth()) - self.label_password.setSizePolicy(sizePolicy5) + sizePolicy6.setHeightForWidth(self.label_password.sizePolicy().hasHeightForWidth()) + self.label_password.setSizePolicy(sizePolicy6) self.gridlayout_login_box.addWidget(self.label_password, 1, 0, 1, 1) @@ -354,66 +361,93 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1474, 253)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1532, 239)) self.gridLayout_18 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_18.setObjectName(u"gridLayout_18") self.gridlayout_progressbar = QGridLayout() self.gridlayout_progressbar.setObjectName(u"gridlayout_progressbar") - self.progressbar_hqporner = QProgressBar(self.scrollAreaWidgetContents) - self.progressbar_hqporner.setObjectName(u"progressbar_hqporner") - sizePolicy2.setHeightForWidth(self.progressbar_hqporner.sizePolicy().hasHeightForWidth()) - self.progressbar_hqporner.setSizePolicy(sizePolicy2) - self.progressbar_hqporner.setMinimumSize(QSize(300, 0)) - self.progressbar_hqporner.setValue(0) - - self.gridlayout_progressbar.addWidget(self.progressbar_hqporner, 0, 1, 1, 1) - - self.progressbar_eporner = QProgressBar(self.scrollAreaWidgetContents) - self.progressbar_eporner.setObjectName(u"progressbar_eporner") - self.progressbar_eporner.setValue(0) - - self.gridlayout_progressbar.addWidget(self.progressbar_eporner, 1, 1, 1, 1) - self.progressbar_xvideos = QProgressBar(self.scrollAreaWidgetContents) self.progressbar_xvideos.setObjectName(u"progressbar_xvideos") self.progressbar_xvideos.setValue(0) - self.gridlayout_progressbar.addWidget(self.progressbar_xvideos, 3, 1, 1, 1) + self.gridlayout_progressbar.addWidget(self.progressbar_xvideos, 4, 1, 1, 1) - self.label_progress_eporner = QLabel(self.scrollAreaWidgetContents) - self.label_progress_eporner.setObjectName(u"label_progress_eporner") + self.label_progress_pornhub = QLabel(self.scrollAreaWidgetContents) + self.label_progress_pornhub.setObjectName(u"label_progress_pornhub") + sizePolicy6.setHeightForWidth(self.label_progress_pornhub.sizePolicy().hasHeightForWidth()) + self.label_progress_pornhub.setSizePolicy(sizePolicy6) + + self.gridlayout_progressbar.addWidget(self.label_progress_pornhub, 0, 0, 1, 1) + + self.label_progress_xvideos = QLabel(self.scrollAreaWidgetContents) + self.label_progress_xvideos.setObjectName(u"label_progress_xvideos") - self.gridlayout_progressbar.addWidget(self.label_progress_eporner, 1, 0, 1, 1) + self.gridlayout_progressbar.addWidget(self.label_progress_xvideos, 4, 0, 1, 1) self.label_progress_xnxx = QLabel(self.scrollAreaWidgetContents) self.label_progress_xnxx.setObjectName(u"label_progress_xnxx") - self.gridlayout_progressbar.addWidget(self.label_progress_xnxx, 2, 0, 1, 1) + self.gridlayout_progressbar.addWidget(self.label_progress_xnxx, 3, 0, 1, 1) + + self.progressbar_xnxx = QProgressBar(self.scrollAreaWidgetContents) + self.progressbar_xnxx.setObjectName(u"progressbar_xnxx") + self.progressbar_xnxx.setValue(0) + + self.gridlayout_progressbar.addWidget(self.progressbar_xnxx, 3, 1, 1, 1) self.label_progress_hqporner = QLabel(self.scrollAreaWidgetContents) self.label_progress_hqporner.setObjectName(u"label_progress_hqporner") - sizePolicy5.setHeightForWidth(self.label_progress_hqporner.sizePolicy().hasHeightForWidth()) - self.label_progress_hqporner.setSizePolicy(sizePolicy5) + sizePolicy6.setHeightForWidth(self.label_progress_hqporner.sizePolicy().hasHeightForWidth()) + self.label_progress_hqporner.setSizePolicy(sizePolicy6) - self.gridlayout_progressbar.addWidget(self.label_progress_hqporner, 0, 0, 1, 1) + self.gridlayout_progressbar.addWidget(self.label_progress_hqporner, 1, 0, 1, 1) - self.label_progress_xvideos = QLabel(self.scrollAreaWidgetContents) - self.label_progress_xvideos.setObjectName(u"label_progress_xvideos") + self.progressbar_hqporner = QProgressBar(self.scrollAreaWidgetContents) + self.progressbar_hqporner.setObjectName(u"progressbar_hqporner") + sizePolicy2.setHeightForWidth(self.progressbar_hqporner.sizePolicy().hasHeightForWidth()) + self.progressbar_hqporner.setSizePolicy(sizePolicy2) + self.progressbar_hqporner.setMinimumSize(QSize(300, 0)) + self.progressbar_hqporner.setValue(0) - self.gridlayout_progressbar.addWidget(self.label_progress_xvideos, 3, 0, 1, 1) + self.gridlayout_progressbar.addWidget(self.progressbar_hqporner, 1, 1, 1, 1) - self.progressbar_xnxx = QProgressBar(self.scrollAreaWidgetContents) - self.progressbar_xnxx.setObjectName(u"progressbar_xnxx") - self.progressbar_xnxx.setValue(0) + self.progressbar_pornhub = QProgressBar(self.scrollAreaWidgetContents) + self.progressbar_pornhub.setObjectName(u"progressbar_pornhub") + sizePolicy2.setHeightForWidth(self.progressbar_pornhub.sizePolicy().hasHeightForWidth()) + self.progressbar_pornhub.setSizePolicy(sizePolicy2) + self.progressbar_pornhub.setMinimumSize(QSize(300, 0)) + self.progressbar_pornhub.setValue(0) - self.gridlayout_progressbar.addWidget(self.progressbar_xnxx, 2, 1, 1, 1) + self.gridlayout_progressbar.addWidget(self.progressbar_pornhub, 0, 1, 1, 1) self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) - self.gridlayout_progressbar.addItem(self.verticalSpacer_2, 4, 1, 1, 1) + self.gridlayout_progressbar.addItem(self.verticalSpacer_2, 6, 1, 1, 1) + + self.progressbar_eporner = QProgressBar(self.scrollAreaWidgetContents) + self.progressbar_eporner.setObjectName(u"progressbar_eporner") + self.progressbar_eporner.setValue(0) + + self.gridlayout_progressbar.addWidget(self.progressbar_eporner, 2, 1, 1, 1) + + self.label_progress_eporner = QLabel(self.scrollAreaWidgetContents) + self.label_progress_eporner.setObjectName(u"label_progress_eporner") + + self.gridlayout_progressbar.addWidget(self.label_progress_eporner, 2, 0, 1, 1) + + self.label_info = QLabel(self.scrollAreaWidgetContents) + self.label_info.setObjectName(u"label_info") + + self.gridlayout_progressbar.addWidget(self.label_info, 5, 0, 1, 1) + + self.lineedit_download_info = QLineEdit(self.scrollAreaWidgetContents) + self.lineedit_download_info.setObjectName(u"lineedit_download_info") + self.lineedit_download_info.setReadOnly(True) + + self.gridlayout_progressbar.addWidget(self.lineedit_download_info, 5, 1, 1, 1) - self.gridLayout_18.addLayout(self.gridlayout_progressbar, 0, 0, 1, 1) + self.gridLayout_18.addLayout(self.gridlayout_progressbar, 1, 0, 1, 1) self.scrollArea.setWidget(self.scrollAreaWidgetContents) @@ -433,14 +467,14 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_top_porn_month = QRadioButton(self.groupBox) self.radio_top_porn_month.setObjectName(u"radio_top_porn_month") self.radio_top_porn_month.setMinimumSize(QSize(0, 10)) - self.radio_top_porn_month.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_top_porn_month.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridLayout.addWidget(self.radio_top_porn_month, 0, 2, 1, 1) self.button_top_porn_get_videos = QPushButton(self.groupBox) self.button_top_porn_get_videos.setObjectName(u"button_top_porn_get_videos") self.button_top_porn_get_videos.setMinimumSize(QSize(0, 10)) - self.button_top_porn_get_videos.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_top_porn_get_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridLayout.addWidget(self.button_top_porn_get_videos, 0, 4, 1, 1) @@ -453,7 +487,7 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_top_porn_week = QRadioButton(self.groupBox) self.radio_top_porn_week.setObjectName(u"radio_top_porn_week") self.radio_top_porn_week.setMinimumSize(QSize(0, 10)) - self.radio_top_porn_week.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_top_porn_week.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.radio_top_porn_week.setChecked(True) self.gridLayout.addWidget(self.radio_top_porn_week, 0, 1, 1, 1) @@ -463,17 +497,17 @@ def setupUi(self, Porn_Fetch_Widget): sizePolicy3.setHeightForWidth(self.button_list_categories.sizePolicy().hasHeightForWidth()) self.button_list_categories.setSizePolicy(sizePolicy3) self.button_list_categories.setMinimumSize(QSize(0, 2)) - self.button_list_categories.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_list_categories.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridLayout.addWidget(self.button_list_categories, 1, 4, 1, 1) self.lineedit_hqporner_category = QLineEdit(self.groupBox) self.lineedit_hqporner_category.setObjectName(u"lineedit_hqporner_category") - sizePolicy6 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) - sizePolicy6.setHorizontalStretch(0) - sizePolicy6.setVerticalStretch(4) - sizePolicy6.setHeightForWidth(self.lineedit_hqporner_category.sizePolicy().hasHeightForWidth()) - self.lineedit_hqporner_category.setSizePolicy(sizePolicy6) + sizePolicy7 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) + sizePolicy7.setHorizontalStretch(0) + sizePolicy7.setVerticalStretch(4) + sizePolicy7.setHeightForWidth(self.lineedit_hqporner_category.sizePolicy().hasHeightForWidth()) + self.lineedit_hqporner_category.setSizePolicy(sizePolicy7) self.lineedit_hqporner_category.setMinimumSize(QSize(100, 4)) self.gridLayout.addWidget(self.lineedit_hqporner_category, 1, 1, 1, 2) @@ -486,40 +520,40 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_top_porn_all_time = QRadioButton(self.groupBox) self.radio_top_porn_all_time.setObjectName(u"radio_top_porn_all_time") self.radio_top_porn_all_time.setMinimumSize(QSize(0, 10)) - self.radio_top_porn_all_time.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_top_porn_all_time.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridLayout.addWidget(self.radio_top_porn_all_time, 0, 3, 1, 1) self.button_hqporner_category_get_videos = QPushButton(self.groupBox) self.button_hqporner_category_get_videos.setObjectName(u"button_hqporner_category_get_videos") - sizePolicy7 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed) - sizePolicy7.setHorizontalStretch(0) - sizePolicy7.setVerticalStretch(2) - sizePolicy7.setHeightForWidth(self.button_hqporner_category_get_videos.sizePolicy().hasHeightForWidth()) - self.button_hqporner_category_get_videos.setSizePolicy(sizePolicy7) + sizePolicy8 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed) + sizePolicy8.setHorizontalStretch(0) + sizePolicy8.setVerticalStretch(2) + sizePolicy8.setHeightForWidth(self.button_hqporner_category_get_videos.sizePolicy().hasHeightForWidth()) + self.button_hqporner_category_get_videos.setSizePolicy(sizePolicy8) self.button_hqporner_category_get_videos.setMinimumSize(QSize(0, 2)) - self.button_hqporner_category_get_videos.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_hqporner_category_get_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridLayout.addWidget(self.button_hqporner_category_get_videos, 1, 3, 1, 1) self.button_get_random_videos = QPushButton(self.groupBox) self.button_get_random_videos.setObjectName(u"button_get_random_videos") - sizePolicy8 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed) - sizePolicy8.setHorizontalStretch(0) - sizePolicy8.setVerticalStretch(0) - sizePolicy8.setHeightForWidth(self.button_get_random_videos.sizePolicy().hasHeightForWidth()) - self.button_get_random_videos.setSizePolicy(sizePolicy8) + sizePolicy9 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed) + sizePolicy9.setHorizontalStretch(0) + sizePolicy9.setVerticalStretch(0) + sizePolicy9.setHeightForWidth(self.button_get_random_videos.sizePolicy().hasHeightForWidth()) + self.button_get_random_videos.setSizePolicy(sizePolicy9) self.button_get_random_videos.setMinimumSize(QSize(0, 10)) - self.button_get_random_videos.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_get_random_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridLayout.addWidget(self.button_get_random_videos, 2, 4, 1, 1) self.button_get_brazzers_videos = QPushButton(self.groupBox) self.button_get_brazzers_videos.setObjectName(u"button_get_brazzers_videos") - sizePolicy8.setHeightForWidth(self.button_get_brazzers_videos.sizePolicy().hasHeightForWidth()) - self.button_get_brazzers_videos.setSizePolicy(sizePolicy8) + sizePolicy9.setHeightForWidth(self.button_get_brazzers_videos.sizePolicy().hasHeightForWidth()) + self.button_get_brazzers_videos.setSizePolicy(sizePolicy9) self.button_get_brazzers_videos.setMinimumSize(QSize(0, 10)) - self.button_get_brazzers_videos.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_get_brazzers_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridLayout.addWidget(self.button_get_brazzers_videos, 3, 4, 1, 1) @@ -555,18 +589,18 @@ def setupUi(self, Porn_Fetch_Widget): self.lineedit_videos_by_category_eporner = QLineEdit(self.groupBox_2) self.lineedit_videos_by_category_eporner.setObjectName(u"lineedit_videos_by_category_eporner") - sizePolicy6.setHeightForWidth(self.lineedit_videos_by_category_eporner.sizePolicy().hasHeightForWidth()) - self.lineedit_videos_by_category_eporner.setSizePolicy(sizePolicy6) + sizePolicy7.setHeightForWidth(self.lineedit_videos_by_category_eporner.sizePolicy().hasHeightForWidth()) + self.lineedit_videos_by_category_eporner.setSizePolicy(sizePolicy7) self.lineedit_videos_by_category_eporner.setMinimumSize(QSize(100, 4)) self.horizontalLayout.addWidget(self.lineedit_videos_by_category_eporner) self.button_eporner_category_get_videos = QPushButton(self.groupBox_2) self.button_eporner_category_get_videos.setObjectName(u"button_eporner_category_get_videos") - sizePolicy7.setHeightForWidth(self.button_eporner_category_get_videos.sizePolicy().hasHeightForWidth()) - self.button_eporner_category_get_videos.setSizePolicy(sizePolicy7) + sizePolicy8.setHeightForWidth(self.button_eporner_category_get_videos.sizePolicy().hasHeightForWidth()) + self.button_eporner_category_get_videos.setSizePolicy(sizePolicy8) self.button_eporner_category_get_videos.setMinimumSize(QSize(0, 2)) - self.button_eporner_category_get_videos.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_eporner_category_get_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontalLayout.addWidget(self.button_eporner_category_get_videos) @@ -575,7 +609,7 @@ def setupUi(self, Porn_Fetch_Widget): sizePolicy3.setHeightForWidth(self.button_list_categories_eporner.sizePolicy().hasHeightForWidth()) self.button_list_categories_eporner.setSizePolicy(sizePolicy3) self.button_list_categories_eporner.setMinimumSize(QSize(0, 2)) - self.button_list_categories_eporner.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_list_categories_eporner.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontalLayout.addWidget(self.button_list_categories_eporner) @@ -591,7 +625,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_stacked_top.setWidget(self.scrollAreaWidgetContents_7) - self.gridLayout_8.addWidget(self.scrollarea_stacked_top, 1, 1, 1, 1) + self.gridLayout_8.addWidget(self.scrollarea_stacked_top, 0, 1, 1, 1) self.verticallayout_treewidget = QVBoxLayout() self.verticallayout_treewidget.setObjectName(u"verticallayout_treewidget") @@ -600,7 +634,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_treewidget.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") - self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1510, 326)) + self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1568, 336)) self.gridLayout_4 = QGridLayout(self.scrollAreaWidgetContents_3) self.gridLayout_4.setObjectName(u"gridLayout_4") self.verticallayout_treewidget_settings = QVBoxLayout() @@ -610,11 +644,11 @@ def setupUi(self, Porn_Fetch_Widget): __qtreewidgetitem.setText(0, u"Title"); self.treeWidget.setHeaderItem(__qtreewidgetitem) self.treeWidget.setObjectName(u"treeWidget") - sizePolicy9 = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.MinimumExpanding) - sizePolicy9.setHorizontalStretch(0) - sizePolicy9.setVerticalStretch(0) - sizePolicy9.setHeightForWidth(self.treeWidget.sizePolicy().hasHeightForWidth()) - self.treeWidget.setSizePolicy(sizePolicy9) + sizePolicy10 = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.MinimumExpanding) + sizePolicy10.setHorizontalStretch(0) + sizePolicy10.setVerticalStretch(0) + sizePolicy10.setHeightForWidth(self.treeWidget.sizePolicy().hasHeightForWidth()) + self.treeWidget.setSizePolicy(sizePolicy10) self.treeWidget.setMinimumSize(QSize(100, 200)) self.verticallayout_treewidget_settings.addWidget(self.treeWidget) @@ -626,9 +660,9 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_16.setObjectName(u"gridLayout_16") self.radio_tree_show_all = QRadioButton(self.scrollAreaWidgetContents_3) self.radio_tree_show_all.setObjectName(u"radio_tree_show_all") - sizePolicy5.setHeightForWidth(self.radio_tree_show_all.sizePolicy().hasHeightForWidth()) - self.radio_tree_show_all.setSizePolicy(sizePolicy5) - self.radio_tree_show_all.setCursor(QCursor(Qt.PointingHandCursor)) + sizePolicy6.setHeightForWidth(self.radio_tree_show_all.sizePolicy().hasHeightForWidth()) + self.radio_tree_show_all.setSizePolicy(sizePolicy6) + self.radio_tree_show_all.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.radio_tree_show_all.setStyleSheet(u"") self.radio_tree_show_all.setCheckable(True) self.radio_tree_show_all.setChecked(False) @@ -647,16 +681,16 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_tree_show_title = QRadioButton(self.scrollAreaWidgetContents_3) self.radio_tree_show_title.setObjectName(u"radio_tree_show_title") - sizePolicy5.setHeightForWidth(self.radio_tree_show_title.sizePolicy().hasHeightForWidth()) - self.radio_tree_show_title.setSizePolicy(sizePolicy5) - self.radio_tree_show_title.setCursor(QCursor(Qt.PointingHandCursor)) + sizePolicy6.setHeightForWidth(self.radio_tree_show_title.sizePolicy().hasHeightForWidth()) + self.radio_tree_show_title.setSizePolicy(sizePolicy6) + self.radio_tree_show_title.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.radio_tree_show_title.setChecked(True) self.gridLayout_16.addWidget(self.radio_tree_show_title, 0, 0, 1, 1) self.checkbox_tree_show_videos_reversed = QCheckBox(self.scrollAreaWidgetContents_3) self.checkbox_tree_show_videos_reversed.setObjectName(u"checkbox_tree_show_videos_reversed") - self.checkbox_tree_show_videos_reversed.setCursor(QCursor(Qt.PointingHandCursor)) + self.checkbox_tree_show_videos_reversed.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridLayout_16.addWidget(self.checkbox_tree_show_videos_reversed, 1, 2, 1, 1) @@ -684,26 +718,38 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_17.setObjectName(u"gridLayout_17") self.button_tree_unselect_all = QPushButton(self.widget) self.button_tree_unselect_all.setObjectName(u"button_tree_unselect_all") - self.button_tree_unselect_all.setCursor(QCursor(Qt.PointingHandCursor)) + sizePolicy5.setHeightForWidth(self.button_tree_unselect_all.sizePolicy().hasHeightForWidth()) + self.button_tree_unselect_all.setSizePolicy(sizePolicy5) + self.button_tree_unselect_all.setMinimumSize(QSize(0, 30)) + self.button_tree_unselect_all.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_tree_unselect_all.setStyleSheet(u"") self.gridLayout_17.addWidget(self.button_tree_unselect_all, 1, 1, 1, 1) self.button_tree_stop = QPushButton(self.widget) self.button_tree_stop.setObjectName(u"button_tree_stop") + sizePolicy5.setHeightForWidth(self.button_tree_stop.sizePolicy().hasHeightForWidth()) + self.button_tree_stop.setSizePolicy(sizePolicy5) + self.button_tree_stop.setMinimumSize(QSize(0, 30)) self.gridLayout_17.addWidget(self.button_tree_stop, 1, 2, 1, 1) self.button_tree_select_range = QPushButton(self.widget) self.button_tree_select_range.setObjectName(u"button_tree_select_range") - self.button_tree_select_range.setCursor(QCursor(Qt.PointingHandCursor)) + sizePolicy5.setHeightForWidth(self.button_tree_select_range.sizePolicy().hasHeightForWidth()) + self.button_tree_select_range.setSizePolicy(sizePolicy5) + self.button_tree_select_range.setMinimumSize(QSize(0, 30)) + self.button_tree_select_range.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_tree_select_range.setStyleSheet(u"") self.gridLayout_17.addWidget(self.button_tree_select_range, 1, 0, 1, 1) self.button_tree_download = QPushButton(self.widget) self.button_tree_download.setObjectName(u"button_tree_download") - self.button_tree_download.setCursor(QCursor(Qt.PointingHandCursor)) + sizePolicy5.setHeightForWidth(self.button_tree_download.sizePolicy().hasHeightForWidth()) + self.button_tree_download.setSizePolicy(sizePolicy5) + self.button_tree_download.setMinimumSize(QSize(0, 30)) + self.button_tree_download.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_tree_download.setStyleSheet(u"") self.gridLayout_17.addWidget(self.button_tree_download, 0, 0, 1, 3) @@ -712,42 +758,7 @@ def setupUi(self, Porn_Fetch_Widget): self.verticallayout_treewidget.addLayout(self.gridLayout_17) - self.gridLayout_8.addLayout(self.verticallayout_treewidget, 2, 1, 1, 1) - - self.horizontalLayout_3 = QHBoxLayout() - self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") - self.label_status_internet = QLabel(self.widget) - self.label_status_internet.setObjectName(u"label_status_internet") - - self.horizontalLayout_3.addWidget(self.label_status_internet) - - self.lineedit_status_internet = QLineEdit(self.widget) - self.lineedit_status_internet.setObjectName(u"lineedit_status_internet") - - self.horizontalLayout_3.addWidget(self.lineedit_status_internet) - - self.label_status_ffmpeg = QLabel(self.widget) - self.label_status_ffmpeg.setObjectName(u"label_status_ffmpeg") - - self.horizontalLayout_3.addWidget(self.label_status_ffmpeg) - - self.lineedit_status_ffmpeg = QLineEdit(self.widget) - self.lineedit_status_ffmpeg.setObjectName(u"lineedit_status_ffmpeg") - - self.horizontalLayout_3.addWidget(self.lineedit_status_ffmpeg) - - self.label_status_update = QLabel(self.widget) - self.label_status_update.setObjectName(u"label_status_update") - - self.horizontalLayout_3.addWidget(self.label_status_update) - - self.lineedit_status_update = QLineEdit(self.widget) - self.lineedit_status_update.setObjectName(u"lineedit_status_update") - - self.horizontalLayout_3.addWidget(self.lineedit_status_update) - - - self.gridLayout_8.addLayout(self.horizontalLayout_3, 0, 1, 1, 1) + self.gridLayout_8.addLayout(self.verticallayout_treewidget, 1, 1, 1, 1) self.stacked_widget_main.addWidget(self.widget) self.page_settings = QWidget() @@ -759,7 +770,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_settings.setWidgetResizable(True) self.scrollAreaWidgetContents_6 = QWidget() self.scrollAreaWidgetContents_6.setObjectName(u"scrollAreaWidgetContents_6") - self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 846, 762)) + self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 721, 720)) self.gridLayout_19 = QGridLayout(self.scrollAreaWidgetContents_6) self.gridLayout_19.setObjectName(u"gridLayout_19") self.button_download_ffmpeg = QPushButton(self.scrollAreaWidgetContents_6) @@ -789,7 +800,7 @@ def setupUi(self, Porn_Fetch_Widget): self.button_semaphore_help = QPushButton(self.groupbox_performance) self.button_semaphore_help.setObjectName(u"button_semaphore_help") - self.button_semaphore_help.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_semaphore_help.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_simultaneous_downloads.addWidget(self.button_semaphore_help) @@ -812,7 +823,7 @@ def setupUi(self, Porn_Fetch_Widget): self.button_workers_help = QPushButton(self.groupbox_performance) self.button_workers_help.setObjectName(u"button_workers_help") - self.button_workers_help.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_workers_help.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_maximal_workers.addWidget(self.button_workers_help) @@ -835,7 +846,7 @@ def setupUi(self, Porn_Fetch_Widget): self.button_pornhub_delay_help = QPushButton(self.groupbox_performance) self.button_pornhub_delay_help.setObjectName(u"button_pornhub_delay_help") - self.button_pornhub_delay_help.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_pornhub_delay_help.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_pornhub_delay.addWidget(self.button_pornhub_delay_help) @@ -846,32 +857,32 @@ def setupUi(self, Porn_Fetch_Widget): self.horizontallayout_threading_mode.setObjectName(u"horizontallayout_threading_mode") self.label_threading_mode = QLabel(self.groupbox_performance) self.label_threading_mode.setObjectName(u"label_threading_mode") - sizePolicy5.setHeightForWidth(self.label_threading_mode.sizePolicy().hasHeightForWidth()) - self.label_threading_mode.setSizePolicy(sizePolicy5) + sizePolicy6.setHeightForWidth(self.label_threading_mode.sizePolicy().hasHeightForWidth()) + self.label_threading_mode.setSizePolicy(sizePolicy6) self.horizontallayout_threading_mode.addWidget(self.label_threading_mode) self.radio_threading_mode_high_performance = QRadioButton(self.groupbox_performance) self.radio_threading_mode_high_performance.setObjectName(u"radio_threading_mode_high_performance") - self.radio_threading_mode_high_performance.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_threading_mode_high_performance.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_threading_mode.addWidget(self.radio_threading_mode_high_performance) self.radio_threading_mode_ffmpeg = QRadioButton(self.groupbox_performance) self.radio_threading_mode_ffmpeg.setObjectName(u"radio_threading_mode_ffmpeg") - self.radio_threading_mode_ffmpeg.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_threading_mode_ffmpeg.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_threading_mode.addWidget(self.radio_threading_mode_ffmpeg) self.radio_threading_mode_default = QRadioButton(self.groupbox_performance) self.radio_threading_mode_default.setObjectName(u"radio_threading_mode_default") - self.radio_threading_mode_default.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_threading_mode_default.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_threading_mode.addWidget(self.radio_threading_mode_default) self.button_threading_mode_help = QPushButton(self.groupbox_performance) self.button_threading_mode_help.setObjectName(u"button_threading_mode_help") - self.button_threading_mode_help.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_threading_mode_help.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_threading_mode.addWidget(self.button_threading_mode_help) @@ -894,7 +905,7 @@ def setupUi(self, Porn_Fetch_Widget): self.button_timeout_help = QPushButton(self.groupbox_performance) self.button_timeout_help.setObjectName(u"button_timeout_help") - self.button_timeout_help.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_timeout_help.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_maximal_timeout.addWidget(self.button_timeout_help) @@ -917,7 +928,7 @@ def setupUi(self, Porn_Fetch_Widget): self.button_timeout_maximal_retries_help = QPushButton(self.groupbox_performance) self.button_timeout_maximal_retries_help.setObjectName(u"button_timeout_maximal_retries_help") - self.button_timeout_maximal_retries_help.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_timeout_maximal_retries_help.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontalLayout_2.addWidget(self.button_timeout_maximal_retries_help) @@ -950,7 +961,7 @@ def setupUi(self, Porn_Fetch_Widget): self.button_result_limit_help = QPushButton(self.groupbox_videos) self.button_result_limit_help.setObjectName(u"button_result_limit_help") - self.button_result_limit_help.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_result_limit_help.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontalLayout_9.addWidget(self.button_result_limit_help) @@ -966,19 +977,19 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_directory_system_yes = QRadioButton(self.groupbox_videos) self.radio_directory_system_yes.setObjectName(u"radio_directory_system_yes") - self.radio_directory_system_yes.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_directory_system_yes.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_directory_system.addWidget(self.radio_directory_system_yes) self.radio_directory_system_no = QRadioButton(self.groupbox_videos) self.radio_directory_system_no.setObjectName(u"radio_directory_system_no") - self.radio_directory_system_no.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_directory_system_no.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_directory_system.addWidget(self.radio_directory_system_no) self.button_directory_system_help = QPushButton(self.groupbox_videos) self.button_directory_system_help.setObjectName(u"button_directory_system_help") - self.button_directory_system_help.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_directory_system_help.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_directory_system.addWidget(self.button_directory_system_help) @@ -989,26 +1000,26 @@ def setupUi(self, Porn_Fetch_Widget): self.horizontallayout_quality.setObjectName(u"horizontallayout_quality") self.label_quality = QLabel(self.groupbox_videos) self.label_quality.setObjectName(u"label_quality") - sizePolicy5.setHeightForWidth(self.label_quality.sizePolicy().hasHeightForWidth()) - self.label_quality.setSizePolicy(sizePolicy5) + sizePolicy6.setHeightForWidth(self.label_quality.sizePolicy().hasHeightForWidth()) + self.label_quality.setSizePolicy(sizePolicy6) self.horizontallayout_quality.addWidget(self.label_quality) self.radio_quality_best = QRadioButton(self.groupbox_videos) self.radio_quality_best.setObjectName(u"radio_quality_best") - self.radio_quality_best.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_quality_best.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_quality.addWidget(self.radio_quality_best) self.radio_quality_half = QRadioButton(self.groupbox_videos) self.radio_quality_half.setObjectName(u"radio_quality_half") - self.radio_quality_half.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_quality_half.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_quality.addWidget(self.radio_quality_half) self.radio_quality_worst = QRadioButton(self.groupbox_videos) self.radio_quality_worst.setObjectName(u"radio_quality_worst") - self.radio_quality_worst.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_quality_worst.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_quality.addWidget(self.radio_quality_worst) @@ -1029,7 +1040,7 @@ def setupUi(self, Porn_Fetch_Widget): self.button_output_path_select = QPushButton(self.groupbox_videos) self.button_output_path_select.setObjectName(u"button_output_path_select") - self.button_output_path_select.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_output_path_select.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_output_path.addWidget(self.button_output_path_select) @@ -1040,7 +1051,7 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_api_language.setObjectName(u"gridlayout_api_language") self.radio_api_language_chinese = QRadioButton(self.groupbox_videos) self.radio_api_language_chinese.setObjectName(u"radio_api_language_chinese") - self.radio_api_language_chinese.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_api_language_chinese.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridlayout_api_language.addWidget(self.radio_api_language_chinese, 2, 1, 1, 1) @@ -1050,7 +1061,7 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_api_language_french = QRadioButton(self.groupbox_videos) self.radio_api_language_french.setObjectName(u"radio_api_language_french") - self.radio_api_language_french.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_api_language_french.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridlayout_api_language.addWidget(self.radio_api_language_french, 4, 0, 1, 1) @@ -1060,7 +1071,7 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_api_language_english = QRadioButton(self.groupbox_videos) self.radio_api_language_english.setObjectName(u"radio_api_language_english") - self.radio_api_language_english.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_api_language_english.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridlayout_api_language.addWidget(self.radio_api_language_english, 2, 0, 1, 1) @@ -1095,7 +1106,7 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_api_language_german = QRadioButton(self.groupbox_videos) self.radio_api_language_german.setObjectName(u"radio_api_language_german") - self.radio_api_language_german.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_api_language_german.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridlayout_api_language.addWidget(self.radio_api_language_german, 3, 0, 1, 1) @@ -1106,14 +1117,14 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_api_language_russian = QRadioButton(self.groupbox_videos) self.radio_api_language_russian.setObjectName(u"radio_api_language_russian") - self.radio_api_language_russian.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_api_language_russian.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridlayout_api_language.addWidget(self.radio_api_language_russian, 3, 1, 1, 1) self.label_api_language = QLabel(self.groupbox_videos) self.label_api_language.setObjectName(u"label_api_language") - sizePolicy5.setHeightForWidth(self.label_api_language.sizePolicy().hasHeightForWidth()) - self.label_api_language.setSizePolicy(sizePolicy5) + sizePolicy6.setHeightForWidth(self.label_api_language.sizePolicy().hasHeightForWidth()) + self.label_api_language.setSizePolicy(sizePolicy6) self.gridlayout_api_language.addWidget(self.label_api_language, 1, 0, 1, 1) @@ -1156,32 +1167,32 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_gui_settings.setObjectName(u"gridlayout_gui_settings") self.radio_ui_language_german = QRadioButton(self.goroupbox_gui) self.radio_ui_language_german.setObjectName(u"radio_ui_language_german") - self.radio_ui_language_german.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_ui_language_german.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridlayout_gui_settings.addWidget(self.radio_ui_language_german, 1, 3, 1, 1) self.radio_ui_language_chinese_simplified = QRadioButton(self.goroupbox_gui) self.radio_ui_language_chinese_simplified.setObjectName(u"radio_ui_language_chinese_simplified") - self.radio_ui_language_chinese_simplified.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_ui_language_chinese_simplified.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridlayout_gui_settings.addWidget(self.radio_ui_language_chinese_simplified, 1, 4, 1, 1) self.radio_ui_language_english = QRadioButton(self.goroupbox_gui) self.radio_ui_language_english.setObjectName(u"radio_ui_language_english") - self.radio_ui_language_english.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_ui_language_english.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridlayout_gui_settings.addWidget(self.radio_ui_language_english, 1, 2, 1, 1) self.radio_ui_language_system_default = QRadioButton(self.goroupbox_gui) self.radio_ui_language_system_default.setObjectName(u"radio_ui_language_system_default") - self.radio_ui_language_system_default.setCursor(QCursor(Qt.PointingHandCursor)) + self.radio_ui_language_system_default.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridlayout_gui_settings.addWidget(self.radio_ui_language_system_default, 1, 1, 1, 1) self.label_ui_language = QLabel(self.goroupbox_gui) self.label_ui_language.setObjectName(u"label_ui_language") - sizePolicy5.setHeightForWidth(self.label_ui_language.sizePolicy().hasHeightForWidth()) - self.label_ui_language.setSizePolicy(sizePolicy5) + sizePolicy6.setHeightForWidth(self.label_ui_language.sizePolicy().hasHeightForWidth()) + self.label_ui_language.setSizePolicy(sizePolicy6) self.gridlayout_gui_settings.addWidget(self.label_ui_language, 1, 0, 1, 1) @@ -1201,13 +1212,13 @@ def setupUi(self, Porn_Fetch_Widget): self.horizontallayout_settings_apply.setObjectName(u"horizontallayout_settings_apply") self.button_settings_apply = QPushButton(self.scrollAreaWidgetContents_6) self.button_settings_apply.setObjectName(u"button_settings_apply") - self.button_settings_apply.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_settings_apply.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.horizontallayout_settings_apply.addWidget(self.button_settings_apply) self.button_settings_reset = QPushButton(self.scrollAreaWidgetContents_6) self.button_settings_reset.setObjectName(u"button_settings_reset") - self.button_settings_reset.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_settings_reset.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_settings_reset.setStyleSheet(u"QPushButton {\n" " background-color: rgb(85, 0, 0)/* Green */\n" " font: bold 14px;\n" @@ -1290,57 +1301,41 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_status = QScrollArea(self.main_widget) self.scrollarea_status.setObjectName(u"scrollarea_status") - sizePolicy10 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Maximum) - sizePolicy10.setHorizontalStretch(0) - sizePolicy10.setVerticalStretch(0) - sizePolicy10.setHeightForWidth(self.scrollarea_status.sizePolicy().hasHeightForWidth()) - self.scrollarea_status.setSizePolicy(sizePolicy10) + sizePolicy5.setHeightForWidth(self.scrollarea_status.sizePolicy().hasHeightForWidth()) + self.scrollarea_status.setSizePolicy(sizePolicy5) self.scrollarea_status.setWidgetResizable(True) self.scrollAreaWidgetContents_5 = QWidget() self.scrollAreaWidgetContents_5.setObjectName(u"scrollAreaWidgetContents_5") - self.scrollAreaWidgetContents_5.setGeometry(QRect(0, 0, 1530, 171)) + self.scrollAreaWidgetContents_5.setGeometry(QRect(0, 0, 1588, 161)) self.gridLayout_33 = QGridLayout(self.scrollAreaWidgetContents_5) self.gridLayout_33.setObjectName(u"gridLayout_33") self.gridlayout_status = QGridLayout() + self.gridlayout_status.setSpacing(0) self.gridlayout_status.setObjectName(u"gridlayout_status") - self.label_progress_pornhub = QLabel(self.scrollAreaWidgetContents_5) - self.label_progress_pornhub.setObjectName(u"label_progress_pornhub") - sizePolicy5.setHeightForWidth(self.label_progress_pornhub.sizePolicy().hasHeightForWidth()) - self.label_progress_pornhub.setSizePolicy(sizePolicy5) - - self.gridlayout_status.addWidget(self.label_progress_pornhub, 0, 0, 1, 1) - - self.progressbar_pornhub = QProgressBar(self.scrollAreaWidgetContents_5) - self.progressbar_pornhub.setObjectName(u"progressbar_pornhub") - sizePolicy2.setHeightForWidth(self.progressbar_pornhub.sizePolicy().hasHeightForWidth()) - self.progressbar_pornhub.setSizePolicy(sizePolicy2) - self.progressbar_pornhub.setMinimumSize(QSize(300, 0)) - self.progressbar_pornhub.setValue(0) - - self.gridlayout_status.addWidget(self.progressbar_pornhub, 0, 1, 1, 1) - - self.label_progress_converting = QLabel(self.scrollAreaWidgetContents_5) - self.label_progress_converting.setObjectName(u"label_progress_converting") + self.label_total_progress = QLabel(self.scrollAreaWidgetContents_5) + self.label_total_progress.setObjectName(u"label_total_progress") + sizePolicy6.setHeightForWidth(self.label_total_progress.sizePolicy().hasHeightForWidth()) + self.label_total_progress.setSizePolicy(sizePolicy6) - self.gridlayout_status.addWidget(self.label_progress_converting, 2, 0, 1, 1) + self.gridlayout_status.addWidget(self.label_total_progress, 2, 0, 1, 1) self.progressbar_converting = QProgressBar(self.scrollAreaWidgetContents_5) self.progressbar_converting.setObjectName(u"progressbar_converting") self.progressbar_converting.setValue(0) - self.gridlayout_status.addWidget(self.progressbar_converting, 2, 1, 1, 1) + self.gridlayout_status.addWidget(self.progressbar_converting, 3, 1, 1, 1) - self.button_view_all_progress_bars = QPushButton(self.scrollAreaWidgetContents_5) - self.button_view_all_progress_bars.setObjectName(u"button_view_all_progress_bars") + self.label_progress_converting = QLabel(self.scrollAreaWidgetContents_5) + self.label_progress_converting.setObjectName(u"label_progress_converting") - self.gridlayout_status.addWidget(self.button_view_all_progress_bars, 8, 0, 1, 2) + self.gridlayout_status.addWidget(self.label_progress_converting, 3, 0, 1, 1) - self.label_total_progress = QLabel(self.scrollAreaWidgetContents_5) - self.label_total_progress.setObjectName(u"label_total_progress") - sizePolicy5.setHeightForWidth(self.label_total_progress.sizePolicy().hasHeightForWidth()) - self.label_total_progress.setSizePolicy(sizePolicy5) + self.label_progress_information = QLabel(self.scrollAreaWidgetContents_5) + self.label_progress_information.setObjectName(u"label_progress_information") + sizePolicy6.setHeightForWidth(self.label_progress_information.sizePolicy().hasHeightForWidth()) + self.label_progress_information.setSizePolicy(sizePolicy6) - self.gridlayout_status.addWidget(self.label_total_progress, 1, 0, 1, 1) + self.gridlayout_status.addWidget(self.label_progress_information, 4, 1, 1, 1) self.progressbar_total = QProgressBar(self.scrollAreaWidgetContents_5) self.progressbar_total.setObjectName(u"progressbar_total") @@ -1349,14 +1344,7 @@ def setupUi(self, Porn_Fetch_Widget): self.progressbar_total.setMinimumSize(QSize(300, 0)) self.progressbar_total.setValue(0) - self.gridlayout_status.addWidget(self.progressbar_total, 1, 1, 1, 1) - - self.label_progress_information = QLabel(self.scrollAreaWidgetContents_5) - self.label_progress_information.setObjectName(u"label_progress_information") - sizePolicy5.setHeightForWidth(self.label_progress_information.sizePolicy().hasHeightForWidth()) - self.label_progress_information.setSizePolicy(sizePolicy5) - - self.gridlayout_status.addWidget(self.label_progress_information, 9, 0, 1, 2) + self.gridlayout_status.addWidget(self.progressbar_total, 2, 1, 1, 1) self.gridLayout_33.addLayout(self.gridlayout_status, 1, 0, 1, 1) @@ -1366,81 +1354,98 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_13.addWidget(self.scrollarea_status, 2, 0, 1, 1) - self.gridLayout_21.addWidget(self.main_widget, 0, 1, 1, 1) + self.gridLayout_21.addWidget(self.main_widget, 0, 0, 1, 1) - self.verticallayout_sidebar = QVBoxLayout() - self.verticallayout_sidebar.setObjectName(u"verticallayout_sidebar") + + self.gridLayout_22.addLayout(self.gridLayout_21, 1, 0, 1, 1) + + self.horizontalLayout_menu_buttons = QHBoxLayout() + self.horizontalLayout_menu_buttons.setSpacing(0) + self.horizontalLayout_menu_buttons.setObjectName(u"horizontalLayout_menu_buttons") self.button_switch_home = QPushButton(self.scrollAreaWidgetContents_4) self.button_switch_home.setObjectName(u"button_switch_home") - self.button_switch_home.setMinimumSize(QSize(50, 50)) - self.button_switch_home.setCursor(QCursor(Qt.PointingHandCursor)) + sizePolicy5.setHeightForWidth(self.button_switch_home.sizePolicy().hasHeightForWidth()) + self.button_switch_home.setSizePolicy(sizePolicy5) + self.button_switch_home.setMinimumSize(QSize(50, 35)) + self.button_switch_home.setMaximumSize(QSize(16777215, 35)) + self.button_switch_home.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_switch_home.setStyleSheet(u"border: none") self.button_switch_home.setIconSize(QSize(32, 32)) - self.verticallayout_sidebar.addWidget(self.button_switch_home) + self.horizontalLayout_menu_buttons.addWidget(self.button_switch_home) self.button_switch_account = QPushButton(self.scrollAreaWidgetContents_4) self.button_switch_account.setObjectName(u"button_switch_account") - self.button_switch_account.setMinimumSize(QSize(50, 50)) - self.button_switch_account.setCursor(QCursor(Qt.PointingHandCursor)) + sizePolicy5.setHeightForWidth(self.button_switch_account.sizePolicy().hasHeightForWidth()) + self.button_switch_account.setSizePolicy(sizePolicy5) + self.button_switch_account.setMinimumSize(QSize(50, 35)) + self.button_switch_account.setMaximumSize(QSize(16777215, 35)) + self.button_switch_account.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_switch_account.setStyleSheet(u"border: none") self.button_switch_account.setIconSize(QSize(32, 32)) - self.verticallayout_sidebar.addWidget(self.button_switch_account) + self.horizontalLayout_menu_buttons.addWidget(self.button_switch_account) self.button_switch_tools = QPushButton(self.scrollAreaWidgetContents_4) self.button_switch_tools.setObjectName(u"button_switch_tools") - self.button_switch_tools.setMinimumSize(QSize(50, 50)) + sizePolicy5.setHeightForWidth(self.button_switch_tools.sizePolicy().hasHeightForWidth()) + self.button_switch_tools.setSizePolicy(sizePolicy5) + self.button_switch_tools.setMinimumSize(QSize(50, 35)) + self.button_switch_tools.setMaximumSize(QSize(16777215, 35)) font = QFont() font.setPointSize(9) self.button_switch_tools.setFont(font) - self.button_switch_tools.setCursor(QCursor(Qt.PointingHandCursor)) + self.button_switch_tools.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_switch_tools.setStyleSheet(u"border: none") self.button_switch_tools.setIconSize(QSize(32, 32)) - self.verticallayout_sidebar.addWidget(self.button_switch_tools) + self.horizontalLayout_menu_buttons.addWidget(self.button_switch_tools) self.button_switch_settings = QPushButton(self.scrollAreaWidgetContents_4) self.button_switch_settings.setObjectName(u"button_switch_settings") - self.button_switch_settings.setMinimumSize(QSize(50, 50)) - self.button_switch_settings.setCursor(QCursor(Qt.PointingHandCursor)) + sizePolicy5.setHeightForWidth(self.button_switch_settings.sizePolicy().hasHeightForWidth()) + self.button_switch_settings.setSizePolicy(sizePolicy5) + self.button_switch_settings.setMinimumSize(QSize(50, 35)) + self.button_switch_settings.setMaximumSize(QSize(16777215, 35)) + self.button_switch_settings.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_switch_settings.setStyleSheet(u"border: none;") self.button_switch_settings.setIconSize(QSize(32, 32)) - self.verticallayout_sidebar.addWidget(self.button_switch_settings) + self.horizontalLayout_menu_buttons.addWidget(self.button_switch_settings) self.button_switch_credits = QPushButton(self.scrollAreaWidgetContents_4) self.button_switch_credits.setObjectName(u"button_switch_credits") - self.button_switch_credits.setMinimumSize(QSize(50, 50)) - self.button_switch_credits.setCursor(QCursor(Qt.PointingHandCursor)) + sizePolicy5.setHeightForWidth(self.button_switch_credits.sizePolicy().hasHeightForWidth()) + self.button_switch_credits.setSizePolicy(sizePolicy5) + self.button_switch_credits.setMinimumSize(QSize(50, 35)) + self.button_switch_credits.setMaximumSize(QSize(16777215, 35)) + self.button_switch_credits.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_switch_credits.setStyleSheet(u"border: none;") self.button_switch_credits.setIconSize(QSize(32, 32)) - self.verticallayout_sidebar.addWidget(self.button_switch_credits) - - self.vertical_spacer_sidebar = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) + self.horizontalLayout_menu_buttons.addWidget(self.button_switch_credits) - self.verticallayout_sidebar.addItem(self.vertical_spacer_sidebar) + self.button_view_progress_bars = QPushButton(self.scrollAreaWidgetContents_4) + self.button_view_progress_bars.setObjectName(u"button_view_progress_bars") + sizePolicy5.setHeightForWidth(self.button_view_progress_bars.sizePolicy().hasHeightForWidth()) + self.button_view_progress_bars.setSizePolicy(sizePolicy5) + self.button_view_progress_bars.setMinimumSize(QSize(50, 35)) + self.button_view_progress_bars.setMaximumSize(QSize(16777215, 35)) + self.button_view_progress_bars.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + self.button_view_progress_bars.setStyleSheet(u"border: none;") + self.button_view_progress_bars.setIconSize(QSize(32, 32)) + self.horizontalLayout_menu_buttons.addWidget(self.button_view_progress_bars) - self.gridLayout_21.addLayout(self.verticallayout_sidebar, 0, 0, 1, 1) - - self.gridLayout_22.addLayout(self.gridLayout_21, 0, 0, 1, 1) + self.gridLayout_22.addLayout(self.horizontalLayout_menu_buttons, 0, 0, 1, 1) self.scroll_area_really_important_lol.setWidget(self.scrollAreaWidgetContents_4) self.gridLayout_20.addWidget(self.scroll_area_really_important_lol, 0, 0, 1, 1) - QWidget.setTabOrder(self.button_switch_home, self.button_switch_account) - QWidget.setTabOrder(self.button_switch_account, self.button_switch_tools) - QWidget.setTabOrder(self.button_switch_tools, self.button_switch_settings) - QWidget.setTabOrder(self.button_switch_settings, self.button_switch_credits) - QWidget.setTabOrder(self.button_switch_credits, self.scrollarea_status) - QWidget.setTabOrder(self.scrollarea_status, self.button_view_all_progress_bars) - QWidget.setTabOrder(self.button_view_all_progress_bars, self.scrollarea_stacked_top) - QWidget.setTabOrder(self.scrollarea_stacked_top, self.button_switch_supported_websites) - QWidget.setTabOrder(self.button_switch_supported_websites, self.lineedit_url) + QWidget.setTabOrder(self.scrollarea_status, self.scrollarea_stacked_top) + QWidget.setTabOrder(self.scrollarea_stacked_top, self.lineedit_url) QWidget.setTabOrder(self.lineedit_url, self.button_download) QWidget.setTabOrder(self.button_download, self.lineedit_playlist_url) QWidget.setTabOrder(self.lineedit_playlist_url, self.button_playlist_get_videos) @@ -1530,7 +1535,7 @@ def setupUi(self, Porn_Fetch_Widget): self.retranslateUi(Porn_Fetch_Widget) self.stacked_widget_main.setCurrentIndex(0) - self.stacked_widget_top.setCurrentIndex(2) + self.stacked_widget_top.setCurrentIndex(0) self.stackedWidget.setCurrentIndex(1) @@ -1541,14 +1546,12 @@ def retranslateUi(self, Porn_Fetch_Widget): Porn_Fetch_Widget.setWindowTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"Porn Fetch V3.4 (C) Johannes Habel GPL 3", None)) self.stacked_widget_main.setStyleSheet("") self.button_search.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Start", None)) - self.label_playlist_url.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Playlist URL:", None)) - self.label_search_website.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Search Website", None)) - self.label_file.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"File:", None)) - self.label_model_url.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Model URL:", None)) + self.lineedit_url.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter video URL", None)) self.button_open_file.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Open File", None)) - self.label_url.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"URL:", None)) + self.label_search_website.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Search Website", None)) self.button_model.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Videos", None)) - self.button_switch_supported_websites.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"See Supported Websites", None)) + self.button_download.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Download", None)) + self.lineedit_model_url.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter Model / Channel / Actress URL", None)) self.radio_search_website_pornhub.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"PornHub", None)) self.radio_search_website_hqporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"HQPorner", None)) self.radio_search_website_xvideos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XVideos", None)) @@ -1556,15 +1559,17 @@ def retranslateUi(self, Porn_Fetch_Widget): self.radio_search_website_xnxx.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XNXX", None)) self.lineedit_file.setText("") self.lineedit_file.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"URLs in the file must be separated with new lines!", None)) + self.label_url.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"URL:", None)) + self.lineedit_playlist_url.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter a PornHub Playlist URL", None)) self.labell_search.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Search Query:", None)) + self.label_playlist_url.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Playlist URL:", None)) + self.label_model_url.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Model URL:", None)) self.button_playlist_get_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Videos", None)) - self.button_download.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Download", None)) - self.button_help_file.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Help", None)) self.lineedit_search_query.setText("") self.lineedit_search_query.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Search for Videos. Select Website below", None)) - self.lineedit_model_url.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter Model / Channel / Actress URL", None)) - self.lineedit_playlist_url.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter a PornHub Playlist URL", None)) - self.lineedit_url.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter video URL", None)) + self.label_file.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"File:", None)) + self.button_help_file.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Help", None)) + self.button_switch_supported_websites.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"See Supported Websites", None)) self.button_get_liked_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Liked videos", None)) self.button_get_watched_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get watched videos", None)) self.label_username.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Username:", None)) @@ -1573,10 +1578,13 @@ def retranslateUi(self, Porn_Fetch_Widget): self.button_get_recommended_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get recommended videos", None)) self.label_password.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Password:", None)) self.lineedit_password.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter your PornHub Password", None)) - self.label_progress_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Eporner", None)) + self.label_progress_pornhub.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"PornHub:", None)) + self.label_progress_xvideos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XVideos", None)) self.label_progress_xnxx.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XNXX", None)) self.label_progress_hqporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"HQPorner:", None)) - self.label_progress_xvideos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XVideos", None)) + self.label_progress_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Eporner", None)) + self.label_info.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Info:", None)) + self.lineedit_download_info.setText("") self.groupBox.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"HQPorner", None)) self.radio_top_porn_month.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Month", None)) self.button_top_porn_get_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Videos", None)) @@ -1619,9 +1627,6 @@ def retranslateUi(self, Porn_Fetch_Widget): #endif // QT_CONFIG(tooltip) self.button_tree_select_range.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Select a range of videos", None)) self.button_tree_download.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Download Selected Videos", None)) - self.label_status_internet.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Internet:", None)) - self.label_status_ffmpeg.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"FFmpeg:", None)) - self.label_status_update.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Update available:", None)) self.button_download_ffmpeg.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Download and Setup FFmpeg", None)) self.groupbox_performance.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"Performance", None)) self.label_semaphore.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Simultaneous downloads:", None)) @@ -1681,63 +1686,60 @@ def retranslateUi(self, Porn_Fetch_Widget): self.textbrowser_websites.setHtml(QCoreApplication.translate("Porn_Fetch_Widget", u"\n" "\n" -"

Supported Websites:

\n" -"


\n" -"

Downloading:

\n" -"


\n" -"

- PornHub.com (supports total progress)

\n" -"

- HQPorner.com

\n" -"

- Eporner.com

\n" -"

- XNXX.com (supports total progress)

\n" -"

- XVideos.com (supports total progress)

\n" -"


\n" -"

All sites support *threaded* downloads and selectable quality!

\n" -"


\n" -"

* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly

\n" -"

downloaded, therefore threading in a segment isn't needed.

\n" -"


\n" -"

Model / Channel Downloads

\n" -"


\n" -"

- PornHub.com

\n" -"

- HQPorner.com

\n" -"

- EPorner.com

\n" -"

- XNXX.com

\n" -"

- XVideos" - ".com

\n" -"


\n" -"

Searching:

\n" -"


\n" -"

- PornHub.com

\n" -"

- HQPorne" - "r.com

\n" -"

- Xvideos.com

\n" -"

- Eporner.com

\n" -"

- XNXX.com

\n" -"


\n" -"

I " - "am constantly working to support more websites.

\n" -"


\n" -"


\n" -"


\n" -"


\n" -"


\n" -"


\n" -"


", None)) - self.label_progress_pornhub.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"PornHub:", None)) - self.label_progress_converting.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Converting:", None)) - self.button_view_all_progress_bars.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"View all other progress bars", None)) +"\n" +"

Supported Websites:

\n" +"


\n" +"

Downloading:

\n" +"


\n" +"

- PornHub.com (supports total progress)

\n" +"

- HQPorner.com

\n" +"

- Eporner.com

\n" +"

- XNXX.com (supports total progress)

\n" +"

- XVideos.com (supports total progress)

\n" +"


\n" +"

All sites support *threaded" + "* downloads and selectable quality!

\n" +"


\n" +"

* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly

\n" +"

downloaded, therefore threading in a segment isn't needed.

\n" +"


\n" +"

Model / Channel Downloads

\n" +"


\n" +"

- PornHub.com

\n" +"

- HQPorner.com

\n" +"

- EPorner.com

\n" +"

- XNXX.com

\n" +"

- XVideos.com

\n" +"


\n" +"

Searching:

\n" +"


\n" +"

- PornHub.com

\n" +"

- HQPorner.com

\n" +"

- Xvideos.com

\n" +"

- Eporner.com

\n" +"

- XNXX.com

\n" +"


\n" +"

I am constantly working to support more websites.

\n" +"


\n" +"


\n" +"


\n" +"


\n" +"


\n" +"


\n" +"


", None)) self.label_total_progress.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Total:", None)) + self.label_progress_converting.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Converting:", None)) self.label_progress_information.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Information: The total progressbar does not count for Eporner and HQPorner, because they are using different mechanisms for downloading.", None)) self.button_switch_home.setText("") self.button_switch_account.setText("") self.button_switch_tools.setText("") self.button_switch_settings.setText("") self.button_switch_credits.setText("") + self.button_view_progress_bars.setText("") # retranslateUi From bca137b609882f8042b60ef126fab9e132c75f5b Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Tue, 25 Jun 2024 20:21:14 +0200 Subject: [PATCH 02/39] - fixed xvideos searching --- main.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/main.py b/main.py index 40d8c6c..92fc9a1 100644 --- a/main.py +++ b/main.py @@ -63,9 +63,6 @@ invalid_input_string = QCoreApplication.tr("Wrong Input, please verify the URL, category or actress!", None) ffmpeg_features = True ffmpeg_path = None -urls = ["https://www.pornhub.com", "https://www.eporner.com", "https://www.hqporner.com", "https://www.xnxx.com", - "https://www.xvideos.com"] - url_linux = "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz" url_windows = "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip" ffmpeg_linux = "ffmpeg-6.1-amd64-static" @@ -1701,7 +1698,7 @@ def basic_search(self): videos = Client().search(query) elif self.ui.radio_search_website_xvideos.isChecked(): - videos = xv_Client.search(query, pages=99) + videos = xv_Client.search(query) elif self.ui.radio_search_website_hqporner.isChecked(): videos = hq_Client.search_videos(query, pages=99) From 20ea4224426ab8f8e0ae7f1496fca0d98de8442a Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Tue, 25 Jun 2024 22:04:25 +0200 Subject: [PATCH 03/39] - fixed searching and pagination --- main.py | 57 ++++++++++++++++++++++++--------------------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/main.py b/main.py index 92fc9a1..70f38a4 100644 --- a/main.py +++ b/main.py @@ -179,7 +179,7 @@ def __init__(self, iterator, search_limit, data_mode, reverse, stop_flag, is_che def process_video(self, video, index): title = video.title - disabled = QCoreApplication().tr("Disabled", None) + disabled = QCoreApplication.tr("Disabled", None) duration = disabled author = disabled @@ -1229,7 +1229,9 @@ def switch_to_all_progress_bars(self): The following functions are related to the tree widget """ - def add_to_tree_widget_thread(self, iterator, search_limit): + def add_to_tree_widget_thread(self, iterator): + search_limit = self.search_limit + if self.ui.radio_tree_show_title.isChecked(): data_mode = 0 @@ -1417,7 +1419,7 @@ def start_single_video(self): else: one_time_iterator.append(video) - self.add_to_tree_widget_thread(iterator=one_time_iterator, search_limit=self.search_limit) + self.add_to_tree_widget_thread(iterator=one_time_iterator) def start_model(self, url=None): """Starts the model downloads""" @@ -1442,7 +1444,7 @@ def start_model(self, url=None): elif hqporner_pattern.match(model): pages = round(search_limit / 46) - videos = hq_Client().get_videos_by_actress(name=model, pages=pages) + videos = hq_Client().get_videos_by_actress(name=model) elif eporner_pattern.match(model): pages = round(search_limit / 38) @@ -1454,13 +1456,13 @@ def start_model(self, url=None): elif xvideos_pattern.match(model): videos = xv_Client().get_pornstar(url=model).videos - self.add_to_tree_widget_thread(videos, search_limit=search_limit) + self.add_to_tree_widget_thread(videos) def start_playlist(self): url = self.ui.lineedit_playlist_url.text() playlist = self.client.get_playlist(url) videos = playlist.sample() - self.add_to_tree_widget_thread(iterator=videos, search_limit=self.search_limit) + self.add_to_tree_widget_thread(iterator=videos) def load_video(self, url): """This starts the thread to load a video""" @@ -1592,7 +1594,7 @@ def receive_url_result(self, iterator, model_iterator, search_iterator): logger_debug(f"Received Search Iterator ({len(search_iterator)} keywords)") logger_debug("Processing Videos...") - self.add_to_tree_widget_thread(iterator, search_limit=self.search_limit) + self.add_to_tree_widget_thread(iterator) logger_debug("Processing Models...") for url in model_iterator: self.start_model(url) @@ -1671,19 +1673,19 @@ def get_watched_videos(self): """Returns the videos watched by the user""" if self.check_login(): watched = self.client.account.watched - self.add_to_tree_widget_thread(watched, search_limit=self.search_limit) + self.add_to_tree_widget_thread(watched) def get_liked_videos(self): """Returns the videos liked by the user""" if self.check_login(): liked = self.client.account.liked - self.add_to_tree_widget_thread(liked, search_limit=self.search_limit) + self.add_to_tree_widget_thread(liked) def get_recommended_videos(self): """Returns the videos recommended for the user""" if self.check_login(): recommended = self.client.account.recommended - self.add_to_tree_widget_thread(recommended, search_limit=self.search_limit) + self.add_to_tree_widget_thread(recommended) """ The following functions are related to the search functionality @@ -1692,7 +1694,6 @@ def get_recommended_videos(self): def basic_search(self): """Does a simple search for videos without filters on selected website""" query = self.ui.lineedit_search_query.text() - search_limit = self.search_limit if self.ui.radio_search_website_pornhub.isChecked(): videos = Client().search(query) @@ -1701,16 +1702,16 @@ def basic_search(self): videos = xv_Client.search(query) elif self.ui.radio_search_website_hqporner.isChecked(): - videos = hq_Client.search_videos(query, pages=99) + videos = hq_Client.search_videos(query) elif self.ui.radio_search_website_eporner.isChecked(): videos = ep_Client().search_videos(query, sorting_gay="", sorting_order="", sorting_low_quality="", page=1, - per_page=search_limit, enable_html_scraping=True) + per_page=self.search_limit, enable_html_scraping=True) elif self.ui.radio_search_website_xnxx.isChecked(): videos = xn_Client().search(query).videos - self.add_to_tree_widget_thread(videos, search_limit=search_limit) + self.add_to_tree_widget_thread(videos) def get_top_porn_hqporner(self): if self.ui.radio_top_porn_week.isChecked(): @@ -1725,10 +1726,8 @@ def get_top_porn_hqporner(self): else: sort = None - search_limit = self.search_limit - pages = round(search_limit / 46) - videos = hq_Client().get_top_porn(sort_by=sort, pages=pages) - self.add_to_tree_widget_thread(iterator=videos, search_limit=search_limit) + videos = hq_Client().get_top_porn(sort_by=sort) + self.add_to_tree_widget_thread(iterator=videos) def get_by_category_hqporner(self): """Returns video by category from HQPorner. I want to add support for EPorner""" # TODO @@ -1736,28 +1735,24 @@ def get_by_category_hqporner(self): "Invalid Category. Press 'list categories' to see all possible ones.", None)) category_name = self.ui.lineedit_hqporner_category.text() all_categories = hq_Client().get_all_categories() - search_limit = self.search_limit - pages = round(search_limit / 46) if not category_name in all_categories: ui_popup(self.list_all_categories_string) else: - videos = hq_Client().get_videos_by_category(category=category_name, pages=pages) - self.add_to_tree_widget_thread(videos, search_limit) + videos = hq_Client().get_videos_by_category(category=category_name) + self.add_to_tree_widget_thread(videos) def get_by_category_eporner(self): """Returns video by category from EPorner""" - search_limit = self.search_limit - pages = round(search_limit / 63) category_name = self.ui.lineedit_videos_by_category_eporner.text() if not category_name in self.all_cateogories_eporner: ui_popup(self.list_all_categories_string) else: - videos = ep_Client().get_videos_by_category(category=category_name, pages=pages, enable_html_scraping=True) - self.add_to_tree_widget_thread(iterator=videos, search_limit=search_limit) + videos = ep_Client().get_videos_by_category(category=category_name, enable_html_scraping=True) + self.add_to_tree_widget_thread(iterator=videos) def list_categories_eporner(self): """Lists all video categories from EPorner""" @@ -1769,10 +1764,8 @@ def list_categories_eporner(self): def get_brazzers_videos(self): """Get brazzers videos from HQPorner""" - search_limit = self.search_limit - pages = round(search_limit / 46) - videos = hq_Client().get_brazzers_videos(pages) - self.add_to_tree_widget_thread(videos, search_limit) + videos = hq_Client().get_brazzers_videos() + self.add_to_tree_widget_thread(videos) @classmethod def list_categories_hqporner(cls): @@ -1783,10 +1776,8 @@ def list_categories_hqporner(cls): def get_random_video(self): """Gets a random video from HQPorner""" - list_object = [] video = hq_Client().get_random_video() - list_object.append(video) - self.add_to_tree_widget_thread(list_object, search_limit=2) + self.add_to_tree_widget_thread([].append(video)) def show_credits(self): """Loads the credits from the CREDITS.md. Credits need to be recompiled in qresource file every time""" From 3f45167a7cb672d51b8de1add2d9f8c46a5f935a Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Tue, 25 Jun 2024 22:36:13 +0200 Subject: [PATCH 04/39] - repositioned some functions --- README/STATUS.md | 1 - main.py | 486 +++++++++++++++++++++++------------------------ 2 files changed, 237 insertions(+), 250 deletions(-) diff --git a/README/STATUS.md b/README/STATUS.md index b88bf9d..133b4f8 100644 --- a/README/STATUS.md +++ b/README/STATUS.md @@ -5,7 +5,6 @@ - [] Fixing searching for xvideos - [] Huge code refactoring - [] Splitting functions into other .py files -- [] Using Qt's logging instead of my own approach - [] Trying to optimize the UI performance with more threading and slower UI repainting - [] Supporting more websites - [] Writing the thumbnail into the video metadata diff --git a/main.py b/main.py index 70f38a4..1a7ee77 100644 --- a/main.py +++ b/main.py @@ -178,6 +178,7 @@ def __init__(self, iterator, search_limit, data_mode, reverse, stop_flag, is_che self.is_checked = is_checked def process_video(self, video, index): + session_urls.append(video.url) title = video.title disabled = QCoreApplication.tr("Disabled", None) duration = disabled @@ -722,193 +723,6 @@ def __init__(self, parent=None): if __build__ == "android": self.setup_android() # Sets up Android, if build mode is Android (handles some UI stuff and things) - def load_style(self): - """Refactored function to load icons and stylesheets.""" - # Setting icons with a loop if applicable - icons = { - self.ui.button_switch_home: "download.svg", - self.ui.button_switch_settings: "settings.svg", - self.ui.button_switch_credits: "information.svg", - self.ui.button_switch_account: "account.svg", - self.ui.button_switch_tools: "tools.svg", - self.ui.button_workers_help: "faq.svg", - self.ui.button_pornhub_delay_help: "faq.svg", - self.ui.button_threading_mode_help: "faq.svg", - self.ui.button_semaphore_help: "faq.svg", - self.ui.button_timeout_help: "faq.svg", - self.ui.button_directory_system_help: "faq.svg", - self.ui.button_result_limit_help: "faq.svg", - self.ui.button_timeout_maximal_retries_help: "faq.svg", - self.ui.button_help_file: "faq.svg", - self.ui.button_view_progress_bars: "progressbars.svg" - } - for button, icon_name in icons.items(): - button.setIcon(QIcon(f":/images/graphics/{icon_name}")) - - self.setWindowIcon(QIcon(":/images/graphics/logo_transparent.ico")) - # Stylesheets - stylesheet_paths = { - "progressbar_pornhub": ":/style/stylesheets/progressbar_pornhub.qss", - "progressbar_hqporner": ":/style/stylesheets/progressbar_hqporner.qss", - "progressbar_eporner": ":/style/stylesheets/progressbar_eporner.qss", - "progressbar_total": ":/style/stylesheets/progressbar_total.qss", - "progressbar_xnxx": ":/style/stylesheets/progressbar_xnxx.qss", - "progressbar_xvideos": ":/style/stylesheets/progressbar_xvideos.qss", - "progressbar_converting": ":/style/stylesheets/progressbar_converting.qss", - "button_blue": ":/style/stylesheets/stylesheet_button_blue.qss", - "button_orange": ":/style/stylesheets/stylesheet_button_orange.qss", - "button_purple": ":/style/stylesheets/stylesheet_button_purple.qss", - "button_green": ":/style/stylesheets/stylesheet_button_green.qss", - "buttons_login": ":/style/stylesheets/stylesheet_buttons_login.qss", - "button_reset": ":/style/stylesheets/stylesheet_button_reset.qss" - } - - stylesheets = {key: load_stylesheet(path) for key, path in stylesheet_paths.items()} - - # Applying stylesheets to specific buttons - # Simplify this part based on actual UI structure and naming - self.ui.button_login.setStyleSheet(stylesheets["button_green"]) - self.ui.progressbar_pornhub.setStyleSheet(stylesheets["progressbar_pornhub"]) - self.ui.progressbar_total.setStyleSheet(stylesheets["progressbar_total"]) - self.ui.progressbar_xnxx.setStyleSheet(stylesheets["progressbar_xnxx"]) - self.ui.progressbar_eporner.setStyleSheet(stylesheets["progressbar_eporner"]) - self.ui.progressbar_hqporner.setStyleSheet(stylesheets["progressbar_hqporner"]) - self.ui.progressbar_xvideos.setStyleSheet(stylesheets["progressbar_xvideos"]) - self.ui.progressbar_converting.setStyleSheet(stylesheets["progressbar_converting"]) - self.ui.button_model.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_search.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_download.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_threading_mode_help.setStyleSheet(stylesheets["button_green"]) - self.ui.button_directory_system_help.setStyleSheet(stylesheets["button_green"]) - self.ui.button_semaphore_help.setStyleSheet(stylesheets["button_green"]) - self.ui.button_tree_download.setStyleSheet(stylesheets["button_orange"]) - self.ui.button_tree_unselect_all.setStyleSheet(stylesheets["button_blue"]) - self.ui.button_tree_select_range.setStyleSheet(stylesheets["button_green"]) - self.ui.button_output_path_select.setStyleSheet(stylesheets["button_blue"]) - self.ui.button_login.setStyleSheet(stylesheets["button_blue"]) - self.ui.button_settings_apply.setStyleSheet(stylesheets["button_blue"]) - self.ui.button_get_random_videos.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_get_brazzers_videos.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_list_categories.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_open_file.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_switch_supported_websites.setStyleSheet(stylesheets["button_blue"]) - self.ui.button_hqporner_category_get_videos.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_top_porn_get_videos.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_get_watched_videos.setStyleSheet(stylesheets["buttons_login"]) - self.ui.button_get_liked_videos.setStyleSheet(stylesheets["buttons_login"]) - self.ui.button_get_recommended_videos.setStyleSheet(stylesheets["buttons_login"]) - self.ui.button_timeout_help.setStyleSheet(stylesheets["button_green"]) - self.ui.button_workers_help.setStyleSheet(stylesheets["button_green"]) - self.ui.button_pornhub_delay_help.setStyleSheet(stylesheets["button_green"]) - self.ui.button_result_limit_help.setStyleSheet(stylesheets["button_green"]) - self.ui.button_settings_reset.setStyleSheet(stylesheets["button_reset"]) - self.ui.button_playlist_get_videos.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_tree_stop.setStyleSheet(stylesheets["button_reset"]) - self.ui.button_tree_export_video_urls.setStyleSheet(stylesheets["button_purple"]) - self.ui.button_timeout_maximal_retries_help.setStyleSheet(stylesheets["button_green"]) - self.ui.button_help_file.setStyleSheet(stylesheets["button_green"]) - self.ui.button_download_ffmpeg.setStyleSheet(stylesheets["button_purple"]) - self.header = self.ui.treeWidget.header() - self.header.resizeSection(0, 300) - self.header.resizeSection(1, 150) - self.header.resizeSection(2, 50) - self.header.sortIndicatorChanged.connect(self.reindex) - - # Sort by the 'Length' column in ascending order - self.ui.treeWidget.sortByColumn(2, Qt.AscendingOrder) - - def check_for_updates(self): - """Checks for updates in a thread, so that the main UI isn't blocked, until update checks are done""" - self.update_thread = CheckUpdates() - self.update_thread.signals.result.connect(self.check_for_updates_result) - self.threadpool.start(self.update_thread) - - def check_for_updates_result(self, value): - """Receives the Update result from the thread""" - if value: - logger_debug(f"Next release v{__next_release__} found!") - try: - changelog = (requests.get(f"https://github.com/EchterAlsFake/Porn_Fetch/tree/master/README/Changelog/" - f"{__next_release__}/Changelog.md").text) - - except Exception as e: - logger_error(f"Couldn't fetch changelog of version: {__next_release__}") - changelog = f"Unknown Error: {e}" - - ui_popup(QCoreApplication().tr(f""" - Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. - Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} - - Changelog: - {markdown.markdown(changelog)} - - """, None)) - - - def check_ffmpeg(self): - # Check if ffmpeg is available in the system PATH - global ffmpeg_path - ffmpeg_path = shutil.which("ffmpeg") - - if ffmpeg_path is None: - # If ffmpeg is not in PATH, check the current directory for ffmpeg binaries - ffmpeg_binary = "ffmpeg.exe" if os.path.isfile("ffmpeg.exe") else "ffmpeg" if os.path.isfile( - "ffmpeg") else None - - if ffmpeg_binary is None: - # If ffmpeg binaries are not found in the current directory, display warning and disable features - if self.conf.get("Performance", "ffmpeg_warning") == "true": - ffmpeg_warning_message = QCoreApplication().tr( - """ -FFmpeg isn't installed on your system... Some features won't be available: - -- The FFmpeg threading mode -- Converting videos into a valid .mp4 format -- Writing tags / metadata into the videos - -These features aren't necessary for Porn Fetch, but can be useful for some people. - -To automatically install ffmpeg, just head over to the settings and press the magical button, or install ffmpeg in your -local PATH (e.g, through your linux package manager, or through the Windows PATH) - -This warning won't be shown again. - """, None) - ui_popup(ffmpeg_warning_message) - self.conf.set("Performance", "ffmpeg_warning", "false") - with open("config.ini", "w") as config_file: - self.conf.write(config_file) - - self.ui.radio_threading_mode_ffmpeg.setDisabled(True) - global ffmpeg_features - ffmpeg_features = False - logger_error("FFMPEG features have been disabled, because ffmpeg wasn't found on your system.") - else: - # If ffmpeg binary is found in the current directory, set it as the ffmpeg path - ffmpeg_path = os.path.abspath(ffmpeg_binary) - else: - # If ffmpeg is found in system PATH, use it directly - ffmpeg_path = shutil.which("ffmpeg") - consts.FFMPEG_EXECUTABLE = ffmpeg_path - bs_consts.FFMPEG_PATH = ffmpeg_path - logger_debug(f"FFMPEG: {ffmpeg_path}") - - def download_ffmpeg(self): - if sys.platform == "linux": - if not os.path.isfile("ffmpeg"): - self.downloader = FFMPEGDownload(url=url_linux, extract_path=".", mode="linux") - - elif sys.platform == "win32": - if not os.path.isfile("ffmpeg.exe"): - self.downloader = FFMPEGDownload(url=url_windows, extract_path=".", mode="windows") - - self.downloader.signals.total_progress.connect(self.update_total_progressbar) - self.downloader.signals.finished.connect(self.ffmpeg_finished) - self.threadpool.start(self.downloader) - - @classmethod - def ffmpeg_finished(cls): - ui_popup(QCoreApplication().tr("FFmpeg has been installed. Please restart Porn Fetch :)", None)) - def button_groups(self): """ The button groups are needed to tell the radio button which of them are in a group. @@ -952,46 +766,6 @@ def button_groups(self): self.radio_hqporner.addButton(self.ui.radio_top_porn_month) self.radio_hqporner.addButton(self.ui.radio_top_porn_all_time) - def setup_android(self): - """Sets up for Porn Fetch for Android devices""" - logger_debug(f"Running on Android: {sys.platform}") - if not get_output_path(): - self.handle_no_output_path() - return # Early return to avoid setting up UI components again at the end. - - self.configure_ui_for_android("/storage/emulated/0/Download/") - - def handle_no_output_path(self): - ui_popup( - QCoreApplication().tr("The output path does not exist or is not writable.", None)) - text, ok = QInputDialog.getText(self, "Enter custom Path", - QCoreApplication().tr("Enter custom Path:", None)) - if ok and get_output_path(text): - ui_popup( - QCoreApplication().tr(f"Success: {text} will be used for this session!", None)) - self.configure_ui_for_android(text) - else: - ui_popup( - QCoreApplication().tr("Invalid path. The application will now exit.", None)) - sys.exit() - - def configure_ui_for_android(self, path): - "" - - def warn_about_high_performance_threading(self): - if self.ui.radio_threading_mode_high_performance.isChecked(): - ui_popup( - QCoreApplication().tr("High Performance threading may cause issues on Android devices.", None)) - - def toggle_sorting(self): - if self.ui.checkbox_tree_allow_sorting.isChecked(): - logger_debug("Enabling sorting on the tree widget") - self.ui.treeWidget.setSortingEnabled(True) - - else: - logger_debug("Disabling sorting on the tree widget") - self.ui.treeWidget.setSortingEnabled(False) - def button_connectors(self): """a function to link the buttons to their functions""" # Menu Bar Switch Button Connections @@ -1038,7 +812,7 @@ def button_connectors(self): self.ui.button_top_porn_get_videos.clicked.connect(self.get_top_porn_hqporner) self.ui.button_get_brazzers_videos.clicked.connect(self.get_brazzers_videos) self.ui.button_list_categories.clicked.connect(self.list_categories_hqporner) - self.ui.button_switch_tools.clicked.connect(self.switch_to_hqporner) + self.ui.button_switch_tools.clicked.connect(self.switch_to_tools) self.ui.button_get_random_videos.clicked.connect(self.get_random_video) # EPorner @@ -1056,22 +830,100 @@ def button_connectors(self): self.ui.button_tree_export_video_urls.clicked.connect(export_urls) self.ui.button_download_ffmpeg.clicked.connect(self.download_ffmpeg) - def switch_login_button_state(self): - """If the user is logged in, I'll change the stylesheets of the buttons""" - file = QFile(":/style/stylesheets/stylesheet_switch_buttons_login_state.qss") - file.open(QFile.ReadOnly | QFile.Text) - stream = QTextStream(file) - stylesheet = stream.readAll() + def load_style(self): + """Refactored function to load icons and stylesheets.""" + # Setting icons with a loop if applicable + icons = { + self.ui.button_switch_home: "download.svg", + self.ui.button_switch_settings: "settings.svg", + self.ui.button_switch_credits: "information.svg", + self.ui.button_switch_account: "account.svg", + self.ui.button_switch_tools: "tools.svg", + self.ui.button_workers_help: "faq.svg", + self.ui.button_pornhub_delay_help: "faq.svg", + self.ui.button_threading_mode_help: "faq.svg", + self.ui.button_semaphore_help: "faq.svg", + self.ui.button_timeout_help: "faq.svg", + self.ui.button_directory_system_help: "faq.svg", + self.ui.button_result_limit_help: "faq.svg", + self.ui.button_timeout_maximal_retries_help: "faq.svg", + self.ui.button_help_file: "faq.svg", + self.ui.button_view_progress_bars: "progressbars.svg" + } + for button, icon_name in icons.items(): + button.setIcon(QIcon(f":/images/graphics/{icon_name}")) - self.ui.button_get_liked_videos.setStyleSheet(stylesheet) - self.ui.button_get_watched_videos.setStyleSheet(stylesheet) - self.ui.button_get_recommended_videos.setStyleSheet(stylesheet) + self.setWindowIcon(QIcon(":/images/graphics/logo_transparent.ico")) + # Stylesheets + stylesheet_paths = { + "progressbar_pornhub": ":/style/stylesheets/progressbar_pornhub.qss", + "progressbar_hqporner": ":/style/stylesheets/progressbar_hqporner.qss", + "progressbar_eporner": ":/style/stylesheets/progressbar_eporner.qss", + "progressbar_total": ":/style/stylesheets/progressbar_total.qss", + "progressbar_xnxx": ":/style/stylesheets/progressbar_xnxx.qss", + "progressbar_xvideos": ":/style/stylesheets/progressbar_xvideos.qss", + "progressbar_converting": ":/style/stylesheets/progressbar_converting.qss", + "button_blue": ":/style/stylesheets/stylesheet_button_blue.qss", + "button_orange": ":/style/stylesheets/stylesheet_button_orange.qss", + "button_purple": ":/style/stylesheets/stylesheet_button_purple.qss", + "button_green": ":/style/stylesheets/stylesheet_button_green.qss", + "buttons_login": ":/style/stylesheets/stylesheet_buttons_login.qss", + "button_reset": ":/style/stylesheets/stylesheet_button_reset.qss" + } - def switch_to_home(self): - self.ui.stacked_widget_main.setCurrentIndex(0) - self.ui.stacked_widget_top.setCurrentIndex(0) - self.ui.stacked_widget_top.setMinimumHeight(220) - self.ui.scrollarea_stacked_top.setMaximumHeight(220) + stylesheets = {key: load_stylesheet(path) for key, path in stylesheet_paths.items()} + + # Applying stylesheets to specific buttons + # Simplify this part based on actual UI structure and naming + self.ui.button_login.setStyleSheet(stylesheets["button_green"]) + self.ui.progressbar_pornhub.setStyleSheet(stylesheets["progressbar_pornhub"]) + self.ui.progressbar_total.setStyleSheet(stylesheets["progressbar_total"]) + self.ui.progressbar_xnxx.setStyleSheet(stylesheets["progressbar_xnxx"]) + self.ui.progressbar_eporner.setStyleSheet(stylesheets["progressbar_eporner"]) + self.ui.progressbar_hqporner.setStyleSheet(stylesheets["progressbar_hqporner"]) + self.ui.progressbar_xvideos.setStyleSheet(stylesheets["progressbar_xvideos"]) + self.ui.progressbar_converting.setStyleSheet(stylesheets["progressbar_converting"]) + self.ui.button_model.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_search.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_download.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_threading_mode_help.setStyleSheet(stylesheets["button_green"]) + self.ui.button_directory_system_help.setStyleSheet(stylesheets["button_green"]) + self.ui.button_semaphore_help.setStyleSheet(stylesheets["button_green"]) + self.ui.button_tree_download.setStyleSheet(stylesheets["button_orange"]) + self.ui.button_tree_unselect_all.setStyleSheet(stylesheets["button_blue"]) + self.ui.button_tree_select_range.setStyleSheet(stylesheets["button_green"]) + self.ui.button_output_path_select.setStyleSheet(stylesheets["button_blue"]) + self.ui.button_login.setStyleSheet(stylesheets["button_blue"]) + self.ui.button_settings_apply.setStyleSheet(stylesheets["button_blue"]) + self.ui.button_get_random_videos.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_get_brazzers_videos.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_list_categories.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_open_file.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_switch_supported_websites.setStyleSheet(stylesheets["button_blue"]) + self.ui.button_hqporner_category_get_videos.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_top_porn_get_videos.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_get_watched_videos.setStyleSheet(stylesheets["buttons_login"]) + self.ui.button_get_liked_videos.setStyleSheet(stylesheets["buttons_login"]) + self.ui.button_get_recommended_videos.setStyleSheet(stylesheets["buttons_login"]) + self.ui.button_timeout_help.setStyleSheet(stylesheets["button_green"]) + self.ui.button_workers_help.setStyleSheet(stylesheets["button_green"]) + self.ui.button_pornhub_delay_help.setStyleSheet(stylesheets["button_green"]) + self.ui.button_result_limit_help.setStyleSheet(stylesheets["button_green"]) + self.ui.button_settings_reset.setStyleSheet(stylesheets["button_reset"]) + self.ui.button_playlist_get_videos.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_tree_stop.setStyleSheet(stylesheets["button_reset"]) + self.ui.button_tree_export_video_urls.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_timeout_maximal_retries_help.setStyleSheet(stylesheets["button_green"]) + self.ui.button_help_file.setStyleSheet(stylesheets["button_green"]) + self.ui.button_download_ffmpeg.setStyleSheet(stylesheets["button_purple"]) + self.header = self.ui.treeWidget.header() + self.header.resizeSection(0, 300) + self.header.resizeSection(1, 150) + self.header.resizeSection(2, 50) + self.header.sortIndicatorChanged.connect(self.reindex) + + # Sort by the 'Length' column in ascending order + self.ui.treeWidget.sortByColumn(2, Qt.AscendingOrder) def settings_maps_initialization(self): # Maps for settings and corresponding UI elements @@ -1191,9 +1043,112 @@ def save_user_settings(self): ui_popup(QCoreApplication().tr("Saved User Settings, please restart Porn Fetch!", None)) logger_debug("Saved User Settings, please restart Porn Fetch.") - """ - Switchers for the Stacked Widgets - """ + def check_for_updates(self): + """Checks for updates in a thread, so that the main UI isn't blocked, until update checks are done""" + self.update_thread = CheckUpdates() + self.update_thread.signals.result.connect(check_for_updates_result) + self.threadpool.start(self.update_thread) + + def check_ffmpeg(self): + # Check if ffmpeg is available in the system PATH + global ffmpeg_path + ffmpeg_path = shutil.which("ffmpeg") + + if ffmpeg_path is None: + # If ffmpeg is not in PATH, check the current directory for ffmpeg binaries + ffmpeg_binary = "ffmpeg.exe" if os.path.isfile("ffmpeg.exe") else "ffmpeg" if os.path.isfile( + "ffmpeg") else None + + if ffmpeg_binary is None: + # If ffmpeg binaries are not found in the current directory, display warning and disable features + if self.conf.get("Performance", "ffmpeg_warning") == "true": + ffmpeg_warning_message = QCoreApplication().tr( + """ +FFmpeg isn't installed on your system... Some features won't be available: + +- The FFmpeg threading mode +- Converting videos into a valid .mp4 format +- Writing tags / metadata into the videos + +These features aren't necessary for Porn Fetch, but can be useful for some people. + +To automatically install ffmpeg, just head over to the settings and press the magical button, or install ffmpeg in your +local PATH (e.g, through your linux package manager, or through the Windows PATH) + +This warning won't be shown again. + """, None) + ui_popup(ffmpeg_warning_message) + self.conf.set("Performance", "ffmpeg_warning", "false") + with open("config.ini", "w") as config_file: + self.conf.write(config_file) + + self.ui.radio_threading_mode_ffmpeg.setDisabled(True) + global ffmpeg_features + ffmpeg_features = False + logger_error("FFMPEG features have been disabled, because ffmpeg wasn't found on your system.") + else: + # If ffmpeg binary is found in the current directory, set it as the ffmpeg path + ffmpeg_path = os.path.abspath(ffmpeg_binary) + else: + # If ffmpeg is found in system PATH, use it directly + ffmpeg_path = shutil.which("ffmpeg") + consts.FFMPEG_EXECUTABLE = ffmpeg_path + bs_consts.FFMPEG_PATH = ffmpeg_path + logger_debug(f"FFMPEG: {ffmpeg_path}") + + def download_ffmpeg(self): + if sys.platform == "linux": + if not os.path.isfile("ffmpeg"): + self.downloader = FFMPEGDownload(url=url_linux, extract_path=".", mode="linux") + + elif sys.platform == "win32": + if not os.path.isfile("ffmpeg.exe"): + self.downloader = FFMPEGDownload(url=url_windows, extract_path=".", mode="windows") + + self.downloader.signals.total_progress.connect(self.update_total_progressbar) + self.downloader.signals.finished.connect(ffmpeg_finished) + self.threadpool.start(self.downloader) + + def setup_android(self): + """Sets up for Porn Fetch for Android devices""" + logger_debug(f"Running on Android: {sys.platform}") + if not get_output_path(): + self.handle_no_output_path() + return # Early return to avoid setting up UI components again at the end. + + self.configure_ui_for_android("/storage/emulated/0/Download/") + + def handle_no_output_path(self): + ui_popup( + QCoreApplication().tr("The output path does not exist or is not writable.", None)) + text, ok = QInputDialog.getText(self, "Enter custom Path", + QCoreApplication().tr("Enter custom Path:", None)) + if ok and get_output_path(text): + ui_popup( + QCoreApplication().tr(f"Success: {text} will be used for this session!", None)) + self.configure_ui_for_android(text) + else: + ui_popup( + QCoreApplication().tr("Invalid path. The application will now exit.", None)) + sys.exit() + + def configure_ui_for_android(self, path): + "" + + def toggle_sorting(self): + if self.ui.checkbox_tree_allow_sorting.isChecked(): + logger_debug("Enabling sorting on the tree widget") + self.ui.treeWidget.setSortingEnabled(True) + + else: + logger_debug("Disabling sorting on the tree widget") + self.ui.treeWidget.setSortingEnabled(False) + + def switch_to_home(self): + self.ui.stacked_widget_main.setCurrentIndex(0) + self.ui.stacked_widget_top.setCurrentIndex(0) + self.ui.stacked_widget_top.setMinimumHeight(220) + self.ui.scrollarea_stacked_top.setMaximumHeight(220) def switch_to_account(self): self.ui.stacked_widget_top.setCurrentIndex(1) @@ -1201,7 +1156,7 @@ def switch_to_account(self): self.ui.stacked_widget_top.setMinimumHeight(150) self.ui.scrollarea_stacked_top.setMaximumHeight(150) - def switch_to_hqporner(self): + def switch_to_tools(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(3) self.ui.stacked_widget_top.setMinimumHeight(300) @@ -1210,9 +1165,6 @@ def switch_to_hqporner(self): def switch_to_settings(self): self.ui.stacked_widget_main.setCurrentIndex(1) - def switch_to_metadata(self): - self.ui.stacked_widget_main.setCurrentIndex(3) - def switch_to_credits(self): self.ui.stacked_widget_main.setCurrentIndex(2) self.show_credits() @@ -1652,6 +1604,17 @@ def login(self): except errors.ClientAlreadyLogged: ui_popup(QCoreApplication().tr("You are already logged in!", None)) + def switch_login_button_state(self): + """If the user is logged in, I'll change the stylesheets of the buttons""" + file = QFile(":/style/stylesheets/stylesheet_switch_buttons_login_state.qss") + file.open(QFile.ReadOnly | QFile.Text) + stream = QTextStream(file) + stylesheet = stream.readAll() + + self.ui.button_get_liked_videos.setStyleSheet(stylesheet) + self.ui.button_get_watched_videos.setStyleSheet(stylesheet) + self.ui.button_get_recommended_videos.setStyleSheet(stylesheet) + def check_login(self): """Checks if the user is logged in, so that no errors are threw if not""" if self.client.logged: @@ -1898,6 +1861,31 @@ def export_urls(): else: ui_popup(QCoreApplication().tr("No URLs in the current session...", None)) + def ffmpeg_finished(): + ui_popup(QCoreApplication().tr("FFmpeg has been installed. Please restart Porn Fetch :)", None)) + + + def check_for_updates_result(value): + """Receives the Update result from the thread""" + if value: + logger_debug(f"Next release v{__next_release__} found!") + try: + changelog = (requests.get(f"https://github.com/EchterAlsFake/Porn_Fetch/tree/master/README/Changelog/" + f"{__next_release__}/Changelog.md").text) + + except Exception as e: + logger_error(f"Couldn't fetch changelog of version: {__next_release__}") + changelog = f"Unknown Error: {e}" + + ui_popup(QCoreApplication().tr(f""" + Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. + Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} + + Changelog: + {markdown.markdown(changelog)} + + """, None)) + parser = argparse.ArgumentParser() parser.add_argument("-v", "--version", help="Shows the version information", action="store_true") From 47a4823d1b5e9fea5bcd4820fd096451afbed370 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Wed, 26 Jun 2024 17:08:17 +0200 Subject: [PATCH 05/39] - refactored loading video attributes (There's still soo much left to do) --- README/STATUS.md | 2 +- main.py | 42 +++++----------------- src/backend/shared_functions.py | 62 ++++++++++++++++++++++++--------- src/frontend/form_desktop.ui | 12 +++---- src/frontend/ui_form_desktop.py | 12 ++++--- 5 files changed, 68 insertions(+), 62 deletions(-) diff --git a/README/STATUS.md b/README/STATUS.md index 133b4f8..9df7107 100644 --- a/README/STATUS.md +++ b/README/STATUS.md @@ -2,7 +2,7 @@ - [] Fixing the completely broken and stupid Android layout - [] Fixing the UI flickering issues on Android - [] Fixing the low thread starting times on Android -- [] Fixing searching for xvideos +- [x] Fixing searching for xvideos - [] Huge code refactoring - [] Splitting functions into other .py files - [] Trying to optimize the UI performance with more threading and slower UI repainting diff --git a/main.py b/main.py index 1a7ee77..987783d 100644 --- a/main.py +++ b/main.py @@ -187,25 +187,9 @@ def process_video(self, video, index): # Checks which mode is selected by the user and loads the video attributes if self.data_mode == 1: if isinstance(video, (hq_Video, xn_Video, xv_Video)): - duration = str(video.length) - - if hasattr(video, 'pornstars'): - author = video.pornstars[0] if video.pornstars else "unknown" - - else: - author = video.author if hasattr(video, 'author') and video.author else "unknown" - - elif isinstance(video, Video): - duration = round(video.duration.seconds / 60) - author = video.author.name - - elif isinstance(video, ep_Video): - duration = round(int(video.length) / 60) - author = video.author - - # Handling exceptions for missing author in xn_Video - if isinstance(video, xn_Video) and not hasattr(video, 'pornstars'): - author = "unknown" + data = load_video_attributes(video) + author = data[1] + duration = data[2] print( f"\r\033[K[{Fore.LIGHTCYAN_EX}{index}/{self.search_limit}]{Fore.RESET}{str(title)} Successfully processed!", @@ -431,7 +415,7 @@ def run(self): self.signals.ffmpeg_progress.emit(round(progress), 100) os.remove(f"{self.output_path}_.tmp") - write_tags(path=self.output_path, video=self.video, ffmpeg_path=ffmpeg_path) + write_tags(path=self.output_path, video=self.video) else: logger_debug("FFMPEG features disabled, writing tags and converting the video won't be available!") @@ -517,17 +501,9 @@ def run(self): ui_popup(invalid_input_string) else: - title = video.title - - if isinstance(video, Video): - author = video.author.name - - elif isinstance(video, hq_Video): - pornstars = video.pornstars - author = pornstars[0] if pornstars else "no_author_found" - else: - author = video.author - + data = load_video_attributes(video) + title = data[0] + author = data[1] output_path = Path(self.output_path) stripped_title = Core().strip_title(title) # Strip the title so that videos with special chars can be # saved on windows. It would raise an OSError otherwise @@ -566,6 +542,7 @@ def run(self): r.raise_for_status() try: total_length = int(r.headers.get('content-length')) + except Exception: total_length = 41313894 @@ -1252,8 +1229,7 @@ def download_tree_widget(self): def clear_tree_widget(self): """ - This (like the name says) clears the tree widget. I try to improve this in the future, to allow the user - the adding of multiple videos, so that the tree widget doesn't get cleared instantly. + This (like the name says) clears the tree widget. """ if not self.ui.checkbox_tree_do_not_clear_videos.isChecked(): self.ui.treeWidget.clear() diff --git a/src/backend/shared_functions.py b/src/backend/shared_functions.py index 573151e..286ee86 100644 --- a/src/backend/shared_functions.py +++ b/src/backend/shared_functions.py @@ -227,33 +227,61 @@ def get_element_safe(list, index): else: return "" +def load_video_attributes(video): -def write_tags(path, video, ffmpeg_path): title = video.title - comment = "Downloaded with Porn Fetch (GPLv3)" - genre = "Porn" - if isinstance(video, hq_Video): - artist = video.pornstars[0] + if isinstance(video, xn_Video): + author = video.author + length = video.length + tags = video.tags + publish_date = video.publish_date - elif hasattr(video.author, "name"): - artist = video.author.name + elif isinstance(video, xv_Video): + author = video.author + length = video.length + tags = video.tags + publish_date = video.publish_date - else: - artist = video.author if not isinstance(video.author, list) else video.author[0] + elif isinstance(video, Video): + try: + author = video.author.name - if artist == "": - artist = "Unknown" + except Exception: + author = video.pornstars[0] - if hasattr(video, "date"): - date = video.date.strftime("%Y/%m/%d") + length = video.duration.seconds + tags = ",".join([tag.name for tag in video.tags]) + publish_date = video.date - elif hasattr(video, "publish_date"): - date = video.publish_date + elif isinstance(video, ep_Video): + author = video.author + length = video.length_minutes + tags = ",".join([tag for tag in video.tags]) + publish_date = video.publish_date - else: - date = "Unknown" + elif isinstance(video, hq_Video): + try: + author = video.pornstars[0] + except Exception: + author = "No pornstars / author" # This can sometimes happen. Very rarely, but can happen... + + length = video.length + tags = ",".join([category for category in video.categories]) + publish_date = video.publish_date + + data = [title, author, length, tags, publish_date] + return data + + +def write_tags(path, video): + data = load_video_attributes(video) + comment = "Downloaded with Porn Fetch (GPLv3)" + genre = "Porn" + title = data[0] + artist = data[1] + date = data[3] logger_debug("Tags [1/3]") audio = MP4(path) diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 63a85b7..5e9f902 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -97,7 +97,7 @@ 0 0 1570 - 277 + 284 @@ -663,8 +663,8 @@ 0 0 - 1532 - 239 + 387 + 206 @@ -1153,7 +1153,7 @@ 0 0 1568 - 336 + 403 @@ -2230,7 +2230,7 @@ p, li { white-space: pre-wrap; } 0 0 1588 - 161 + 87 @@ -2338,7 +2338,7 @@ p, li { white-space: pre-wrap; } PointingHandCursor - border: none + border: none; diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index a32128b..c4a0913 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -69,7 +69,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_stacked_top.setWidgetResizable(True) self.scrollAreaWidgetContents_7 = QWidget() self.scrollAreaWidgetContents_7.setObjectName(u"scrollAreaWidgetContents_7") - self.scrollAreaWidgetContents_7.setGeometry(QRect(0, 0, 1570, 277)) + self.scrollAreaWidgetContents_7.setGeometry(QRect(0, 0, 1570, 284)) self.gridLayout_14 = QGridLayout(self.scrollAreaWidgetContents_7) self.gridLayout_14.setObjectName(u"gridLayout_14") self.stacked_widget_top = QStackedWidget(self.scrollAreaWidgetContents_7) @@ -361,7 +361,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1532, 239)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 387, 206)) self.gridLayout_18 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_18.setObjectName(u"gridLayout_18") self.gridlayout_progressbar = QGridLayout() @@ -634,7 +634,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_treewidget.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") - self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1568, 336)) + self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1568, 403)) self.gridLayout_4 = QGridLayout(self.scrollAreaWidgetContents_3) self.gridLayout_4.setObjectName(u"gridLayout_4") self.verticallayout_treewidget_settings = QVBoxLayout() @@ -1306,7 +1306,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_status.setWidgetResizable(True) self.scrollAreaWidgetContents_5 = QWidget() self.scrollAreaWidgetContents_5.setObjectName(u"scrollAreaWidgetContents_5") - self.scrollAreaWidgetContents_5.setGeometry(QRect(0, 0, 1588, 161)) + self.scrollAreaWidgetContents_5.setGeometry(QRect(0, 0, 1588, 87)) self.gridLayout_33 = QGridLayout(self.scrollAreaWidgetContents_5) self.gridLayout_33.setObjectName(u"gridLayout_33") self.gridlayout_status = QGridLayout() @@ -1369,7 +1369,9 @@ def setupUi(self, Porn_Fetch_Widget): self.button_switch_home.setMinimumSize(QSize(50, 35)) self.button_switch_home.setMaximumSize(QSize(16777215, 35)) self.button_switch_home.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.button_switch_home.setStyleSheet(u"border: none") + self.button_switch_home.setStyleSheet(u"border: 2px;\n" +"border-color: yellow;\n" +"border-style: double-dotted") self.button_switch_home.setIconSize(QSize(32, 32)) self.horizontalLayout_menu_buttons.addWidget(self.button_switch_home) From de97f0c2d1fe05f7b8af35b4773ca5885857d7f0 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Wed, 26 Jun 2024 21:29:00 +0200 Subject: [PATCH 06/39] - refactoring and improving the layout (not finished) - refactored the attribute loading and tag writing functions (not fully finished, thumbnail is missing) --- main.py | 85 +- src/backend/shared_functions.py | 20 +- src/frontend/form_desktop.ui | 4536 +++++++++++------------ src/frontend/resources.py | 163 +- src/frontend/stylesheets/stylesheet.qss | 3 - src/frontend/ui_form_desktop.py | 1011 ++--- 6 files changed, 2653 insertions(+), 3165 deletions(-) diff --git a/main.py b/main.py index 987783d..c6bec25 100644 --- a/main.py +++ b/main.py @@ -178,26 +178,22 @@ def __init__(self, iterator, search_limit, data_mode, reverse, stop_flag, is_che self.is_checked = is_checked def process_video(self, video, index): + data = load_video_attributes(video) session_urls.append(video.url) - title = video.title + title = data[0] disabled = QCoreApplication.tr("Disabled", None) duration = disabled author = disabled # Checks which mode is selected by the user and loads the video attributes if self.data_mode == 1: - if isinstance(video, (hq_Video, xn_Video, xv_Video)): - data = load_video_attributes(video) - author = data[1] - duration = data[2] + author = data[1] + duration = str(parse_length(data[2])) print( f"\r\033[K[{Fore.LIGHTCYAN_EX}{index}/{self.search_limit}]{Fore.RESET}{str(title)} Successfully processed!", end='', flush=True) - if self.data_mode == 1: - duration = str(parse_length(duration)) - return [str(title), str(author), str(duration), str(index), video] def run(self): @@ -663,12 +659,11 @@ def __init__(self, parent=None): self.directory_system_map = None self.threading_mode_map = None self.threading_map = None - self.language_map = None self.quality_map = None self.selected_category = None self.excluded_categories_filter = None self.client = None - self.api_language = None + self.api_language = "en" self.delay = None self.search_limit = None self.semaphore_limit = None @@ -714,19 +709,6 @@ def button_groups(self): self.group_quality.addButton(self.ui.radio_quality_half) self.group_quality.addButton(self.ui.radio_quality_best) - self.group_api_language = QButtonGroup() - self.group_api_language.addButton(self.ui.radio_api_language_chinese) - self.group_api_language.addButton(self.ui.radio_api_language_german) - self.group_api_language.addButton(self.ui.radio_api_language_french) - self.group_api_language.addButton(self.ui.radio_api_language_english) - self.group_api_language.addButton(self.ui.radio_api_language_russian) - self.group_api_language.addButton(self.ui.radio_api_language_czech) - self.group_api_language.addButton(self.ui.radio_api_language_italian) - self.group_api_language.addButton(self.ui.radio_api_language_spanish) - self.group_api_language.addButton(self.ui.radio_api_language_portuguese) - self.group_api_language.addButton(self.ui.radio_api_language_dutch) - self.group_api_language.addButton(self.ui.radio_api_language_japanese) - self.directory_system_group = QButtonGroup() self.directory_system_group.addButton(self.ui.radio_directory_system_no) self.directory_system_group.addButton(self.ui.radio_directory_system_yes) @@ -910,20 +892,6 @@ def settings_maps_initialization(self): "worst": self.ui.radio_quality_worst } - self.language_map = { - "en": self.ui.radio_api_language_english, - "fr": self.ui.radio_api_language_french, - "de": self.ui.radio_api_language_german, - "zh": self.ui.radio_api_language_chinese, - "nl": self.ui.radio_api_language_dutch, - "ru": self.ui.radio_api_language_russian, - "jp": self.ui.radio_api_language_japanese, - "pt": self.ui.radio_api_language_portuguese, - "es": self.ui.radio_api_language_spanish, - "cz": self.ui.radio_api_language_czech, - "it": self.ui.radio_api_language_italian - } - self.threading_mode_map = { "threaded": self.ui.radio_threading_mode_high_performance, "FFMPEG": self.ui.radio_threading_mode_ffmpeg, @@ -950,7 +918,6 @@ def load_user_settings(self): self.quality_map.get(self.conf.get("Video", "quality")).setChecked(True) self.threading_mode_map.get(self.conf.get("Performance", "threading_mode")).setChecked(True) self.directory_system_map.get(self.conf.get("Video", "directory_system")).setChecked(True) - self.language_map.get(self.conf.get("Video", "language")).setChecked(True) self.gui_language_map.get(self.conf.get("UI", "language")).setChecked(True) self.ui.spinbox_semaphore.setValue(int(self.conf.get("Performance", "semaphore"))) self.ui.spinbox_treewidget_limit.setValue(int(self.conf.get("Video", "search_limit"))) @@ -986,11 +953,6 @@ def save_user_settings(self): if radio_button.isChecked(): self.conf.set("Video", "quality", quality) - # Save language setting - for language, radio_button in self.language_map.items(): - if radio_button.isChecked(): - self.conf.set("Video", "language", language) - # Save threading mode for mode, radio_button in self.threading_mode_map.items(): if radio_button.isChecked(): @@ -1017,7 +979,7 @@ def save_user_settings(self): with open("config.ini", "w") as config_file: self.conf.write(config_file) - ui_popup(QCoreApplication().tr("Saved User Settings, please restart Porn Fetch!", None)) + ui_popup(QCoreApplication.tr(self, "Saved User Settings, please restart Porn Fetch!", None)) logger_debug("Saved User Settings, please restart Porn Fetch.") def check_for_updates(self): @@ -1039,7 +1001,7 @@ def check_ffmpeg(self): if ffmpeg_binary is None: # If ffmpeg binaries are not found in the current directory, display warning and disable features if self.conf.get("Performance", "ffmpeg_warning") == "true": - ffmpeg_warning_message = QCoreApplication().tr( + ffmpeg_warning_message = QCoreApplication.tr(self, """ FFmpeg isn't installed on your system... Some features won't be available: @@ -1097,16 +1059,16 @@ def setup_android(self): def handle_no_output_path(self): ui_popup( - QCoreApplication().tr("The output path does not exist or is not writable.", None)) + QCoreApplication.tr(self, "The output path does not exist or is not writable.", None)) text, ok = QInputDialog.getText(self, "Enter custom Path", - QCoreApplication().tr("Enter custom Path:", None)) + QCoreApplication.tr(self, "Enter custom Path:", None)) if ok and get_output_path(text): ui_popup( - QCoreApplication().tr(f"Success: {text} will be used for this session!", None)) + QCoreApplication.tr(self, f"Success: {text} will be used for this session!", None)) self.configure_ui_for_android(text) else: ui_popup( - QCoreApplication().tr("Invalid path. The application will now exit.", None)) + QCoreApplication.tr(self, "Invalid path. The application will now exit.", None)) sys.exit() def configure_ui_for_android(self, path): @@ -1125,19 +1087,16 @@ def switch_to_home(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(0) self.ui.stacked_widget_top.setMinimumHeight(220) - self.ui.scrollarea_stacked_top.setMaximumHeight(220) def switch_to_account(self): self.ui.stacked_widget_top.setCurrentIndex(1) self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setMinimumHeight(150) - self.ui.scrollarea_stacked_top.setMaximumHeight(150) def switch_to_tools(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(3) self.ui.stacked_widget_top.setMinimumHeight(300) - self.ui.scrollarea_stacked_top.setMaximumHeight(300) def switch_to_settings(self): self.ui.stacked_widget_main.setCurrentIndex(1) @@ -1414,7 +1373,7 @@ def on_video_loaded(self, video, author, stripped_title, output_file_path, threa def on_video_load_error(self, error_message): # Handle errors, possibly show message to user logger_debug(f"Error loading video: {error_message}") - ui_popup(QCoreApplication().tr(f"Some error occurred in loading a video. Please report this: {error_message}", + ui_popup(QCoreApplication.tr(self, f"Some error occurred in loading a video. Please report this: {error_message}", None)) def process_video_thread(self, output_path, video, threading_mode, quality): @@ -1565,20 +1524,20 @@ def login(self): password = self.ui.lineedit_password.text() if len(username) <= 2 or len(password) <= 2: ui_popup( - QCoreApplication().tr("Those credentials don't seem to be valid...", None)) + QCoreApplication.tr(self, "Those credentials don't seem to be valid...", None)) return try: self.client = Client(username, password, language=self.api_language, delay=self.delay) logger_debug("Login Successful!") - ui_popup(QCoreApplication().tr("Login Successful!", None)) + ui_popup(QCoreApplication.tr(self, "Login Successful!", None)) self.switch_login_button_state() except errors.LoginFailed: - ui_popup(QCoreApplication().tr("Login Failed, please check your credentials and try again!", None)) + ui_popup(QCoreApplication.tr(self, "Login Failed, please check your credentials and try again!", None)) except errors.ClientAlreadyLogged: - ui_popup(QCoreApplication().tr("You are already logged in!", None)) + ui_popup(QCoreApplication.tr(self, "You are already logged in!", None)) def switch_login_button_state(self): """If the user is logged in, I'll change the stylesheets of the buttons""" @@ -1599,7 +1558,7 @@ def check_login(self): elif not self.client.logged: self.login() if not self.client.logged: - text = (QCoreApplication().tr( + text = (QCoreApplication.tr(self, "There's a problem with the login. Please make sure you login first and then you try to " "get videos based on your account.", None)) ui_popup(text) @@ -1670,7 +1629,7 @@ def get_top_porn_hqporner(self): def get_by_category_hqporner(self): """Returns video by category from HQPorner. I want to add support for EPorner""" # TODO - self.list_all_categories_string = (QCoreApplication().tr( + self.list_all_categories_string = (QCoreApplication.tr(self, "Invalid Category. Press 'list categories' to see all possible ones.", None)) category_name = self.ui.lineedit_hqporner_category.text() all_categories = hq_Client().get_all_categories() @@ -1811,7 +1770,7 @@ def load_stylesheet(path): def reset_pornfetch(): setup_config_file(force=True) - ui_popup(QCoreApplication().tr("Done! Please restart.", None)) + ui_popup(QCoreApplication.tr("Done! Please restart.", None)) def switch_stop_state_2(): @@ -1835,10 +1794,10 @@ def export_urls(): ui_popup(f"Success! Saved: {len(session_urls)} URLs") else: - ui_popup(QCoreApplication().tr("No URLs in the current session...", None)) + ui_popup(QCoreApplication.tr("No URLs in the current session...", None)) def ffmpeg_finished(): - ui_popup(QCoreApplication().tr("FFmpeg has been installed. Please restart Porn Fetch :)", None)) + ui_popup(QCoreApplication.tr("FFmpeg has been installed. Please restart Porn Fetch :)", None)) def check_for_updates_result(value): @@ -1853,7 +1812,7 @@ def check_for_updates_result(value): logger_error(f"Couldn't fetch changelog of version: {__next_release__}") changelog = f"Unknown Error: {e}" - ui_popup(QCoreApplication().tr(f""" + ui_popup(QCoreApplication.tr(f""" Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} diff --git a/src/backend/shared_functions.py b/src/backend/shared_functions.py index 286ee86..9ed60ff 100644 --- a/src/backend/shared_functions.py +++ b/src/backend/shared_functions.py @@ -7,7 +7,7 @@ import re import requests -from mutagen.mp4 import MP4 +from mutagen.mp4 import MP4, MP4Cover from phub import Client, errors, Video from phub.modules import download as download from colorama import Fore @@ -70,7 +70,6 @@ [Video] quality = best -language = en output_path = ./ directory_system = 0 search_limit = 50 @@ -78,7 +77,6 @@ [UI] language = system -discord = false """ @@ -227,8 +225,8 @@ def get_element_safe(list, index): else: return "" -def load_video_attributes(video): +def load_video_attributes(video): title = video.title if isinstance(video, xn_Video): @@ -236,12 +234,14 @@ def load_video_attributes(video): length = video.length tags = video.tags publish_date = video.publish_date + thumbnail = video.thumbnail_url[0] elif isinstance(video, xv_Video): author = video.author length = video.length tags = video.tags publish_date = video.publish_date + thumbnail = video.thumbnail_url elif isinstance(video, Video): try: @@ -250,15 +250,17 @@ def load_video_attributes(video): except Exception: author = video.pornstars[0] - length = video.duration.seconds + length = video.duration.seconds / 60 tags = ",".join([tag.name for tag in video.tags]) publish_date = video.date + thumbnail = video.image.url elif isinstance(video, ep_Video): author = video.author length = video.length_minutes tags = ",".join([tag for tag in video.tags]) publish_date = video.publish_date + thumbnail = video.thumbnail elif isinstance(video, hq_Video): try: @@ -269,8 +271,9 @@ def load_video_attributes(video): length = video.length tags = ",".join([category for category in video.categories]) publish_date = video.publish_date + thumbnail = video.get_thumbnails()[0] - data = [title, author, length, tags, publish_date] + data = [title, author, length, tags, publish_date, thumbnail] return data @@ -282,6 +285,7 @@ def write_tags(path, video): title = data[0] artist = data[1] date = data[3] + thumbnail = data[5] logger_debug("Tags [1/3]") audio = MP4(path) @@ -291,7 +295,9 @@ def write_tags(path, video): audio.tags["\xa9gen"] = genre audio.tags["\xa9day"] = date - logger_debug("Tags: [2/3]") + logger_debug("Tags: [2/3] - Writing Thumbnail") + content = requests.get(thumbnail).content + audio.tags["covr"] = MP4Cover(content, imageformat=MP4Cover.FORMAT_PNG) audio.save() logger_debug("Tags: [3/3] ✔") diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 5e9f902..7bbdd85 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -27,2074 +27,2072 @@ - - - Qt::ScrollBarAsNeeded - - - true - - - - - 0 - 0 - 1610 - 943 - - - - - + + + + + Porn Fetch Menu + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + PointingHandCursor + + + border: none; + + + + + + + 32 + 32 + + + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + + 9 + + + + PointingHandCursor + + + border: none + + + + + + + 32 + 32 + + + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + PointingHandCursor + + + border: none; + + + + + + + 32 + 32 + + + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + PointingHandCursor + + + border: none; + + + + + + + 32 + 32 + + + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + PointingHandCursor + + + border: none + + + + + + + 32 + 32 + + + + + + + + + 0 + 0 + + + + + 50 + 35 + + + + + 16777215 + 35 + + + + PointingHandCursor + + + border: none; + + + + + + + 32 + 32 + + + + + + + + + + + + + + 0 + + + + + + + + + true + + + + + 0 + 0 + 1588 + 415 + + + + + + + + + + 0 + 0 + + + + + 100 + 200 + + + + + Title + + + + + Author + + + + + Duration + + + + + + + + + + + + + 0 + 0 + + + + PointingHandCursor + + + + + + + + + Get Title, Author, Duration + + + true + + + false + + + + + + + Export video URLs + + + + + + + Do not clear videos + + + + + + + + 0 + 0 + + + + PointingHandCursor + + + Only Title (a lot faster) + + + true + + + + + + + PointingHandCursor + + + Show videos in reverse + + + + + + + Allow Sorting + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + Does not stop downloading videos + + + Stop loading videos + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + PointingHandCursor + + + Automatically checks a range of videos + + + + + + Select a range of videos + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + PointingHandCursor + + + Unselects all videos in the tree widget + + + + + + Unselect all + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + PointingHandCursor + + + + + + Download Selected Videos + + + + + + + + + + + + 0 + 0 + + + + + 650 + 100 + + + + b + + + 0 + + + + + + + QLayout::SetMaximumSize + + + 0 + + + 6 + + + + + + 0 + 0 + + + + PointingHandCursor + + + Start + + + + + + + + 0 + 0 + + + + + 300 + 4 + + + + Enter video URL + + + + + + + + 0 + 0 + + + + + 60 + 2 + + + + PointingHandCursor + + + + + + Open File + + + + + + + + 0 + 0 + + + + Search Website + + + + + + + + 0 + 0 + + + + + 60 + 2 + + + + PointingHandCursor + + + + + + Get Videos + + + + + + + + 0 + 0 + + + + + 60 + 2 + + + + PointingHandCursor + + + + + + Download + + + + + + + + 0 + 0 + + + + + 300 + 2 + + + + Enter Model / Channel / Actress URL + + + + + + + 4 + + + 5 + + + 5 + + + + + PornHub + + + true + + + + + + + HQPorner + + + + + + + XVideos + + + + + + + EPorner + + + + + + + XNXX + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + + 300 + 2 + + + + + + + true + + + URLs in the file must be separated with new lines! + + + + + + + + 0 + 0 + + + + + 100 + 2 + + + + URL: + + + + + + + Enter a PornHub Playlist URL + + + + + + + Search Query: + + + + + + + Playlist URL: + + + + + + + + 0 + 0 + + + + + 100 + 2 + + + + Model URL: + + + + + + + Get Videos + + + + + + + + 0 + 0 + + + + + 300 + 0 + + + + + + + Search for Videos. Select Website below + + + + + + + + 0 + 0 + + + + + 100 + 2 + + + + File: + + + + + + + Help + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + + 16777215 + 20 + + + + PointingHandCursor + + + See Supported Websites + + + + + + + + + + + + + 0 + + + + + PointingHandCursor + + + + + + Get Liked videos + + + + + + + PointingHandCursor + + + + + + Get watched videos + + + + + + + + 0 + 0 + + + + Username: + + + + + + + + 0 + 0 + + + + PointingHandCursor + + + + + + Login + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + Enter your PornHub Username + + + + + + + PointingHandCursor + + + + + + Get recommended videos + + + + + + + + 0 + 0 + + + + Password: + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + QLineEdit::Password + + + Enter your PornHub Password + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + true + + + + + 0 + 0 + 387 + 206 + + + + + + + + + 0 + + + + + + + + 0 + 0 + + + + PornHub: + + + + + + + XVideos + + + + + + + XNXX + + + + + + + 0 + + + + + + + + 0 + 0 + + + + HQPorner: + + + + + + + + 0 + 0 + + + + + 300 + 0 + + + + 0 + + + + + + + + 0 + 0 + + + + + 300 + 0 + + + + 0 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0 + + + + + + + Eporner + + + + + + + Info: + + + + + + + + + + true + + + + + + + + + + + + + + + + + HQPorner + + + + + + + + + 0 + 10 + + + + PointingHandCursor + + + Month + + + + + + + + 0 + 10 + + + + PointingHandCursor + + + Get Videos + + + + + + + + 0 + 4 + + + + Get Brazzers videos + + + + + + + + 0 + 10 + + + + PointingHandCursor + + + Week + + + true + + + + + + + + 0 + 0 + + + + + 0 + 2 + + + + PointingHandCursor + + + List of all categories + + + + + + + + 0 + 4 + + + + + 100 + 4 + + + + + + + + Get Top Porn: + + + + + + + + 0 + 10 + + + + PointingHandCursor + + + All Time + + + + + + + + 0 + 2 + + + + + 0 + 2 + + + + PointingHandCursor + + + Get Videos + + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + PointingHandCursor + + + Get Video + + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + PointingHandCursor + + + Get Videos + + + + + + + + 0 + 4 + + + + Get random video + + + + + + + + 0 + 4 + + + + Get videos by category + + + + + + + + + + + + EPorner + + + + + + + + + 0 + 4 + + + + Get videos by category + + + + + + + + 0 + 4 + + + + + 100 + 4 + + + + + + + + + 0 + 2 + + + + + 0 + 2 + + + + PointingHandCursor + + + Get Videos + + + + + + + + 0 + 0 + + + + + 0 + 2 + + + + PointingHandCursor + + + List of all categories + + + + + + + + + + + + + + + + - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 + + + true + + + + + 0 + 0 + 1570 + 771 + - - - - - - - 0 - - - - - - - - 0 - 0 - - - - - 0 - 100 - - - - true - - - - - 0 - 0 - 1570 - 284 - - - - - - - - 0 - 0 - + + + + + Download and Setup FFmpeg + + + + + + + + + Performance + + + + + + + + Simultaneous downloads: + + + + + + + 1 - - - 600 - 100 - + + 5000 - - b + + + + + + PointingHandCursor - - 0 + + Help - - - - - - QLayout::SetMaximumSize - - - 0 - - - - - - 0 - 0 - - - - PointingHandCursor - - - Start - - - - - - - - 0 - 0 - - - - - 300 - 4 - - - - Enter video URL - - - - - - - - 0 - 0 - - - - - 60 - 2 - - - - PointingHandCursor - - - - - - Open File - - - - - - - Search Website - - - - - - - - 0 - 0 - - - - - 60 - 2 - - - - PointingHandCursor - - - - - - Get Videos - - - - - - - - 0 - 0 - - - - - 60 - 2 - - - - PointingHandCursor - - - - - - Download - - - - - - - - 0 - 0 - - - - - 300 - 2 - - - - Enter Model / Channel / Actress URL - - - - - - - 4 - - - 5 - - - 5 - - - - - PornHub - - - true - - - - - - - HQPorner - - - - - - - XVideos - - - - - - - EPorner - - - - - - - XNXX - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - - 300 - 2 - - - - - - - true - - - URLs in the file must be separated with new lines! - - - - - - - - 0 - 0 - - - - - 100 - 2 - - - - URL: - - - - - - - Enter a PornHub Playlist URL - - - - - - - Search Query: - - - - - - - Playlist URL: - - - - - - - - 0 - 0 - - - - - 100 - 2 - - - - Model URL: - - - - - - - Get Videos - - - - - - - - 0 - 0 - - - - - 300 - 0 - - - - - - - Search for Videos. Select Website below - - - - - - - - 0 - 0 - - - - - 100 - 2 - - - - File: - - - - - - - Help - - - - - - - - 0 - 0 - - - - - 0 - 25 - - - - - 16777215 - 20 - - - - PointingHandCursor - - - See Supported Websites - - - - - - - - - - - - - 0 - - - - - PointingHandCursor - - - - - - Get Liked videos - - - - - - - PointingHandCursor - - - - - - Get watched videos - - - - - - - - 0 - 0 - - - - Username: - - - - - - - - 0 - 0 - - - - PointingHandCursor - - - - - - Login - - - - - - - - 0 - 0 - - - - - 150 - 0 - - - - Enter your PornHub Username - - - - - - - PointingHandCursor - - - - - - Get recommended videos - - - - - - - - 0 - 0 - - - - Password: - - - - - - - - 0 - 0 - - - - - 150 - 0 - - - - QLineEdit::Password - - - Enter your PornHub Password - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - true - - - - - 0 - 0 - 387 - 206 - - - - - - - - - 0 - - - - - - - - 0 - 0 - - - - PornHub: - - - - - - - XVideos - - - - - - - XNXX - - - - - - - 0 - - - - - - - - 0 - 0 - - - - HQPorner: - - - - - - - - 0 - 0 - - - - - 300 - 0 - - - - 0 - - - - - - - - 0 - 0 - - - - - 300 - 0 - - - - 0 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - 0 - - - - - - - Eporner - - - - - - - Info: - - - - - - - - - - true - - - - - - - - - - - - - - - - - HQPorner - - - - - - - - - 0 - 10 - - - - PointingHandCursor - - - Month - - - - - - - - 0 - 10 - - - - PointingHandCursor - - - Get Videos - - - - - - - - 0 - 4 - - - - Get Brazzers videos - - - - - - - - 0 - 10 - - - - PointingHandCursor - - - Week - - - true - - - - - - - - 0 - 0 - - - - - 0 - 2 - - - - PointingHandCursor - - - List of all categories - - - - - - - - 0 - 4 - - - - - 100 - 4 - - - - - - - - Get Top Porn: - - - - - - - - 0 - 10 - - - - PointingHandCursor - - - All Time - - - - - - - - 0 - 2 - - - - - 0 - 2 - - - - PointingHandCursor - - - Get Videos - - - - - - - - 0 - 0 - - - - - 0 - 10 - - - - PointingHandCursor - - - Get Video - - - - - - - - 0 - 0 - - - - - 0 - 10 - - - - PointingHandCursor - - - Get Videos - - - - - - - - 0 - 4 - - - - Get random video - - - - - - - - 0 - 4 - - - - Get videos by category - - - - - - - - - - - - EPorner - - - - - - - - - 0 - 4 - - - - Get videos by category - - - - - - - - 0 - 4 - - - - - 100 - 4 - - - - - - - - - 0 - 2 - - - - - 0 - 2 - - - - PointingHandCursor - - - Get Videos - - - - - - - - 0 - 0 - - - - - 0 - 2 - - - - PointingHandCursor - - - List of all categories - - - - - - - - - - - - - - - - - - - true - - - - - 0 - 0 - 1568 - 403 - - - - - - - - - - 0 - 0 - - - - - 100 - 200 - - - - - Title - - - - - Author - - - - - Duration - - - - - - - - - - - - - 0 - 0 - - - - PointingHandCursor - - - - - - - - - Get Title, Author, Duration - - - true - - - false - - - - - - - Export video URLs - - - - - - - Do not clear videos - - - - - - - - 0 - 0 - - - - PointingHandCursor - - - Only Title (a lot faster) - - - true - - - - - - - PointingHandCursor - - - Show videos in reverse - - - - - - - Allow Sorting - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - - 0 - 0 - + + + + + + Maximal workers: + + + + + + + 1 - - - 0 - 30 - + + 5000 + + + + PointingHandCursor - - Unselects all videos in the tree widget + + Help + + + + + + + + + + + PornHub Delay (0 = Disabled) in seconds: + + + + + + + 0 + + + 5000 - - + + + + + + PointingHandCursor - Unselect all + Help - - + + + + + + - + 0 0 - - - 0 - 30 - + + Threading Mode: - - Does not stop downloading videos + + + + + + PointingHandCursor - Stop loading videos + High Performance - - - - - 0 - 0 - + + + + PointingHandCursor - - - 0 - 30 - + + FFMPEG + + + + PointingHandCursor - - Automatically checks a range of videos + + Default + + + + + + + PointingHandCursor - - + + Help + + + + + + + + - Select a range of videos + Maximal timeout: - - - - - 0 - 0 - + + + + 5 - - - 0 - 30 - + + 5000 + + + + PointingHandCursor - - + + Help + + + + + + + + + + + Maximal retries: + + + + + + + 5 + + + 5000 + + + + + + + PointingHandCursor - Download Selected Videos + Help + + + + + + + + Videos + + + + + + + + Use Directory system? + + + + + + + PointingHandCursor + + + Yes + + + + + + + PointingHandCursor + + + No + + + + + + + PointingHandCursor + + + Help + + + + + + + + + + + Output path: + + + + + + + Enter "./" for current directory + + + + + + + PointingHandCursor + + + Open + + + + + + + + + + + + 0 + 0 + + + + Quality: + + + + + + + PointingHandCursor + + + Best + + + + + + + PointingHandCursor + + + Half + + + + + + + PointingHandCursor + + + Worst + + + + + + + + + + + Result Limit: + + + + + + + 1 + + + 5000 + + + + + + + PointingHandCursor + + + Help + + + + + + + + + + + + Graphical User Interface + + + + + + + + PointingHandCursor + + + German + + + + + + + PointingHandCursor + + + Chinese (simplified) + + + + + + + PointingHandCursor + + + English + + + + + + + PointingHandCursor + + + System default + + + + + + + + 0 + 0 + + + + Graphical User Interface Language: + + + + + + + true + + + French + + + + - - - - - - true - - - - - 0 - 0 - 721 - 720 - - - - - - - Download and Setup FFmpeg - - - - - - - - - Performance - - - - - - - - Simultaneous downloads: - - - - - - - 1 - - - 5000 - - - - - - - PointingHandCursor - - - Help - - - - - - - - - - - Maximal workers: - - - - - - - 1 - - - 5000 - - - - - - - PointingHandCursor - - - Help - - - - - - - - - - - PornHub Delay (0 = Disabled) in seconds: - - - - - - - 0 - - - 5000 - - - - - - - PointingHandCursor - - - Help - - - - - - - - - - - - 0 - 0 - - - - Threading Mode: - - - - - - - PointingHandCursor - - - High Performance - - - - - - - PointingHandCursor - - - FFMPEG - - - - - - - PointingHandCursor - - - Default - - - - - - - PointingHandCursor - - - Help - - - - - - - - - - - Maximal timeout: - - - - - - - 5 - - - 5000 - - - - - - - PointingHandCursor - - - Help - - - - - - - - - - - Maximal retries: - - - - - - - 5 - - - 5000 - - - - - - - PointingHandCursor - - - Help - - - - - - - - - - - - - - Videos - - - - - - - - Result Limit: - - - - - - - 1 - - - 5000 - - - - - - - PointingHandCursor - - - Help - - - - - - - - - - - Use Directory system? - - - - - - - PointingHandCursor - - - Yes - - - - - - - PointingHandCursor - - - No - - - - - - - PointingHandCursor - - - Help - - - - - - - - - - - - 0 - 0 - - - - Quality: - - - - - - - PointingHandCursor - - - Best - - - - - - - PointingHandCursor - - - Half - - - - - - - PointingHandCursor - - - Worst - - - - - - - - - - - Output path: - - - - - - - Enter "./" for current directory - - - - - - - PointingHandCursor - - - Open - - - - - - - - - - - PointingHandCursor - - - Chinese - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - PointingHandCursor - - - French - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - PointingHandCursor - - - English - - - - - - - Spanish - - - - - - - Portuguese - - - - - - - Japanese - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Italian - - - - - - - Czech - - - - - - - PointingHandCursor - - - German - - - - - - - Dutch - - - - - - - PointingHandCursor - - - Russian - - - - - - - - 0 - 0 - - - - PornHub Language (affects video titles) - - - - - - - - - - - - Graphical User Interface - - - - - - - - Discord Rich Presence: - - - - - - - Yes - - - - - - - No - - - - - - - Help - - - - - - - - - - - PointingHandCursor - - - German - - - - - - - PointingHandCursor - - - Chinese (simplified) - - - - - - - PointingHandCursor - - - English - - - - - - - PointingHandCursor - - - System default - - - - - - - - 0 - 0 - - - - Graphical User Interface Language: - - - - - - - true - - - French - - - - - - - - - - - - - - PointingHandCursor - - - Apply (needs restart) - - - - - - - PointingHandCursor - - - QPushButton { + + + + + + + PointingHandCursor + + + Apply (needs restart) + + + + + + + PointingHandCursor + + + QPushButton { background-color: rgb(85, 0, 0)/* Green */ font: bold 14px; min-width: 5em; @@ -2111,52 +2109,52 @@ QPushButton:pressed { background-color: rgb(108, 0, 52) /* Dark green */ } - - - Reset Porn Fetch to default settings - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - 0 - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + Reset Porn Fetch to default settings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + 0 + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> @@ -2199,359 +2197,91 @@ p, li { white-space: pre-wrap; } <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - - - - - - - - - - - - - - - - 0 - 0 - - - - true - - - - - 0 - 0 - 1588 - 87 - - - - - - - 0 - - - - - - 0 - 0 - - - - Total: - - - - - - - 0 - - - - - - - Converting: - - - - - - - - 0 - 0 - - - - Information: The total progressbar does not count for Eporner and HQPorner, because they are using different mechanisms for downloading. - - - - - - - - 0 - 0 - - - - - 300 - 0 - - - - 0 - - - - - - - - - - + + + + + + + + + + + + + + + 0 + + + + + + 0 + 0 + + + + Total: + + - - - + + + 0 - - - - - 0 - 0 - - - - - 50 - 35 - - - - - 16777215 - 35 - - - - PointingHandCursor - - - border: none; - - - - - - - 32 - 32 - - - - - - - - - 0 - 0 - - - - - 50 - 35 - - - - - 16777215 - 35 - - - - PointingHandCursor - - - border: none - - - - - - - 32 - 32 - - - - - - - - - 0 - 0 - - - - - 50 - 35 - - - - - 16777215 - 35 - - - - - 9 - - - - PointingHandCursor - - - border: none - - - - - - - 32 - 32 - - - - - - - - - 0 - 0 - - - - - 50 - 35 - - - - - 16777215 - 35 - - - - PointingHandCursor - - - border: none; - - - - - - - 32 - 32 - - - - - - - - - 0 - 0 - - - - - 50 - 35 - - - - - 16777215 - 35 - - - - PointingHandCursor - - - border: none; - - - - - - - 32 - 32 - - - - - - - - - 0 - 0 - - - - - 50 - 35 - - - - - 16777215 - 35 - - - - PointingHandCursor - - - border: none; - - - - - - - 32 - 32 - - - - - + + + + + + Converting: + + + + + + + + 0 + 0 + + + + Information: The total progressbar does not count for Eporner and HQPorner, because they are using different mechanisms for downloading. + + + + + + + + 0 + 0 + + + + + 300 + 0 + + + + 0 + + - - + + - scrollarea_status - scrollarea_stacked_top lineedit_url button_download lineedit_playlist_url @@ -2615,28 +2345,14 @@ p, li { white-space: pre-wrap; } button_directory_system_help spinbox_treewidget_limit button_result_limit_help - radio_api_language_english - radio_api_language_chinese - radio_api_language_spanish - radio_api_language_czech - radio_api_language_german - radio_api_language_russian - radio_api_language_italian - radio_api_language_japanese - radio_api_language_french - radio_api_language_dutch - radio_api_language_portuguese radio_ui_language_system_default radio_ui_language_english radio_ui_language_german radio_ui_language_chinese_simplified radio_ui_language_french - radio_discord_yes - radio_discord_no button_settings_apply button_settings_reset textBrowser - discord_rich_presence_help textbrowser_websites diff --git a/src/frontend/resources.py b/src/frontend/resources.py index 8d8432e..51a8f6e 100644 --- a/src/frontend/resources.py +++ b/src/frontend/resources.py @@ -8822,70 +8822,69 @@ .26,0,0,0,12,2.7\ 5Z\x22><\ /svg>\ -\x00\x00\x03\xde\ +\x00\x00\x03\xc6\ \x00\ -\x00\x0e\x8fx\xda\xbdWIo\xdb8\x14\xbe\xfbW\x10\ -\xe8\xa1\x0b\xa2\xda\xb1-\xdb\x92Or\x96\xcea\x06\xa8\ -\xa7\x9d\xce\x99\x96\x18\x89\x13\x85\x14H*n\x1b\xe4\xbf\ -\xcf#\xb5X\xd4f\x17\x03\x8c\x8d 0\xc5\xf7\xbd\xef\ -\xedO\xfb\xbfi\x14\x13\x85^&\x08>!O\xb9\xf0\ -\xd1\x9b\xbb\x1b\xfd\xdd\x224\xfd\x80v\x82\xc6\x89\x22\x8c\ -D\xe8\x81\x0bt J\x11\x017\x99\x12X*\xf4a\ -j$\x0f8|\x8c\x05\xcfY\xe4T \xf3\x95\xfen\ -5\xc6-\x16\x8fg\x11\xb8\x88\x08\xc81\xce\xc8\xd6\x9c\ -<\xc0\x0dG\xd2\x9f\xc4G\xd7\xf3\xec\xfbv\xf2:\x99\ -\xec\x7f\xa7\x8c\xdcE\xb4b\x5cI\xc1s$yJ#\ -\xf4\xc6u\xdd\x82y\x10\xfd\x93Kek}\xa6\x92\x1e\ -hJ\xd5\x0f[\xaf#pDs\xe9\xa3\xa5V\xd48\ -/\xad\x11\xf1\x01\xbf[-\xaf\xe6s\xf8\x9bm\xae\x90\ -7{_\xdc\xcbp\x14Q\x16\xfb\xc8\xad%\xbb\xbeX\ -,\x16\x05\xa7/\xa9\xf6f\xfa\x03\x99\xff@Hs\x8b\ -\xa8T\x94\x85\x8arV\xb1jE\xc22\xdd\x7f\xe0a\ -.\xc7\x1c\xe0y\xf7\xf7\xcd\xe8\xa1C\x9a\x13\xa48\xa2\ -,\xa2!V\x04\x15\x10\xa0L\x03\xff\x09\xb6\xf3]\xae\ -\x14\xe8\xefM\x04s&3\x1c\x9e\x0cm\xc9\xf9~\x09\ -\x0d\xe6\x14\x10G\x1a\xa9\x04\x22\xb7\xa8\xdc\x92\x10M\xa5\ -y\xd2r\xfdz\x1c\xd7\xcfY\x98\x90\xf0\x11\x02\xfa2\ -\xe4g\x1d{\xcb-\xd7'\xb7\xac\xd7\xebQ\xf8\xb3\xe0\ -\xeb`\x1d\x80_\x87\xf0\xdd\xc05\x8fGT$\xfc\x99\ -\x08+p5\xb8\x17x\xb54$\x89\x06\xf7A?\x08\ -\x80\x94\xa0?\xa1\x16p\xda\x8a\xb9\xa5|\x1el\xe6E\ -\xcc?\xe7\x22KIyk<\xf9\xab\x98l\xba\xb9[\ -f\xed`\x8d4\x89&\x98Ei\x1f\xd1&ZI\xf1\ -\x8c\x05V\xee\xd4\xb4\x9e\xb0\x88)\xf3\x91\xb3\x02\x81Y\ -/)\xafMJ\xe6\x07'\xc3\xf1\xa5\xb4\xb4\xe8WA\ -\x88\xd5\x10\x87\xdb\xda\x90\x19\x8b\xc0\xbb\x9d\x97\xc5\xfe\x09\ -\xe0X3\x0e\xe4)K\xb0\xa4r\xa0\xf7\xd4\x85\xd5\xe0\ -\xb1\xff\x8d`\xb8\xf3\x8d\x92#\x98D\x8a&\xf12\xd6\ -g\xce9\xb8RP@\x0e\x95\xad\xdb)[\xd7.[\ -\x1b\xdb\xae;+S\xd0\x80\xc2S=\xdbu1P\xd5\ -\xaf\xfd v\xd5\xd2'\x1dp\x94\x8b\xf4\xdd[\x7fj\ -~\xc9i,p\x96\xd0PN#\x18-\x1f\xe5s\xfc\ -\xf6}\xe1\x85O\xa0&\xdb\xf1\xef\xc3\xadty\x13\xdc\ -\xbb\xb3\x22\x9a\x7fpA\xa0\x84\x9e\xe1<6\x81\xbd4\ -\xa2\xa7\x04v\x14\xcf\xc0o\xb3\xea\xd4\x9e\x1dMJ\xbe\ -\xaf\xa8\x82\x22.\x98A*\x9bq\xc9S\x07r\xd9T\ -B\x01\xb8m?\xce\xb8\xa4:E|\xe8\xf6\x19\x0a\x09\ -\x83\xba\x1f\x9cJ\xa5uV\xc7\xbf7\x1f3\xb5\xef\x98\ -\xcc\x05\xb8\xf6\x98P\x98\x18\xe6\x82\xb1yhr_w\ -\xfcf{y\xff9\x97\x895f\xcep\x1a\x01\xee\xf1\ -\xf5\xa2\xcf\xab\xa5\xb3\x87x\x9c\xcb\xbc\xd5j\xb7[\x05\ -#\xf2\x99 R\x8e\x0d\x8d\xc5fs\xb7\xa8\x068>\ -\x90td\xc2\xd6\xc4\xe7\x95)\x9d\x15\xa8\xbb)i\xe0\ -\x13\xa1+\xb4\xbf\xd1\x15q\xca\xeaQE\xee\xc0(^\ -^T\xeb\x03\xfd\xc7ft\xe9\xd0k\xd1\xeen\x1b\xd5\ -\x85\xff\xa3gi\x85\xbd\x1a\xffK\xbf\xe9\x07\xfc\xd5.\ -\x08\x03.\xa3\xac\xd1\xb5~q\x0aTVw{O\x89\ -\xeb\xfby\xe6\x1c\xaal\xaa\x0f#~d\xe5\xf1\x05\xfb\ -\xd7\xb8c\xb0\x10\xfc\xf8\x91\x86\x1c<\xa3;\xcd_\x8c\ ->Pp\xaaJ\x08\x82SVo\xa6]J\x85\x97\x06\ -\x88\x9d/\xe7\x95m\xeae\x9bt!\x12B\x7fM\x03\ -A\xb0Vn~\xec\xb0\x18\xd9\xc8n\xafgK\xaf~\ -\xfdAY\xb1\x95\xe9\x06\xda\xf3\x122RJ\xb5\xaej\ -\xcf\xea\xdbb\xbc\xc0uo\x17F\xdb73\xa2\x1a\xea\ -\xca\xed\xaf\xf5\x96\xd1\x82\x86lpRx\xc1h\x1aW\ -\xecP\xfatDe\x1b\x08\x22e\xc2k\x03\x99 \x99\ -\xf3\xde\x1d\xac\xf0\xd5\xe4\xf5_\xff\xe0\x81\x89\ +\x00\x0e\x14x\xda\xa5VIo\xdb:\x10\xbe\xe7W\x10\ +\xe8\xa1\x0b\xa2\xda\xb1\x22\xdb\x92Or\x96\xbeC\x0b\xd4\ +oi\xcf\xb4\xc4H|QH\x81\xa4\xe2\xb6A\xff{\ +\x87\xd4bm\x94]\xd4\x82a\x98\xe2|\xf3\xcd>\xbb\ +\xaf4N\x88B/\x17\x08>\x11\xcf\xb8\x08\xd0\xab\xbb\ +\x1b\xfdl\x10\x9a\xbdC[A\x93T\x11Fb\xf4\xc0\ +\x05\xda\x13\xa5\x88\x80\x9bL\x09,\x15z73\x92{\ +\x1c=&\x82\x17,vj\x90\xc5R?\x1b\x8dq\x8b\ +\xc5\xe3I\x04.b\x02r\x8c3\xb21'\x0fp\xc3\ +\x91\xf4\x07\x09\xd0\xd5\x22\xff\xb6\xb9\xf8yq\xb1\xfbH\ +\x19\xb9\x8bi\xcd\xb8\x96\x82\xf7H\xf2\x8c\xc6\xe8\x95\xe7\ +y%\xf30\xfe\xbf\x90\xaa\xab\xf5\x99J\xba\xa7\x19U\ +\xdf\xbbz\x1d\x81cZ\xc8\x00]kE\xad\xf3\xca\x1a\ +\x91\xec\xf1\x9b\xe5\xf5\xe5b\x01\xdf\xf9\xfa\x12\xf9\xf3\xb7\ +\xe5\xbd\x1c\xc71eI\x80\xbcFr\xe8\x0b\xd7uK\ +N\xffd\xda\x9b\xd9wd~\x81\x90\xe6\x16S\xa9(\ +\x8b\x14\xe5\xacf\xd5\x8bD\xc7\xf4\xe0\x81G\x85\x9cr\ +\x80\xef\xdf\xdf\xb7\xa3\x87\xf6YA\x90\xe2\x88\xb2\x98F\ +X\x11TB\x802\x0d\xfc7\xd8\xce\xb7\x85R\xa0\x7f\ +4\x11\xcc\x99\xccqt4\xb4'\x17\x04\x154\x98S\ +B\x1ch\xacR\x88\x9c[\xbb%%\x9aJ\xfb\xa4\xe7\ +\xfa\xd54nP\xb0(%\xd1#\x04\xf4\xc5\xe6g\x1d\ +\xfb\x8e[\xae\x8enY\xadV\x93\xf0'\xc1W\xe1*\ +\x04\xbf\xda\xf0\xbd\xd03\xaf'T\xa4\xfc\x99\x88N\xe0\ +\x1ap?\xf4\x1biH\x12\x0d\x1e\x80~\x10\x00)A\ +\x7f@-\xe0\xac\x17\xf3\x8e\xf2E\xb8^\x941\xff\x5c\ +\x88<#\xd5\xad\xe9\xe4\xafc\xb2\x1e\xe6n\x95\xb5\xd6\ +\x1ai\x13M1\x8b\xb31\xa2m\xb4\x8a\xe2\x09\x0b:\ +\xb9\xd3\xd0z\xc2\x22\xa1,@\xce\x12\x04\xe6\xa3\xa4\xfc\ +>)Y\xec\x9d\x1c'\xe7\xd2\xd2\xa2\xff\x0aB:\x0d\ +\xd1\xde\xd6lf\xb8\xa1\x7f\xbb\xa8\x8a\xfd\x03\xc0\xb1v\ +\x1c\xc8S\x9ebI\xa5\xa5\xf74\x85\xd5\xe2\xb1\xfb\x8b\ +`\xb8\xf3\x85\x92\x03\x98D\xca&\xf12\xd5g\x1a\x84\ +R\xc6V\x97\xde\xa0.=K]\xeap#\x0b\xe8\xb1\ +(\xbb\xc9m)\xcd\x9f\xe3 \xdd\xd2\xa3O:j\xa8\ +\x10\xd9\x9b\xd7\xc1\xcc\xfc\x93\xb3D\xe0<\xa5\x91\x9c\xc5\ +0\x1f\xde\xcb\xe7\xe4\xf5\xdb\xd2\xd2\x0f\xa0&\xdf\xf2o\ +\xf6~x}\x13\xde{\xf32$\x9f\xb8 P\x07\xcf\ +p\x9e\x98\xe8\x9c\x1b\x96c\x16:\x8a\xe7\xe0\xady}\ +\xda\x1d\x00mJA\xa0\xa8\x82J,\x99A>\x9a\x99\ +\xc73\x07\x12\xd2\xa4s\x09\xb8\xe9\xbf\xce\xb9\xa4:\xce\ +\x01\xb4\xec\x1cE\x84A\xf1ZGKe]\xa7m\xdf\ +\x9b\x8f\x19\xbdwL\x16\x02\x5c{H)\xb4}s\xc1\ +\xd8l\x1b\xbfW\x03\xbfu\xbd\xbc\xfb\x5c\xc8\xb43+\ +Np\x9a\x00\x1e\xf1\xb5;\xe6\xd5\xca\xd96\x1e\xa72\ +o\xb9\xdcn\x97\xe1\x84|.\x88\x94S\x9d\xdf]\xaf\ +\xef\xdcz\x0a\xe3=\xc9&\xc6dC|Q\x9b2\xd8\ +c\x86\xeb\x8e\x06>\x12\xbaD\xbb\x1b]\x11\xc7\xac\x9e\ +T4U\xb7\xd6n\xdb\x0c\xca\x89&bs\xb1}r\ +\xf5h\x0fW\x86\xfa\xc2\x1f\xf4%\x8b\x1d\xe3#jT\ +\xe3\x9f\xf4\x9bq\xc0\xdf\xed\x820\xa5r\xcaZ]\xcb\ +\x12\x85SV\x0f{O\x85\x1b\x04E\xee\xec\xeblj\ +\x0ec~`\xd5\xf1\x19K\xd4\xb4c\xb0\x10\xfc\xf0\x9e\ +F\x1c<\xa3;\xcd\x7f\x8c>Pp\xaaJ\x09\x82S\ +\xd6\xac\x97CJ\xa5\x97,\xc4N\x97\xf3\xb2k\xeay\ +\xebp)\x12A\x7f\xcdBA\xb0Vn\xfel\xb18\ +c\x9e6w\xebegl\x95\xf0C\xcf\xbbu\x8d3\ +\xbe\x98\x11\x93\x97\x9bXk\x05\xeb\xad\xfa=h\x88\xa6\ +\x93\xc1\x96\xdf&W.2\xfatBe\x1f\x08 Date: Wed, 26 Jun 2024 22:52:00 +0200 Subject: [PATCH 07/39] - implemented thumbnail writing into the metadata of the mp4 header --- README/STATUS.md | 2 +- src/backend/shared_functions.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README/STATUS.md b/README/STATUS.md index 9df7107..308f83b 100644 --- a/README/STATUS.md +++ b/README/STATUS.md @@ -7,7 +7,7 @@ - [] Splitting functions into other .py files - [] Trying to optimize the UI performance with more threading and slower UI repainting - [] Supporting more websites -- [] Writing the thumbnail into the video metadata +- [x] Writing the thumbnail into the video metadata - [] Improving the sorting mechanism, to be less confusing - [] Entirely reworking the progressbars and progress reporting in general - [] Fixing the errors with the playlist diff --git a/src/backend/shared_functions.py b/src/backend/shared_functions.py index 9ed60ff..d213027 100644 --- a/src/backend/shared_functions.py +++ b/src/backend/shared_functions.py @@ -297,7 +297,8 @@ def write_tags(path, video): logger_debug("Tags: [2/3] - Writing Thumbnail") content = requests.get(thumbnail).content - audio.tags["covr"] = MP4Cover(content, imageformat=MP4Cover.FORMAT_PNG) + cover = MP4Cover(content, imageformat=MP4Cover.FORMAT_JPEG) + audio.tags["covr"] = [cover] audio.save() logger_debug("Tags: [3/3] ✔") From e7210dd2a69da7cd08a5b73e2cbbeb53a0dccfc5 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Wed, 26 Jun 2024 23:42:42 +0200 Subject: [PATCH 08/39] - fixed something in the layout which pissed me off for months. Damn it was soo simple xD --- main.py | 2 +- src/frontend/form_desktop.ui | 112 +++++++++++++++++++++++++++++--- src/frontend/ui_form_desktop.py | 24 +++++-- 3 files changed, 124 insertions(+), 14 deletions(-) diff --git a/main.py b/main.py index c6bec25..af5d806 100644 --- a/main.py +++ b/main.py @@ -1086,7 +1086,7 @@ def toggle_sorting(self): def switch_to_home(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(0) - self.ui.stacked_widget_top.setMinimumHeight(220) + self.ui.stacked_widget_top.setMinimumHeight(240) def switch_to_account(self): self.ui.stacked_widget_top.setCurrentIndex(1) diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 7bbdd85..92a5631 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -269,11 +269,29 @@ + + 1 + - 0 + 2 + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + @@ -286,8 +304,8 @@ 0 0 - 1588 - 415 + 1606 + 446 @@ -564,11 +582,29 @@ b + + 1 + - 0 + 2 + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + @@ -959,6 +995,21 @@ + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + @@ -1108,6 +1159,21 @@ + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + @@ -1118,8 +1184,8 @@ 0 0 - 387 - 206 + 1608 + 257 @@ -1595,6 +1661,21 @@ + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + @@ -1605,8 +1686,8 @@ 0 0 - 1570 - 771 + 1608 + 781 @@ -2125,6 +2206,21 @@ QPushButton:pressed { + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index 1d7cf2c..3a580b6 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -124,10 +124,13 @@ def setupUi(self, Porn_Fetch_Widget): self.stacked_widget_main = QStackedWidget(Porn_Fetch_Widget) self.stacked_widget_main.setObjectName(u"stacked_widget_main") + self.stacked_widget_main.setLineWidth(1) self.widget = QWidget() self.widget.setObjectName(u"widget") self.gridLayout_8 = QGridLayout(self.widget) + self.gridLayout_8.setSpacing(0) self.gridLayout_8.setObjectName(u"gridLayout_8") + self.gridLayout_8.setContentsMargins(0, 0, 0, 0) self.verticallayout_treewidget = QVBoxLayout() self.verticallayout_treewidget.setObjectName(u"verticallayout_treewidget") self.scrollarea_treewidget = QScrollArea(self.widget) @@ -135,7 +138,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_treewidget.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") - self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1588, 415)) + self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1606, 446)) self.gridLayout_4 = QGridLayout(self.scrollAreaWidgetContents_3) self.gridLayout_4.setObjectName(u"gridLayout_4") self.verticallayout_treewidget_settings = QVBoxLayout() @@ -273,10 +276,13 @@ def setupUi(self, Porn_Fetch_Widget): self.stacked_widget_top.setSizePolicy(sizePolicy4) self.stacked_widget_top.setMinimumSize(QSize(650, 100)) self.stacked_widget_top.setStyleSheet(u"b") + self.stacked_widget_top.setLineWidth(1) self.page_download = QWidget() self.page_download.setObjectName(u"page_download") self.gridLayout_5 = QGridLayout(self.page_download) + self.gridLayout_5.setSpacing(0) self.gridLayout_5.setObjectName(u"gridLayout_5") + self.gridLayout_5.setContentsMargins(0, 0, 0, 0) self.gridlayout_downloading = QGridLayout() self.gridlayout_downloading.setObjectName(u"gridlayout_downloading") self.gridlayout_downloading.setSizeConstraint(QLayout.SetMaximumSize) @@ -472,7 +478,9 @@ def setupUi(self, Porn_Fetch_Widget): self.page_login = QWidget() self.page_login.setObjectName(u"page_login") self.gridLayout_2 = QGridLayout(self.page_login) + self.gridLayout_2.setSpacing(0) self.gridLayout_2.setObjectName(u"gridLayout_2") + self.gridLayout_2.setContentsMargins(0, 0, 0, 0) self.gridlayout_login_box = QGridLayout() self.gridlayout_login_box.setSpacing(0) self.gridlayout_login_box.setObjectName(u"gridlayout_login_box") @@ -547,13 +555,15 @@ def setupUi(self, Porn_Fetch_Widget): self.page_nothing_2 = QWidget() self.page_nothing_2.setObjectName(u"page_nothing_2") self.gridLayout_6 = QGridLayout(self.page_nothing_2) + self.gridLayout_6.setSpacing(0) self.gridLayout_6.setObjectName(u"gridLayout_6") + self.gridLayout_6.setContentsMargins(0, 0, 0, 0) self.scrollArea = QScrollArea(self.page_nothing_2) self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 387, 206)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1608, 257)) self.gridLayout_18 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_18.setObjectName(u"gridLayout_18") self.gridlayout_progressbar = QGridLayout() @@ -819,13 +829,15 @@ def setupUi(self, Porn_Fetch_Widget): self.page_settings = QWidget() self.page_settings.setObjectName(u"page_settings") self.gridLayout_25 = QGridLayout(self.page_settings) + self.gridLayout_25.setSpacing(0) self.gridLayout_25.setObjectName(u"gridLayout_25") + self.gridLayout_25.setContentsMargins(0, 0, 0, 0) self.scrollarea_settings = QScrollArea(self.page_settings) self.scrollarea_settings.setObjectName(u"scrollarea_settings") self.scrollarea_settings.setWidgetResizable(True) self.scrollAreaWidgetContents_6 = QWidget() self.scrollAreaWidgetContents_6.setObjectName(u"scrollAreaWidgetContents_6") - self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 1570, 771)) + self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 1608, 781)) self.gridLayout_19 = QGridLayout(self.scrollAreaWidgetContents_6) self.gridLayout_19.setObjectName(u"gridLayout_19") self.button_download_ffmpeg = QPushButton(self.scrollAreaWidgetContents_6) @@ -1196,7 +1208,9 @@ def setupUi(self, Porn_Fetch_Widget): self.page_credits = QWidget() self.page_credits.setObjectName(u"page_credits") self.gridLayout_26 = QGridLayout(self.page_credits) + self.gridLayout_26.setSpacing(0) self.gridLayout_26.setObjectName(u"gridLayout_26") + self.gridLayout_26.setContentsMargins(0, 0, 0, 0) self.gridlayout_textbrowser = QGridLayout() self.gridlayout_textbrowser.setObjectName(u"gridlayout_textbrowser") self.textBrowser = QTextBrowser(self.page_credits) @@ -1362,8 +1376,8 @@ def setupUi(self, Porn_Fetch_Widget): self.retranslateUi(Porn_Fetch_Widget) - self.stacked_widget_main.setCurrentIndex(0) - self.stacked_widget_top.setCurrentIndex(0) + self.stacked_widget_main.setCurrentIndex(2) + self.stacked_widget_top.setCurrentIndex(2) self.stackedWidget.setCurrentIndex(1) From cf11c77e3914e5085a9c5966a8f2af090418ca9c Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Thu, 27 Jun 2024 00:01:56 +0200 Subject: [PATCH 09/39] - some more (unstable) layout fixes --- main.py | 6 +- src/frontend/form_desktop.ui | 2541 +++++++++++++++---------------- src/frontend/ui_form_desktop.py | 661 ++++---- 3 files changed, 1591 insertions(+), 1617 deletions(-) diff --git a/main.py b/main.py index af5d806..0d5c404 100644 --- a/main.py +++ b/main.py @@ -1086,17 +1086,14 @@ def toggle_sorting(self): def switch_to_home(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(0) - self.ui.stacked_widget_top.setMinimumHeight(240) def switch_to_account(self): self.ui.stacked_widget_top.setCurrentIndex(1) self.ui.stacked_widget_main.setCurrentIndex(0) - self.ui.stacked_widget_top.setMinimumHeight(150) def switch_to_tools(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(3) - self.ui.stacked_widget_top.setMinimumHeight(300) def switch_to_settings(self): self.ui.stacked_widget_main.setCurrentIndex(1) @@ -1106,8 +1103,7 @@ def switch_to_credits(self): self.show_credits() def switch_to_supported_websites(self): - self.ui.stacked_widget_main.setCurrentIndex(4) - self.ui.stackedWidget.setCurrentIndex(0) + self.ui.stacked_widget_main.setCurrentIndex(3) def switch_to_all_progress_bars(self): self.ui.stacked_widget_top.setCurrentIndex(2) diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 92a5631..20d0f56 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -25,15 +25,21 @@ Porn Fetch V3.4 (C) Johannes Habel GPL 3 - + + + 0 + Porn Fetch Menu + + 0 + @@ -264,7 +270,7 @@ - + @@ -273,7 +279,7 @@ 1 - 2 + 0 @@ -292,1370 +298,1370 @@ 0 - + - - - true + + + + 0 + 0 + - - - - 0 - 0 - 1606 - 446 - - - - - - - + + + 650 + 20 + + + + b + + + 1 + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QLayout::SetMaximumSize + + + 0 + + + 6 + + + - + + 0 + 0 + + + + PointingHandCursor + + + Start + + + + + + + 0 0 - 100 - 200 + 300 + 4 - - - Title - - - - - Author - - - - - Duration - - + + Enter video URL + - - - - - - + + - + 0 0 + + + 60 + 2 + + PointingHandCursor - - - - Get Title, Author, Duration - - - true - - - false + Open File - - - - Export video URLs + + + + + 0 + 0 + - - - - - Do not clear videos + Search Website - - + + - + 0 0 + + + 60 + 2 + + PointingHandCursor - - Only Title (a lot faster) + + - - true + + Get Videos - - + + + + + 0 + 0 + + + + + 60 + 2 + + PointingHandCursor + + + - Show videos in reverse + Download - - - - Allow Sorting + + + + + 0 + 0 + + + + + 300 + 2 + + + + Enter Model / Channel / Actress URL - - - - Qt::Horizontal + + + + 4 - + + 5 + + + 5 + + + + + PornHub + + + true + + + + + + + HQPorner + + + + + + + XVideos + + + + + + + EPorner + + + + + + + XNXX + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + + 16777215 + 20 + + + + PointingHandCursor + + + See Supported Websites + + + + + + + + + + 0 + 0 + + + - 40 - 20 + 300 + 2 - + + + + + true + + + URLs in the file must be separated with new lines! + + - - - - Qt::Horizontal + + + + + 0 + 0 + - + - 40 - 20 + 100 + 1 - + + URL: + + - - - - - - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - Does not stop downloading videos - - - Stop loading videos - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - PointingHandCursor - - - Automatically checks a range of videos - - - - - - Select a range of videos - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - PointingHandCursor - - - Unselects all videos in the tree widget - - - - - - Unselect all - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - PointingHandCursor - - - - - - Download Selected Videos - - - - - - - - - - - - 0 - 0 - - - - - 650 - 100 - - - - b - - - 1 - - - 2 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QLayout::SetMaximumSize - - - 0 - - - 6 - - - - - - 0 - 0 - - - - PointingHandCursor - - - Start - - - - - - - - 0 - 0 - - - - - 300 - 4 - - - - Enter video URL - - - - - - - - 0 - 0 - - - - - 60 - 2 - - - - PointingHandCursor - - - - - - Open File - - - - - - - - 0 - 0 - - - - Search Website - - - - - - - - 0 - 0 - - - - - 60 - 2 - - - - PointingHandCursor - - - - - - Get Videos - - - - - - - - 0 - 0 - - - - - 60 - 2 - - - - PointingHandCursor - - - - - - Download - - - - - - - - 0 - 0 - - - - - 300 - 2 - - - - Enter Model / Channel / Actress URL - - - - - - - 4 - - - 5 - - - 5 - - - - - PornHub + + + + Enter a PornHub Playlist URL - - true + + + + + + Search Query: - - + + - HQPorner + Playlist URL: - - + + + + + 0 + 0 + + + + + 100 + 2 + + - XVideos + Model URL: - - + + - EPorner + Get Videos - - + + + + + 0 + 0 + + + + + 300 + 0 + + - XNXX + + + + Search for Videos. Select Website below - - - - Qt::Horizontal + + + + + 0 + 0 + - + - 40 - 20 + 100 + 2 - + + File: + + + + + + + Help + + - - - - - 0 - 0 - - - - - 300 - 2 - - - - - - - true - - - URLs in the file must be separated with new lines! - - - - - - - - 0 - 0 - - - - - 100 - 2 - + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 - - URL: - - - - - - - Enter a PornHub Playlist URL - - - - - - - Search Query: - - - - - - - Playlist URL: - - - - - - - - 0 - 0 - - - - - 100 - 2 - - - - Model URL: - - - - - - - Get Videos - - - - - - - - 0 - 0 - - - - - 300 - 0 - - - - - - - Search for Videos. Select Website below - - - - - - - - 0 - 0 - - - - - 100 - 2 - - - - File: - - - - - - - Help - - - - - - - - 0 - 0 - - - - - 0 - 25 - - - - - 16777215 - 20 - - - - PointingHandCursor - - - See Supported Websites - - + + + + PointingHandCursor + + + + + + Get Liked videos + + + + + + + PointingHandCursor + + + + + + Get watched videos + + + + + + + + 0 + 0 + + + + Username: + + + + + + + + 0 + 0 + + + + PointingHandCursor + + + + + + Login + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + Enter your PornHub Username + + + + + + + PointingHandCursor + + + + + + Get recommended videos + + + + + + + + 0 + 0 + + + + Password: + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + QLineEdit::Password + + + Enter your PornHub Password + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - + + + + + 0 + + + 0 + + + 0 + + + 0 + 0 - - - - PointingHandCursor - - - - - - Get Liked videos - - - - - - - PointingHandCursor - - - - - - Get watched videos - - - - - - - 0 - 0 - - - - Username: + + + true + + + + 0 + 0 + 1588 + 257 + + + + + + + + + 0 + + + + + + + + 0 + 0 + + + + PornHub: + + + + + + + XVideos + + + + + + + XNXX + + + + + + + 0 + + + + + + + + 0 + 0 + + + + HQPorner: + + + + + + + + 0 + 0 + + + + + 300 + 0 + + + + 0 + + + + + + + + 0 + 0 + + + + + 300 + 0 + + + + 0 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0 + + + + + + + Eporner + + + + + + + Info: + + + + + + + + + + true + + + + + + + - - - - - 0 - 0 - - - - PointingHandCursor - - - - - - Login + + + + + + + + EPorner + + + + + + + + 0 + 4 + + + + Get videos by category + + + + + + + + 0 + 4 + + + + + 100 + 4 + + + + + + + + + 0 + 2 + + + + + 0 + 2 + + + + PointingHandCursor + + + Get Videos + + + + + + + + 0 + 0 + + + + + 0 + 2 + + + + PointingHandCursor + + + List of all categories + + + + + + - - - - - 0 - 0 - - - - - 150 - 0 - - - - Enter your PornHub Username - - - - - - - PointingHandCursor - - - - - - Get recommended videos - - - - - - - - 0 - 0 - - - - Password: - - - - - - - - 0 - 0 - - - - - 150 - 0 - - - - QLineEdit::Password - - - Enter your PornHub Password + + + + HQPorner + + + + + + + + 0 + 10 + + + + PointingHandCursor + + + Month + + + + + + + + 0 + 10 + + + + PointingHandCursor + + + Get Videos + + + + + + + + 0 + 4 + + + + Get Brazzers videos + + + + + + + + 0 + 10 + + + + PointingHandCursor + + + Week + + + true + + + + + + + + 0 + 0 + + + + + 0 + 2 + + + + PointingHandCursor + + + List of all categories + + + + + + + + 0 + 4 + + + + + 100 + 4 + + + + + + + + Get Top Porn: + + + + + + + + 0 + 10 + + + + PointingHandCursor + + + All Time + + + + + + + + 0 + 2 + + + + + 0 + 2 + + + + PointingHandCursor + + + Get Videos + + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + PointingHandCursor + + + Get Video + + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + PointingHandCursor + + + Get Videos + + + + + + + + 0 + 4 + + + + Get random video + + + + + + + + 0 + 4 + + + + Get videos by category + + + + + + - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 + + + + + + + true - - - - true - - - - - 0 - 0 - 1608 - 257 - - - + + + + 0 + 0 + 1606 + 449 + + + + + + + + + + 0 + 0 + + + + + 100 + 200 + + + + + Title + + + + + Author + + + + + Duration + + + + + + + + + + + + + 0 + 0 + + + + PointingHandCursor + + + + + + + + + Get Title, Author, Duration + + + true + + + false + + + + + + + Do not clear videos + + + + + + + PointingHandCursor + + + Show videos in reverse + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + - - - - - 0 - - - - - - - - 0 - 0 - - - - PornHub: - - - - - - - XVideos - - - - - - - XNXX - - - - - - - 0 - - - - - - - - 0 - 0 - - - - HQPorner: - - - - - - - - 0 - 0 - - - - - 300 - 0 - - - - 0 - - - - - - - - 0 - 0 - - - - - 300 - 0 - - - - 0 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - 0 - - - - - - - Eporner - - - - - - - Info: - - - - - - - - - - true - - - - + + + Allow Sorting + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Export video URLs + + + + + + + + 0 + 0 + + + + PointingHandCursor + + + Only Title (a lot faster) + + + true + + - + + + + + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + Does not stop downloading videos + + + Stop loading videos + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + PointingHandCursor + + + Automatically checks a range of videos + + + + + + Select a range of videos + - - - - - - - - HQPorner + + + + + 0 + 0 + + + + + 0 + 30 + + + + PointingHandCursor + + + Unselects all videos in the tree widget + + + + + + Unselect all - - - - - - - - 0 - 10 - - - - PointingHandCursor - - - Month - - - - - - - - 0 - 10 - - - - PointingHandCursor - - - Get Videos - - - - - - - - 0 - 4 - - - - Get Brazzers videos - - - - - - - - 0 - 10 - - - - PointingHandCursor - - - Week - - - true - - - - - - - - 0 - 0 - - - - - 0 - 2 - - - - PointingHandCursor - - - List of all categories - - - - - - - - 0 - 4 - - - - - 100 - 4 - - - - - - - - Get Top Porn: - - - - - - - - 0 - 10 - - - - PointingHandCursor - - - All Time - - - - - - - - 0 - 2 - - - - - 0 - 2 - - - - PointingHandCursor - - - Get Videos - - - - - - - - 0 - 0 - - - - - 0 - 10 - - - - PointingHandCursor - - - Get Video - - - - - - - - 0 - 0 - - - - - 0 - 10 - - - - PointingHandCursor - - - Get Videos - - - - - - - - 0 - 4 - - - - Get random video - - - - - - - - 0 - 4 - - - - Get videos by category - - - - - - - - - - EPorner + + + + + 0 + 0 + + + + + 0 + 30 + + + + PointingHandCursor + + + + + + Download Selected Videos - - - - - - - - 0 - 4 - - - - Get videos by category - - - - - - - - 0 - 4 - - - - - 100 - 4 - - - - - - - - - 0 - 2 - - - - - 0 - 2 - - - - PointingHandCursor - - - Get Videos - - - - - - - - 0 - 0 - - - - - 0 - 2 - - - - PointingHandCursor - - - List of all categories - - - - - - - - + + @@ -2230,27 +2236,27 @@ QPushButton:pressed { - - - + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - - - 1 - - - - - - - 0 - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> @@ -2293,21 +2299,14 @@ p, li { white-space: pre-wrap; } <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - - - - - + - + 0 diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index 3a580b6..fcd094f 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -33,14 +33,16 @@ def setupUi(self, Porn_Fetch_Widget): sizePolicy.setHeightForWidth(Porn_Fetch_Widget.sizePolicy().hasHeightForWidth()) Porn_Fetch_Widget.setSizePolicy(sizePolicy) Porn_Fetch_Widget.setMinimumSize(QSize(100, 50)) - self.gridLayout_20 = QGridLayout(Porn_Fetch_Widget) - self.gridLayout_20.setObjectName(u"gridLayout_20") + self.gridLayout_3 = QGridLayout(Porn_Fetch_Widget) + self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_13 = QGridLayout() self.gridLayout_13.setObjectName(u"gridLayout_13") + self.gridLayout_13.setContentsMargins(-1, -1, -1, 0) self.groupBox_3 = QGroupBox(Porn_Fetch_Widget) self.groupBox_3.setObjectName(u"groupBox_3") self.gridLayout_14 = QGridLayout(self.groupBox_3) self.gridLayout_14.setObjectName(u"gridLayout_14") + self.gridLayout_14.setContentsMargins(-1, -1, -1, 0) self.button_switch_settings = QPushButton(self.groupBox_3) self.button_switch_settings.setObjectName(u"button_switch_settings") sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Maximum) @@ -133,148 +135,14 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_8.setContentsMargins(0, 0, 0, 0) self.verticallayout_treewidget = QVBoxLayout() self.verticallayout_treewidget.setObjectName(u"verticallayout_treewidget") - self.scrollarea_treewidget = QScrollArea(self.widget) - self.scrollarea_treewidget.setObjectName(u"scrollarea_treewidget") - self.scrollarea_treewidget.setWidgetResizable(True) - self.scrollAreaWidgetContents_3 = QWidget() - self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") - self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1606, 446)) - self.gridLayout_4 = QGridLayout(self.scrollAreaWidgetContents_3) - self.gridLayout_4.setObjectName(u"gridLayout_4") - self.verticallayout_treewidget_settings = QVBoxLayout() - self.verticallayout_treewidget_settings.setObjectName(u"verticallayout_treewidget_settings") - self.treeWidget = QTreeWidget(self.scrollAreaWidgetContents_3) - __qtreewidgetitem = QTreeWidgetItem() - __qtreewidgetitem.setText(0, u"Title"); - self.treeWidget.setHeaderItem(__qtreewidgetitem) - self.treeWidget.setObjectName(u"treeWidget") - sizePolicy2 = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.MinimumExpanding) - sizePolicy2.setHorizontalStretch(0) - sizePolicy2.setVerticalStretch(0) - sizePolicy2.setHeightForWidth(self.treeWidget.sizePolicy().hasHeightForWidth()) - self.treeWidget.setSizePolicy(sizePolicy2) - self.treeWidget.setMinimumSize(QSize(100, 200)) - - self.verticallayout_treewidget_settings.addWidget(self.treeWidget) - - - self.gridLayout_4.addLayout(self.verticallayout_treewidget_settings, 1, 0, 1, 1) - - self.gridLayout_16 = QGridLayout() - self.gridLayout_16.setObjectName(u"gridLayout_16") - self.radio_tree_show_all = QRadioButton(self.scrollAreaWidgetContents_3) - self.radio_tree_show_all.setObjectName(u"radio_tree_show_all") - sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) - sizePolicy3.setHorizontalStretch(0) - sizePolicy3.setVerticalStretch(0) - sizePolicy3.setHeightForWidth(self.radio_tree_show_all.sizePolicy().hasHeightForWidth()) - self.radio_tree_show_all.setSizePolicy(sizePolicy3) - self.radio_tree_show_all.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.radio_tree_show_all.setStyleSheet(u"") - self.radio_tree_show_all.setCheckable(True) - self.radio_tree_show_all.setChecked(False) - - self.gridLayout_16.addWidget(self.radio_tree_show_all, 0, 1, 1, 1) - - self.button_tree_export_video_urls = QPushButton(self.scrollAreaWidgetContents_3) - self.button_tree_export_video_urls.setObjectName(u"button_tree_export_video_urls") - - self.gridLayout_16.addWidget(self.button_tree_export_video_urls, 0, 2, 1, 1) - - self.checkbox_tree_do_not_clear_videos = QCheckBox(self.scrollAreaWidgetContents_3) - self.checkbox_tree_do_not_clear_videos.setObjectName(u"checkbox_tree_do_not_clear_videos") - - self.gridLayout_16.addWidget(self.checkbox_tree_do_not_clear_videos, 1, 1, 1, 1) - - self.radio_tree_show_title = QRadioButton(self.scrollAreaWidgetContents_3) - self.radio_tree_show_title.setObjectName(u"radio_tree_show_title") - sizePolicy3.setHeightForWidth(self.radio_tree_show_title.sizePolicy().hasHeightForWidth()) - self.radio_tree_show_title.setSizePolicy(sizePolicy3) - self.radio_tree_show_title.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.radio_tree_show_title.setChecked(True) - - self.gridLayout_16.addWidget(self.radio_tree_show_title, 0, 0, 1, 1) - - self.checkbox_tree_show_videos_reversed = QCheckBox(self.scrollAreaWidgetContents_3) - self.checkbox_tree_show_videos_reversed.setObjectName(u"checkbox_tree_show_videos_reversed") - self.checkbox_tree_show_videos_reversed.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - - self.gridLayout_16.addWidget(self.checkbox_tree_show_videos_reversed, 1, 2, 1, 1) - - self.checkbox_tree_allow_sorting = QCheckBox(self.scrollAreaWidgetContents_3) - self.checkbox_tree_allow_sorting.setObjectName(u"checkbox_tree_allow_sorting") - - self.gridLayout_16.addWidget(self.checkbox_tree_allow_sorting, 1, 0, 1, 1) - - self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) - - self.gridLayout_16.addItem(self.horizontalSpacer, 0, 3, 1, 1) - - self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) - - self.gridLayout_16.addItem(self.horizontalSpacer_2, 1, 3, 1, 1) - - - self.gridLayout_4.addLayout(self.gridLayout_16, 0, 0, 1, 1) - - self.scrollarea_treewidget.setWidget(self.scrollAreaWidgetContents_3) - - self.verticallayout_treewidget.addWidget(self.scrollarea_treewidget) - - self.gridLayout_17 = QGridLayout() - self.gridLayout_17.setObjectName(u"gridLayout_17") - self.button_tree_stop = QPushButton(self.widget) - self.button_tree_stop.setObjectName(u"button_tree_stop") - sizePolicy1.setHeightForWidth(self.button_tree_stop.sizePolicy().hasHeightForWidth()) - self.button_tree_stop.setSizePolicy(sizePolicy1) - self.button_tree_stop.setMinimumSize(QSize(0, 30)) - - self.gridLayout_17.addWidget(self.button_tree_stop, 1, 2, 1, 1) - - self.button_tree_select_range = QPushButton(self.widget) - self.button_tree_select_range.setObjectName(u"button_tree_select_range") - sizePolicy1.setHeightForWidth(self.button_tree_select_range.sizePolicy().hasHeightForWidth()) - self.button_tree_select_range.setSizePolicy(sizePolicy1) - self.button_tree_select_range.setMinimumSize(QSize(0, 30)) - self.button_tree_select_range.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.button_tree_select_range.setStyleSheet(u"") - - self.gridLayout_17.addWidget(self.button_tree_select_range, 1, 0, 1, 1) - - self.button_tree_unselect_all = QPushButton(self.widget) - self.button_tree_unselect_all.setObjectName(u"button_tree_unselect_all") - sizePolicy1.setHeightForWidth(self.button_tree_unselect_all.sizePolicy().hasHeightForWidth()) - self.button_tree_unselect_all.setSizePolicy(sizePolicy1) - self.button_tree_unselect_all.setMinimumSize(QSize(0, 30)) - self.button_tree_unselect_all.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.button_tree_unselect_all.setStyleSheet(u"") - - self.gridLayout_17.addWidget(self.button_tree_unselect_all, 1, 1, 1, 1) - - self.button_tree_download = QPushButton(self.widget) - self.button_tree_download.setObjectName(u"button_tree_download") - sizePolicy1.setHeightForWidth(self.button_tree_download.sizePolicy().hasHeightForWidth()) - self.button_tree_download.setSizePolicy(sizePolicy1) - self.button_tree_download.setMinimumSize(QSize(0, 30)) - self.button_tree_download.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.button_tree_download.setStyleSheet(u"") - - self.gridLayout_17.addWidget(self.button_tree_download, 0, 0, 1, 3) - - - self.verticallayout_treewidget.addLayout(self.gridLayout_17) - - - self.gridLayout_8.addLayout(self.verticallayout_treewidget, 1, 1, 1, 1) - self.stacked_widget_top = QStackedWidget(self.widget) self.stacked_widget_top.setObjectName(u"stacked_widget_top") - sizePolicy4 = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Maximum) - sizePolicy4.setHorizontalStretch(0) - sizePolicy4.setVerticalStretch(0) - sizePolicy4.setHeightForWidth(self.stacked_widget_top.sizePolicy().hasHeightForWidth()) - self.stacked_widget_top.setSizePolicy(sizePolicy4) - self.stacked_widget_top.setMinimumSize(QSize(650, 100)) + sizePolicy2 = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Maximum) + sizePolicy2.setHorizontalStretch(0) + sizePolicy2.setVerticalStretch(0) + sizePolicy2.setHeightForWidth(self.stacked_widget_top.sizePolicy().hasHeightForWidth()) + self.stacked_widget_top.setSizePolicy(sizePolicy2) + self.stacked_widget_top.setMinimumSize(QSize(650, 20)) self.stacked_widget_top.setStyleSheet(u"b") self.stacked_widget_top.setLineWidth(1) self.page_download = QWidget() @@ -290,30 +158,30 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_downloading.setVerticalSpacing(6) self.button_search = QPushButton(self.page_download) self.button_search.setObjectName(u"button_search") - sizePolicy5 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed) - sizePolicy5.setHorizontalStretch(0) - sizePolicy5.setVerticalStretch(0) - sizePolicy5.setHeightForWidth(self.button_search.sizePolicy().hasHeightForWidth()) - self.button_search.setSizePolicy(sizePolicy5) + sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed) + sizePolicy3.setHorizontalStretch(0) + sizePolicy3.setVerticalStretch(0) + sizePolicy3.setHeightForWidth(self.button_search.sizePolicy().hasHeightForWidth()) + self.button_search.setSizePolicy(sizePolicy3) self.button_search.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.gridlayout_downloading.addWidget(self.button_search, 7, 3, 1, 1) self.lineedit_url = QLineEdit(self.page_download) self.lineedit_url.setObjectName(u"lineedit_url") - sizePolicy6 = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Fixed) - sizePolicy6.setHorizontalStretch(0) - sizePolicy6.setVerticalStretch(0) - sizePolicy6.setHeightForWidth(self.lineedit_url.sizePolicy().hasHeightForWidth()) - self.lineedit_url.setSizePolicy(sizePolicy6) + sizePolicy4 = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Fixed) + sizePolicy4.setHorizontalStretch(0) + sizePolicy4.setVerticalStretch(0) + sizePolicy4.setHeightForWidth(self.lineedit_url.sizePolicy().hasHeightForWidth()) + self.lineedit_url.setSizePolicy(sizePolicy4) self.lineedit_url.setMinimumSize(QSize(300, 4)) self.gridlayout_downloading.addWidget(self.lineedit_url, 2, 1, 1, 2) self.button_open_file = QPushButton(self.page_download) self.button_open_file.setObjectName(u"button_open_file") - sizePolicy5.setHeightForWidth(self.button_open_file.sizePolicy().hasHeightForWidth()) - self.button_open_file.setSizePolicy(sizePolicy5) + sizePolicy3.setHeightForWidth(self.button_open_file.sizePolicy().hasHeightForWidth()) + self.button_open_file.setSizePolicy(sizePolicy3) self.button_open_file.setMinimumSize(QSize(60, 2)) self.button_open_file.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_open_file.setStyleSheet(u"") @@ -322,15 +190,18 @@ def setupUi(self, Porn_Fetch_Widget): self.label_search_website = QLabel(self.page_download) self.label_search_website.setObjectName(u"label_search_website") - sizePolicy3.setHeightForWidth(self.label_search_website.sizePolicy().hasHeightForWidth()) - self.label_search_website.setSizePolicy(sizePolicy3) + sizePolicy5 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) + sizePolicy5.setHorizontalStretch(0) + sizePolicy5.setVerticalStretch(0) + sizePolicy5.setHeightForWidth(self.label_search_website.sizePolicy().hasHeightForWidth()) + self.label_search_website.setSizePolicy(sizePolicy5) self.gridlayout_downloading.addWidget(self.label_search_website, 9, 0, 1, 1) self.button_model = QPushButton(self.page_download) self.button_model.setObjectName(u"button_model") - sizePolicy5.setHeightForWidth(self.button_model.sizePolicy().hasHeightForWidth()) - self.button_model.setSizePolicy(sizePolicy5) + sizePolicy3.setHeightForWidth(self.button_model.sizePolicy().hasHeightForWidth()) + self.button_model.setSizePolicy(sizePolicy3) self.button_model.setMinimumSize(QSize(60, 2)) self.button_model.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_model.setStyleSheet(u"") @@ -339,8 +210,8 @@ def setupUi(self, Porn_Fetch_Widget): self.button_download = QPushButton(self.page_download) self.button_download.setObjectName(u"button_download") - sizePolicy5.setHeightForWidth(self.button_download.sizePolicy().hasHeightForWidth()) - self.button_download.setSizePolicy(sizePolicy5) + sizePolicy3.setHeightForWidth(self.button_download.sizePolicy().hasHeightForWidth()) + self.button_download.setSizePolicy(sizePolicy3) self.button_download.setMinimumSize(QSize(60, 2)) self.button_download.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_download.setStyleSheet(u"") @@ -349,8 +220,8 @@ def setupUi(self, Porn_Fetch_Widget): self.lineedit_model_url = QLineEdit(self.page_download) self.lineedit_model_url.setObjectName(u"lineedit_model_url") - sizePolicy6.setHeightForWidth(self.lineedit_model_url.sizePolicy().hasHeightForWidth()) - self.lineedit_model_url.setSizePolicy(sizePolicy6) + sizePolicy4.setHeightForWidth(self.lineedit_model_url.sizePolicy().hasHeightForWidth()) + self.lineedit_model_url.setSizePolicy(sizePolicy4) self.lineedit_model_url.setMinimumSize(QSize(300, 2)) self.gridlayout_downloading.addWidget(self.lineedit_model_url, 5, 1, 1, 2) @@ -385,17 +256,27 @@ def setupUi(self, Porn_Fetch_Widget): self.horizontallayout_searching_websites.addWidget(self.radio_search_website_xnxx) - self.horizontal_spacer_searching = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) - self.horizontallayout_searching_websites.addItem(self.horizontal_spacer_searching) + self.horizontallayout_searching_websites.addItem(self.horizontalSpacer_3) + + self.button_switch_supported_websites = QPushButton(self.page_download) + self.button_switch_supported_websites.setObjectName(u"button_switch_supported_websites") + sizePolicy1.setHeightForWidth(self.button_switch_supported_websites.sizePolicy().hasHeightForWidth()) + self.button_switch_supported_websites.setSizePolicy(sizePolicy1) + self.button_switch_supported_websites.setMinimumSize(QSize(0, 25)) + self.button_switch_supported_websites.setMaximumSize(QSize(16777215, 20)) + self.button_switch_supported_websites.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + + self.horizontallayout_searching_websites.addWidget(self.button_switch_supported_websites) self.gridlayout_downloading.addLayout(self.horizontallayout_searching_websites, 9, 1, 1, 3) self.lineedit_file = QLineEdit(self.page_download) self.lineedit_file.setObjectName(u"lineedit_file") - sizePolicy6.setHeightForWidth(self.lineedit_file.sizePolicy().hasHeightForWidth()) - self.lineedit_file.setSizePolicy(sizePolicy6) + sizePolicy4.setHeightForWidth(self.lineedit_file.sizePolicy().hasHeightForWidth()) + self.lineedit_file.setSizePolicy(sizePolicy4) self.lineedit_file.setMinimumSize(QSize(300, 2)) self.lineedit_file.setReadOnly(True) @@ -403,12 +284,12 @@ def setupUi(self, Porn_Fetch_Widget): self.label_url = QLabel(self.page_download) self.label_url.setObjectName(u"label_url") - sizePolicy7 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) - sizePolicy7.setHorizontalStretch(0) - sizePolicy7.setVerticalStretch(0) - sizePolicy7.setHeightForWidth(self.label_url.sizePolicy().hasHeightForWidth()) - self.label_url.setSizePolicy(sizePolicy7) - self.label_url.setMinimumSize(QSize(100, 2)) + sizePolicy6 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) + sizePolicy6.setHorizontalStretch(0) + sizePolicy6.setVerticalStretch(0) + sizePolicy6.setHeightForWidth(self.label_url.sizePolicy().hasHeightForWidth()) + self.label_url.setSizePolicy(sizePolicy6) + self.label_url.setMinimumSize(QSize(100, 1)) self.gridlayout_downloading.addWidget(self.label_url, 2, 0, 1, 1) @@ -429,8 +310,8 @@ def setupUi(self, Porn_Fetch_Widget): self.label_model_url = QLabel(self.page_download) self.label_model_url.setObjectName(u"label_model_url") - sizePolicy7.setHeightForWidth(self.label_model_url.sizePolicy().hasHeightForWidth()) - self.label_model_url.setSizePolicy(sizePolicy7) + sizePolicy6.setHeightForWidth(self.label_model_url.sizePolicy().hasHeightForWidth()) + self.label_model_url.setSizePolicy(sizePolicy6) self.label_model_url.setMinimumSize(QSize(100, 2)) self.gridlayout_downloading.addWidget(self.label_model_url, 5, 0, 1, 1) @@ -442,16 +323,16 @@ def setupUi(self, Porn_Fetch_Widget): self.lineedit_search_query = QLineEdit(self.page_download) self.lineedit_search_query.setObjectName(u"lineedit_search_query") - sizePolicy6.setHeightForWidth(self.lineedit_search_query.sizePolicy().hasHeightForWidth()) - self.lineedit_search_query.setSizePolicy(sizePolicy6) + sizePolicy4.setHeightForWidth(self.lineedit_search_query.sizePolicy().hasHeightForWidth()) + self.lineedit_search_query.setSizePolicy(sizePolicy4) self.lineedit_search_query.setMinimumSize(QSize(300, 0)) self.gridlayout_downloading.addWidget(self.lineedit_search_query, 7, 1, 1, 2) self.label_file = QLabel(self.page_download) self.label_file.setObjectName(u"label_file") - sizePolicy7.setHeightForWidth(self.label_file.sizePolicy().hasHeightForWidth()) - self.label_file.setSizePolicy(sizePolicy7) + sizePolicy6.setHeightForWidth(self.label_file.sizePolicy().hasHeightForWidth()) + self.label_file.setSizePolicy(sizePolicy6) self.label_file.setMinimumSize(QSize(100, 2)) self.gridlayout_downloading.addWidget(self.label_file, 6, 0, 1, 1) @@ -461,16 +342,6 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_downloading.addWidget(self.button_help_file, 6, 2, 1, 1) - self.button_switch_supported_websites = QPushButton(self.page_download) - self.button_switch_supported_websites.setObjectName(u"button_switch_supported_websites") - sizePolicy1.setHeightForWidth(self.button_switch_supported_websites.sizePolicy().hasHeightForWidth()) - self.button_switch_supported_websites.setSizePolicy(sizePolicy1) - self.button_switch_supported_websites.setMinimumSize(QSize(0, 25)) - self.button_switch_supported_websites.setMaximumSize(QSize(16777215, 20)) - self.button_switch_supported_websites.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - - self.gridlayout_downloading.addWidget(self.button_switch_supported_websites, 1, 1, 1, 2) - self.gridLayout_5.addLayout(self.gridlayout_downloading, 0, 0, 1, 1) @@ -500,8 +371,8 @@ def setupUi(self, Porn_Fetch_Widget): self.label_username = QLabel(self.page_login) self.label_username.setObjectName(u"label_username") - sizePolicy3.setHeightForWidth(self.label_username.sizePolicy().hasHeightForWidth()) - self.label_username.setSizePolicy(sizePolicy3) + sizePolicy5.setHeightForWidth(self.label_username.sizePolicy().hasHeightForWidth()) + self.label_username.setSizePolicy(sizePolicy5) self.gridlayout_login_box.addWidget(self.label_username, 0, 0, 1, 1) @@ -515,8 +386,8 @@ def setupUi(self, Porn_Fetch_Widget): self.lineedit_username = QLineEdit(self.page_login) self.lineedit_username.setObjectName(u"lineedit_username") - sizePolicy6.setHeightForWidth(self.lineedit_username.sizePolicy().hasHeightForWidth()) - self.lineedit_username.setSizePolicy(sizePolicy6) + sizePolicy4.setHeightForWidth(self.lineedit_username.sizePolicy().hasHeightForWidth()) + self.lineedit_username.setSizePolicy(sizePolicy4) self.lineedit_username.setMinimumSize(QSize(150, 0)) self.gridlayout_login_box.addWidget(self.lineedit_username, 0, 1, 1, 3) @@ -530,15 +401,15 @@ def setupUi(self, Porn_Fetch_Widget): self.label_password = QLabel(self.page_login) self.label_password.setObjectName(u"label_password") - sizePolicy3.setHeightForWidth(self.label_password.sizePolicy().hasHeightForWidth()) - self.label_password.setSizePolicy(sizePolicy3) + sizePolicy5.setHeightForWidth(self.label_password.sizePolicy().hasHeightForWidth()) + self.label_password.setSizePolicy(sizePolicy5) self.gridlayout_login_box.addWidget(self.label_password, 1, 0, 1, 1) self.lineedit_password = QLineEdit(self.page_login) self.lineedit_password.setObjectName(u"lineedit_password") - sizePolicy6.setHeightForWidth(self.lineedit_password.sizePolicy().hasHeightForWidth()) - self.lineedit_password.setSizePolicy(sizePolicy6) + sizePolicy4.setHeightForWidth(self.lineedit_password.sizePolicy().hasHeightForWidth()) + self.lineedit_password.setSizePolicy(sizePolicy4) self.lineedit_password.setMinimumSize(QSize(150, 0)) self.lineedit_password.setEchoMode(QLineEdit.Password) @@ -552,18 +423,18 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_2.addLayout(self.gridlayout_login_box, 0, 0, 1, 1) self.stacked_widget_top.addWidget(self.page_login) - self.page_nothing_2 = QWidget() - self.page_nothing_2.setObjectName(u"page_nothing_2") - self.gridLayout_6 = QGridLayout(self.page_nothing_2) + self.page_progressbars = QWidget() + self.page_progressbars.setObjectName(u"page_progressbars") + self.gridLayout_6 = QGridLayout(self.page_progressbars) self.gridLayout_6.setSpacing(0) self.gridLayout_6.setObjectName(u"gridLayout_6") self.gridLayout_6.setContentsMargins(0, 0, 0, 0) - self.scrollArea = QScrollArea(self.page_nothing_2) + self.scrollArea = QScrollArea(self.page_progressbars) self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1608, 257)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1588, 257)) self.gridLayout_18 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_18.setObjectName(u"gridLayout_18") self.gridlayout_progressbar = QGridLayout() @@ -576,8 +447,8 @@ def setupUi(self, Porn_Fetch_Widget): self.label_progress_pornhub = QLabel(self.scrollAreaWidgetContents) self.label_progress_pornhub.setObjectName(u"label_progress_pornhub") - sizePolicy3.setHeightForWidth(self.label_progress_pornhub.sizePolicy().hasHeightForWidth()) - self.label_progress_pornhub.setSizePolicy(sizePolicy3) + sizePolicy5.setHeightForWidth(self.label_progress_pornhub.sizePolicy().hasHeightForWidth()) + self.label_progress_pornhub.setSizePolicy(sizePolicy5) self.gridlayout_progressbar.addWidget(self.label_progress_pornhub, 0, 0, 1, 1) @@ -599,15 +470,15 @@ def setupUi(self, Porn_Fetch_Widget): self.label_progress_hqporner = QLabel(self.scrollAreaWidgetContents) self.label_progress_hqporner.setObjectName(u"label_progress_hqporner") - sizePolicy3.setHeightForWidth(self.label_progress_hqporner.sizePolicy().hasHeightForWidth()) - self.label_progress_hqporner.setSizePolicy(sizePolicy3) + sizePolicy5.setHeightForWidth(self.label_progress_hqporner.sizePolicy().hasHeightForWidth()) + self.label_progress_hqporner.setSizePolicy(sizePolicy5) self.gridlayout_progressbar.addWidget(self.label_progress_hqporner, 1, 0, 1, 1) self.progressbar_hqporner = QProgressBar(self.scrollAreaWidgetContents) self.progressbar_hqporner.setObjectName(u"progressbar_hqporner") - sizePolicy6.setHeightForWidth(self.progressbar_hqporner.sizePolicy().hasHeightForWidth()) - self.progressbar_hqporner.setSizePolicy(sizePolicy6) + sizePolicy4.setHeightForWidth(self.progressbar_hqporner.sizePolicy().hasHeightForWidth()) + self.progressbar_hqporner.setSizePolicy(sizePolicy4) self.progressbar_hqporner.setMinimumSize(QSize(300, 0)) self.progressbar_hqporner.setValue(0) @@ -615,8 +486,8 @@ def setupUi(self, Porn_Fetch_Widget): self.progressbar_pornhub = QProgressBar(self.scrollAreaWidgetContents) self.progressbar_pornhub.setObjectName(u"progressbar_pornhub") - sizePolicy6.setHeightForWidth(self.progressbar_pornhub.sizePolicy().hasHeightForWidth()) - self.progressbar_pornhub.setSizePolicy(sizePolicy6) + sizePolicy4.setHeightForWidth(self.progressbar_pornhub.sizePolicy().hasHeightForWidth()) + self.progressbar_pornhub.setSizePolicy(sizePolicy4) self.progressbar_pornhub.setMinimumSize(QSize(300, 0)) self.progressbar_pornhub.setValue(0) @@ -655,12 +526,62 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_6.addWidget(self.scrollArea, 0, 0, 1, 1) - self.stacked_widget_top.addWidget(self.page_nothing_2) - self.page_hqporner = QWidget() - self.page_hqporner.setObjectName(u"page_hqporner") - self.gridLayout_29 = QGridLayout(self.page_hqporner) + self.stacked_widget_top.addWidget(self.page_progressbars) + self.page_tools = QWidget() + self.page_tools.setObjectName(u"page_tools") + self.gridLayout_29 = QGridLayout(self.page_tools) self.gridLayout_29.setObjectName(u"gridLayout_29") - self.groupBox = QGroupBox(self.page_hqporner) + self.groupBox_2 = QGroupBox(self.page_tools) + self.groupBox_2.setObjectName(u"groupBox_2") + self.gridLayout_15 = QGridLayout(self.groupBox_2) + self.gridLayout_15.setObjectName(u"gridLayout_15") + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.label_videos_by_category_eporner = QLabel(self.groupBox_2) + self.label_videos_by_category_eporner.setObjectName(u"label_videos_by_category_eporner") + self.label_videos_by_category_eporner.setMinimumSize(QSize(0, 4)) + + self.horizontalLayout.addWidget(self.label_videos_by_category_eporner) + + self.lineedit_videos_by_category_eporner = QLineEdit(self.groupBox_2) + self.lineedit_videos_by_category_eporner.setObjectName(u"lineedit_videos_by_category_eporner") + sizePolicy7 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) + sizePolicy7.setHorizontalStretch(0) + sizePolicy7.setVerticalStretch(4) + sizePolicy7.setHeightForWidth(self.lineedit_videos_by_category_eporner.sizePolicy().hasHeightForWidth()) + self.lineedit_videos_by_category_eporner.setSizePolicy(sizePolicy7) + self.lineedit_videos_by_category_eporner.setMinimumSize(QSize(100, 4)) + + self.horizontalLayout.addWidget(self.lineedit_videos_by_category_eporner) + + self.button_eporner_category_get_videos = QPushButton(self.groupBox_2) + self.button_eporner_category_get_videos.setObjectName(u"button_eporner_category_get_videos") + sizePolicy8 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed) + sizePolicy8.setHorizontalStretch(0) + sizePolicy8.setVerticalStretch(2) + sizePolicy8.setHeightForWidth(self.button_eporner_category_get_videos.sizePolicy().hasHeightForWidth()) + self.button_eporner_category_get_videos.setSizePolicy(sizePolicy8) + self.button_eporner_category_get_videos.setMinimumSize(QSize(0, 2)) + self.button_eporner_category_get_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + + self.horizontalLayout.addWidget(self.button_eporner_category_get_videos) + + self.button_list_categories_eporner = QPushButton(self.groupBox_2) + self.button_list_categories_eporner.setObjectName(u"button_list_categories_eporner") + sizePolicy3.setHeightForWidth(self.button_list_categories_eporner.sizePolicy().hasHeightForWidth()) + self.button_list_categories_eporner.setSizePolicy(sizePolicy3) + self.button_list_categories_eporner.setMinimumSize(QSize(0, 2)) + self.button_list_categories_eporner.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + + self.horizontalLayout.addWidget(self.button_list_categories_eporner) + + + self.gridLayout_15.addLayout(self.horizontalLayout, 0, 0, 1, 1) + + + self.gridLayout_29.addWidget(self.groupBox_2, 1, 1, 1, 1) + + self.groupBox = QGroupBox(self.page_tools) self.groupBox.setObjectName(u"groupBox") self.gridLayout_7 = QGridLayout(self.groupBox) self.gridLayout_7.setObjectName(u"gridLayout_7") @@ -696,8 +617,8 @@ def setupUi(self, Porn_Fetch_Widget): self.button_list_categories = QPushButton(self.groupBox) self.button_list_categories.setObjectName(u"button_list_categories") - sizePolicy5.setHeightForWidth(self.button_list_categories.sizePolicy().hasHeightForWidth()) - self.button_list_categories.setSizePolicy(sizePolicy5) + sizePolicy3.setHeightForWidth(self.button_list_categories.sizePolicy().hasHeightForWidth()) + self.button_list_categories.setSizePolicy(sizePolicy3) self.button_list_categories.setMinimumSize(QSize(0, 2)) self.button_list_categories.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) @@ -705,11 +626,8 @@ def setupUi(self, Porn_Fetch_Widget): self.lineedit_hqporner_category = QLineEdit(self.groupBox) self.lineedit_hqporner_category.setObjectName(u"lineedit_hqporner_category") - sizePolicy8 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) - sizePolicy8.setHorizontalStretch(0) - sizePolicy8.setVerticalStretch(4) - sizePolicy8.setHeightForWidth(self.lineedit_hqporner_category.sizePolicy().hasHeightForWidth()) - self.lineedit_hqporner_category.setSizePolicy(sizePolicy8) + sizePolicy7.setHeightForWidth(self.lineedit_hqporner_category.sizePolicy().hasHeightForWidth()) + self.lineedit_hqporner_category.setSizePolicy(sizePolicy7) self.lineedit_hqporner_category.setMinimumSize(QSize(100, 4)) self.gridLayout.addWidget(self.lineedit_hqporner_category, 1, 1, 1, 2) @@ -728,11 +646,8 @@ def setupUi(self, Porn_Fetch_Widget): self.button_hqporner_category_get_videos = QPushButton(self.groupBox) self.button_hqporner_category_get_videos.setObjectName(u"button_hqporner_category_get_videos") - sizePolicy9 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed) - sizePolicy9.setHorizontalStretch(0) - sizePolicy9.setVerticalStretch(2) - sizePolicy9.setHeightForWidth(self.button_hqporner_category_get_videos.sizePolicy().hasHeightForWidth()) - self.button_hqporner_category_get_videos.setSizePolicy(sizePolicy9) + sizePolicy8.setHeightForWidth(self.button_hqporner_category_get_videos.sizePolicy().hasHeightForWidth()) + self.button_hqporner_category_get_videos.setSizePolicy(sizePolicy8) self.button_hqporner_category_get_videos.setMinimumSize(QSize(0, 2)) self.button_hqporner_category_get_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) @@ -740,11 +655,11 @@ def setupUi(self, Porn_Fetch_Widget): self.button_get_random_videos = QPushButton(self.groupBox) self.button_get_random_videos.setObjectName(u"button_get_random_videos") - sizePolicy10 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed) - sizePolicy10.setHorizontalStretch(0) - sizePolicy10.setVerticalStretch(0) - sizePolicy10.setHeightForWidth(self.button_get_random_videos.sizePolicy().hasHeightForWidth()) - self.button_get_random_videos.setSizePolicy(sizePolicy10) + sizePolicy9 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed) + sizePolicy9.setHorizontalStretch(0) + sizePolicy9.setVerticalStretch(0) + sizePolicy9.setHeightForWidth(self.button_get_random_videos.sizePolicy().hasHeightForWidth()) + self.button_get_random_videos.setSizePolicy(sizePolicy9) self.button_get_random_videos.setMinimumSize(QSize(0, 10)) self.button_get_random_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) @@ -752,8 +667,8 @@ def setupUi(self, Porn_Fetch_Widget): self.button_get_brazzers_videos = QPushButton(self.groupBox) self.button_get_brazzers_videos.setObjectName(u"button_get_brazzers_videos") - sizePolicy10.setHeightForWidth(self.button_get_brazzers_videos.sizePolicy().hasHeightForWidth()) - self.button_get_brazzers_videos.setSizePolicy(sizePolicy10) + sizePolicy9.setHeightForWidth(self.button_get_brazzers_videos.sizePolicy().hasHeightForWidth()) + self.button_get_brazzers_videos.setSizePolicy(sizePolicy9) self.button_get_brazzers_videos.setMinimumSize(QSize(0, 10)) self.button_get_brazzers_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) @@ -777,53 +692,140 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_29.addWidget(self.groupBox, 0, 1, 1, 1) - self.groupBox_2 = QGroupBox(self.page_hqporner) - self.groupBox_2.setObjectName(u"groupBox_2") - self.gridLayout_15 = QGridLayout(self.groupBox_2) - self.gridLayout_15.setObjectName(u"gridLayout_15") - self.horizontalLayout = QHBoxLayout() - self.horizontalLayout.setObjectName(u"horizontalLayout") - self.label_videos_by_category_eporner = QLabel(self.groupBox_2) - self.label_videos_by_category_eporner.setObjectName(u"label_videos_by_category_eporner") - self.label_videos_by_category_eporner.setMinimumSize(QSize(0, 4)) + self.stacked_widget_top.addWidget(self.page_tools) - self.horizontalLayout.addWidget(self.label_videos_by_category_eporner) + self.verticallayout_treewidget.addWidget(self.stacked_widget_top) - self.lineedit_videos_by_category_eporner = QLineEdit(self.groupBox_2) - self.lineedit_videos_by_category_eporner.setObjectName(u"lineedit_videos_by_category_eporner") - sizePolicy8.setHeightForWidth(self.lineedit_videos_by_category_eporner.sizePolicy().hasHeightForWidth()) - self.lineedit_videos_by_category_eporner.setSizePolicy(sizePolicy8) - self.lineedit_videos_by_category_eporner.setMinimumSize(QSize(100, 4)) + self.scrollarea_treewidget = QScrollArea(self.widget) + self.scrollarea_treewidget.setObjectName(u"scrollarea_treewidget") + self.scrollarea_treewidget.setWidgetResizable(True) + self.scrollAreaWidgetContents_3 = QWidget() + self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") + self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1606, 449)) + self.gridLayout_4 = QGridLayout(self.scrollAreaWidgetContents_3) + self.gridLayout_4.setObjectName(u"gridLayout_4") + self.verticallayout_treewidget_settings = QVBoxLayout() + self.verticallayout_treewidget_settings.setObjectName(u"verticallayout_treewidget_settings") + self.treeWidget = QTreeWidget(self.scrollAreaWidgetContents_3) + __qtreewidgetitem = QTreeWidgetItem() + __qtreewidgetitem.setText(0, u"Title"); + self.treeWidget.setHeaderItem(__qtreewidgetitem) + self.treeWidget.setObjectName(u"treeWidget") + sizePolicy10 = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.MinimumExpanding) + sizePolicy10.setHorizontalStretch(0) + sizePolicy10.setVerticalStretch(0) + sizePolicy10.setHeightForWidth(self.treeWidget.sizePolicy().hasHeightForWidth()) + self.treeWidget.setSizePolicy(sizePolicy10) + self.treeWidget.setMinimumSize(QSize(100, 200)) - self.horizontalLayout.addWidget(self.lineedit_videos_by_category_eporner) + self.verticallayout_treewidget_settings.addWidget(self.treeWidget) - self.button_eporner_category_get_videos = QPushButton(self.groupBox_2) - self.button_eporner_category_get_videos.setObjectName(u"button_eporner_category_get_videos") - sizePolicy9.setHeightForWidth(self.button_eporner_category_get_videos.sizePolicy().hasHeightForWidth()) - self.button_eporner_category_get_videos.setSizePolicy(sizePolicy9) - self.button_eporner_category_get_videos.setMinimumSize(QSize(0, 2)) - self.button_eporner_category_get_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.horizontalLayout.addWidget(self.button_eporner_category_get_videos) + self.gridLayout_4.addLayout(self.verticallayout_treewidget_settings, 2, 0, 1, 1) - self.button_list_categories_eporner = QPushButton(self.groupBox_2) - self.button_list_categories_eporner.setObjectName(u"button_list_categories_eporner") - sizePolicy5.setHeightForWidth(self.button_list_categories_eporner.sizePolicy().hasHeightForWidth()) - self.button_list_categories_eporner.setSizePolicy(sizePolicy5) - self.button_list_categories_eporner.setMinimumSize(QSize(0, 2)) - self.button_list_categories_eporner.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + self.gridLayout_16 = QGridLayout() + self.gridLayout_16.setObjectName(u"gridLayout_16") + self.radio_tree_show_all = QRadioButton(self.scrollAreaWidgetContents_3) + self.radio_tree_show_all.setObjectName(u"radio_tree_show_all") + sizePolicy5.setHeightForWidth(self.radio_tree_show_all.sizePolicy().hasHeightForWidth()) + self.radio_tree_show_all.setSizePolicy(sizePolicy5) + self.radio_tree_show_all.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + self.radio_tree_show_all.setStyleSheet(u"") + self.radio_tree_show_all.setCheckable(True) + self.radio_tree_show_all.setChecked(False) - self.horizontalLayout.addWidget(self.button_list_categories_eporner) + self.gridLayout_16.addWidget(self.radio_tree_show_all, 0, 1, 1, 1) + self.checkbox_tree_do_not_clear_videos = QCheckBox(self.scrollAreaWidgetContents_3) + self.checkbox_tree_do_not_clear_videos.setObjectName(u"checkbox_tree_do_not_clear_videos") - self.gridLayout_15.addLayout(self.horizontalLayout, 0, 0, 1, 1) + self.gridLayout_16.addWidget(self.checkbox_tree_do_not_clear_videos, 1, 1, 1, 1) + self.checkbox_tree_show_videos_reversed = QCheckBox(self.scrollAreaWidgetContents_3) + self.checkbox_tree_show_videos_reversed.setObjectName(u"checkbox_tree_show_videos_reversed") + self.checkbox_tree_show_videos_reversed.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridLayout_29.addWidget(self.groupBox_2, 1, 1, 1, 1) + self.gridLayout_16.addWidget(self.checkbox_tree_show_videos_reversed, 1, 2, 1, 1) + + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + + self.gridLayout_16.addItem(self.horizontalSpacer, 0, 3, 1, 1) + + self.checkbox_tree_allow_sorting = QCheckBox(self.scrollAreaWidgetContents_3) + self.checkbox_tree_allow_sorting.setObjectName(u"checkbox_tree_allow_sorting") + + self.gridLayout_16.addWidget(self.checkbox_tree_allow_sorting, 1, 0, 1, 1) + + self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + + self.gridLayout_16.addItem(self.horizontalSpacer_2, 1, 3, 1, 1) + + self.button_tree_export_video_urls = QPushButton(self.scrollAreaWidgetContents_3) + self.button_tree_export_video_urls.setObjectName(u"button_tree_export_video_urls") + + self.gridLayout_16.addWidget(self.button_tree_export_video_urls, 0, 2, 1, 1) + + self.radio_tree_show_title = QRadioButton(self.scrollAreaWidgetContents_3) + self.radio_tree_show_title.setObjectName(u"radio_tree_show_title") + sizePolicy5.setHeightForWidth(self.radio_tree_show_title.sizePolicy().hasHeightForWidth()) + self.radio_tree_show_title.setSizePolicy(sizePolicy5) + self.radio_tree_show_title.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + self.radio_tree_show_title.setChecked(True) + + self.gridLayout_16.addWidget(self.radio_tree_show_title, 0, 0, 1, 1) + + + self.gridLayout_4.addLayout(self.gridLayout_16, 1, 0, 1, 1) + + self.scrollarea_treewidget.setWidget(self.scrollAreaWidgetContents_3) + + self.verticallayout_treewidget.addWidget(self.scrollarea_treewidget) + + self.gridLayout_17 = QGridLayout() + self.gridLayout_17.setObjectName(u"gridLayout_17") + self.button_tree_stop = QPushButton(self.widget) + self.button_tree_stop.setObjectName(u"button_tree_stop") + sizePolicy1.setHeightForWidth(self.button_tree_stop.sizePolicy().hasHeightForWidth()) + self.button_tree_stop.setSizePolicy(sizePolicy1) + self.button_tree_stop.setMinimumSize(QSize(0, 30)) - self.stacked_widget_top.addWidget(self.page_hqporner) + self.gridLayout_17.addWidget(self.button_tree_stop, 1, 2, 1, 1) + + self.button_tree_select_range = QPushButton(self.widget) + self.button_tree_select_range.setObjectName(u"button_tree_select_range") + sizePolicy1.setHeightForWidth(self.button_tree_select_range.sizePolicy().hasHeightForWidth()) + self.button_tree_select_range.setSizePolicy(sizePolicy1) + self.button_tree_select_range.setMinimumSize(QSize(0, 30)) + self.button_tree_select_range.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + self.button_tree_select_range.setStyleSheet(u"") + + self.gridLayout_17.addWidget(self.button_tree_select_range, 1, 0, 1, 1) + + self.button_tree_unselect_all = QPushButton(self.widget) + self.button_tree_unselect_all.setObjectName(u"button_tree_unselect_all") + sizePolicy1.setHeightForWidth(self.button_tree_unselect_all.sizePolicy().hasHeightForWidth()) + self.button_tree_unselect_all.setSizePolicy(sizePolicy1) + self.button_tree_unselect_all.setMinimumSize(QSize(0, 30)) + self.button_tree_unselect_all.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + self.button_tree_unselect_all.setStyleSheet(u"") + + self.gridLayout_17.addWidget(self.button_tree_unselect_all, 1, 1, 1, 1) + + self.button_tree_download = QPushButton(self.widget) + self.button_tree_download.setObjectName(u"button_tree_download") + sizePolicy1.setHeightForWidth(self.button_tree_download.sizePolicy().hasHeightForWidth()) + self.button_tree_download.setSizePolicy(sizePolicy1) + self.button_tree_download.setMinimumSize(QSize(0, 30)) + self.button_tree_download.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + self.button_tree_download.setStyleSheet(u"") + + self.gridLayout_17.addWidget(self.button_tree_download, 0, 0, 1, 3) - self.gridLayout_8.addWidget(self.stacked_widget_top, 0, 1, 1, 1) + + self.verticallayout_treewidget.addLayout(self.gridLayout_17) + + + self.gridLayout_8.addLayout(self.verticallayout_treewidget, 0, 0, 1, 1) self.stacked_widget_main.addWidget(self.widget) self.page_settings = QWidget() @@ -924,8 +926,8 @@ def setupUi(self, Porn_Fetch_Widget): self.horizontallayout_threading_mode.setObjectName(u"horizontallayout_threading_mode") self.label_threading_mode = QLabel(self.groupbox_performance) self.label_threading_mode.setObjectName(u"label_threading_mode") - sizePolicy3.setHeightForWidth(self.label_threading_mode.sizePolicy().hasHeightForWidth()) - self.label_threading_mode.setSizePolicy(sizePolicy3) + sizePolicy5.setHeightForWidth(self.label_threading_mode.sizePolicy().hasHeightForWidth()) + self.label_threading_mode.setSizePolicy(sizePolicy5) self.horizontallayout_threading_mode.addWidget(self.label_threading_mode) @@ -1065,8 +1067,8 @@ def setupUi(self, Porn_Fetch_Widget): self.horizontallayout_quality.setObjectName(u"horizontallayout_quality") self.label_quality = QLabel(self.groupbox_videos) self.label_quality.setObjectName(u"label_quality") - sizePolicy3.setHeightForWidth(self.label_quality.sizePolicy().hasHeightForWidth()) - self.label_quality.setSizePolicy(sizePolicy3) + sizePolicy5.setHeightForWidth(self.label_quality.sizePolicy().hasHeightForWidth()) + self.label_quality.setSizePolicy(sizePolicy5) self.horizontallayout_quality.addWidget(self.label_quality) @@ -1149,8 +1151,8 @@ def setupUi(self, Porn_Fetch_Widget): self.label_ui_language = QLabel(self.goroupbox_gui) self.label_ui_language.setObjectName(u"label_ui_language") - sizePolicy3.setHeightForWidth(self.label_ui_language.sizePolicy().hasHeightForWidth()) - self.label_ui_language.setSizePolicy(sizePolicy3) + sizePolicy5.setHeightForWidth(self.label_ui_language.sizePolicy().hasHeightForWidth()) + self.label_ui_language.setSizePolicy(sizePolicy5) self.gridlayout_gui_settings.addWidget(self.label_ui_language, 1, 0, 1, 1) @@ -1222,50 +1224,28 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_26.addLayout(self.gridlayout_textbrowser, 0, 0, 1, 1) self.stacked_widget_main.addWidget(self.page_credits) - self.page_metadata = QWidget() - self.page_metadata.setObjectName(u"page_metadata") - self.gridLayout_32 = QGridLayout(self.page_metadata) - self.gridLayout_32.setObjectName(u"gridLayout_32") - self.stacked_widget_main.addWidget(self.page_metadata) self.page_supported_websites = QWidget() self.page_supported_websites.setObjectName(u"page_supported_websites") self.gridLayout_11 = QGridLayout(self.page_supported_websites) + self.gridLayout_11.setSpacing(0) self.gridLayout_11.setObjectName(u"gridLayout_11") - self.stackedWidget = QStackedWidget(self.page_supported_websites) - self.stackedWidget.setObjectName(u"stackedWidget") - self.page_i_dont_know = QWidget() - self.page_i_dont_know.setObjectName(u"page_i_dont_know") - self.gridLayout_3 = QGridLayout(self.page_i_dont_know) - self.gridLayout_3.setObjectName(u"gridLayout_3") - self.verticalLayout = QVBoxLayout() - self.verticalLayout.setSpacing(0) - self.verticalLayout.setObjectName(u"verticalLayout") - self.textbrowser_websites = QTextBrowser(self.page_i_dont_know) + self.gridLayout_11.setContentsMargins(0, 0, 0, 0) + self.textbrowser_websites = QTextBrowser(self.page_supported_websites) self.textbrowser_websites.setObjectName(u"textbrowser_websites") - self.verticalLayout.addWidget(self.textbrowser_websites) - - - self.gridLayout_3.addLayout(self.verticalLayout, 0, 0, 1, 1) - - self.stackedWidget.addWidget(self.page_i_dont_know) - self.page_nothing_3 = QWidget() - self.page_nothing_3.setObjectName(u"page_nothing_3") - self.stackedWidget.addWidget(self.page_nothing_3) - - self.gridLayout_11.addWidget(self.stackedWidget, 0, 0, 1, 1) + self.gridLayout_11.addWidget(self.textbrowser_websites, 0, 0, 1, 1) self.stacked_widget_main.addWidget(self.page_supported_websites) - self.gridLayout_13.addWidget(self.stacked_widget_main, 1, 0, 1, 1) + self.gridLayout_13.addWidget(self.stacked_widget_main, 2, 0, 1, 1) self.gridlayout_status = QGridLayout() self.gridlayout_status.setSpacing(0) self.gridlayout_status.setObjectName(u"gridlayout_status") self.label_total_progress = QLabel(Porn_Fetch_Widget) self.label_total_progress.setObjectName(u"label_total_progress") - sizePolicy3.setHeightForWidth(self.label_total_progress.sizePolicy().hasHeightForWidth()) - self.label_total_progress.setSizePolicy(sizePolicy3) + sizePolicy5.setHeightForWidth(self.label_total_progress.sizePolicy().hasHeightForWidth()) + self.label_total_progress.setSizePolicy(sizePolicy5) self.gridlayout_status.addWidget(self.label_total_progress, 2, 0, 1, 1) @@ -1282,25 +1262,25 @@ def setupUi(self, Porn_Fetch_Widget): self.label_progress_information = QLabel(Porn_Fetch_Widget) self.label_progress_information.setObjectName(u"label_progress_information") - sizePolicy3.setHeightForWidth(self.label_progress_information.sizePolicy().hasHeightForWidth()) - self.label_progress_information.setSizePolicy(sizePolicy3) + sizePolicy5.setHeightForWidth(self.label_progress_information.sizePolicy().hasHeightForWidth()) + self.label_progress_information.setSizePolicy(sizePolicy5) self.gridlayout_status.addWidget(self.label_progress_information, 4, 1, 1, 1) self.progressbar_total = QProgressBar(Porn_Fetch_Widget) self.progressbar_total.setObjectName(u"progressbar_total") - sizePolicy6.setHeightForWidth(self.progressbar_total.sizePolicy().hasHeightForWidth()) - self.progressbar_total.setSizePolicy(sizePolicy6) + sizePolicy4.setHeightForWidth(self.progressbar_total.sizePolicy().hasHeightForWidth()) + self.progressbar_total.setSizePolicy(sizePolicy4) self.progressbar_total.setMinimumSize(QSize(300, 0)) self.progressbar_total.setValue(0) self.gridlayout_status.addWidget(self.progressbar_total, 2, 1, 1, 1) - self.gridLayout_13.addLayout(self.gridlayout_status, 2, 0, 1, 1) + self.gridLayout_13.addLayout(self.gridlayout_status, 3, 0, 1, 1) - self.gridLayout_20.addLayout(self.gridLayout_13, 0, 0, 1, 1) + self.gridLayout_3.addLayout(self.gridLayout_13, 0, 0, 1, 1) QWidget.setTabOrder(self.lineedit_url, self.button_download) QWidget.setTabOrder(self.button_download, self.lineedit_playlist_url) @@ -1376,9 +1356,8 @@ def setupUi(self, Porn_Fetch_Widget): self.retranslateUi(Porn_Fetch_Widget) - self.stacked_widget_main.setCurrentIndex(2) - self.stacked_widget_top.setCurrentIndex(2) - self.stackedWidget.setCurrentIndex(1) + self.stacked_widget_main.setCurrentIndex(0) + self.stacked_widget_top.setCurrentIndex(0) QMetaObject.connectSlotsByName(Porn_Fetch_Widget) @@ -1394,31 +1373,6 @@ def retranslateUi(self, Porn_Fetch_Widget): self.button_switch_account.setText("") self.button_view_progress_bars.setText("") self.stacked_widget_main.setStyleSheet("") - ___qtreewidgetitem = self.treeWidget.headerItem() - ___qtreewidgetitem.setText(2, QCoreApplication.translate("Porn_Fetch_Widget", u"Duration", None)); - ___qtreewidgetitem.setText(1, QCoreApplication.translate("Porn_Fetch_Widget", u"Author", None)); -#if QT_CONFIG(tooltip) - self.radio_tree_show_all.setToolTip("") -#endif // QT_CONFIG(tooltip) - self.radio_tree_show_all.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Title, Author, Duration", None)) - self.button_tree_export_video_urls.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Export video URLs", None)) - self.checkbox_tree_do_not_clear_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Do not clear videos", None)) - self.radio_tree_show_title.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Only Title (a lot faster)", None)) - self.checkbox_tree_show_videos_reversed.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Show videos in reverse", None)) - self.checkbox_tree_allow_sorting.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Allow Sorting", None)) -#if QT_CONFIG(tooltip) - self.button_tree_stop.setToolTip(QCoreApplication.translate("Porn_Fetch_Widget", u"Does not stop downloading videos", None)) -#endif // QT_CONFIG(tooltip) - self.button_tree_stop.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Stop loading videos", None)) -#if QT_CONFIG(tooltip) - self.button_tree_select_range.setToolTip(QCoreApplication.translate("Porn_Fetch_Widget", u"Automatically checks a range of videos", None)) -#endif // QT_CONFIG(tooltip) - self.button_tree_select_range.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Select a range of videos", None)) -#if QT_CONFIG(tooltip) - self.button_tree_unselect_all.setToolTip(QCoreApplication.translate("Porn_Fetch_Widget", u"Unselects all videos in the tree widget", None)) -#endif // QT_CONFIG(tooltip) - self.button_tree_unselect_all.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Unselect all", None)) - self.button_tree_download.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Download Selected Videos", None)) self.button_search.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Start", None)) self.lineedit_url.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter video URL", None)) self.button_open_file.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Open File", None)) @@ -1431,6 +1385,7 @@ def retranslateUi(self, Porn_Fetch_Widget): self.radio_search_website_xvideos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XVideos", None)) self.radio_search_website_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"EPorner", None)) self.radio_search_website_xnxx.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XNXX", None)) + self.button_switch_supported_websites.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"See Supported Websites", None)) self.lineedit_file.setText("") self.lineedit_file.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"URLs in the file must be separated with new lines!", None)) self.label_url.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"URL:", None)) @@ -1443,7 +1398,6 @@ def retranslateUi(self, Porn_Fetch_Widget): self.lineedit_search_query.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Search for Videos. Select Website below", None)) self.label_file.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"File:", None)) self.button_help_file.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Help", None)) - self.button_switch_supported_websites.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"See Supported Websites", None)) self.button_get_liked_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Liked videos", None)) self.button_get_watched_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get watched videos", None)) self.label_username.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Username:", None)) @@ -1459,6 +1413,10 @@ def retranslateUi(self, Porn_Fetch_Widget): self.label_progress_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Eporner", None)) self.label_info.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Info:", None)) self.lineedit_download_info.setText("") + self.groupBox_2.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"EPorner", None)) + self.label_videos_by_category_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get videos by category", None)) + self.button_eporner_category_get_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Videos", None)) + self.button_list_categories_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"List of all categories", None)) self.groupBox.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"HQPorner", None)) self.radio_top_porn_month.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Month", None)) self.button_top_porn_get_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Videos", None)) @@ -1472,10 +1430,31 @@ def retranslateUi(self, Porn_Fetch_Widget): self.button_get_brazzers_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Videos", None)) self.labe_get_random_video.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get random video", None)) self.label_videos_by_category.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get videos by category", None)) - self.groupBox_2.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"EPorner", None)) - self.label_videos_by_category_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get videos by category", None)) - self.button_eporner_category_get_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Videos", None)) - self.button_list_categories_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"List of all categories", None)) + ___qtreewidgetitem = self.treeWidget.headerItem() + ___qtreewidgetitem.setText(2, QCoreApplication.translate("Porn_Fetch_Widget", u"Duration", None)); + ___qtreewidgetitem.setText(1, QCoreApplication.translate("Porn_Fetch_Widget", u"Author", None)); +#if QT_CONFIG(tooltip) + self.radio_tree_show_all.setToolTip("") +#endif // QT_CONFIG(tooltip) + self.radio_tree_show_all.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Title, Author, Duration", None)) + self.checkbox_tree_do_not_clear_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Do not clear videos", None)) + self.checkbox_tree_show_videos_reversed.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Show videos in reverse", None)) + self.checkbox_tree_allow_sorting.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Allow Sorting", None)) + self.button_tree_export_video_urls.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Export video URLs", None)) + self.radio_tree_show_title.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Only Title (a lot faster)", None)) +#if QT_CONFIG(tooltip) + self.button_tree_stop.setToolTip(QCoreApplication.translate("Porn_Fetch_Widget", u"Does not stop downloading videos", None)) +#endif // QT_CONFIG(tooltip) + self.button_tree_stop.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Stop loading videos", None)) +#if QT_CONFIG(tooltip) + self.button_tree_select_range.setToolTip(QCoreApplication.translate("Porn_Fetch_Widget", u"Automatically checks a range of videos", None)) +#endif // QT_CONFIG(tooltip) + self.button_tree_select_range.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Select a range of videos", None)) +#if QT_CONFIG(tooltip) + self.button_tree_unselect_all.setToolTip(QCoreApplication.translate("Porn_Fetch_Widget", u"Unselects all videos in the tree widget", None)) +#endif // QT_CONFIG(tooltip) + self.button_tree_unselect_all.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Unselect all", None)) + self.button_tree_download.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Download Selected Videos", None)) self.button_download_ffmpeg.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Download and Setup FFmpeg", None)) self.groupbox_performance.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"Performance", None)) self.label_semaphore.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Simultaneous downloads:", None)) From 36af3177fc2cd9b87e26b999f798642ca9bf55ed Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Thu, 27 Jun 2024 14:27:07 +0200 Subject: [PATCH 10/39] - some progress on fixing sorting - fixed the tag writing function - fixed the parse length function (when length is floating minute) --- README/STATUS.md | 12 +++++------ main.py | 35 ++++++++++++++++++++++----------- src/backend/shared_functions.py | 28 +++++++++++++++++++++++--- src/frontend/form_desktop.ui | 10 +++++----- src/frontend/ui_form_desktop.py | 6 +++--- 5 files changed, 62 insertions(+), 29 deletions(-) diff --git a/README/STATUS.md b/README/STATUS.md index 308f83b..0b13ed9 100644 --- a/README/STATUS.md +++ b/README/STATUS.md @@ -5,14 +5,14 @@ - [x] Fixing searching for xvideos - [] Huge code refactoring - [] Splitting functions into other .py files -- [] Trying to optimize the UI performance with more threading and slower UI repainting +- [x] Trying to optimize the UI performance with more threading and slower UI repainting - [] Supporting more websites - [x] Writing the thumbnail into the video metadata - [] Improving the sorting mechanism, to be less confusing -- [] Entirely reworking the progressbars and progress reporting in general -- [] Fixing the errors with the playlist +- [] --Entirely reworking the progressbars and progress reporting in general-- (Won't do that fr) +- [x] Fixing the errors with the playlist - [] Fixing file progress -- [] Fixing the tag writing function +- [x] Fixing the tag writing function - [] Entirely reworking the Layout, the UI design AND the Android Layout """ @@ -27,6 +27,6 @@ In 2 weeks I have summer holidays (21th June) and then we can bring some 🔥 in """"" # Maybe or maybe not: -- [] Enabling optional downloading over the tor network or proxies +- [] Enabling optional downloading over the tor network or proxies (Nope, won't do that, sorry) - [] Distributing Porn Fetch over the p2p network too -- [] Supporting FFmpeg on Android \ No newline at end of file +- [] -- Supporting FFmpeg on Android -- (Nope, won't do that) \ No newline at end of file diff --git a/main.py b/main.py index 0d5c404..1c26fe1 100644 --- a/main.py +++ b/main.py @@ -188,11 +188,13 @@ def process_video(self, video, index): # Checks which mode is selected by the user and loads the video attributes if self.data_mode == 1: author = data[1] + logger_debug(f"Unparsed duration: {data[2]}") duration = str(parse_length(data[2])) + logger_debug(f"Parsed duration: {duration}") - print( - f"\r\033[K[{Fore.LIGHTCYAN_EX}{index}/{self.search_limit}]{Fore.RESET}{str(title)} Successfully processed!", - end='', flush=True) + #print( + # f"\r\033[K[{Fore.LIGHTCYAN_EX}{index}/{self.search_limit}]{Fore.RESET}{str(title)} Successfully processed!", + #end='', flush=True) return [str(title), str(author), str(duration), str(index), video] @@ -660,8 +662,6 @@ def __init__(self, parent=None): self.threading_mode_map = None self.threading_map = None self.quality_map = None - self.selected_category = None - self.excluded_categories_filter = None self.client = None self.api_language = "en" self.delay = None @@ -1147,10 +1147,11 @@ def add_to_tree_widget_signal(self, data): title = data[0] author = data[1] try: - duration = int(data[2]) # Ensure duration is an integer - + duration = float(data[2]) # Ensure duration is a float + print(duration) except ValueError: - duration = int(00000) + logger_error("Value Error occurred :(") + duration = parse_length(data[2]) index = data[3] video = data[4] @@ -1158,11 +1159,21 @@ def add_to_tree_widget_signal(self, data): item = QTreeWidgetItem(self.ui.treeWidget) item.setText(0, f"{index}) {title}") item.setText(1, author) - # Format duration as a fixed-width string with leading zeros for better sorting, e.g., "00104" - formatted_duration = f"{duration:05d}" - item.setText(2, formatted_duration) # Set the text as the zero-padded number - item.setData(2, Qt.UserRole, int(duration)) # Store the actual integer value in UserRole if needed later + # Determine how many zeros are needed based on the type and value of duration + if isinstance(duration, float): + formatted_duration = f"{int(duration):05d}" + # Handle the decimal part separately if needed + decimal_part = str(duration).split('.')[1] + if decimal_part != '0': + formatted_duration += '.' + decimal_part + + else: + formatted_duration = f"{duration:05d}" + + duration = str(duration).strip("0").strip(".") + item.setText(2, duration) # Set the text as the zero-padded number or float + item.setData(2, Qt.UserRole, formatted_duration) # Store the original duration for sorting item.setCheckState(0, Qt.Unchecked) item.setData(0, Qt.UserRole, video) diff --git a/src/backend/shared_functions.py b/src/backend/shared_functions.py index d213027..db1590c 100644 --- a/src/backend/shared_functions.py +++ b/src/backend/shared_functions.py @@ -253,6 +253,7 @@ def load_video_attributes(video): length = video.duration.seconds / 60 tags = ",".join([tag.name for tag in video.tags]) publish_date = video.date + video.refresh() # Throws an error otherwise. I have no idea why. thumbnail = video.image.url elif isinstance(video, ep_Video): @@ -305,28 +306,49 @@ def write_tags(path, video): def parse_length(length): try: - if str(length).isdigit(): + # Check if length is a valid integer string representing minutes + if isinstance(length, int) or (isinstance(length, str) and length.isdigit()): return int(length) + # Check for decimal format like "9.3333334" which represents minutes and fractions of minutes + if isinstance(length, float) or (isinstance(length, str) and '.' in length): + try: + return int(round(length)) + except ValueError: + pass + + # Initialize a dictionary for time units conversion time_units = {'s': 1 / 60, 'm': 1, 'h': 60} total_minutes = 0 + + # Split the length string by spaces parts = length.split() for part in parts: + # Extract the numeric value and the time unit value = int(part[:-1]) unit = part[-1] + + # Convert the value to minutes if the unit is valid if unit in time_units: total_minutes += value * time_units[unit] + # If a valid time conversion was found, return the total minutes if total_minutes > 0: - return int(total_minutes) + return total_minutes + # Check for format ending with 'min' if length.endswith('min'): return int(length[:-3]) + # Check for format like '24 seconds' + if length.endswith('seconds'): + value = int(length.split()[0]) + return value / 60 # Convert seconds to minutes + return None except Exception: - return int(00000) + return 0 def resolve_threading_mode(video, mode, workers, timeout): diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 20d0f56..7e5b865 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -919,8 +919,8 @@ 0 0 - 1588 - 257 + 387 + 206 @@ -1435,7 +1435,7 @@ - Duration + Duration (minutes) @@ -1692,8 +1692,8 @@ 0 0 - 1608 - 781 + 721 + 575 diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index fcd094f..17d1f23 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -434,7 +434,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1588, 257)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 387, 206)) self.gridLayout_18 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_18.setObjectName(u"gridLayout_18") self.gridlayout_progressbar = QGridLayout() @@ -839,7 +839,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_settings.setWidgetResizable(True) self.scrollAreaWidgetContents_6 = QWidget() self.scrollAreaWidgetContents_6.setObjectName(u"scrollAreaWidgetContents_6") - self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 1608, 781)) + self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 721, 575)) self.gridLayout_19 = QGridLayout(self.scrollAreaWidgetContents_6) self.gridLayout_19.setObjectName(u"gridLayout_19") self.button_download_ffmpeg = QPushButton(self.scrollAreaWidgetContents_6) @@ -1431,7 +1431,7 @@ def retranslateUi(self, Porn_Fetch_Widget): self.labe_get_random_video.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get random video", None)) self.label_videos_by_category.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get videos by category", None)) ___qtreewidgetitem = self.treeWidget.headerItem() - ___qtreewidgetitem.setText(2, QCoreApplication.translate("Porn_Fetch_Widget", u"Duration", None)); + ___qtreewidgetitem.setText(2, QCoreApplication.translate("Porn_Fetch_Widget", u"Duration (minutes)", None)); ___qtreewidgetitem.setText(1, QCoreApplication.translate("Porn_Fetch_Widget", u"Author", None)); #if QT_CONFIG(tooltip) self.radio_tree_show_all.setToolTip("") From 8b508a63a6ddac5faba73c4c83e142e2382753ec Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Thu, 27 Jun 2024 21:47:28 +0200 Subject: [PATCH 11/39] - finished fixing the sorting - some improvements to the top bar (need to fix icons) --- README/STATUS.md | 2 +- main.py | 18 +--- src/frontend/form_desktop.ui | 166 ++++++++++++++++++++++++-------- src/frontend/range_selector.py | 36 +++---- src/frontend/range_selector.ui | 30 +++--- src/frontend/ui_form_desktop.py | 149 ++++++++++++++++++++++------ 6 files changed, 282 insertions(+), 119 deletions(-) diff --git a/README/STATUS.md b/README/STATUS.md index 0b13ed9..36987bd 100644 --- a/README/STATUS.md +++ b/README/STATUS.md @@ -8,7 +8,7 @@ - [x] Trying to optimize the UI performance with more threading and slower UI repainting - [] Supporting more websites - [x] Writing the thumbnail into the video metadata -- [] Improving the sorting mechanism, to be less confusing +- [x] Improving the sorting mechanism, to be less confusing - [] --Entirely reworking the progressbars and progress reporting in general-- (Won't do that fr) - [x] Fixing the errors with the playlist - [] Fixing file progress diff --git a/main.py b/main.py index 1c26fe1..e33610b 100644 --- a/main.py +++ b/main.py @@ -188,13 +188,11 @@ def process_video(self, video, index): # Checks which mode is selected by the user and loads the video attributes if self.data_mode == 1: author = data[1] - logger_debug(f"Unparsed duration: {data[2]}") duration = str(parse_length(data[2])) - logger_debug(f"Parsed duration: {duration}") - #print( - # f"\r\033[K[{Fore.LIGHTCYAN_EX}{index}/{self.search_limit}]{Fore.RESET}{str(title)} Successfully processed!", - #end='', flush=True) + print( + f"\r\033[K[{Fore.LIGHTCYAN_EX}{index}/{self.search_limit}]{Fore.RESET}{str(title)} Successfully processed!", + end='', flush=True) return [str(title), str(author), str(duration), str(index), video] @@ -783,7 +781,6 @@ def button_connectors(self): self.ui.button_open_file.clicked.connect(self.open_file_dialog) # Other stuff idk - self.ui.checkbox_tree_allow_sorting.checkStateChanged.connect(self.toggle_sorting) self.ui.button_tree_select_range.clicked.connect(self.select_range_of_items) self.ui.button_tree_stop.clicked.connect(switch_stop_state) self.ui.button_tree_export_video_urls.clicked.connect(export_urls) @@ -1074,15 +1071,6 @@ def handle_no_output_path(self): def configure_ui_for_android(self, path): "" - def toggle_sorting(self): - if self.ui.checkbox_tree_allow_sorting.isChecked(): - logger_debug("Enabling sorting on the tree widget") - self.ui.treeWidget.setSortingEnabled(True) - - else: - logger_debug("Disabling sorting on the tree widget") - self.ui.treeWidget.setSortingEnabled(False) - def switch_to_home(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(0) diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 7e5b865..4c6e22d 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -38,7 +38,10 @@ - 0 + 3 + + + 3 @@ -64,7 +67,23 @@ PointingHandCursor - border: none; + QPushButton { + background-color: #800080; + color: white; + border-radius: 8px; + border: 3px solid #dda0dd; + padding: 8px 10px; +} + +QPushButton:hover { + background-color: #9932cc; + border: 3px solid #ba55d3; +} + +QPushButton:pressed { + background-color: #4b0082; +} + @@ -106,7 +125,22 @@ PointingHandCursor - border: none + QPushButton { + background-color: #000000; + color: #ffffff; + border-radius: 8px; + border: 2px solid #ffffff; + padding: 8px 10px; +} + +QPushButton:hover { + background-color: #333333; +} + +QPushButton:pressed { + background-color: #666666; +} + @@ -143,7 +177,23 @@ PointingHandCursor - border: none; + QPushButton { + background-color: #4CAF50; + color: white; + border-radius: 8px; + border: 2px solid #0078d7; + padding: 8px 10px; +} + +QPushButton:hover { + background-color: #66BB6A; + border: 2px solid #005bb5; +} + +QPushButton:pressed { + background-color: #388E3C; +} + @@ -180,7 +230,22 @@ PointingHandCursor - border: none; + QPushButton { + background-color: #008CBA; + color: white; + border-radius: 8px; + border: none; + padding: 8px 10px; +} + +QPushButton:hover { + background-color: #00A3CC; +} + +QPushButton:pressed { + background-color: #005F8C; +} + @@ -217,7 +282,22 @@ PointingHandCursor - border: none + QPushButton { + background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 #ff7f50, stop:1 #ff4500); + color: white; + border-radius: 8px; + border: none; + padding: 8px 10px; +} + +QPushButton:hover { + background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 #ffa07a, stop:1 #ff6347); +} + +QPushButton:pressed { + background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 #cd5c5c, stop:1 #b22222); +} + @@ -254,7 +334,22 @@ PointingHandCursor - border: none; + QPushButton { + background-color: #808080; + color: white; + border-radius: 8px; + border: 2px solid #a9a9a9; + padding: 8px 10px; +} + +QPushButton:hover { + background-color: #a9a9a9; +} + +QPushButton:pressed { + background-color: #696969; +} + @@ -1403,7 +1498,7 @@ 0 0 1606 - 449 + 446 @@ -1472,23 +1567,6 @@ - - - - Do not clear videos - - - - - - - PointingHandCursor - - - Show videos in reverse - - - @@ -1502,13 +1580,6 @@ - - - - Allow Sorting - - - @@ -1522,13 +1593,6 @@ - - - - Export video URLs - - - @@ -1548,6 +1612,30 @@ + + + + Do not clear videos + + + + + + + PointingHandCursor + + + Show videos in reverse + + + + + + + Export video URLs + + + diff --git a/src/frontend/range_selector.py b/src/frontend/range_selector.py index 24c58d4..942b2e5 100644 --- a/src/frontend/range_selector.py +++ b/src/frontend/range_selector.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'range_selector.ui' ## -## Created by: Qt User Interface Compiler version 6.7.0 +## Created by: Qt User Interface Compiler version 6.7.2 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -111,26 +111,26 @@ def retranslateUi(self, Form): Form.setWindowTitle(QCoreApplication.translate("Form", u"Video selector...", None)) self.label_apply_by_index.setText(QCoreApplication.translate("Form", u"Apply by Index:", None)) self.label_range_start.setText(QCoreApplication.translate("Form", u"Start:", None)) - self.lineedit_range_start.setText(QCoreApplication.translate("Form", u"00000", None)) - self.lineedit_range_end.setText(QCoreApplication.translate("Form", u"00000", None)) + self.lineedit_range_start.setText(QCoreApplication.translate("Form", u"0", None)) + self.lineedit_range_end.setText(QCoreApplication.translate("Form", u"0", None)) self.textbrowser_range.setHtml(QCoreApplication.translate("Form", u"\n" "\n" -"

Select the range of videos to be automatically selected.

\n" -"


\n" -"

For example, if you set the start to 5 and the end to 20, then" - " all videos between 5-20 will be checked for downloading :)

\n" -"


\n" -"

Or select by a range in time:

\n" -"


\n" -"

For example if you want to download all videos in between 10 and 20 minutes do:

\n" -"


\n" -"

Start: 000010

\n" -"

End: 00020

\n" -"


\n" -"

And click Apply.

", None)) +"\n" +"

Select the range of videos to be automatically selected.

\n" +"


\n" +"

For example, if you set the start to 5 and the end to 20, then all videos between 5-20 will be checked for " + "downloading :)

\n" +"


\n" +"

Or select by a range in time:

\n" +"


\n" +"

For example if you want to download all videos in between 10 and 20 minutes do:

\n" +"


\n" +"

Start: 10

\n" +"

End: 20

\n" +"


\n" +"

And click Apply.

", None)) self.label_range_time_end.setText(QCoreApplication.translate("Form", u"End:", None)) self.label_apply_by_time.setText(QCoreApplication.translate("Form", u"Apply by time:", None)) self.button_range_apply_index.setText(QCoreApplication.translate("Form", u"Apply", None)) diff --git a/src/frontend/range_selector.ui b/src/frontend/range_selector.ui index 499d3b9..61dae0f 100644 --- a/src/frontend/range_selector.ui +++ b/src/frontend/range_selector.ui @@ -36,7 +36,7 @@ - 00000 + 0 @@ -46,7 +46,7 @@ - 00000 + 0 @@ -56,19 +56,19 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Select the range of videos to be automatically selected.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">For example, if you set the start to 5 and the end to 20, then all videos between 5-20 will be checked for downloading :)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Or select by a range in time:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">For example if you want to download all videos in between 10 and 20 minutes do:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Start: 000010</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">End: 00020</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">And click Apply.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI';">Select the range of videos to be automatically selected.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI';"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI';">For example, if you set the start to 5 and the end to 20, then all videos between 5-20 will be checked for downloading :)</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI';"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI';">Or select by a range in time:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI';"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI';">For example if you want to download all videos in between 10 and 20 minutes do:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI';"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI';">Start: 10</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI';">End: 20</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI';"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI';">And click Apply.</span></p></body></html>
diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index 17d1f23..925676c 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -41,8 +41,9 @@ def setupUi(self, Porn_Fetch_Widget): self.groupBox_3 = QGroupBox(Porn_Fetch_Widget) self.groupBox_3.setObjectName(u"groupBox_3") self.gridLayout_14 = QGridLayout(self.groupBox_3) + self.gridLayout_14.setSpacing(3) self.gridLayout_14.setObjectName(u"gridLayout_14") - self.gridLayout_14.setContentsMargins(-1, -1, -1, 0) + self.gridLayout_14.setContentsMargins(-1, -1, -1, 3) self.button_switch_settings = QPushButton(self.groupBox_3) self.button_switch_settings.setObjectName(u"button_switch_settings") sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Maximum) @@ -53,7 +54,23 @@ def setupUi(self, Porn_Fetch_Widget): self.button_switch_settings.setMinimumSize(QSize(50, 35)) self.button_switch_settings.setMaximumSize(QSize(16777215, 35)) self.button_switch_settings.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.button_switch_settings.setStyleSheet(u"border: none;") + self.button_switch_settings.setStyleSheet(u"QPushButton {\n" +" background-color: #800080;\n" +" color: white;\n" +" border-radius: 8px;\n" +" border: 3px solid #dda0dd;\n" +" padding: 8px 10px;\n" +"}\n" +"\n" +"QPushButton:hover {\n" +" background-color: #9932cc;\n" +" border: 3px solid #ba55d3;\n" +"}\n" +"\n" +"QPushButton:pressed {\n" +" background-color: #4b0082;\n" +"}\n" +"") self.button_switch_settings.setIconSize(QSize(32, 32)) self.gridLayout_14.addWidget(self.button_switch_settings, 0, 3, 1, 1) @@ -68,7 +85,22 @@ def setupUi(self, Porn_Fetch_Widget): font.setPointSize(9) self.button_switch_tools.setFont(font) self.button_switch_tools.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.button_switch_tools.setStyleSheet(u"border: none") + self.button_switch_tools.setStyleSheet(u"QPushButton {\n" +" background-color: #000000;\n" +" color: #ffffff;\n" +" border-radius: 8px;\n" +" border: 2px solid #ffffff;\n" +" padding: 8px 10px;\n" +"}\n" +"\n" +"QPushButton:hover {\n" +" background-color: #333333;\n" +"}\n" +"\n" +"QPushButton:pressed {\n" +" background-color: #666666;\n" +"}\n" +"") self.button_switch_tools.setIconSize(QSize(32, 32)) self.gridLayout_14.addWidget(self.button_switch_tools, 0, 2, 1, 1) @@ -80,7 +112,23 @@ def setupUi(self, Porn_Fetch_Widget): self.button_switch_home.setMinimumSize(QSize(50, 35)) self.button_switch_home.setMaximumSize(QSize(16777215, 35)) self.button_switch_home.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.button_switch_home.setStyleSheet(u"border: none;") + self.button_switch_home.setStyleSheet(u"QPushButton {\n" +" background-color: #4CAF50;\n" +" color: white;\n" +" border-radius: 8px;\n" +" border: 2px solid #0078d7;\n" +" padding: 8px 10px;\n" +"}\n" +"\n" +"QPushButton:hover {\n" +" background-color: #66BB6A;\n" +" border: 2px solid #005bb5;\n" +"}\n" +"\n" +"QPushButton:pressed {\n" +" background-color: #388E3C;\n" +"}\n" +"") self.button_switch_home.setIconSize(QSize(32, 32)) self.gridLayout_14.addWidget(self.button_switch_home, 0, 0, 1, 1) @@ -92,7 +140,22 @@ def setupUi(self, Porn_Fetch_Widget): self.button_switch_credits.setMinimumSize(QSize(50, 35)) self.button_switch_credits.setMaximumSize(QSize(16777215, 35)) self.button_switch_credits.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.button_switch_credits.setStyleSheet(u"border: none;") + self.button_switch_credits.setStyleSheet(u"QPushButton {\n" +" background-color: #008CBA;\n" +" color: white;\n" +" border-radius: 8px;\n" +" border: none;\n" +" padding: 8px 10px;\n" +"}\n" +"\n" +"QPushButton:hover {\n" +" background-color: #00A3CC;\n" +"}\n" +"\n" +"QPushButton:pressed {\n" +" background-color: #005F8C;\n" +"}\n" +"") self.button_switch_credits.setIconSize(QSize(32, 32)) self.gridLayout_14.addWidget(self.button_switch_credits, 0, 4, 1, 1) @@ -104,7 +167,22 @@ def setupUi(self, Porn_Fetch_Widget): self.button_switch_account.setMinimumSize(QSize(50, 35)) self.button_switch_account.setMaximumSize(QSize(16777215, 35)) self.button_switch_account.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.button_switch_account.setStyleSheet(u"border: none") + self.button_switch_account.setStyleSheet(u"QPushButton {\n" +" background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 #ff7f50, stop:1 #ff4500);\n" +" color: white;\n" +" border-radius: 8px;\n" +" border: none;\n" +" padding: 8px 10px;\n" +"}\n" +"\n" +"QPushButton:hover {\n" +" background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 #ffa07a, stop:1 #ff6347);\n" +"}\n" +"\n" +"QPushButton:pressed {\n" +" background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 #cd5c5c, stop:1 #b22222);\n" +"}\n" +"") self.button_switch_account.setIconSize(QSize(32, 32)) self.gridLayout_14.addWidget(self.button_switch_account, 0, 1, 1, 1) @@ -116,7 +194,22 @@ def setupUi(self, Porn_Fetch_Widget): self.button_view_progress_bars.setMinimumSize(QSize(50, 35)) self.button_view_progress_bars.setMaximumSize(QSize(16777215, 35)) self.button_view_progress_bars.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.button_view_progress_bars.setStyleSheet(u"border: none;") + self.button_view_progress_bars.setStyleSheet(u"QPushButton {\n" +" background-color: #808080;\n" +" color: white;\n" +" border-radius: 8px;\n" +" border: 2px solid #a9a9a9;\n" +" padding: 8px 10px;\n" +"}\n" +"\n" +"QPushButton:hover {\n" +" background-color: #a9a9a9;\n" +"}\n" +"\n" +"QPushButton:pressed {\n" +" background-color: #696969;\n" +"}\n" +"") self.button_view_progress_bars.setIconSize(QSize(32, 32)) self.gridLayout_14.addWidget(self.button_view_progress_bars, 0, 5, 1, 1) @@ -701,7 +794,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_treewidget.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") - self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1606, 449)) + self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1606, 446)) self.gridLayout_4 = QGridLayout(self.scrollAreaWidgetContents_3) self.gridLayout_4.setObjectName(u"gridLayout_4") self.verticallayout_treewidget_settings = QVBoxLayout() @@ -736,35 +829,14 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_16.addWidget(self.radio_tree_show_all, 0, 1, 1, 1) - self.checkbox_tree_do_not_clear_videos = QCheckBox(self.scrollAreaWidgetContents_3) - self.checkbox_tree_do_not_clear_videos.setObjectName(u"checkbox_tree_do_not_clear_videos") - - self.gridLayout_16.addWidget(self.checkbox_tree_do_not_clear_videos, 1, 1, 1, 1) - - self.checkbox_tree_show_videos_reversed = QCheckBox(self.scrollAreaWidgetContents_3) - self.checkbox_tree_show_videos_reversed.setObjectName(u"checkbox_tree_show_videos_reversed") - self.checkbox_tree_show_videos_reversed.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - - self.gridLayout_16.addWidget(self.checkbox_tree_show_videos_reversed, 1, 2, 1, 1) - self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_16.addItem(self.horizontalSpacer, 0, 3, 1, 1) - self.checkbox_tree_allow_sorting = QCheckBox(self.scrollAreaWidgetContents_3) - self.checkbox_tree_allow_sorting.setObjectName(u"checkbox_tree_allow_sorting") - - self.gridLayout_16.addWidget(self.checkbox_tree_allow_sorting, 1, 0, 1, 1) - self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) self.gridLayout_16.addItem(self.horizontalSpacer_2, 1, 3, 1, 1) - self.button_tree_export_video_urls = QPushButton(self.scrollAreaWidgetContents_3) - self.button_tree_export_video_urls.setObjectName(u"button_tree_export_video_urls") - - self.gridLayout_16.addWidget(self.button_tree_export_video_urls, 0, 2, 1, 1) - self.radio_tree_show_title = QRadioButton(self.scrollAreaWidgetContents_3) self.radio_tree_show_title.setObjectName(u"radio_tree_show_title") sizePolicy5.setHeightForWidth(self.radio_tree_show_title.sizePolicy().hasHeightForWidth()) @@ -774,6 +846,22 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_16.addWidget(self.radio_tree_show_title, 0, 0, 1, 1) + self.checkbox_tree_do_not_clear_videos = QCheckBox(self.scrollAreaWidgetContents_3) + self.checkbox_tree_do_not_clear_videos.setObjectName(u"checkbox_tree_do_not_clear_videos") + + self.gridLayout_16.addWidget(self.checkbox_tree_do_not_clear_videos, 1, 0, 1, 1) + + self.checkbox_tree_show_videos_reversed = QCheckBox(self.scrollAreaWidgetContents_3) + self.checkbox_tree_show_videos_reversed.setObjectName(u"checkbox_tree_show_videos_reversed") + self.checkbox_tree_show_videos_reversed.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) + + self.gridLayout_16.addWidget(self.checkbox_tree_show_videos_reversed, 1, 1, 1, 1) + + self.button_tree_export_video_urls = QPushButton(self.scrollAreaWidgetContents_3) + self.button_tree_export_video_urls.setObjectName(u"button_tree_export_video_urls") + + self.gridLayout_16.addWidget(self.button_tree_export_video_urls, 0, 2, 1, 1) + self.gridLayout_4.addLayout(self.gridLayout_16, 1, 0, 1, 1) @@ -1437,11 +1525,10 @@ def retranslateUi(self, Porn_Fetch_Widget): self.radio_tree_show_all.setToolTip("") #endif // QT_CONFIG(tooltip) self.radio_tree_show_all.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Title, Author, Duration", None)) + self.radio_tree_show_title.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Only Title (a lot faster)", None)) self.checkbox_tree_do_not_clear_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Do not clear videos", None)) self.checkbox_tree_show_videos_reversed.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Show videos in reverse", None)) - self.checkbox_tree_allow_sorting.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Allow Sorting", None)) self.button_tree_export_video_urls.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Export video URLs", None)) - self.radio_tree_show_title.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Only Title (a lot faster)", None)) #if QT_CONFIG(tooltip) self.button_tree_stop.setToolTip(QCoreApplication.translate("Porn_Fetch_Widget", u"Does not stop downloading videos", None)) #endif // QT_CONFIG(tooltip) From 4a370dc564c49dc4f6d8c75df8438398c1e3910e Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Thu, 27 Jun 2024 23:26:37 +0200 Subject: [PATCH 12/39] - announcement for xhamster --- README/FAQ.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README/FAQ.md b/README/FAQ.md index f92cf08..b26e908 100644 --- a/README/FAQ.md +++ b/README/FAQ.md @@ -32,7 +32,6 @@ of progress. Since some websites don't use HLS streaming (for good reasons), the make sense to mix them. I don't want to go in too much detail, but it has its reasons. -## Q: Why is macOS only "untested" available? +## Q; Will XHamster be supported? -Because I don't have an Apple device with macOS nor a friend with macOS, so I am not able to run Porn Fetch on it. -I can just give you the compiled binary and hope that it works. \ No newline at end of file +Unfortunately xhamster encrypts its videos, so we can't access the content. \ No newline at end of file From cd3f64645a9b0c19b88ca0304a6a56552ce2b488 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Fri, 28 Jun 2024 22:49:21 +0200 Subject: [PATCH 13/39] - removed pypresence from android requirements --- src/build/requirements_android.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build/requirements_android.txt b/src/build/requirements_android.txt index 34f1cca..02fb866 100644 --- a/src/build/requirements_android.txt +++ b/src/build/requirements_android.txt @@ -19,4 +19,4 @@ Those are the requirements. Add them to buildozer. DO NOT CHANGE VERSION NUMBERS The wheels I am using can be found here: https://github.com/EchterAlsFake/PySide6-to-Android/releases/1.0 -,charset-normalizer==2.1.1,git+https://github.com/EchterAlsFake/PHUB,idna,urllib3,certifi,hue_shift,markdown,colorama,requests,git+https://github.com/EchterAlsFake/hqporner_api,ffmpeg-progress-yield,tqdm,git+https://github.com/EchterAlsFake/eporner_api,git+https://github.com/EchterAlsFake/xnxx_api,git+https://github.com/EchterAlsFake/xvideos_api,beautifulsoup4,mutagen,git+https://github.com/EchterAlsFake/eaf_base_api,pypresence \ No newline at end of file +,charset-normalizer==2.1.1,git+https://github.com/EchterAlsFake/PHUB,idna,urllib3,certifi,hue_shift,markdown,colorama,requests,git+https://github.com/EchterAlsFake/hqporner_api,ffmpeg-progress-yield,tqdm,git+https://github.com/EchterAlsFake/eporner_api,git+https://github.com/EchterAlsFake/xnxx_api,git+https://github.com/EchterAlsFake/xvideos_api,beautifulsoup4,mutagen,git+https://github.com/EchterAlsFake/eaf_base_api \ No newline at end of file From 7dfa03eb5c9d82d2b10b57646155efd343731cac Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Sun, 30 Jun 2024 04:14:34 +0200 Subject: [PATCH 14/39] - fixed top bar button icon size --- main.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index e33610b..d8c967e 100644 --- a/main.py +++ b/main.py @@ -25,7 +25,7 @@ from src.frontend.range_selector import Ui_Form from PySide6.QtCore import (QFile, QTextStream, Signal, QRunnable, QThreadPool, QObject, QSemaphore, Qt, QLocale, - QTranslator, QCoreApplication) + QTranslator, QCoreApplication, QSize) from PySide6.QtWidgets import QWidget, QApplication, QInputDialog, QTreeWidgetItem, QButtonGroup, QFileDialog from PySide6.QtGui import QIcon, QFont @@ -807,6 +807,10 @@ def load_style(self): self.ui.button_view_progress_bars: "progressbars.svg" } for button, icon_name in icons.items(): + if icon_name == "settings.svg" or icon_name == "tools.svg": + button.setIcon(QIcon(f":/images/graphics/{icon_name}"),) + button.setIconSize(QSize(24, 24)) + button.setIcon(QIcon(f":/images/graphics/{icon_name}")) self.setWindowIcon(QIcon(":/images/graphics/logo_transparent.ico")) From f78b1ec76b77e4f0bcc477a5c7764cadea4bc0ea Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Sun, 30 Jun 2024 04:34:27 +0200 Subject: [PATCH 15/39] - correctly renamed some widgets - fixed the top widget height when using porn hub login - removed the api language entirely - applied changes to config file checking process --- main.py | 35 ++++--- src/backend/shared_functions.py | 9 +- src/frontend/form_desktop.ui | 38 +++---- src/frontend/ui_form_desktop.py | 180 ++++++++++++++++---------------- 4 files changed, 132 insertions(+), 130 deletions(-) diff --git a/main.py b/main.py index d8c967e..f2cbd12 100644 --- a/main.py +++ b/main.py @@ -69,6 +69,7 @@ ffmpeg_windows = "ffmpeg-7.0-essentials_build" android_arch = None session_urls = [] # This list saves all URls used in the current session. Used for the URL export function +total_downloaded_videos = 0 class Signals(QObject): @@ -478,11 +479,10 @@ class VideoLoaderSignals(QObject): class VideoLoader(QRunnable): - def __init__(self, url, output_path, api_language, threading_mode, directory_system, quality, delay): + def __init__(self, url, output_path, threading_mode, directory_system, quality, delay): super(VideoLoader, self).__init__() self.url = url self.output_path = output_path - self.api_language = api_language self.threading_mode = threading_mode self.directory_system = directory_system self.quality = quality @@ -491,7 +491,7 @@ def __init__(self, url, output_path, api_language, threading_mode, directory_sys def run(self): try: - video = check_video(self.url, language=self.api_language, delay=self.delay) + video = check_video(self.url, delay=self.delay) if video is False: ui_popup(invalid_input_string) @@ -598,11 +598,10 @@ class AddUrls(QRunnable): all URLs / Models / Search terms have been processed. This is why I made this threading class """ - def __init__(self, file, api_language, delay): + def __init__(self, file, delay): super(AddUrls, self).__init__() self.signals = Signals() self.file = file - self.api_language = api_language self.delay = delay def run(self): @@ -632,7 +631,7 @@ def run(self): "query": query}) else: - video = check_video(line, language=self.api_language, delay=self.delay) + video = check_video(line, delay=self.delay) if video is not False: iterator.append(video) @@ -661,7 +660,6 @@ def __init__(self, parent=None): self.threading_map = None self.quality_map = None self.client = None - self.api_language = "en" self.delay = None self.search_limit = None self.semaphore_limit = None @@ -678,6 +676,7 @@ def __init__(self, parent=None): self.ui = Ui_Porn_Fetch_Widget() self.ui.setupUi(self) + self.default_max_height = self.ui.stacked_widget_top.maximumHeight() self.button_connectors() # Connects the buttons to their functions self.button_groups() # Groups the buttons, so that the Radio buttons are split from themselves (hard to explain) self.load_style() # Loads all the User Interface stylesheets @@ -931,7 +930,6 @@ def load_user_settings(self): self.gui_language = self.conf.get("UI", "language") self.quality = self.conf["Video"]["quality"] self.threading_mode = self.conf["Performance"]["threading_mode"] - self.api_language = self.conf["Video"]["language"] self.semaphore = QSemaphore(int(self.semaphore_limit)) self.delay = int(self.conf["Video"]["delay"]) self.timeout = int(self.conf["Performance"]["timeout"]) @@ -945,7 +943,7 @@ def load_user_settings(self): bs_consts.REQUEST_DELAY = self.delay bs_consts.MAX_RETRIES = self.max_retries consts.FFMPEG_EXECUTABLE = ffmpeg_path - self.client = Client(delay=self.delay, language=self.api_language) + self.client = Client(delay=self.delay) def save_user_settings(self): """Saves the user settings to the configuration file based on the UI state.""" @@ -1078,14 +1076,17 @@ def configure_ui_for_android(self, path): def switch_to_home(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(0) + self.ui.stacked_widget_top.setMaximumHeight(self.default_max_height) def switch_to_account(self): self.ui.stacked_widget_top.setCurrentIndex(1) self.ui.stacked_widget_main.setCurrentIndex(0) + self.ui.stacked_widget_top.setMaximumHeight(140) def switch_to_tools(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(3) + self.ui.stacked_widget_top.setMaximumHeight(self.default_max_height) def switch_to_settings(self): self.ui.stacked_widget_main.setCurrentIndex(1) @@ -1098,6 +1099,7 @@ def switch_to_supported_websites(self): self.ui.stacked_widget_main.setCurrentIndex(3) def switch_to_all_progress_bars(self): + self.ui.stacked_widget_top.setMaximumHeight(self.default_max_height) self.ui.stacked_widget_top.setCurrentIndex(2) self.ui.stacked_widget_main.setCurrentIndex(0) @@ -1296,10 +1298,9 @@ def start_single_video(self): implemented this feature into the tree widget and I don't want to write code 2 times """ url = self.ui.lineedit_url.text() - api_language = self.api_language one_time_iterator = [] - video = check_video(url=url, language=api_language, delay=self.delay) + video = check_video(url=url, delay=self.delay) if video is False: # If a video url is invalid, check_video will return it as False ui_popup(invalid_input_string) @@ -1318,9 +1319,8 @@ def start_model(self, url=None): search_limit = self.search_limit if pornhub_pattern.match(model): - api_language = self.api_language if not isinstance(self.client, Client): - client = Client(language=api_language, delay=self.delay) + client = Client(delay=self.delay) else: client = self.client @@ -1352,7 +1352,7 @@ def start_playlist(self): def load_video(self, url): """This starts the thread to load a video""" - video_loader = VideoLoader(url, self.output_path, self.api_language, self.threading_mode, self.directory_system, + video_loader = VideoLoader(url, self.output_path, self.threading_mode, self.directory_system, self.quality, delay=self.delay) # Connect signals to your slots @@ -1435,6 +1435,9 @@ def update_progressbar_xvideos(self, value, maximum): def download_completed(self): """If a video is downloaded, the semaphore is released""" logger_debug("Download Completed!") + global total_downloaded_videos + total_downloaded_videos += 1 + self.ui.lineedit_download_info.setText(f"Downloaded: {total_downloaded_videos} video(s) this session.") self.ui.progressbar_total.setMaximum(100) self.semaphore.release() @@ -1469,7 +1472,7 @@ def open_file_dialog(self): def start_it(self): file = self.ui.lineedit_file.text() - self.url_thread = AddUrls(file, api_language=self.api_language, delay=self.delay) + self.url_thread = AddUrls(file, delay=self.delay) self.url_thread.signals.total_progress.connect(self.update_total_progressbar) self.url_thread.signals.url_iterators.connect(self.receive_url_result) self.threadpool.start(self.url_thread) @@ -1527,7 +1530,7 @@ def login(self): return try: - self.client = Client(username, password, language=self.api_language, delay=self.delay) + self.client = Client(username, password, delay=self.delay) logger_debug("Login Successful!") ui_popup(QCoreApplication.tr(self, "Login Successful!", None)) self.switch_login_button_state() diff --git a/src/backend/shared_functions.py b/src/backend/shared_functions.py index db1590c..8c37e78 100644 --- a/src/backend/shared_functions.py +++ b/src/backend/shared_functions.py @@ -30,9 +30,9 @@ sections = ["Performance", "License", "Video", "UI"] options_performance = ["semaphore", "threading_mode", "workers", "timeout", "retries", "ffmpeg_warning"] -options_video = ["quality", "language", "output_path", "directory_system", "search_limit", "delay"] +options_video = ["quality", "output_path", "directory_system", "search_limit", "delay"] options_license = ["accepted"] -options_ui = ["language", "discord"] +options_ui = ["language"] pornhub_pattern = re.compile(r'(.*?)pornhub(.*)') # can also be .org hqporner_pattern = re.compile(r'(.*?)hqporner.com(.*)') @@ -88,8 +88,7 @@ def logger_debug(e): print(f"{datetime.now()} : {Fore.LIGHTCYAN_EX}[DEBUG] : {return_color()} : {e} {reset()}") -def check_video(url, language, is_url=True, delay=False): - +def check_video(url, is_url=True, delay=False): if is_url: if hqporner_pattern.search(str(url)): @@ -122,7 +121,7 @@ def check_video(url, language, is_url=True, delay=False): elif isinstance(url, str) and not str(url).endswith(".html"): try: - video = Client(language=language, delay=delay).get(url) + video = Client(delay=delay).get(url) video.fetch("page@") return video diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 4c6e22d..36038cb 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -27,12 +27,12 @@ - + 0 - + Porn Fetch Menu @@ -374,7 +374,7 @@ QPushButton:pressed { 1 - 0 + 1 @@ -416,7 +416,7 @@ QPushButton:pressed { 1 - 0 + 3 @@ -638,7 +638,7 @@ QPushButton:pressed { - + Qt::Horizontal @@ -1014,8 +1014,8 @@ QPushButton:pressed { 0 0 - 387 - 206 + 1606 + 257 @@ -1114,7 +1114,7 @@ QPushButton:pressed { - + Qt::Vertical @@ -1254,13 +1254,13 @@ QPushButton:pressed { - + HQPorner - + @@ -1538,7 +1538,7 @@ QPushButton:pressed { - + @@ -1568,7 +1568,7 @@ QPushButton:pressed { - + Qt::Horizontal @@ -1581,7 +1581,7 @@ QPushButton:pressed { - + Qt::Horizontal @@ -1629,7 +1629,7 @@ QPushButton:pressed { - + Export video URLs @@ -1643,7 +1643,7 @@ QPushButton:pressed { - + @@ -1780,8 +1780,8 @@ QPushButton:pressed { 0 0 - 721 - 575 + 1608 + 787 @@ -1982,7 +1982,7 @@ QPushButton:pressed { - + @@ -2140,7 +2140,7 @@ QPushButton:pressed { - + diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index 925676c..bc0d08a 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -35,16 +35,16 @@ def setupUi(self, Porn_Fetch_Widget): Porn_Fetch_Widget.setMinimumSize(QSize(100, 50)) self.gridLayout_3 = QGridLayout(Porn_Fetch_Widget) self.gridLayout_3.setObjectName(u"gridLayout_3") - self.gridLayout_13 = QGridLayout() - self.gridLayout_13.setObjectName(u"gridLayout_13") - self.gridLayout_13.setContentsMargins(-1, -1, -1, 0) - self.groupBox_3 = QGroupBox(Porn_Fetch_Widget) - self.groupBox_3.setObjectName(u"groupBox_3") - self.gridLayout_14 = QGridLayout(self.groupBox_3) + self.gridlayout_main = QGridLayout() + self.gridlayout_main.setObjectName(u"gridlayout_main") + self.gridlayout_main.setContentsMargins(-1, -1, -1, 0) + self.groupbox_top_bar = QGroupBox(Porn_Fetch_Widget) + self.groupbox_top_bar.setObjectName(u"groupbox_top_bar") + self.gridLayout_14 = QGridLayout(self.groupbox_top_bar) self.gridLayout_14.setSpacing(3) self.gridLayout_14.setObjectName(u"gridLayout_14") self.gridLayout_14.setContentsMargins(-1, -1, -1, 3) - self.button_switch_settings = QPushButton(self.groupBox_3) + self.button_switch_settings = QPushButton(self.groupbox_top_bar) self.button_switch_settings.setObjectName(u"button_switch_settings") sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Maximum) sizePolicy1.setHorizontalStretch(0) @@ -75,7 +75,7 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_14.addWidget(self.button_switch_settings, 0, 3, 1, 1) - self.button_switch_tools = QPushButton(self.groupBox_3) + self.button_switch_tools = QPushButton(self.groupbox_top_bar) self.button_switch_tools.setObjectName(u"button_switch_tools") sizePolicy1.setHeightForWidth(self.button_switch_tools.sizePolicy().hasHeightForWidth()) self.button_switch_tools.setSizePolicy(sizePolicy1) @@ -105,7 +105,7 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_14.addWidget(self.button_switch_tools, 0, 2, 1, 1) - self.button_switch_home = QPushButton(self.groupBox_3) + self.button_switch_home = QPushButton(self.groupbox_top_bar) self.button_switch_home.setObjectName(u"button_switch_home") sizePolicy1.setHeightForWidth(self.button_switch_home.sizePolicy().hasHeightForWidth()) self.button_switch_home.setSizePolicy(sizePolicy1) @@ -133,7 +133,7 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_14.addWidget(self.button_switch_home, 0, 0, 1, 1) - self.button_switch_credits = QPushButton(self.groupBox_3) + self.button_switch_credits = QPushButton(self.groupbox_top_bar) self.button_switch_credits.setObjectName(u"button_switch_credits") sizePolicy1.setHeightForWidth(self.button_switch_credits.sizePolicy().hasHeightForWidth()) self.button_switch_credits.setSizePolicy(sizePolicy1) @@ -160,7 +160,7 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_14.addWidget(self.button_switch_credits, 0, 4, 1, 1) - self.button_switch_account = QPushButton(self.groupBox_3) + self.button_switch_account = QPushButton(self.groupbox_top_bar) self.button_switch_account.setObjectName(u"button_switch_account") sizePolicy1.setHeightForWidth(self.button_switch_account.sizePolicy().hasHeightForWidth()) self.button_switch_account.setSizePolicy(sizePolicy1) @@ -187,7 +187,7 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_14.addWidget(self.button_switch_account, 0, 1, 1, 1) - self.button_view_progress_bars = QPushButton(self.groupBox_3) + self.button_view_progress_bars = QPushButton(self.groupbox_top_bar) self.button_view_progress_bars.setObjectName(u"button_view_progress_bars") sizePolicy1.setHeightForWidth(self.button_view_progress_bars.sizePolicy().hasHeightForWidth()) self.button_view_progress_bars.setSizePolicy(sizePolicy1) @@ -215,7 +215,7 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_14.addWidget(self.button_view_progress_bars, 0, 5, 1, 1) - self.gridLayout_13.addWidget(self.groupBox_3, 0, 0, 1, 1) + self.gridlayout_main.addWidget(self.groupbox_top_bar, 0, 0, 1, 1) self.stacked_widget_main = QStackedWidget(Porn_Fetch_Widget) self.stacked_widget_main.setObjectName(u"stacked_widget_main") @@ -349,9 +349,9 @@ def setupUi(self, Porn_Fetch_Widget): self.horizontallayout_searching_websites.addWidget(self.radio_search_website_xnxx) - self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + self.horizontalspacer_search = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) - self.horizontallayout_searching_websites.addItem(self.horizontalSpacer_3) + self.horizontallayout_searching_websites.addItem(self.horizontalspacer_search) self.button_switch_supported_websites = QPushButton(self.page_download) self.button_switch_supported_websites.setObjectName(u"button_switch_supported_websites") @@ -527,7 +527,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 387, 206)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1606, 257)) self.gridLayout_18 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_18.setObjectName(u"gridLayout_18") self.gridlayout_progressbar = QGridLayout() @@ -586,9 +586,9 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_progressbar.addWidget(self.progressbar_pornhub, 0, 1, 1, 1) - self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) + self.verticalspacer_progress_bars = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) - self.gridlayout_progressbar.addItem(self.verticalSpacer_2, 6, 1, 1, 1) + self.gridlayout_progressbar.addItem(self.verticalspacer_progress_bars, 6, 1, 1, 1) self.progressbar_eporner = QProgressBar(self.scrollAreaWidgetContents) self.progressbar_eporner.setObjectName(u"progressbar_eporner") @@ -674,79 +674,79 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_29.addWidget(self.groupBox_2, 1, 1, 1, 1) - self.groupBox = QGroupBox(self.page_tools) - self.groupBox.setObjectName(u"groupBox") - self.gridLayout_7 = QGridLayout(self.groupBox) + self.groupbox_tools = QGroupBox(self.page_tools) + self.groupbox_tools.setObjectName(u"groupbox_tools") + self.gridLayout_7 = QGridLayout(self.groupbox_tools) self.gridLayout_7.setObjectName(u"gridLayout_7") - self.gridLayout = QGridLayout() - self.gridLayout.setObjectName(u"gridLayout") - self.radio_top_porn_month = QRadioButton(self.groupBox) + self.gridlayout_tools_hqporner = QGridLayout() + self.gridlayout_tools_hqporner.setObjectName(u"gridlayout_tools_hqporner") + self.radio_top_porn_month = QRadioButton(self.groupbox_tools) self.radio_top_porn_month.setObjectName(u"radio_top_porn_month") self.radio_top_porn_month.setMinimumSize(QSize(0, 10)) self.radio_top_porn_month.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridLayout.addWidget(self.radio_top_porn_month, 0, 2, 1, 1) + self.gridlayout_tools_hqporner.addWidget(self.radio_top_porn_month, 0, 2, 1, 1) - self.button_top_porn_get_videos = QPushButton(self.groupBox) + self.button_top_porn_get_videos = QPushButton(self.groupbox_tools) self.button_top_porn_get_videos.setObjectName(u"button_top_porn_get_videos") self.button_top_porn_get_videos.setMinimumSize(QSize(0, 10)) self.button_top_porn_get_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridLayout.addWidget(self.button_top_porn_get_videos, 0, 4, 1, 1) + self.gridlayout_tools_hqporner.addWidget(self.button_top_porn_get_videos, 0, 4, 1, 1) - self.label_get_brazzers_videos = QLabel(self.groupBox) + self.label_get_brazzers_videos = QLabel(self.groupbox_tools) self.label_get_brazzers_videos.setObjectName(u"label_get_brazzers_videos") self.label_get_brazzers_videos.setMinimumSize(QSize(0, 4)) - self.gridLayout.addWidget(self.label_get_brazzers_videos, 3, 0, 1, 4) + self.gridlayout_tools_hqporner.addWidget(self.label_get_brazzers_videos, 3, 0, 1, 4) - self.radio_top_porn_week = QRadioButton(self.groupBox) + self.radio_top_porn_week = QRadioButton(self.groupbox_tools) self.radio_top_porn_week.setObjectName(u"radio_top_porn_week") self.radio_top_porn_week.setMinimumSize(QSize(0, 10)) self.radio_top_porn_week.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.radio_top_porn_week.setChecked(True) - self.gridLayout.addWidget(self.radio_top_porn_week, 0, 1, 1, 1) + self.gridlayout_tools_hqporner.addWidget(self.radio_top_porn_week, 0, 1, 1, 1) - self.button_list_categories = QPushButton(self.groupBox) + self.button_list_categories = QPushButton(self.groupbox_tools) self.button_list_categories.setObjectName(u"button_list_categories") sizePolicy3.setHeightForWidth(self.button_list_categories.sizePolicy().hasHeightForWidth()) self.button_list_categories.setSizePolicy(sizePolicy3) self.button_list_categories.setMinimumSize(QSize(0, 2)) self.button_list_categories.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridLayout.addWidget(self.button_list_categories, 1, 4, 1, 1) + self.gridlayout_tools_hqporner.addWidget(self.button_list_categories, 1, 4, 1, 1) - self.lineedit_hqporner_category = QLineEdit(self.groupBox) + self.lineedit_hqporner_category = QLineEdit(self.groupbox_tools) self.lineedit_hqporner_category.setObjectName(u"lineedit_hqporner_category") sizePolicy7.setHeightForWidth(self.lineedit_hqporner_category.sizePolicy().hasHeightForWidth()) self.lineedit_hqporner_category.setSizePolicy(sizePolicy7) self.lineedit_hqporner_category.setMinimumSize(QSize(100, 4)) - self.gridLayout.addWidget(self.lineedit_hqporner_category, 1, 1, 1, 2) + self.gridlayout_tools_hqporner.addWidget(self.lineedit_hqporner_category, 1, 1, 1, 2) - self.label_get_top_porn = QLabel(self.groupBox) + self.label_get_top_porn = QLabel(self.groupbox_tools) self.label_get_top_porn.setObjectName(u"label_get_top_porn") - self.gridLayout.addWidget(self.label_get_top_porn, 0, 0, 1, 1) + self.gridlayout_tools_hqporner.addWidget(self.label_get_top_porn, 0, 0, 1, 1) - self.radio_top_porn_all_time = QRadioButton(self.groupBox) + self.radio_top_porn_all_time = QRadioButton(self.groupbox_tools) self.radio_top_porn_all_time.setObjectName(u"radio_top_porn_all_time") self.radio_top_porn_all_time.setMinimumSize(QSize(0, 10)) self.radio_top_porn_all_time.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridLayout.addWidget(self.radio_top_porn_all_time, 0, 3, 1, 1) + self.gridlayout_tools_hqporner.addWidget(self.radio_top_porn_all_time, 0, 3, 1, 1) - self.button_hqporner_category_get_videos = QPushButton(self.groupBox) + self.button_hqporner_category_get_videos = QPushButton(self.groupbox_tools) self.button_hqporner_category_get_videos.setObjectName(u"button_hqporner_category_get_videos") sizePolicy8.setHeightForWidth(self.button_hqporner_category_get_videos.sizePolicy().hasHeightForWidth()) self.button_hqporner_category_get_videos.setSizePolicy(sizePolicy8) self.button_hqporner_category_get_videos.setMinimumSize(QSize(0, 2)) self.button_hqporner_category_get_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridLayout.addWidget(self.button_hqporner_category_get_videos, 1, 3, 1, 1) + self.gridlayout_tools_hqporner.addWidget(self.button_hqporner_category_get_videos, 1, 3, 1, 1) - self.button_get_random_videos = QPushButton(self.groupBox) + self.button_get_random_videos = QPushButton(self.groupbox_tools) self.button_get_random_videos.setObjectName(u"button_get_random_videos") sizePolicy9 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed) sizePolicy9.setHorizontalStretch(0) @@ -756,34 +756,34 @@ def setupUi(self, Porn_Fetch_Widget): self.button_get_random_videos.setMinimumSize(QSize(0, 10)) self.button_get_random_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridLayout.addWidget(self.button_get_random_videos, 2, 4, 1, 1) + self.gridlayout_tools_hqporner.addWidget(self.button_get_random_videos, 2, 4, 1, 1) - self.button_get_brazzers_videos = QPushButton(self.groupBox) + self.button_get_brazzers_videos = QPushButton(self.groupbox_tools) self.button_get_brazzers_videos.setObjectName(u"button_get_brazzers_videos") sizePolicy9.setHeightForWidth(self.button_get_brazzers_videos.sizePolicy().hasHeightForWidth()) self.button_get_brazzers_videos.setSizePolicy(sizePolicy9) self.button_get_brazzers_videos.setMinimumSize(QSize(0, 10)) self.button_get_brazzers_videos.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridLayout.addWidget(self.button_get_brazzers_videos, 3, 4, 1, 1) + self.gridlayout_tools_hqporner.addWidget(self.button_get_brazzers_videos, 3, 4, 1, 1) - self.labe_get_random_video = QLabel(self.groupBox) + self.labe_get_random_video = QLabel(self.groupbox_tools) self.labe_get_random_video.setObjectName(u"labe_get_random_video") self.labe_get_random_video.setMinimumSize(QSize(0, 4)) - self.gridLayout.addWidget(self.labe_get_random_video, 2, 0, 1, 4) + self.gridlayout_tools_hqporner.addWidget(self.labe_get_random_video, 2, 0, 1, 4) - self.label_videos_by_category = QLabel(self.groupBox) + self.label_videos_by_category = QLabel(self.groupbox_tools) self.label_videos_by_category.setObjectName(u"label_videos_by_category") self.label_videos_by_category.setMinimumSize(QSize(0, 4)) - self.gridLayout.addWidget(self.label_videos_by_category, 1, 0, 1, 1) + self.gridlayout_tools_hqporner.addWidget(self.label_videos_by_category, 1, 0, 1, 1) - self.gridLayout_7.addLayout(self.gridLayout, 0, 0, 1, 1) + self.gridLayout_7.addLayout(self.gridlayout_tools_hqporner, 0, 0, 1, 1) - self.gridLayout_29.addWidget(self.groupBox, 0, 1, 1, 1) + self.gridLayout_29.addWidget(self.groupbox_tools, 0, 1, 1, 1) self.stacked_widget_top.addWidget(self.page_tools) @@ -816,8 +816,8 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_4.addLayout(self.verticallayout_treewidget_settings, 2, 0, 1, 1) - self.gridLayout_16 = QGridLayout() - self.gridLayout_16.setObjectName(u"gridLayout_16") + self.gridlayout_tree_settings = QGridLayout() + self.gridlayout_tree_settings.setObjectName(u"gridlayout_tree_settings") self.radio_tree_show_all = QRadioButton(self.scrollAreaWidgetContents_3) self.radio_tree_show_all.setObjectName(u"radio_tree_show_all") sizePolicy5.setHeightForWidth(self.radio_tree_show_all.sizePolicy().hasHeightForWidth()) @@ -827,15 +827,15 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_tree_show_all.setCheckable(True) self.radio_tree_show_all.setChecked(False) - self.gridLayout_16.addWidget(self.radio_tree_show_all, 0, 1, 1, 1) + self.gridlayout_tree_settings.addWidget(self.radio_tree_show_all, 0, 1, 1, 1) - self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + self.horizontalspacer_tree_1 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) - self.gridLayout_16.addItem(self.horizontalSpacer, 0, 3, 1, 1) + self.gridlayout_tree_settings.addItem(self.horizontalspacer_tree_1, 0, 3, 1, 1) - self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + self.horizontalspacer_tree_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) - self.gridLayout_16.addItem(self.horizontalSpacer_2, 1, 3, 1, 1) + self.gridlayout_tree_settings.addItem(self.horizontalspacer_tree_2, 1, 3, 1, 1) self.radio_tree_show_title = QRadioButton(self.scrollAreaWidgetContents_3) self.radio_tree_show_title.setObjectName(u"radio_tree_show_title") @@ -844,40 +844,40 @@ def setupUi(self, Porn_Fetch_Widget): self.radio_tree_show_title.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.radio_tree_show_title.setChecked(True) - self.gridLayout_16.addWidget(self.radio_tree_show_title, 0, 0, 1, 1) + self.gridlayout_tree_settings.addWidget(self.radio_tree_show_title, 0, 0, 1, 1) self.checkbox_tree_do_not_clear_videos = QCheckBox(self.scrollAreaWidgetContents_3) self.checkbox_tree_do_not_clear_videos.setObjectName(u"checkbox_tree_do_not_clear_videos") - self.gridLayout_16.addWidget(self.checkbox_tree_do_not_clear_videos, 1, 0, 1, 1) + self.gridlayout_tree_settings.addWidget(self.checkbox_tree_do_not_clear_videos, 1, 0, 1, 1) self.checkbox_tree_show_videos_reversed = QCheckBox(self.scrollAreaWidgetContents_3) self.checkbox_tree_show_videos_reversed.setObjectName(u"checkbox_tree_show_videos_reversed") self.checkbox_tree_show_videos_reversed.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.gridLayout_16.addWidget(self.checkbox_tree_show_videos_reversed, 1, 1, 1, 1) + self.gridlayout_tree_settings.addWidget(self.checkbox_tree_show_videos_reversed, 1, 1, 1, 1) self.button_tree_export_video_urls = QPushButton(self.scrollAreaWidgetContents_3) self.button_tree_export_video_urls.setObjectName(u"button_tree_export_video_urls") - self.gridLayout_16.addWidget(self.button_tree_export_video_urls, 0, 2, 1, 1) + self.gridlayout_tree_settings.addWidget(self.button_tree_export_video_urls, 1, 2, 1, 1) - self.gridLayout_4.addLayout(self.gridLayout_16, 1, 0, 1, 1) + self.gridLayout_4.addLayout(self.gridlayout_tree_settings, 1, 0, 1, 1) self.scrollarea_treewidget.setWidget(self.scrollAreaWidgetContents_3) self.verticallayout_treewidget.addWidget(self.scrollarea_treewidget) - self.gridLayout_17 = QGridLayout() - self.gridLayout_17.setObjectName(u"gridLayout_17") + self.gridlayout_tree_buttons = QGridLayout() + self.gridlayout_tree_buttons.setObjectName(u"gridlayout_tree_buttons") self.button_tree_stop = QPushButton(self.widget) self.button_tree_stop.setObjectName(u"button_tree_stop") sizePolicy1.setHeightForWidth(self.button_tree_stop.sizePolicy().hasHeightForWidth()) self.button_tree_stop.setSizePolicy(sizePolicy1) self.button_tree_stop.setMinimumSize(QSize(0, 30)) - self.gridLayout_17.addWidget(self.button_tree_stop, 1, 2, 1, 1) + self.gridlayout_tree_buttons.addWidget(self.button_tree_stop, 1, 2, 1, 1) self.button_tree_select_range = QPushButton(self.widget) self.button_tree_select_range.setObjectName(u"button_tree_select_range") @@ -887,7 +887,7 @@ def setupUi(self, Porn_Fetch_Widget): self.button_tree_select_range.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_tree_select_range.setStyleSheet(u"") - self.gridLayout_17.addWidget(self.button_tree_select_range, 1, 0, 1, 1) + self.gridlayout_tree_buttons.addWidget(self.button_tree_select_range, 1, 0, 1, 1) self.button_tree_unselect_all = QPushButton(self.widget) self.button_tree_unselect_all.setObjectName(u"button_tree_unselect_all") @@ -897,7 +897,7 @@ def setupUi(self, Porn_Fetch_Widget): self.button_tree_unselect_all.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_tree_unselect_all.setStyleSheet(u"") - self.gridLayout_17.addWidget(self.button_tree_unselect_all, 1, 1, 1, 1) + self.gridlayout_tree_buttons.addWidget(self.button_tree_unselect_all, 1, 1, 1, 1) self.button_tree_download = QPushButton(self.widget) self.button_tree_download.setObjectName(u"button_tree_download") @@ -907,10 +907,10 @@ def setupUi(self, Porn_Fetch_Widget): self.button_tree_download.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button_tree_download.setStyleSheet(u"") - self.gridLayout_17.addWidget(self.button_tree_download, 0, 0, 1, 3) + self.gridlayout_tree_buttons.addWidget(self.button_tree_download, 0, 0, 1, 3) - self.verticallayout_treewidget.addLayout(self.gridLayout_17) + self.verticallayout_treewidget.addLayout(self.gridlayout_tree_buttons) self.gridLayout_8.addLayout(self.verticallayout_treewidget, 0, 0, 1, 1) @@ -927,7 +927,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_settings.setWidgetResizable(True) self.scrollAreaWidgetContents_6 = QWidget() self.scrollAreaWidgetContents_6.setObjectName(u"scrollAreaWidgetContents_6") - self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 721, 575)) + self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 1608, 787)) self.gridLayout_19 = QGridLayout(self.scrollAreaWidgetContents_6) self.gridLayout_19.setObjectName(u"gridLayout_19") self.button_download_ffmpeg = QPushButton(self.scrollAreaWidgetContents_6) @@ -1069,28 +1069,28 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_9.addLayout(self.horizontallayout_maximal_timeout, 5, 0, 1, 1) - self.horizontalLayout_2 = QHBoxLayout() - self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") + self.horizontallayout_maximal_retries = QHBoxLayout() + self.horizontallayout_maximal_retries.setObjectName(u"horizontallayout_maximal_retries") self.label_maximal_retries = QLabel(self.groupbox_performance) self.label_maximal_retries.setObjectName(u"label_maximal_retries") - self.horizontalLayout_2.addWidget(self.label_maximal_retries) + self.horizontallayout_maximal_retries.addWidget(self.label_maximal_retries) self.spinbox_maximal_retries = QSpinBox(self.groupbox_performance) self.spinbox_maximal_retries.setObjectName(u"spinbox_maximal_retries") self.spinbox_maximal_retries.setMinimum(5) self.spinbox_maximal_retries.setMaximum(5000) - self.horizontalLayout_2.addWidget(self.spinbox_maximal_retries) + self.horizontallayout_maximal_retries.addWidget(self.spinbox_maximal_retries) self.button_timeout_maximal_retries_help = QPushButton(self.groupbox_performance) self.button_timeout_maximal_retries_help.setObjectName(u"button_timeout_maximal_retries_help") self.button_timeout_maximal_retries_help.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.horizontalLayout_2.addWidget(self.button_timeout_maximal_retries_help) + self.horizontallayout_maximal_retries.addWidget(self.button_timeout_maximal_retries_help) - self.gridLayout_9.addLayout(self.horizontalLayout_2, 6, 0, 1, 1) + self.gridLayout_9.addLayout(self.horizontallayout_maximal_retries, 6, 0, 1, 1) self.gridlayout_settings.addWidget(self.groupbox_performance, 0, 0, 1, 1) @@ -1181,28 +1181,28 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_10.addLayout(self.horizontallayout_quality, 0, 0, 1, 1) - self.horizontalLayout_9 = QHBoxLayout() - self.horizontalLayout_9.setObjectName(u"horizontalLayout_9") + self.horizontallayout_result_limit = QHBoxLayout() + self.horizontallayout_result_limit.setObjectName(u"horizontallayout_result_limit") self.label_searching_limit = QLabel(self.groupbox_videos) self.label_searching_limit.setObjectName(u"label_searching_limit") - self.horizontalLayout_9.addWidget(self.label_searching_limit) + self.horizontallayout_result_limit.addWidget(self.label_searching_limit) self.spinbox_treewidget_limit = QSpinBox(self.groupbox_videos) self.spinbox_treewidget_limit.setObjectName(u"spinbox_treewidget_limit") self.spinbox_treewidget_limit.setMinimum(1) self.spinbox_treewidget_limit.setMaximum(5000) - self.horizontalLayout_9.addWidget(self.spinbox_treewidget_limit) + self.horizontallayout_result_limit.addWidget(self.spinbox_treewidget_limit) self.button_result_limit_help = QPushButton(self.groupbox_videos) self.button_result_limit_help.setObjectName(u"button_result_limit_help") self.button_result_limit_help.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) - self.horizontalLayout_9.addWidget(self.button_result_limit_help) + self.horizontallayout_result_limit.addWidget(self.button_result_limit_help) - self.gridLayout_10.addLayout(self.horizontalLayout_9, 3, 0, 1, 1) + self.gridLayout_10.addLayout(self.horizontallayout_result_limit, 3, 0, 1, 1) self.gridLayout_19.addWidget(self.groupbox_videos, 2, 0, 1, 1) @@ -1325,7 +1325,7 @@ def setupUi(self, Porn_Fetch_Widget): self.stacked_widget_main.addWidget(self.page_supported_websites) - self.gridLayout_13.addWidget(self.stacked_widget_main, 2, 0, 1, 1) + self.gridlayout_main.addWidget(self.stacked_widget_main, 2, 0, 1, 1) self.gridlayout_status = QGridLayout() self.gridlayout_status.setSpacing(0) @@ -1365,10 +1365,10 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_status.addWidget(self.progressbar_total, 2, 1, 1, 1) - self.gridLayout_13.addLayout(self.gridlayout_status, 3, 0, 1, 1) + self.gridlayout_main.addLayout(self.gridlayout_status, 3, 0, 1, 1) - self.gridLayout_3.addLayout(self.gridLayout_13, 0, 0, 1, 1) + self.gridLayout_3.addLayout(self.gridlayout_main, 0, 0, 1, 1) QWidget.setTabOrder(self.lineedit_url, self.button_download) QWidget.setTabOrder(self.button_download, self.lineedit_playlist_url) @@ -1444,8 +1444,8 @@ def setupUi(self, Porn_Fetch_Widget): self.retranslateUi(Porn_Fetch_Widget) - self.stacked_widget_main.setCurrentIndex(0) - self.stacked_widget_top.setCurrentIndex(0) + self.stacked_widget_main.setCurrentIndex(1) + self.stacked_widget_top.setCurrentIndex(3) QMetaObject.connectSlotsByName(Porn_Fetch_Widget) @@ -1453,7 +1453,7 @@ def setupUi(self, Porn_Fetch_Widget): def retranslateUi(self, Porn_Fetch_Widget): Porn_Fetch_Widget.setWindowTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"Porn Fetch V3.4 (C) Johannes Habel GPL 3", None)) - self.groupBox_3.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"Porn Fetch Menu", None)) + self.groupbox_top_bar.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"Porn Fetch Menu", None)) self.button_switch_settings.setText("") self.button_switch_tools.setText("") self.button_switch_home.setText("") @@ -1505,7 +1505,7 @@ def retranslateUi(self, Porn_Fetch_Widget): self.label_videos_by_category_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get videos by category", None)) self.button_eporner_category_get_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Videos", None)) self.button_list_categories_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"List of all categories", None)) - self.groupBox.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"HQPorner", None)) + self.groupbox_tools.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"HQPorner", None)) self.radio_top_porn_month.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Month", None)) self.button_top_porn_get_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Videos", None)) self.label_get_brazzers_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Brazzers videos", None)) From 1147f80975c88fa478c360af690539f298d673a1 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Sun, 30 Jun 2024 04:39:08 +0200 Subject: [PATCH 16/39] - small change for the icons (btw the reaons why I do so small commits is because my kernel likes to panic very often :skull:) --- main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/main.py b/main.py index f2cbd12..c7db43b 100644 --- a/main.py +++ b/main.py @@ -807,7 +807,6 @@ def load_style(self): } for button, icon_name in icons.items(): if icon_name == "settings.svg" or icon_name == "tools.svg": - button.setIcon(QIcon(f":/images/graphics/{icon_name}"),) button.setIconSize(QSize(24, 24)) button.setIcon(QIcon(f":/images/graphics/{icon_name}")) From e49779492d1b70c18b95637cfadd2e9ff9f81aee Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Sun, 30 Jun 2024 06:45:26 +0200 Subject: [PATCH 17/39] - added tree widget auto apply by author's name - changed some button colors - repositioned the "sele ct everything" button back into the main ui - set a minimum height to the stacked top widget, so that resizing doesn't break it - added exception for update check in case of a connection error --- main.py | 35 ++++++++--- src/frontend/form_desktop.ui | 87 +++++++++++++------------ src/frontend/range_selector.py | 92 +++++++++++++++------------ src/frontend/range_selector.ui | 108 ++++++++++++++++++-------------- src/frontend/ui_form_desktop.py | 58 +++++++++-------- 5 files changed, 219 insertions(+), 161 deletions(-) diff --git a/main.py b/main.py index c7db43b..03184ce 100644 --- a/main.py +++ b/main.py @@ -160,11 +160,15 @@ def __init__(self): def run(self): url = f"https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/{__next_release__}" - if requests.get(url).status_code == 200: - self.signals.result.emit(True) + try: + if requests.get(url).status_code == 200: + self.signals.result.emit(True) - else: - self.signals.result.emit(False) + else: + self.signals.result.emit(False) + + except requests.exceptions.ConnectionError: + logger_error("Couldn't check for updates, because of a Connection Error") class AddToTreeWidget(QRunnable): @@ -784,6 +788,7 @@ def button_connectors(self): self.ui.button_tree_stop.clicked.connect(switch_stop_state) self.ui.button_tree_export_video_urls.clicked.connect(export_urls) self.ui.button_download_ffmpeg.clicked.connect(self.download_ffmpeg) + self.ui.button_range_apply_everything.clicked.connect(self.select_all_items) def load_style(self): """Refactored function to load icons and stylesheets.""" @@ -847,7 +852,7 @@ def load_style(self): self.ui.button_threading_mode_help.setStyleSheet(stylesheets["button_green"]) self.ui.button_directory_system_help.setStyleSheet(stylesheets["button_green"]) self.ui.button_semaphore_help.setStyleSheet(stylesheets["button_green"]) - self.ui.button_tree_download.setStyleSheet(stylesheets["button_orange"]) + self.ui.button_tree_download.setStyleSheet(stylesheets["button_purple"]) self.ui.button_tree_unselect_all.setStyleSheet(stylesheets["button_blue"]) self.ui.button_tree_select_range.setStyleSheet(stylesheets["button_green"]) self.ui.button_output_path_select.setStyleSheet(stylesheets["button_blue"]) @@ -874,6 +879,7 @@ def load_style(self): self.ui.button_timeout_maximal_retries_help.setStyleSheet(stylesheets["button_green"]) self.ui.button_help_file.setStyleSheet(stylesheets["button_green"]) self.ui.button_download_ffmpeg.setStyleSheet(stylesheets["button_purple"]) + self.ui.button_range_apply_everything.setStyleSheet(stylesheets["button_orange"]) self.header = self.ui.treeWidget.header() self.header.resizeSection(0, 300) self.header.resizeSection(1, 150) @@ -1076,6 +1082,7 @@ def switch_to_home(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(0) self.ui.stacked_widget_top.setMaximumHeight(self.default_max_height) + self.ui.stacked_widget_top.setMinimumHeight(225) def switch_to_account(self): self.ui.stacked_widget_top.setCurrentIndex(1) @@ -1086,6 +1093,7 @@ def switch_to_tools(self): self.ui.stacked_widget_main.setCurrentIndex(0) self.ui.stacked_widget_top.setCurrentIndex(3) self.ui.stacked_widget_top.setMaximumHeight(self.default_max_height) + self.ui.stacked_widget_top.setMinimumHeight(258) def switch_to_settings(self): self.ui.stacked_widget_main.setCurrentIndex(1) @@ -1169,6 +1177,7 @@ def add_to_tree_widget_signal(self, data): item.setData(2, Qt.UserRole, formatted_duration) # Store the original duration for sorting item.setCheckState(0, Qt.Unchecked) item.setData(0, Qt.UserRole, video) + item.setData(1, Qt.UserRole, author) def download_tree_widget(self): """ @@ -1239,7 +1248,7 @@ def select_range_of_items(self): self.range_ui.spinbox_range_end.setMaximum(item_count) self.range_ui.button_range_apply_index.clicked.connect(self.process_range_of_items_selection_index) self.range_ui.button_range_apply_time.clicked.connect(self.process_range_of_items_selection_time) - self.range_ui.button_range_apply_everything.clicked.connect(self.select_all_items) + self.range_ui.button_range_apply_author.clicked.connect(self.process_range_of_items_author) # Show the new widget self.widget.show() @@ -1284,12 +1293,22 @@ def process_range_of_items_selection_time(self): # Check if the duration is within the specified start and end times if start_time <= duration <= end_time: item.setCheckState(0, Qt.Checked) - else: - item.setCheckState(0, Qt.Unchecked) # Optionally uncheck items outside the range # Assuming this is meant to close the widget, but it might be better to handle this outside this function self.widget.deleteLater() + def process_range_of_items_author(self): + name = str(self.range_ui.lineedit_range_author.text()) + root = self.ui.treeWidget.invisibleRootItem() + + for i in range(root.childCount()): + item = root.child(i) + author = str(item.data(1, Qt.UserRole)) + if str(author).lower() == str(name).lower(): + item.setCheckState(0, Qt.Checked) + + self.widget.deleteLater() + def start_single_video(self): """ Starts the download of a single video. diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 36038cb..52bf85b 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -6,8 +6,8 @@ 0 0 - 1630 - 963 + 1210 + 869 @@ -25,7 +25,7 @@ Porn Fetch V3.4 (C) Johannes Habel GPL 3 - + @@ -374,7 +374,7 @@ QPushButton:pressed { 1 - 1 + 0 @@ -1014,8 +1014,8 @@ QPushButton:pressed { 0 0 - 1606 - 257 + 387 + 206 @@ -1497,8 +1497,8 @@ QPushButton:pressed { 0 0 - 1606 - 446 + 1186 + 352 @@ -1636,6 +1636,28 @@ QPushButton:pressed { + + + + + 0 + 0 + + + + + 0 + 30 + + + + Does not stop downloading videos + + + Stop loading videos + + + @@ -1644,29 +1666,7 @@ QPushButton:pressed { - - - - - 0 - 0 - - - - - 0 - 30 - - - - Does not stop downloading videos - - - Stop loading videos - - - - + @@ -1694,8 +1694,15 @@ QPushButton:pressed { - - + + + + Select everything + + + + + 0 @@ -1711,19 +1718,16 @@ QPushButton:pressed { PointingHandCursor - - Unselects all videos in the tree widget - - Unselect all + Download Selected Videos - - + + 0 @@ -1739,11 +1743,14 @@ QPushButton:pressed { PointingHandCursor + + Unselects all videos in the tree widget + - Download Selected Videos + Unselect all diff --git a/src/frontend/range_selector.py b/src/frontend/range_selector.py index 942b2e5..be4dd68 100644 --- a/src/frontend/range_selector.py +++ b/src/frontend/range_selector.py @@ -28,75 +28,85 @@ def setupUi(self, Form): self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout = QGridLayout() self.gridLayout.setObjectName(u"gridLayout") - self.spinbox_range_start = QSpinBox(Form) - self.spinbox_range_start.setObjectName(u"spinbox_range_start") + self.textbrowser_range = QTextBrowser(Form) + self.textbrowser_range.setObjectName(u"textbrowser_range") - self.gridLayout.addWidget(self.spinbox_range_start, 9, 1, 1, 1) + self.gridLayout.addWidget(self.textbrowser_range, 0, 0, 1, 5) - self.label_apply_by_index = QLabel(Form) - self.label_apply_by_index.setObjectName(u"label_apply_by_index") + self.button_range_apply_time = QPushButton(Form) + self.button_range_apply_time.setObjectName(u"button_range_apply_time") - self.gridLayout.addWidget(self.label_apply_by_index, 6, 0, 1, 4) + self.gridLayout.addWidget(self.button_range_apply_time, 5, 4, 1, 1) - self.label_range_start = QLabel(Form) - self.label_range_start.setObjectName(u"label_range_start") + self.label_apply_by_time = QLabel(Form) + self.label_apply_by_time.setObjectName(u"label_apply_by_time") - self.gridLayout.addWidget(self.label_range_start, 9, 0, 1, 1) + self.gridLayout.addWidget(self.label_apply_by_time, 4, 0, 1, 4) self.lineedit_range_start = QLineEdit(Form) self.lineedit_range_start.setObjectName(u"lineedit_range_start") self.gridLayout.addWidget(self.lineedit_range_start, 5, 1, 1, 1) + self.lineedit_range_author = QLineEdit(Form) + self.lineedit_range_author.setObjectName(u"lineedit_range_author") + + self.gridLayout.addWidget(self.lineedit_range_author, 1, 1, 1, 1) + self.spinbox_range_end = QSpinBox(Form) self.spinbox_range_end.setObjectName(u"spinbox_range_end") self.gridLayout.addWidget(self.spinbox_range_end, 9, 3, 1, 1) - self.lineedit_range_end = QLineEdit(Form) - self.lineedit_range_end.setObjectName(u"lineedit_range_end") + self.label_apply_by_index = QLabel(Form) + self.label_apply_by_index.setObjectName(u"label_apply_by_index") - self.gridLayout.addWidget(self.lineedit_range_end, 5, 3, 1, 1) + self.gridLayout.addWidget(self.label_apply_by_index, 6, 0, 1, 4) - self.textbrowser_range = QTextBrowser(Form) - self.textbrowser_range.setObjectName(u"textbrowser_range") + self.label_range_end = QLabel(Form) + self.label_range_end.setObjectName(u"label_range_end") - self.gridLayout.addWidget(self.textbrowser_range, 0, 0, 1, 5) + self.gridLayout.addWidget(self.label_range_end, 9, 2, 1, 1) + + self.button_range_apply_index = QPushButton(Form) + self.button_range_apply_index.setObjectName(u"button_range_apply_index") + + self.gridLayout.addWidget(self.button_range_apply_index, 9, 4, 1, 1) self.label_range_time_end = QLabel(Form) self.label_range_time_end.setObjectName(u"label_range_time_end") self.gridLayout.addWidget(self.label_range_time_end, 5, 2, 1, 1) - self.label_apply_by_time = QLabel(Form) - self.label_apply_by_time.setObjectName(u"label_apply_by_time") + self.label_range_start = QLabel(Form) + self.label_range_start.setObjectName(u"label_range_start") - self.gridLayout.addWidget(self.label_apply_by_time, 4, 0, 1, 4) + self.gridLayout.addWidget(self.label_range_start, 9, 0, 1, 1) - self.button_range_apply_index = QPushButton(Form) - self.button_range_apply_index.setObjectName(u"button_range_apply_index") + self.button_range_apply_author = QPushButton(Form) + self.button_range_apply_author.setObjectName(u"button_range_apply_author") - self.gridLayout.addWidget(self.button_range_apply_index, 9, 4, 1, 1) + self.gridLayout.addWidget(self.button_range_apply_author, 1, 2, 1, 3) - self.label_range_end = QLabel(Form) - self.label_range_end.setObjectName(u"label_range_end") + self.spinbox_range_start = QSpinBox(Form) + self.spinbox_range_start.setObjectName(u"spinbox_range_start") - self.gridLayout.addWidget(self.label_range_end, 9, 2, 1, 1) + self.gridLayout.addWidget(self.spinbox_range_start, 9, 1, 1, 1) + + self.lineedit_range_end = QLineEdit(Form) + self.lineedit_range_end.setObjectName(u"lineedit_range_end") + + self.gridLayout.addWidget(self.lineedit_range_end, 5, 3, 1, 1) self.label_range_time_start = QLabel(Form) self.label_range_time_start.setObjectName(u"label_range_time_start") self.gridLayout.addWidget(self.label_range_time_start, 5, 0, 1, 1) - self.button_range_apply_everything = QPushButton(Form) - self.button_range_apply_everything.setObjectName(u"button_range_apply_everything") + self.label_range_by_author = QLabel(Form) + self.label_range_by_author.setObjectName(u"label_range_by_author") - self.gridLayout.addWidget(self.button_range_apply_everything, 11, 0, 1, 5) - - self.button_range_apply_time = QPushButton(Form) - self.button_range_apply_time.setObjectName(u"button_range_apply_time") - - self.gridLayout.addWidget(self.button_range_apply_time, 5, 4, 1, 1) + self.gridLayout.addWidget(self.label_range_by_author, 1, 0, 1, 1) self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) @@ -109,10 +119,6 @@ def setupUi(self, Form): def retranslateUi(self, Form): Form.setWindowTitle(QCoreApplication.translate("Form", u"Video selector...", None)) - self.label_apply_by_index.setText(QCoreApplication.translate("Form", u"Apply by Index:", None)) - self.label_range_start.setText(QCoreApplication.translate("Form", u"Start:", None)) - self.lineedit_range_start.setText(QCoreApplication.translate("Form", u"0", None)) - self.lineedit_range_end.setText(QCoreApplication.translate("Form", u"0", None)) self.textbrowser_range.setHtml(QCoreApplication.translate("Form", u"\n" "\n" "

Supported Websites:

\n" "


\n" "

Downloading:

\n" -"


\n" -"

- PornHub.com (supports total progress)

\n" +"


\n" +"

- PornHub.com (supports total progress)

\n" "

- HQPorner.com

\n" "

- Eporner.com

\n" "

- XNXX.com (supports total progress)

\n" "

- XVideos.com (supports total progress)

\n" -"


\n" -"

All sites support *threaded" - "* downloads and selectable quality!

\n" +"


\n" +"

All sites support *threaded* downloads and selectable quality!

\n" "


\n" "

* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly

\n" "

downloaded, therefore threading in a segment isn't needed.

\n" "


\n" -"

Model / Channel Downloads

\n" -"


\n" +"

Model / Channel Downloads

\n" +"


\n" "

- PornHub.com

\n" "

- HQPorner.com

\n" "

- EPorner.com

\n" "

- XNXX.com

\n" "

- XVideos.com

\n" -"


\n" -"

Searching:

\n" +"


\n" +"

Searching:

\n" "


\n" "

- PornHub.com

\n" "

- HQPorner.com

\n" "

- Xvideos.com

\n" "

- Eporner.com

\n" -"

- XNXX.com

\n" -"


\n" +"

- XNXX.com

\n" +"


\n" "

I am constantly working to support more websites.

\n" "


\n" "


\n" "


\n" +"


\n" "


\n" -"


\n" "


\n" "


", None)) - self.label_total_progress.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Total:", None)) - self.label_progress_converting.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Converting:", None)) - self.label_progress_information.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Information: The total progressbar does not count for Eporner and HQPorner, because they are using different mechanisms for downloading.", None)) + self.groupbox_top_bar.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"Porn Fetch Menu", None)) + self.button_switch_settings.setText("") + self.button_switch_tools.setText("") + self.button_switch_home.setText("") + self.button_switch_credits.setText("") + self.button_switch_account.setText("") + self.button_view_progress_bars.setText("") # retranslateUi From d66ab6486d64019a2579f9d64fa2cd12e3a68403 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Mon, 29 Jul 2024 22:35:40 +0200 Subject: [PATCH 26/39] merging #48 into v3.4 Reworking the scripts now... --- src/scripts/install.sh | 54 ++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/src/scripts/install.sh b/src/scripts/install.sh index 4f3b687..678e5a7 100644 --- a/src/scripts/install.sh +++ b/src/scripts/install.sh @@ -1,7 +1,8 @@ #!/bin/bash # Automatic compile script -# Detect distribution +# If not on a Linux distro, the OS name is used to ensure compatibility + if [ -f /etc/os-release ]; then . /etc/os-release OS=$ID @@ -22,17 +23,6 @@ fi OS=$(echo $OS | tr '[:upper:]' '[:lower:]') case $OS in - "arch"|"archlinux") - # Arch Linux commands - echo "Detected Arch Linux" - sudo pacman -S python-virtualenv git - ;; - "ubuntu") - # Ubuntu commands - echo "Detected Ubuntu" - sudo apt-get update - sudo apt-get install build-essential cmake python3-dev libssl-dev qtbase5-dev qtdeclarative5-dev qttools5-dev libqt5svg5-dev qt5-default git wget python3-venv -y - ;; "termux") # Termux commands echo "Detected Termux" @@ -40,16 +30,6 @@ case $OS in apt-get full-upgrade -y apt-get install python3 python-pip git wget ldd binutils ;; - "fedora") - # Fedora commands - echo "Detected Fedora" - sudo dnf install -y git python3-virtualenv qt5-devel - ;; - "opensuse"|"suse") - # OpenSUSE commands - echo "Detected OpenSUSE" - sudo zypper install -y git python3-virtualenv libqt5-qtbase-devel - ;; "darwin") # macOS commands echo "Detected macOS" @@ -61,11 +41,29 @@ case $OS in fi brew install python3 git ;; - *) - echo "Unsupported distribution: $OS" - exit 1 - ;; -esac + esac + +# For most Linux Distros +# Detect Package Manager +if command -v pacman ; then +# Arch Linux commands + echo "Detected Arch Linux" + sudo pacman -S python-virtualenv git +elif command -v apt ; then +# Ubuntu commands + echo "Detected Ubuntu/Debian" + sudo apt-get update + sudo apt-get install build-essential cmake python3-dev libssl-dev qtbase5-dev qtdeclarative5-dev qttools5-dev libqt5svg5-dev qt5-default git wget python3-venv -y +elif command -v dnf ; then +# Fedora commands + echo "Detected Fedora" + sudo dnf install -y git python3-virtualenv qt5-devel +elif command -v zypper ; then +# OpenSUSE commands + echo "Detected OpenSUSE" + sudo zypper install -y git python3-virtualenv libqt5-qtbase-devel +fi + # Common commands git clone https://github.com/EchterAlsFake/Porn_Fetch @@ -78,4 +76,4 @@ pyinstaller -F main.py cd dist chmod +x main mv main Porn_Fetch -echo "Porn Fetch is now installed in $(pwd)" +echo "Porn Fetch is now installed in $(pwd)" \ No newline at end of file From 76e318b0cfb1f323a34abc892c93f902fb9f9f1d Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Mon, 29 Jul 2024 23:29:27 +0200 Subject: [PATCH 27/39] - testing python3.12 nuitka build --- src/build/pysidedeploy_linux.spec | 4 ++-- src/build/pysidedeploy_macos.spec | 4 ++-- src/build/pysidedeploy_windows.spec | 2 +- src/scripts/install.sh | 21 ++++++++++++++------- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/build/pysidedeploy_linux.spec b/src/build/pysidedeploy_linux.spec index 51f2f52..1d8b7e4 100755 --- a/src/build/pysidedeploy_linux.spec +++ b/src/build/pysidedeploy_linux.spec @@ -1,6 +1,6 @@ [app] # title of your application -title = main +title = Porn Fetch # project directory. the general assumption is that project_dir is the parent directory # of input_file project_dir = . @@ -19,7 +19,7 @@ python_path = # python packages to install # ordered-set = increase compile time performance of nuitka packaging # zstandard = provides final executable size optimization -packages = Nuitka==2.1 +packages = Nuitka==2.3.7 # buildozer = for deploying Android application android_packages = buildozer==1.5.0,cython==0.29.33 diff --git a/src/build/pysidedeploy_macos.spec b/src/build/pysidedeploy_macos.spec index a596c42..d2dcd9a 100755 --- a/src/build/pysidedeploy_macos.spec +++ b/src/build/pysidedeploy_macos.spec @@ -1,6 +1,6 @@ [app] # title of your application -title = main +title = Porn Fetch # project directory. the general assumption is that project_dir is the parent directory # of input_file project_dir = . @@ -19,7 +19,7 @@ python_path = # python packages to install # ordered-set = increase compile time performance of nuitka packaging # zstandard = provides final executable size optimization -packages = Nuitka==2.1 +packages = Nuitka==2.3 # buildozer = for deploying Android application android_packages = buildozer==1.5.0,cython==0.29.33 diff --git a/src/build/pysidedeploy_windows.spec b/src/build/pysidedeploy_windows.spec index 529a6d7..c07366c 100755 --- a/src/build/pysidedeploy_windows.spec +++ b/src/build/pysidedeploy_windows.spec @@ -1,6 +1,6 @@ [app] # title of your application -title = main +title = Porn Fetch # project directory. the general assumption is that project_dir is the parent directory # of input_file project_dir = . diff --git a/src/scripts/install.sh b/src/scripts/install.sh index 678e5a7..5c2f41c 100644 --- a/src/scripts/install.sh +++ b/src/scripts/install.sh @@ -29,6 +29,13 @@ case $OS in apt-get update apt-get full-upgrade -y apt-get install python3 python-pip git wget ldd binutils + pip install -r requirements_cli.txt + pip install pyinstaller + pyinstaller -F main.py + cd dist + chmod +x main + mv main Porn_Fetch + echo "Porn Fetch is now installed in $(pwd)" ;; "darwin") # macOS commands @@ -68,12 +75,12 @@ fi # Common commands git clone https://github.com/EchterAlsFake/Porn_Fetch cd Porn_Fetch -python3 -m venv venv -source venv/bin/activate +git checkout 3.4 # This is only temporary for testing, don't worry... +python3 -m venv /tmp/.venv # This is needed, because Qt has some issues if the virtual environment is in the same directory, as there the script gets executed in +source /tmp/.venv/bin/activate pip install -r requirements.txt -pip install pyinstaller -pyinstaller -F main.py -cd dist -chmod +x main -mv main Porn_Fetch +pyside6-deploy main.py -c src/build/pysidedeploy_linux.spec -f -v +deactivate +echo "Deleting the temporary created virtual environment..." +rm -rf /tmp/.venv echo "Porn Fetch is now installed in $(pwd)" \ No newline at end of file From 6060e0bb247c27adde53c99afbc86c664a745028 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Mon, 29 Jul 2024 23:46:05 +0200 Subject: [PATCH 28/39] - python3.12 nuitka build succeeded on Linux.... Testing now on Windows :skull: (Please kill me) --- src/build/pysidedeploy_linux.spec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/build/pysidedeploy_linux.spec b/src/build/pysidedeploy_linux.spec index 1d8b7e4..ef9ec41 100755 --- a/src/build/pysidedeploy_linux.spec +++ b/src/build/pysidedeploy_linux.spec @@ -5,17 +5,17 @@ title = Porn Fetch # of input_file project_dir = . # source file path -input_file = +input_file = /home/asuna/Porn_Fetch/src/scripts/Porn_Fetch/main.py # directory where exec is stored exec_directory = . # path to .pyproject project file project_file = # application icon -icon = src/frontend/graphics/logo_transparent.png +icon = /home/asuna/Porn_Fetch/src/scripts/Porn_Fetch/src/frontend/graphics/logo_transparent.png [python] # python path -python_path = +python_path = /tmp/.venv/bin/python3.11 # python packages to install # ordered-set = increase compile time performance of nuitka packaging # zstandard = provides final executable size optimization From 568f4a1edd440b5340ab555b33d876ad4ee95b26 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Mon, 29 Jul 2024 23:46:05 +0200 Subject: [PATCH 29/39] - python3.12 nuitka build succeeded on Linux.... Testing now on Windows :skull: (Please kill me) --- src/scripts/install.sh | 2 +- src/scripts/install_windows.ps1 | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/scripts/install.sh b/src/scripts/install.sh index 5c2f41c..861656d 100644 --- a/src/scripts/install.sh +++ b/src/scripts/install.sh @@ -83,4 +83,4 @@ pyside6-deploy main.py -c src/build/pysidedeploy_linux.spec -f -v deactivate echo "Deleting the temporary created virtual environment..." rm -rf /tmp/.venv -echo "Porn Fetch is now installed in $(pwd)" \ No newline at end of file +echo "Porn Fetch is now installed in $(pwd)/main.bin" \ No newline at end of file diff --git a/src/scripts/install_windows.ps1 b/src/scripts/install_windows.ps1 index 99ac001..be192d4 100644 --- a/src/scripts/install_windows.ps1 +++ b/src/scripts/install_windows.ps1 @@ -15,18 +15,18 @@ try { if (-not $pythonInstalled) { # Download and install Python - Write-Output "Downloading Python 3.11.6..." - Invoke-WebRequest -Uri "https://www.python.org/ftp/python/3.11.6/python-3.11.6-amd64.exe" -OutFile "python-3.11.6-amd64.exe" + Write-Output "Downloading Python 3.12.4..." + Invoke-WebRequest -Uri "https://www.python.org/ftp/python/3.12.4/python-3.12.4-amd64.exe" -OutFile "python-3.12.4-amd64.exe" - Write-Output "Installing Python 3.11.6 silently..." - Start-Process -Wait "python-3.11.6-amd64.exe" -ArgumentList "/quiet InstallAllUsers=1 PrependPath=1" + Write-Output "Installing Python 3.12.4 silently..." + Start-Process -Wait "python-3.12.4-amd64.exe" -ArgumentList "/quiet InstallAllUsers=1 PrependPath=1" } else { Write-Output "Python is already installed." } # Download and extract the project ZIP Write-Output "Downloading project ZIP..." -Invoke-WebRequest -Uri "https://github.com/EchterAlsFake/Porn_Fetch/archive/refs/heads/master.zip" -OutFile "master.zip" +Invoke-WebRequest -Uri "https://github.com/EchterAlsFake/Porn_Fetch/archive/refs/heads/3.4.zip" -OutFile "master.zip" Write-Output "Extracting project ZIP..." Expand-Archive -Path "master.zip" -DestinationPath "." @@ -36,10 +36,8 @@ Set-Location -Path ".\Porn_Fetch-master" Write-Output "Installing pip requirements..." pip install -r requirements.txt -pip install pyinstaller - # Build the project Write-Output "Building the project..." -pyinstaller -F main.py +pyside6-deploy main.py -c src/build/pysidedeploy_windows.spec -f -v Write-Output "Done!" From e9c4dba4bf78c31d44a1e0d8b9da06c0ef21db4b Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Tue, 30 Jul 2024 00:58:40 +0200 Subject: [PATCH 30/39] - fixing nuitka version in windows / macos build --- src/build/pysidedeploy_macos.spec | 2 +- src/build/pysidedeploy_windows.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/build/pysidedeploy_macos.spec b/src/build/pysidedeploy_macos.spec index d2dcd9a..370e871 100755 --- a/src/build/pysidedeploy_macos.spec +++ b/src/build/pysidedeploy_macos.spec @@ -19,7 +19,7 @@ python_path = # python packages to install # ordered-set = increase compile time performance of nuitka packaging # zstandard = provides final executable size optimization -packages = Nuitka==2.3 +packages = Nuitka==2.3.7 # buildozer = for deploying Android application android_packages = buildozer==1.5.0,cython==0.29.33 diff --git a/src/build/pysidedeploy_windows.spec b/src/build/pysidedeploy_windows.spec index c07366c..a8e47a9 100755 --- a/src/build/pysidedeploy_windows.spec +++ b/src/build/pysidedeploy_windows.spec @@ -19,7 +19,7 @@ python_path = # python packages to install # ordered-set = increase compile time performance of nuitka packaging # zstandard = provides final executable size optimization -packages = Nuitka==2.1 +packages = Nuitka==2.3.7 # buildozer = for deploying Android application android_packages = buildozer==1.5.0,cython==0.29.33 From 74ebc32417420deedaa5339cc7d12a5c21e76c8f Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Tue, 30 Jul 2024 02:26:04 +0200 Subject: [PATCH 31/39] - fixed the windows build script --- README/CHANGELOG.md | 3 +- README/STATUS.md | 1 + src/scripts/install_windows.ps1 | 89 +++++++++++++++++++++++++-------- 3 files changed, 71 insertions(+), 22 deletions(-) diff --git a/README/CHANGELOG.md b/README/CHANGELOG.md index 3caf6fc..fd0dba7 100644 --- a/README/CHANGELOG.md +++ b/README/CHANGELOG.md @@ -413,4 +413,5 @@ I tested it on Android 12 & 13 on two devices. - Fixed playlist downloading - Fixed file progress - Fixed an issue where the semaphore wouldn't release in the CLI which makes downloading almost impossible, because -the thread is permanently locked \ No newline at end of file +the thread is permanently locked +- Fixed the build scripts for Windows and Linux | Thanks @omar-st [Pull Request #48](https://github.com/EchterAlsFake/Porn_Fetch/commit/2d9cc2885c1383369020a5c26e957fe5cdf0f886) [Related Issue #46](https://github.com/EchterAlsFake/Porn_Fetch/issues/46) \ No newline at end of file diff --git a/README/STATUS.md b/README/STATUS.md index 85515c7..15d7845 100644 --- a/README/STATUS.md +++ b/README/STATUS.md @@ -13,6 +13,7 @@ - [x] Fixing the errors with the playlist - [x] Fixing file progress - [x] Fixing the tag writing function +- [x] Fixed the build scripts - [] Entirely reworking the Layout, the UI design AND the Android Layout - [] Adding support for Spankbang (easy) - [] Adding support for Porntrex (even easier) (I don't know who tf wrote their JS code, but this guy should be fire) diff --git a/src/scripts/install_windows.ps1 b/src/scripts/install_windows.ps1 index be192d4..9376278 100644 --- a/src/scripts/install_windows.ps1 +++ b/src/scripts/install_windows.ps1 @@ -5,39 +5,86 @@ if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdenti exit } -# Check if Python is already installed -$pythonInstalled = $true -try { - python --version | Out-Null -} catch { - $pythonInstalled = $false +$userDir = [Environment]::GetFolderPath('UserProfile') +$desktopDir = [System.IO.Path]::Combine($userDir, "Desktop") +$tempDir = [System.IO.Path]::GetTempPath() + +# Define the downloads directory +$downloadsDir = "$env:TEMP" + +function Check-PythonInstalled { + try { + $pythonVersion = py --version 2>&1 + if ($pythonVersion -match "Python (\d+\.\d+\.\d+)") { + return $true + } else { + return $false + } + } catch { + return $false + } } -if (-not $pythonInstalled) { +function Install-Python { # Download and install Python Write-Output "Downloading Python 3.12.4..." - Invoke-WebRequest -Uri "https://www.python.org/ftp/python/3.12.4/python-3.12.4-amd64.exe" -OutFile "python-3.12.4-amd64.exe" - + $pythonInstallerPath = [System.IO.Path]::Combine($downloadsDir, "python-3.12.4-amd64.exe") + try { + Invoke-WebRequest -Uri "https://www.python.org/ftp/python/3.12.4/python-3.12.4-amd64.exe" -OutFile $pythonInstallerPath -ErrorAction Stop + } catch { + Write-Output "Failed to download Python installer. Please check your internet connection." + return + } + Write-Output "Installing Python 3.12.4 silently..." - Start-Process -Wait "python-3.12.4-amd64.exe" -ArgumentList "/quiet InstallAllUsers=1 PrependPath=1" + try { + Start-Process -FilePath $pythonInstallerPath -ArgumentList "/quiet InstallAllUsers=1 PrependPath=1" -Wait -ErrorAction Stop + } catch { + Write-Output "Python installation failed. Please run the installer manually." + return + } + + # Verify installation + if (Check-PythonInstalled) { + Write-Output "Python installation succeeded. Version: $(py --version 2>&1)" + } else { + Write-Output "Python installation failed. Please install it manually from https://www.python.org/downloads/" + } +} + +if (Check-PythonInstalled) { + Write-Output "Python is already installed. Version: $(py --version 2>&1)" } else { - Write-Output "Python is already installed." + Write-Output "Python is not installed." + Install-Python } # Download and extract the project ZIP Write-Output "Downloading project ZIP..." -Invoke-WebRequest -Uri "https://github.com/EchterAlsFake/Porn_Fetch/archive/refs/heads/3.4.zip" -OutFile "master.zip" - +$projectZipPath = [System.IO.Path]::Combine($downloadsDir, "master.zip") +Invoke-WebRequest -Uri "https://github.com/EchterAlsFake/Porn_Fetch/archive/refs/heads/master.zip" -OutFile $projectZipPath Write-Output "Extracting project ZIP..." -Expand-Archive -Path "master.zip" -DestinationPath "." - -# Install pip requirements -Set-Location -Path ".\Porn_Fetch-master" +Expand-Archive -Path $projectZipPath -DestinationPath $downloadsDir -Force -Write-Output "Installing pip requirements..." +# Use Invoke-Command to run commands within the virtual environment +$projectDir = Join-Path -Path $downloadsDir -ChildPath "Porn_Fetch-master" +Set-Location -Path $projectDir +py -m venv ..\venv\ +..\venv\Scripts\activate.ps1 pip install -r requirements.txt -# Build the project -Write-Output "Building the project..." -pyside6-deploy main.py -c src/build/pysidedeploy_windows.spec -f -v +echo Y | pyside6-deploy main.py -c src/build/pysidedeploy_windows.spec -f -v + +# Move the final executable to the user's Desktop +$finalExePath = Join-Path -Path $projectDir -ChildPath "main.exe" +$renamedExe = Join-Path -Path $projectDir -ChildPath "Porn Fetch.exe" +if (Test-Path -Path $finalExePath) { + Rename-Item -Path $finalExePath -NewName "Porn Fetch.exe" + Move-Item -Path $renamedExe -Destination (Join-Path $desktopDir "Porn Fetch.exe") +} +#Set-Location -Path $userDir +# Clean up +Write-Output "Cleaning up..." +Remove-Item -Path $projectZipPath -Force +Remove-Item -Recurse -Force -Path (Join-Path $downloadsDir "Porn_Fetch-master") Write-Output "Done!" From 3c314876a8f912d20fae6f6eccedfed0ac11a925 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Wed, 31 Jul 2024 01:52:05 +0200 Subject: [PATCH 32/39] - fixed the translations in the code - fixed the layout for hqporner / eporner entirely This is causing the master branch of Porn Fetch to completely crash everytime, when running in non english mode. This was caused, because I am too lazy to read a documentation to the end. --- main.py | 62 ++- src/backend/class_help.py | 28 +- src/frontend/form_desktop.ui | 220 +++++------ src/frontend/translations/en.ts | 668 +++++++++++++------------------- src/frontend/ui_form_desktop.py | 10 +- 5 files changed, 418 insertions(+), 570 deletions(-) diff --git a/main.py b/main.py index 7138198..e71ff72 100644 --- a/main.py +++ b/main.py @@ -7,8 +7,7 @@ import zipfile import shutil import tarfile -import logging -import src.frontend.resources +import src.frontend.resources # Your IDE may tell you that this is an unused import statement, but that is WRONG! from itertools import islice, chain from threading import Event @@ -59,11 +58,13 @@ __build__ = "desktop" # android or desktop __author__ = "Johannes Habel" __next_release__ = "3.5" +context = "Porn Fetch" # This is used to tell the Translator from what thing the translation actually comes total_segments = 0 downloaded_segments = 0 last_index = 0 stop_flag = Event() -invalid_input_string = QCoreApplication.tr("Wrong Input, please verify the URL, category or actress!", None) +invalid_input_string = QCoreApplication.translate(context, "Wrong Input, please verify the URL, category or" + " actress!", None) ffmpeg_features = True ffmpeg_path = None url_linux = "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz" @@ -190,7 +191,7 @@ def process_video(self, video, index): data = load_video_attributes(video) session_urls.append(video.url) title = data[0] - disabled = QCoreApplication.tr("Disabled", None) + disabled = QCoreApplication.translate(context, "Disabled", None) duration = disabled author = disabled @@ -1040,7 +1041,7 @@ def save_user_settings(self): with open("config.ini", "w") as config_file: self.conf.write(config_file) - ui_popup(QCoreApplication.tr("Saved User Settings, please restart Porn Fetch!", None)) + ui_popup(self.tr("Saved User Settings, please restart Porn Fetch!", None)) logger.debug("Saved User Settings, please restart Porn Fetch.") def check_for_updates(self): @@ -1062,7 +1063,7 @@ def check_ffmpeg(self): if ffmpeg_binary is None: # If ffmpeg binaries are not found in the current directory, display warning and disable features if self.conf.get("Performance", "ffmpeg_warning") == "true": - ffmpeg_warning_message = QCoreApplication.tr(self, + ffmpeg_warning_message = self.tr( """ FFmpeg isn't installed on your system... Some features won't be available: @@ -1119,17 +1120,14 @@ def setup_android(self): self.configure_ui_for_android("/storage/emulated/0/Download/") def handle_no_output_path(self): - ui_popup( - QCoreApplication.tr(self, "The output path does not exist or is not writable.", None)) + ui_popup(self.tr( "The output path does not exist or is not writable.", None)) text, ok = QInputDialog.getText(self, "Enter custom Path", - QCoreApplication.tr(self, "Enter custom Path:", None)) + self.tr( "Enter custom Path:", None)) if ok and get_output_path(text): - ui_popup( - QCoreApplication.tr(self, f"Success: {text} will be used for this session!", None)) + ui_popup(self.tr(f"Success: {text} will be used for this session!", None)) self.configure_ui_for_android(text) else: - ui_popup( - QCoreApplication.tr(self, "Invalid path. The application will now exit.", None)) + ui_popup(self.tr("Invalid path. The application will now exit.", None)) sys.exit() def configure_ui_for_android(self, path): @@ -1452,7 +1450,7 @@ def on_video_loaded(self, video, author, stripped_title, output_file_path, threa def on_video_load_error(self, error_message): # Handle errors, possibly show message to user logger.debug(f"Error loading video: {error_message}") - ui_popup(QCoreApplication.tr(self, f"Some error occurred in loading a video. Please report this: {error_message}", + ui_popup(self.tr( f"Some error occurred in loading a video. Please report this: {error_message}", None)) def process_video_thread(self, output_path, video, threading_mode, quality): @@ -1589,12 +1587,14 @@ def receive_url_result(self, iterator, model_iterator, search_iterator): self.ui.radio_search_website_eporner.setChecked(True) else: - ui_popup(f"Information: The Website {website} specified in the URL file isn't valid.") + ui_popup(self.tr(f"Information: The Website {website} specified in the URL file isn't valid.", None)) return self.ui.lineedit_search_query.setText(query) self.basic_search() + self.ui.lineedit_search_query.clear() + def login(self): """ This handles logging in into the users PornHub accounts @@ -1605,21 +1605,20 @@ def login(self): username = self.ui.lineedit_username.text() password = self.ui.lineedit_password.text() if len(username) <= 2 or len(password) <= 2: - ui_popup( - QCoreApplication.tr(self, "Those credentials don't seem to be valid...", None)) + ui_popup(self.tr("Those credentials don't seem to be valid...", None)) return try: self.client = Client(username, password, delay=self.delay) logger.debug("Login Successful!") - ui_popup(QCoreApplication.tr(self, "Login Successful!", None)) + ui_popup(self.tr( "Login Successful!", None)) self.switch_login_button_state() except errors.LoginFailed: - ui_popup(QCoreApplication.tr(self, "Login Failed, please check your credentials and try again!", None)) + ui_popup(self.tr("Login Failed, please check your credentials and try again!", None)) except errors.ClientAlreadyLogged: - ui_popup(QCoreApplication.tr(self, "You are already logged in!", None)) + ui_popup(self.tr("You are already logged in!", None)) def switch_login_button_state(self): """If the user is logged in, I'll change the stylesheets of the buttons""" @@ -1640,9 +1639,8 @@ def check_login(self): elif not self.client.logged: self.login() if not self.client.logged: - text = (QCoreApplication.tr(self, - "There's a problem with the login. Please make sure you login first and then you try to " - "get videos based on your account.", None)) + text = self.tr("There's a problem with the login. Please make sure you login first and then " + "you try to get videos based on your account.", None) ui_popup(text) return False @@ -1711,8 +1709,8 @@ def get_top_porn_hqporner(self): def get_by_category_hqporner(self): """Returns video by category from HQPorner. I want to add support for EPorner""" # TODO - self.list_all_categories_string = (QCoreApplication.tr(self, - "Invalid Category. Press 'list categories' to see all possible ones.", None)) + self.list_all_categories_string = self.tr("Invalid Category. Press 'list categories' to see all " + "possible ones.", None) category_name = self.ui.lineedit_hqporner_category.text() all_categories = hq_Client().get_all_categories() @@ -1776,10 +1774,7 @@ def main(): setup_config_file() app = QApplication(sys.argv) app.setStyle("Fusion") - """ - I had many problems with coding in general where something didn't work but the translations are the hardest - thing I've ever done. Now where I've understand it it makes sense but the Qt documentation is a piece of shit... - """ + conf = ConfigParser() conf.read("config.ini") language = conf["UI"]["language"] @@ -1831,7 +1826,6 @@ def main(): if __name__ == "__main__": - """ These functions are static functions which I won't need while coding. These just exist for some reason, but I don't want to scroll through endless lines of code, @@ -1852,7 +1846,7 @@ def load_stylesheet(path): def reset_pornfetch(): setup_config_file(force=True) - ui_popup(QCoreApplication.tr("Done! Please restart.", None)) + ui_popup(QCoreApplication.translate("Done! Please restart.", None)) def switch_stop_state_2(): @@ -1876,10 +1870,10 @@ def export_urls(): ui_popup(f"Success! Saved: {len(session_urls)} URLs") else: - ui_popup(QCoreApplication.tr("No URLs in the current session...", None)) + ui_popup(QCoreApplication.translate(context, "No URLs in the current session...", None)) def ffmpeg_finished(): - ui_popup(QCoreApplication.tr("FFmpeg has been installed. Please restart Porn Fetch :)", None)) + ui_popup(QCoreApplication.translate(context, "FFmpeg has been installed. Please restart Porn Fetch :)", None)) def check_for_updates_result(value): @@ -1894,7 +1888,7 @@ def check_for_updates_result(value): logger.error(f"Couldn't fetch changelog of version: {__next_release__}") changelog = f"Unknown Error: {e}" - ui_popup(QCoreApplication.tr(f""" + ui_popup(QCoreApplication.translate(context, f""" Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} diff --git a/src/backend/class_help.py b/src/backend/class_help.py index 698dfc4..cee195e 100644 --- a/src/backend/class_help.py +++ b/src/backend/class_help.py @@ -1,9 +1,11 @@ from PySide6.QtCore import QCoreApplication from src.backend.shared_gui import ui_popup +context = "Porn Fetch" + def result_limit_help(): - text = QCoreApplication.tr(f""" + text = QCoreApplication.translate(context, f""" The result limit defines how many videos will be returned when performing a search or doing other operations which involves loading multiple videos. This also affects models / channels and your liked videos. The result limit is basically the number of videos which can be loaded into the tree widget (this thing where videos are displayed). @@ -12,7 +14,7 @@ def result_limit_help(): def pornhub_delay_help(): - text = QCoreApplication.tr(f""" + text = QCoreApplication.translate(context, f""" You can set a delay between requests from you to PornHub. If you are downloading a lot of videos or experiencing 'client.call' errors, you should enable a delay. By default the delay is turned off with the value 0 @@ -25,7 +27,7 @@ def pornhub_delay_help(): def maximal_workers_help(): - text = QCoreApplication.tr(f""" + text = QCoreApplication.translate(context, f""" The maximal workers define the amount of maximal threads which can be started when using the threaded download mode. One thread handles downloading one segment, so (in theory) 20 threads can download 20 segments at the same time. This can of course be helpful when you have a very fast internet connection, but when you have a poor PC or running on @@ -37,15 +39,15 @@ def maximal_workers_help(): def timeout_help(): - text = QCoreApplication.tr(f""" -The timeout handles the timeout for retrieving segments when using the treaded download mode. If you have a poor + text = QCoreApplication.translate(context, f""" +The timeout handles the timeout for retrieving segments when using the threaded download mode. If you have a poor internet connection you can set this higher than 10. But this isn't required for most users! """, None) ui_popup(text) def button_semaphore_help(): - text = QCoreApplication.tr(f""" + text = QCoreApplication.translate(context, f""" The Semaphore is a tool to limit the number of simultaneous actions / downloads. For example: If the semaphore is set to 1, only 1 video will be downloaded at the same time. @@ -56,7 +58,7 @@ def button_semaphore_help(): def button_threading_mode_help(): - text = QCoreApplication.tr(""" + text = QCoreApplication.translate(context, """ The different threading modes are used for different scenarios. 1) High Performance: Uses a class of workers to download multiple video segments at a time. Can be really fast if you @@ -74,7 +76,7 @@ def button_threading_mode_help(): def button_directory_system_help(): - text = QCoreApplication.tr(""" + text = QCoreApplication.translate(context, """ The directory system will save videos in an intelligent way. If you download 3 videos form one Pornstar and 5 videos from another, Porn Fetch will automatically make folders for it and move the 3 videos into that one folder and the other 5 into the other. (This will still apply with your selected output path) @@ -85,7 +87,7 @@ def button_directory_system_help(): def open_file_help(): - text = QCoreApplication.tr(""" + text = QCoreApplication.translate(context, """ Create a .txt file and add URLs like this: url1 @@ -108,7 +110,7 @@ def open_file_help(): def max_retries_help(): - text = QCoreApplication.tr(""" + text = QCoreApplication.translate(context, """ The maximal retries defines how much attempts will be used for a network request. For example if an API calls a URL for a website there will be of attempts until an error is thrown. """, None) @@ -116,11 +118,11 @@ def max_retries_help(): def skip_existing_files_help(): - text = QCoreApplication.tr(""" + text = QCoreApplication.translate(context, """ If you fetch a video and the exact same filename already exists, usually Porn Fetch would just skip this file. If you set this option to No, then Porn Fetch instead download the video and append a random number to it. -For example you have downloded a video called: +For example you have downloaded a video called: Spain_didnt_win_against_Germany.mp4 @@ -132,7 +134,7 @@ def skip_existing_files_help(): def model_videos_help(): - text = QCoreApplication.tr(""" + text = QCoreApplication.translate(context, """ User uploads and featured videos are two different things. User uploads are the videos which were really uploaded by the model and the featured videos are videos the model is part or featured in. diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 6179330..11d5115 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -1126,117 +1126,117 @@
- - - - EPorner +
+ +
+ + + + EPorner + + + + + + + + + 0 + 4 + + + + Get videos by category + + + + + + + + 0 + 4 + + + + + 100 + 4 + + + + + + + + + 0 + 2 + + + + + 0 + 2 + + + + PointingHandCursor + + + Get Videos + + + + + + + + 0 + 0 + + + + + 0 + 2 + + + + PointingHandCursor + + + List of all categories + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Orientation::Vertical - - - - - - - - 0 - 4 - - - - Get videos by category - - - - - - - - 0 - 4 - - - - - 100 - 4 - - - - - - - - - 0 - 2 - - - - - 0 - 2 - - - - PointingHandCursor - - - Get Videos - - - - - - - - 0 - 0 - - - - - 0 - 2 - - - - PointingHandCursor - - - List of all categories - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Orientation::Vertical - - - - 20 - 40 - - - - - - + + + 20 + 40 + + +
diff --git a/src/frontend/translations/en.ts b/src/frontend/translations/en.ts index ea27b10..94bbc00 100644 --- a/src/frontend/translations/en.ts +++ b/src/frontend/translations/en.ts @@ -2,813 +2,665 @@ - Form + Porn_Fetch - - Video selector... + + Saved User Settings, please restart Porn Fetch! - - Apply by Index: + + +FFmpeg isn't installed on your system... Some features won't be available: + +- The FFmpeg threading mode +- Converting videos into a valid .mp4 format +- Writing tags / metadata into the videos + +These features aren't necessary for Porn Fetch, but can be useful for some people. + +To automatically install ffmpeg, just head over to the settings and press the magical button, or install ffmpeg in your +local PATH (e.g, through your linux package manager, or through the Windows PATH) + +This warning won't be shown again. + - - - Start: + + The output path does not exist or is not writable. - - - 00000 + + Enter custom Path: - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Select the range of videos to be automatically selected.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">For example, if you set the start to 5 and the end to 20, then all videos between 5-20 will be checked for downloading :)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Or select by a range in time:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">For example if you want to download all videos in between 10 and 20 minutes do:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Start: 000010</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">End: 00020</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">And click Apply.</span></p></body></html> + + Success: {text} will be used for this session! + + + + + Invalid path. The application will now exit. - - - End: + + Some error occurred in loading a video. Please report this: {error_message} - - Apply by time: + + Information: The Website {website} specified in the URL file isn't valid. - - - Apply + + Those credentials don't seem to be valid... - - Select everything + + Login Successful! + + + + + Login Failed, please check your credentials and try again! + + + + + You are already logged in! + + + + + There's a problem with the login. Please make sure you login first and then you try to get videos based on your account. + + + + + Invalid Category. Press 'list categories' to see all possible ones. Porn_Fetch_Widget - + Total: - + PornHub: - + HQPorner: - + + Info: + + + + + Duration (minutes) + + + + Only Title (a lot faster) - - Unselect all + + Select everything - - Download Selected Videos + + Unselect all - - Author + + Download Selected Videos - - Duration + + Author - + Get Title, Author, Duration - + Show videos in reverse - - + + EPorner - + URLs in the file must be separated with new lines! - + Enter your PornHub Username - + Get Liked videos - + Get watched videos - + Password: - + Login - + Get recommended videos - + Username: - + Enter your PornHub Password - - - - - - + + + + + + Get Videos - + Search Query: - + Download - + File: - + Open File - + Model URL: - + URL: - - + + No - - + + Yes - + High Performance - + Default - + FFMPEG - - - - - - - - - - + + + + + + + + + + + Help - + Half - + Best - + Worst - + Use Directory system? - + Enter "./" for current directory - + Output path: - - + German - - + + Get videos by category - + Eporner - - + + XNXX - - + + XVideos - + Enter video URL - + + Porn Fetch V3.4 (C) Johannes Habel GPL 3 + + + + Search Website - + See Supported Websites - + Search for Videos. Select Website below - + PornHub - - + + HQPorner - - + + List of all categories - + Get Top Porn: - + Week - + Month - + All Time - + Get random video - + Get Video - + Get Brazzers videos - + Threading Mode: - + Quality: - - - French - - - - - - English + + Skip existing files: - - Graphical User Interface Language: + + Model videos (PornHub) - - System default + + User uploads - - Chinese (simplified) + + Featured videos - - PornHub Language (affects video titles) + + Both - - Spanish - - - - - Portuguese - - - - - Chinese - - - - - Dutch + + French - - Italian + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +hr { height: 1px; border-width: 0; } +li.unchecked::marker { content: "\2610"; } +li.checked::marker { content: "\2612"; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Supported Websites:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Downloading:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com (supports total progress)</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All sites support *threaded* downloads and selectable quality!</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">downloaded, therefore threading in a segment isn't needed.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Model / Channel Downloads</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- EPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Searching:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Xvideos.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I am constantly working to support more websites.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + + + Porn Fetch Menu + + + + + English - - Russian + + Graphical User Interface Language: - - Czech + + System default - - Japanese + + Chinese (simplified) - + Open - + Result Limit: - + Enter Model / Channel / Actress URL - + Playlist URL: - - Porn Fetch V3.3 (C) Johannes Habel GPL 3 - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Supported Websites:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Downloading:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com (supports total progress)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Eporner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com (supports total progress)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XVideos.com (supports total progress)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">All sites support *threaded* downloads and selectable quality!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">downloaded, therefore threading in a segment isn't needed.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Model / Channel Downloads</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- EPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XVideos.com</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Searching:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Xvideos.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Eporner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">I am constantly working to support more websites.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> - - - - + Information: The total progressbar does not count for Eporner and HQPorner, because they are using different mechanisms for downloading. - - View all other progress bars - - - - + Converting: - + Export video URLs - + Do not clear videos - + Enter a PornHub Playlist URL - + Graphical User Interface - + Videos - + Performance - - Allow Sorting - - - - + Unselects all videos in the tree widget - + Does not stop downloading videos - + Stop loading videos - + Automatically checks a range of videos - + Select a range of videos - - Internet: - - - - - FFmpeg: - - - - - Update available: - - - - + Simultaneous downloads: - + Maximal workers: - + PornHub Delay (0 = Disabled) in seconds: - + Maximal timeout: - + Maximal retries: - - Discord Rich Presence: - - - - + Apply (needs restart) - + Reset Porn Fetch to default settings - + Download and Setup FFmpeg - + Start - - QCoreApplication - - - Disabled - - - - - Saved User Settings, please restart Porn Fetch! - - - - - Login Failed, please check your credentials and try again! - - - - - Login Successful! - - - - - -FFmpeg isn't installed on your system... Some features won't be available: - -- The FFmpeg threading mode -- Converting videos into a valid .mp4 format -- Writing tags / metadata into the videos - -These features aren't necessary for Porn Fetch, but can be useful for some people. - -To automatically install ffmpeg, just head over to the settings and press the magical button, or install ffmpeg in your -local PATH (e.g, through your linux package manager, or through the Windows PATH) - -This warning won't be shown again. - - - - - - FFmpeg has been installed. Please restart Porn Fetch :) - - - - - Enter custom Path: - - - - - Success: {text} will be used for this session! - - - - - Not supported on Android - - - - - Porn Fetch will now reset to its default settings... - - - - - Done! Please restart. - - - - - No video URLs found. Are there videos in the tree widget? - - - - - Permission Error, please select a file from your user space,or run Porn Fetch with admin permissions (not recommended!) - - - - - Some error occurred in loading a video. Please report this: {error_message} - - - - - Wrong Input, please verify the URL, category or actress! - - - - - - Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. - Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} - - - - - The output path does not exist or is not writable. - - - - - Invalid path. The application will now exit. - - - - - High Performance threading may cause issues on Android devices. - - - - - Those credentials don't seem to be valid... - - - - - You are already logged in! - - - - - There's a problem with the login. Please make sure you login first and then you try to get videos based on your account. - - - - - Invalid Category. Press 'list categories' to see all possible ones. - - - diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index a8c2ce1..3c13b5c 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -602,7 +602,10 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_7.addLayout(self.gridlayout_tools_hqporner, 0, 0, 1, 1) - self.groupBox_2 = QGroupBox(self.groupbox_tools) + + self.gridLayout_29.addWidget(self.groupbox_tools, 0, 1, 1, 1) + + self.groupBox_2 = QGroupBox(self.page_tools) self.groupBox_2.setObjectName(u"groupBox_2") self.gridLayout_15 = QGridLayout(self.groupBox_2) self.gridLayout_15.setObjectName(u"gridLayout_15") @@ -652,10 +655,7 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_15.addItem(self.verticalSpacer_2, 1, 0, 1, 1) - self.gridLayout_7.addWidget(self.groupBox_2, 0, 2, 1, 1) - - - self.gridLayout_29.addWidget(self.groupbox_tools, 0, 1, 1, 1) + self.gridLayout_29.addWidget(self.groupBox_2, 0, 2, 1, 1) self.stacked_widget_top.addWidget(self.page_tools) From fec5ba985eb08b5d3c21750a60d6cf1a51b3d15e Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Wed, 31 Jul 2024 02:22:13 +0200 Subject: [PATCH 33/39] - improved the ffmpeg installation cleanup Porn Fetch will now check which version of FFmpeg has been installed using a regex search for all files. The version numbers may change in the future, and it should work without manually updating it. This makes it more robust. --- main.py | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/main.py b/main.py index e71ff72..58484e6 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,5 @@ import random +import re import time import sys import os.path @@ -69,8 +70,6 @@ ffmpeg_path = None url_linux = "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz" url_windows = "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip" -ffmpeg_linux = "ffmpeg-6.1-amd64-static" -ffmpeg_windows = "ffmpeg-7.0-essentials_build" android_arch = None session_urls = [] # This list saves all URls used in the current session. Used for the URL export function total_downloaded_videos = 0 @@ -551,6 +550,28 @@ def __init__(self, url, extract_path, mode): self.mode = mode self.signals = Signals() + def delete_dir(self): + files = os.listdir("./") + + for file in files: + try: + search = re.search(pattern=r'ffmpeg-(.*?)-', string=file) # It's all about the version number + if len(search.groups()) == 1: + + if sys.platform == "win32": + shutil.rmtree(f"ffmpeg-{search.group(1)}-essentials_build") + return True + + elif sys.platform == "linux" or sys.platform == "linux2": + shutil.rmtree(f"ffmpeg-{search.group(1)}-amd64-static") + return True + + except AttributeError: + pass + + return False + + def run(self): # Download the file logger.debug(f"Downloading: {self.url}") @@ -603,13 +624,13 @@ def run(self): self.signals.total_progress.emit(total_length, total_length) # Ensure progress bar reaches 100% os.remove(filename) # Clean up downloaded archive - if sys.platform == "linux": - shutil.rmtree(ffmpeg_linux) - elif sys.platform == "win32": - shutil.rmtree(ffmpeg_windows) + if self.delete_dir(): + logger.debug("FFMPEG: [4/4] Cleaned Up") + + else: + logger.error("The Regex for finding the FFmpeg version failed. Please report this on GitHub!, Thanks.") - logger.debug("FFMPEG: [4/4] Cleaned Up") self.signals.finished.emit() From 9884a587af58539e3391b51ecb519a9e39be464b Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Wed, 31 Jul 2024 02:26:51 +0200 Subject: [PATCH 34/39] - last fix for the translations - fixed the deprecation warning for the tar extraction of ffmpeg, which also solves a security issue. --- main.py | 11 ++++------- src/frontend/translations/en.ts | 28 ++++++++++++++-------------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/main.py b/main.py index 58484e6..b8ac2da 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,4 @@ import random -import re import time import sys import os.path @@ -550,9 +549,9 @@ def __init__(self, url, extract_path, mode): self.mode = mode self.signals = Signals() - def delete_dir(self): + @staticmethod + def delete_dir(): files = os.listdir("./") - for file in files: try: search = re.search(pattern=r'ffmpeg-(.*?)-', string=file) # It's all about the version number @@ -571,7 +570,6 @@ def delete_dir(self): return False - def run(self): # Download the file logger.debug(f"Downloading: {self.url}") @@ -602,7 +600,7 @@ def run(self): for idx, member in enumerate(tar.getmembers()): if 'ffmpeg' in member.name and (member.name.endswith('ffmpeg')): - tar.extract(member, self.extract_path) + tar.extract(member, self.extract_path, filter="data") extracted_path = os.path.join(self.extract_path, member.path) shutil.move(extracted_path, "./") @@ -624,7 +622,6 @@ def run(self): self.signals.total_progress.emit(total_length, total_length) # Ensure progress bar reaches 100% os.remove(filename) # Clean up downloaded archive - if self.delete_dir(): logger.debug("FFMPEG: [4/4] Cleaned Up") @@ -1867,7 +1864,7 @@ def load_stylesheet(path): def reset_pornfetch(): setup_config_file(force=True) - ui_popup(QCoreApplication.translate("Done! Please restart.", None)) + ui_popup(QCoreApplication.translate(context, "Done! Please restart.", None)) def switch_stop_state_2(): diff --git a/src/frontend/translations/en.ts b/src/frontend/translations/en.ts index 94bbc00..86006cf 100644 --- a/src/frontend/translations/en.ts +++ b/src/frontend/translations/en.ts @@ -4,12 +4,12 @@ Porn_Fetch - + Saved User Settings, please restart Porn Fetch! - + FFmpeg isn't installed on your system... Some features won't be available: @@ -27,62 +27,62 @@ This warning won't be shown again. - + The output path does not exist or is not writable. - + Enter custom Path: - + Success: {text} will be used for this session! - + Invalid path. The application will now exit. - + Some error occurred in loading a video. Please report this: {error_message} - + Information: The Website {website} specified in the URL file isn't valid. - + Those credentials don't seem to be valid... - + Login Successful! - + Login Failed, please check your credentials and try again! - + You are already logged in! - + There's a problem with the login. Please make sure you login first and then you try to get videos based on your account. - + Invalid Category. Press 'list categories' to see all possible ones. From 53c32955c1f7d676824e0c3fb99adf464894fce2 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Thu, 1 Aug 2024 01:39:01 +0200 Subject: [PATCH 35/39] - fix for the settings layout So I tried to rework the progress system, but hell no I don't do this. I even don't understand it now how my code works :joy: --- src/frontend/form_desktop.ui | 1068 ++++++++++++++++--------------- src/frontend/ui_form_desktop.py | 20 +- 2 files changed, 556 insertions(+), 532 deletions(-) diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 11d5115..e27d9e6 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -6,8 +6,8 @@ 0 0 - 1210 - 869 + 1044 + 795 @@ -106,7 +106,7 @@ 1 - 0 + 1 @@ -1536,70 +1536,348 @@ 0 - - - true - - - - - 0 - 0 - 1188 - 693 - - - - - - - + + + + + true + + + + + 0 + 0 + 1006 + 647 + + + + + + + + + Performance + + + + + + + + Simultaneous downloads: + + + + + + + 1 + + + 5000 + + + + + + + PointingHandCursor + + + Help + + + + + + + + + + + Maximal workers: + + + + + + + 1 + + + 5000 + + + + + + + PointingHandCursor + + + Help + + + + + + + + + + + Maximal timeout: + + + + + + + 5 + + + 5000 + + + + + + + PointingHandCursor + + + Help + + + + + + + + + + + Maximal retries: + + + + + + + 5 + + + 5000 + + + + + + + PointingHandCursor + + + Help + + + + + + + + + + + PornHub Delay (0 = Disabled) in seconds: + + + + + + + 0 + + + 5000 + + + + + + + PointingHandCursor + + + Help + + + + + + + + + + + + 0 + 0 + + + + Threading Mode: + + + + + + + PointingHandCursor + + + High Performance + + + + + + + PointingHandCursor + + + FFMPEG + + + + + + + PointingHandCursor + + + Default + + + + + + + PointingHandCursor + + + Help + + + + + + + + + + + + + + + + PointingHandCursor + + + Apply (needs restart) + + + + + + + PointingHandCursor + + + QPushButton { + background-color: rgb(85, 0, 0)/* Green */ + font: bold 14px; + min-width: 5em; + padding: 3px; + color: white; + border-radius: 10px; +} + +QPushButton:hover { + background-color: rgb(222, 0, 41)/* Lighter green */ +} + +QPushButton:pressed { + background-color: rgb(108, 0, 52) /* Dark green */ +} + + + + Reset Porn Fetch to default settings + + + + + + + - Performance + Videos - - - + + + - + - Simultaneous downloads: + Output path: - - - 1 - - - 5000 + + + Enter "./" for current directory - + PointingHandCursor - Help + Open + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + - - + + - + - Maximal workers: + Result Limit: - + 1 @@ -1609,7 +1887,7 @@ - + PointingHandCursor @@ -1618,91 +1896,157 @@ + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + - - + + - + + + + 0 + 0 + + - Maximal timeout: + Quality: - - - 5 + + + PointingHandCursor - - 5000 + + Best - + PointingHandCursor - Help + Half + + + + PointingHandCursor + + + Worst + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + - - + + - + - Maximal retries: + Skip existing files: - - - 5 - - - 5000 + + + Yes - - - PointingHandCursor + + + No + + + + Help + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + - - + + - + - PornHub Delay (0 = Disabled) in seconds: + Use Directory system? - - - 0 + + + PointingHandCursor - - 5000 + + Yes + + + + + + + PointingHandCursor + + + No - + PointingHandCursor @@ -1711,504 +2055,177 @@ + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + - - + + - - - - 0 - 0 - + + + Model videos (PornHub) + + + + + + + User uploads + + + + + + + Featured videos + + + + - Threading Mode: + Both - + + + Help + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Graphical User Interface + + + + + + PointingHandCursor - High Performance + German - - + + PointingHandCursor - FFMPEG + Chinese (simplified) - - + + PointingHandCursor - Default + English - - + + PointingHandCursor - Help + System default + + + + + + + + 0 + 0 + + + + Graphical User Interface Language: + + + + + + + true + + + French - - - - - - - - - - - PointingHandCursor - - - Apply (needs restart) - - - - - - - PointingHandCursor - - - QPushButton { - background-color: rgb(85, 0, 0)/* Green */ - font: bold 14px; - min-width: 5em; - padding: 3px; - color: white; - border-radius: 10px; -} - -QPushButton:hover { - background-color: rgb(222, 0, 41)/* Lighter green */ -} - -QPushButton:pressed { - background-color: rgb(108, 0, 52) /* Dark green */ -} - - - - Reset Porn Fetch to default settings - - - - - - - - - Videos - - - - - - - - Output path: - - - - - - - Enter "./" for current directory - - - - - - - PointingHandCursor - - - Open - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Result Limit: - - - - - - - 1 - - - 5000 - - - - - - - PointingHandCursor - - - Help - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 0 - - - - Quality: - - - - - - - PointingHandCursor - - - Best - - - - - - - PointingHandCursor - - - Half - - - - - - - PointingHandCursor - - - Worst - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Skip existing files: - - - - - - - Yes - - - - - - - No - - - - - - - Help - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Use Directory system? - - - - - - - PointingHandCursor - - - Yes - - - - - - - PointingHandCursor - - - No - - - - - - - PointingHandCursor - - - Help - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Model videos (PornHub) - - - - - - - User uploads - - - - - - - Featured videos - - - - - - - Both - - - - - - - Help - - - - - + + - Qt::Orientation::Horizontal + Qt::Orientation::Vertical - 40 - 20 + 20 + 40 - - - - - - - - Graphical User Interface - - - - - - - - PointingHandCursor - - - German - - - - - - - PointingHandCursor - - - Chinese (simplified) - - - - - - - PointingHandCursor - - - English - - - - - - - PointingHandCursor - - - System default - - - - - - - - 0 - 0 - - - - Graphical User Interface Language: - - - - - - - true - - - French - - - - - - - - - - - - Download and Setup FFmpeg - - - - - - + + + + + + Download and Setup FFmpeg + + + + + + + + @@ -2685,7 +2702,6 @@ QPushButton:pressed { lineedit_videos_by_category_eporner button_eporner_category_get_videos button_list_categories_eporner - scrollarea_settings button_download_ffmpeg radio_threading_mode_high_performance radio_threading_mode_ffmpeg diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index 3c13b5c..2055e0c 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -26,7 +26,7 @@ class Ui_Porn_Fetch_Widget(object): def setupUi(self, Porn_Fetch_Widget): if not Porn_Fetch_Widget.objectName(): Porn_Fetch_Widget.setObjectName(u"Porn_Fetch_Widget") - Porn_Fetch_Widget.resize(1210, 869) + Porn_Fetch_Widget.resize(1044, 795) sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -799,12 +799,14 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_25.setSpacing(0) self.gridLayout_25.setObjectName(u"gridLayout_25") self.gridLayout_25.setContentsMargins(0, 0, 0, 0) + self.verticalLayout = QVBoxLayout() + self.verticalLayout.setObjectName(u"verticalLayout") self.scrollarea_settings = QScrollArea(self.page_settings) self.scrollarea_settings.setObjectName(u"scrollarea_settings") self.scrollarea_settings.setWidgetResizable(True) self.scrollAreaWidgetContents_6 = QWidget() self.scrollAreaWidgetContents_6.setObjectName(u"scrollAreaWidgetContents_6") - self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 1188, 693)) + self.scrollAreaWidgetContents_6.setGeometry(QRect(0, -24, 1006, 647)) self.gridLayout_19 = QGridLayout(self.scrollAreaWidgetContents_6) self.gridLayout_19.setObjectName(u"gridLayout_19") self.gridlayout_settings = QGridLayout() @@ -1238,6 +1240,10 @@ def setupUi(self, Porn_Fetch_Widget): self.gridLayout_12.addLayout(self.gridlayout_gui_settings, 0, 0, 1, 1) + self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) + + self.gridLayout_12.addItem(self.verticalSpacer_3, 1, 0, 1, 1) + self.gridLayout_19.addWidget(self.goroupbox_gui, 3, 0, 1, 2) @@ -1248,7 +1254,10 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_settings.setWidget(self.scrollAreaWidgetContents_6) - self.gridLayout_25.addWidget(self.scrollarea_settings, 0, 0, 1, 1) + self.verticalLayout.addWidget(self.scrollarea_settings) + + + self.gridLayout_25.addLayout(self.verticalLayout, 0, 0, 1, 1) self.stacked_widget_main.addWidget(self.page_settings) self.page_credits = QWidget() @@ -1496,8 +1505,7 @@ def setupUi(self, Porn_Fetch_Widget): QWidget.setTabOrder(self.button_list_categories, self.lineedit_videos_by_category_eporner) QWidget.setTabOrder(self.lineedit_videos_by_category_eporner, self.button_eporner_category_get_videos) QWidget.setTabOrder(self.button_eporner_category_get_videos, self.button_list_categories_eporner) - QWidget.setTabOrder(self.button_list_categories_eporner, self.scrollarea_settings) - QWidget.setTabOrder(self.scrollarea_settings, self.button_download_ffmpeg) + QWidget.setTabOrder(self.button_list_categories_eporner, self.button_download_ffmpeg) QWidget.setTabOrder(self.button_download_ffmpeg, self.radio_threading_mode_high_performance) QWidget.setTabOrder(self.radio_threading_mode_high_performance, self.radio_threading_mode_ffmpeg) QWidget.setTabOrder(self.radio_threading_mode_ffmpeg, self.radio_threading_mode_default) @@ -1534,7 +1542,7 @@ def setupUi(self, Porn_Fetch_Widget): self.retranslateUi(Porn_Fetch_Widget) - self.stacked_widget_main.setCurrentIndex(0) + self.stacked_widget_main.setCurrentIndex(1) self.stacked_widget_top.setCurrentIndex(3) From c0ca0d55b8479808fca4a0f243c347d26c6add96 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Thu, 1 Aug 2024 01:59:06 +0200 Subject: [PATCH 36/39] - added downloading support for spankbang --- Porn_Fetch_CLI.py | 23 ++-- README.md | 3 +- main.py | 22 ++- src/frontend/form_desktop.ui | 130 ++++++++++-------- src/frontend/qressource_file.qrc | 1 + src/frontend/resources.py | 102 +++++++++----- .../stylesheets/progressbar_spankbang.qss | 12 ++ src/frontend/ui_form_desktop.py | 96 +++++++------ 8 files changed, 236 insertions(+), 153 deletions(-) create mode 100644 src/frontend/stylesheets/progressbar_spankbang.qss diff --git a/Porn_Fetch_CLI.py b/Porn_Fetch_CLI.py index 10ba69b..ec839c5 100644 --- a/Porn_Fetch_CLI.py +++ b/Porn_Fetch_CLI.py @@ -3,12 +3,15 @@ import phub.consts from src.backend.shared_functions import * +from src.backend.log_config import setup_logging from base_api.modules.download import * from base_api.modules.progress_bars import * from base_api.base import Core from rich import print as rprint from rich.markdown import Markdown +logger = setup_logging() + class CLI: def __init__(self): @@ -127,8 +130,8 @@ def load_user_settings(self): phub.consts.FFMPEG_EXECUTABLE = self.ffmpeg_path else: - logger_error("FFMPEG wasn't found... Have you extracted it from the .zip file?") - logger_error("FFMPEG Features won't be available!") + logger.warning("FFMPEG wasn't found... Have you extracted it from the .zip file?") + logger.warning("FFMPEG Features won't be available!") self.ffmpeg_features = False def save_user_settings(self): @@ -333,7 +336,7 @@ def search_videos(self): self.iterate_generator(Client().search(query)) elif website == "2": - self.iterate_generator(hq_Client().search_videos(query=query, pages=10)) + self.iterate_generator(hq_Client().search_videos(query=query)) elif website == "3": self.iterate_generator(xv_Client().search(query)) @@ -342,9 +345,9 @@ def search_videos(self): self.iterate_generator(xn_Client().search(query).videos) elif website == "5": - self.iterate_generator(ep_Client().search_videos(query, page=1, per_page=self.result_limit, + self.iterate_generator(ep_Client().search_videos(query, per_page=self.result_limit, sorting_order="", sorting_gay="", sorting_low_quality="", - enable_html_scraping=True)) + enable_html_scraping=True, page=1)) def process_file(self): videos = [] @@ -364,14 +367,14 @@ def process_file(self): else: videos.append(line) - logger_debug(f"{return_color()}Processing Models / Videos...") + logger.debug(f"{return_color()}Processing Models / Videos...") for video in videos: - objects.append(check_video(video, language=self.language, delay=self.delay)) + objects.append(check_video(video, delay=self.delay)) for video in models: objects.append(video) - logger_debug(f"{return_color()}Done!") + logger.debug(f"{return_color()}Done!") self.iterate_generator(objects) def download(self, video, output_path): @@ -390,7 +393,7 @@ def download(self, video, output_path): callback=Callback.text_progress_bar) finally: - logger_debug(f"{return_color()}Finished downloading for: {video.title}") + logger.debug(f"{return_color()}Finished downloading for: {video.title}") self.semaphore.release() if self.ffmpeg_features: os.rename(f"{output_path}", f"{output_path}_.tmp") @@ -403,7 +406,7 @@ def download(self, video, output_path): os.remove(f"{output_path}_.tmp") write_tags(path=output_path, video=video, ffmpeg_path=None) else: - logger_debug("FFMPEG features disabled, writing tags and converting the video won't be available!") + logger.debug("FFMPEG features disabled, writing tags and converting the video won't be available!") @staticmethod def credits(): diff --git a/README.md b/README.md index aa1d63c..2aa6cf3 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ - Multiple user interface languages - Native Android application - modern looking user interface +- Supports over 115 MB/s download speed thanks to well optimized HLS downloading ## General Information > [!NOTE] @@ -63,7 +64,7 @@ - Windows (10 / 11) - Linux (X11 / Wayland) -- Android +- Android (Android is very unstable, please consider using the CLI on Termux instead!) - macOS (Untested) The Graphical User Interface is only for 64bit systems. The CLI supports 64 and 32bit systems. diff --git a/main.py b/main.py index b8ac2da..5987099 100644 --- a/main.py +++ b/main.py @@ -85,6 +85,7 @@ class Signals(QObject): progress_eporner = Signal(int, int) progress_xnxx = Signal(int, int) progress_xvideos = Signal(int, int) + progress_spankbang = Signal(int, int) total_progress = Signal(int, int) progress_video = Signal(object) ffmpeg_progress = Signal(int, int) @@ -302,6 +303,7 @@ def __init__(self, video, quality, output_path, threading_mode, workers, timeout 'eporner': self.signals.progress_eporner, 'xnxx': self.signals.progress_xnxx, 'xvideos': self.signals.progress_xvideos, + 'spankbang': self.signals.progress_spankbang } def generic_callback(self, pos, total, signal, video_source, ffmpeg=False): @@ -405,19 +407,24 @@ def run(self): elif isinstance(self.video, xn_Video): video_source = "xnxx" - self.video.download(downloader=self.threading_mode, path=self.output_path, - quality=self.quality, + self.video.download(downloader=self.threading_mode, path=self.output_path, quality=self.quality, callback=lambda pos, total: self.generic_callback(pos, total, self.signals.progress_xnxx, video_source, self.ffmpeg)) elif isinstance(self.video, xv_Video): video_source = "xvideos" - self.video.download(downloader=self.threading_mode, path=self.output_path, - quality=self.quality, + self.video.download(downloader=self.threading_mode, path=self.output_path, quality=self.quality, callback=lambda pos, total: self.generic_callback(pos, total, self.signals.progress_xvideos, video_source, self.ffmpeg)) + elif isinstance(self.video, sp_Video): + video_source = "spankbang" + self.video.download(downloader=self.threading_mode, path=self.output_path, quality=self.quality, + callback=lambda pos, total: self.generic_callback(pos, total, + self.signals.progress_spankbang, + video_source, self.ffmpeg), + no_title=True, use_hls=True) # ... other video types ... @@ -876,6 +883,7 @@ def load_style(self): "progressbar_total": ":/style/stylesheets/progressbar_total.qss", "progressbar_xnxx": ":/style/stylesheets/progressbar_xnxx.qss", "progressbar_xvideos": ":/style/stylesheets/progressbar_xvideos.qss", + "progressbar_spankbang": ":/style/stylesheets/progressbar_spankbang.qss", "progressbar_converting": ":/style/stylesheets/progressbar_converting.qss", "button_blue": ":/style/stylesheets/stylesheet_button_blue.qss", "button_orange": ":/style/stylesheets/stylesheet_button_orange.qss", @@ -896,6 +904,7 @@ def load_style(self): self.ui.progressbar_eporner.setStyleSheet(stylesheets["progressbar_eporner"]) self.ui.progressbar_hqporner.setStyleSheet(stylesheets["progressbar_hqporner"]) self.ui.progressbar_xvideos.setStyleSheet(stylesheets["progressbar_xvideos"]) + self.ui.progressbar_spankbang.setStyleSheet(stylesheets["progressbar_spankbang"]) self.ui.progressbar_converting.setStyleSheet(stylesheets["progressbar_converting"]) self.ui.button_model.setStyleSheet(stylesheets["button_purple"]) self.ui.button_search.setStyleSheet(stylesheets["button_purple"]) @@ -1482,6 +1491,7 @@ def process_video_thread(self, output_path, video, threading_mode, quality): self.download_thread.signals.progress_eporner.connect(self.update_progressbar_eporner) self.download_thread.signals.progress_xnxx.connect(self.update_progressbar_xnxx) self.download_thread.signals.progress_xvideos.connect(self.update_progressbar_xvideos) + self.download_thread.signals.progress_spankbang.connect(self.update_progressbar_spankbang) self.download_thread.signals.ffmpeg_progress.connect(self.update_converting) # ADAPTION self.download_thread.signals.completed.connect(self.download_completed) @@ -1527,6 +1537,10 @@ def update_progressbar_xvideos(self, value, maximum): self.ui.progressbar_xvideos.setMaximum(maximum) self.ui.progressbar_xvideos.setValue(value) + def update_progressbar_spankbang(self, value, maximum): + self.ui.progressbar_spankbang.setMaximum(maximum) + self.ui.progressbar_spankbang.setValue(value) + # ADAPTION def download_completed(self): """If a video is downloaded, the semaphore is released""" diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index e27d9e6..06f599b 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -106,7 +106,7 @@ 1 - 1 + 0 @@ -148,7 +148,7 @@ 1 - 3 + 2 @@ -746,8 +746,8 @@ 0 0 - 383 - 206 + 1020 + 246 @@ -760,42 +760,18 @@ - - - - - 0 - 0 - - - - PornHub: - - - - - - - XVideos - - - - - + + - XNXX + - - - - - - 0 + + true - - + + 0 @@ -803,7 +779,7 @@ - HQPorner: + PornHub: @@ -826,6 +802,26 @@ + + + + XVideos: + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + @@ -845,19 +841,6 @@ - - - - Qt::Orientation::Vertical - - - - 20 - 40 - - - - @@ -868,24 +851,55 @@ - Eporner + Eporner: - + + + + XNXX: + + + + + + + 0 + + + + Info: - - + + + + + 0 + 0 + + - + HQPorner: - - true + + + + + + Spankbang: + + + + + + + 0 @@ -1255,8 +1269,8 @@ 0 0 - 1186 - 363 + 1020 + 289 diff --git a/src/frontend/qressource_file.qrc b/src/frontend/qressource_file.qrc index fc3dd36..6d2aa7b 100644 --- a/src/frontend/qressource_file.qrc +++ b/src/frontend/qressource_file.qrc @@ -21,6 +21,7 @@ stylesheets/progressbar_eporner.qss stylesheets/progressbar_xnxx.qss stylesheets/progressbar_xvideos.qss + stylesheets/progressbar_spankbang.qss stylesheets/progressbar_total.qss stylesheets/progressbar_converting.qss stylesheets/stylesheet_button_blue.qss diff --git a/src/frontend/resources.py b/src/frontend/resources.py index 51a8f6e..3e96af7 100644 --- a/src/frontend/resources.py +++ b/src/frontend/resources.py @@ -9193,6 +9193,25 @@ color: #1976D2; \ /* Darker blue *\ /\x0a}\x0a\ +\x00\x00\x01\x0b\ +Q\ +ProgressBar {\x0a \ + color: #E0E0E0\ +;\x0a border: 2p\ +x solid #5A2A82;\ +\x0a border-radi\ +us: 5px;\x0a tex\ +t-align: center;\ +\x0a background-\ +color: #3C3C3C;\x0a\ +}\x0a\x0aQProgressBar:\ +:chunk {\x0a bac\ +kground-color: r\ +gb(255, 0, 81); \ +/* Adjusted to a\ + consistent mage\ +nta */\x0a width\ +: 20px;\x0a}\x0a\ \x00\x00\x06&\ \x00\ \x00\x18\x22x\xda\xddXko\xdb6\x14\xfd\xee_q\ @@ -10759,6 +10778,11 @@ \x00s\ \x00t\x00y\x00l\x00e\x00s\x00h\x00e\x00e\x00t\x00_\x00b\x00u\x00t\x00t\x00o\x00n\ \x00_\x00b\x00l\x00u\x00e\x00.\x00q\x00s\x00s\ +\x00\x19\ +\x06O\x9b#\ +\x00p\ +\x00r\x00o\x00g\x00r\x00e\x00s\x00s\x00b\x00a\x00r\x00_\x00s\x00p\x00a\x00n\x00k\ +\x00b\x00a\x00n\x00g\x00.\x00q\x00s\x00s\ \x00\x06\ \x05iY\x15\ \x00R\ @@ -10794,76 +10818,78 @@ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x06\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x05\x86\x00\x00\x00\x00\x00\x01\x00\x02@j\ -\x00\x00\x01\x90O\xb8\x19Y\ -\x00\x00\x05\x96\x00\x01\x00\x00\x00\x01\x00\x02[j\ -\x00\x00\x01\x90O\xb8\x19Y\ -\x00\x00\x05\xac\x00\x00\x00\x00\x00\x01\x00\x02{!\ -\x00\x00\x01\x90O\xb8\x19Y\ -\x00\x00\x05Z\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0a\ +\x00\x00\x05\xbe\x00\x00\x00\x00\x00\x01\x00\x02Ay\ +\x00\x00\x01\x90\xc8\x93\xd8O\ +\x00\x00\x05\xce\x00\x01\x00\x00\x00\x01\x00\x02\x5cy\ +\x00\x00\x01\x90\xc8\x93\xd8L\ +\x00\x00\x05\xe4\x00\x00\x00\x00\x00\x01\x00\x02|0\ +\x00\x00\x01\x90\xc8\x93\xd8O\ +\x00\x00\x05\x92\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0a\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x05l\x00\x01\x00\x00\x00\x01\x00\x02:@\ -\x00\x00\x01\x90O\xe2\x09u\ +\x00\x00\x05\xa4\x00\x01\x00\x00\x00\x01\x00\x02;O\ +\x00\x00\x01\x90\xfa;(\x8b\ \x00\x00\x00T\x00\x02\x00\x00\x00\x0d\x00\x00\x00\x0c\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x01\xbc\x00\x01\x00\x00\x00\x01\x00\x02\x1d\x8a\ -\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01\x90\xc8\x93\xd8B\ \x00\x00\x01b\x00\x00\x00\x00\x00\x01\x00\x01\xbfk\ -\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01\x90\xc8\x93\xd8B\ \x00\x00\x00\xca\x00\x00\x00\x00\x00\x01\x00\x00\x17S\ -\x00\x00\x01\x90O\xe1+5\ +\x00\x00\x01\x90\xfa;(\x8f\ \x00\x00\x00j\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x90O\xb8\x19R\ +\x00\x00\x01\x90\xc8\x93\xd8I\ \x00\x00\x00\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x16f\ -\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01\x90\xc8\x93\xd8B\ \x00\x00\x01\x10\x00\x00\x00\x00\x00\x01\x00\x00\x223\ -\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01\x90\xc8\x93\xd8B\ \x00\x00\x014\x00\x00\x00\x00\x00\x01\x00\x00&M\ -\x00\x00\x01\x90O\xb8\x19O\ +\x00\x00\x01\x90\xc8\x93\xd8E\ \x00\x00\x01\x9e\x00\x01\x00\x00\x00\x01\x00\x01\xd1J\ -\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01\x90\xc8\x93\xd8B\ \x00\x00\x01\x84\x00\x00\x00\x00\x00\x01\x00\x01\xce.\ -\x00\x00\x01\x90O\xb8\x19R\ +\x00\x00\x01\x90\xc8\x93\xd8I\ \x00\x00\x00\x82\x00\x00\x00\x00\x00\x01\x00\x00\x06\xea\ -\x00\x00\x01\x90O\xb8\x19R\ +\x00\x00\x01\x90\xc8\x93\xd8I\ \x00\x00\x00\xa0\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xf0\ -\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01\x90\xc8\x93\xd8B\ \x00\x00\x01\xd2\x00\x00\x00\x00\x00\x01\x00\x02\x22W\ -\x00\x00\x01\x90O\xb8\x19K\ +\x00\x00\x01\x90\xc8\x93\xd8B\ \x00\x00\x00\xf0\x00\x00\x00\x00\x00\x01\x00\x00\x18P\ -\x00\x00\x01\x90O\xb8\x19R\ -\x00\x00\x01\xee\x00\x02\x00\x00\x00\x0f\x00\x00\x00\x1a\ +\x00\x00\x01\x90\xc8\x93\xd8I\ +\x00\x00\x01\xee\x00\x02\x00\x00\x00\x10\x00\x00\x00\x1a\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x02\xee\x00\x00\x00\x00\x00\x01\x00\x02,\x11\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x02\x0a\x00\x01\x00\x00\x00\x01\x00\x02%1\ -\x00\x00\x01\x90U\xf8\x86\xa9\ +\x00\x00\x01\x90\xfa;(\x92\ \x00\x00\x03Z\x00\x00\x00\x00\x00\x01\x00\x02.\xcb\ -\x00\x00\x01\x90O\xb8\x19U\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x03\x1c\x00\x00\x00\x00\x00\x01\x00\x02-\x15\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ +\x00\x00\x05Z\x00\x00\x00\x00\x00\x01\x00\x02:@\ +\x00\x00\x01\x91\x0b4\x02\x11\ \x00\x00\x02\xb8\x00\x00\x00\x00\x00\x01\x00\x02+\x0b\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x04\xb6\x00\x00\x00\x00\x00\x01\x00\x025\xfd\ -\x00\x00\x01\x90O\xb8\x19U\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x05 \x00\x00\x00\x00\x00\x01\x00\x028\xc7\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x04\x82\x00\x00\x00\x00\x00\x01\x00\x024\xf6\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x04F\x00\x00\x00\x00\x00\x01\x00\x023\xca\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x04\x08\x00\x00\x00\x00\x00\x01\x00\x022\xb6\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x04\xf0\x00\x00\x00\x00\x00\x01\x00\x027\xc3\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x03\x8e\x00\x00\x00\x00\x00\x01\x00\x020\x8a\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x02`\x00\x00\x00\x00\x00\x01\x00\x02*\x01\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x03\xca\x00\x00\x00\x00\x00\x01\x00\x021\x9c\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ \x00\x00\x02,\x00\x00\x00\x00\x00\x01\x00\x02(\xfb\ -\x00\x00\x01\x90O\xb8\x19Y\ +\x00\x00\x01\x90\xc8\x93\xd8L\ " def qInitResources(): diff --git a/src/frontend/stylesheets/progressbar_spankbang.qss b/src/frontend/stylesheets/progressbar_spankbang.qss new file mode 100644 index 0000000..7a59d37 --- /dev/null +++ b/src/frontend/stylesheets/progressbar_spankbang.qss @@ -0,0 +1,12 @@ +QProgressBar { + color: #E0E0E0; + border: 2px solid #5A2A82; + border-radius: 5px; + text-align: center; + background-color: #3C3C3C; +} + +QProgressBar::chunk { + background-color: rgb(255, 0, 81); /* Adjusted to a consistent magenta */ + width: 20px; +} diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index 2055e0c..fc0a39e 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -391,7 +391,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 383, 206)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1020, 246)) self.gridLayout_18 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_18.setObjectName(u"gridLayout_18") self.gridlayout_progressbar = QGridLayout() @@ -402,6 +402,12 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_progressbar.addWidget(self.progressbar_xvideos, 4, 1, 1, 1) + self.lineedit_download_info = QLineEdit(self.scrollAreaWidgetContents) + self.lineedit_download_info.setObjectName(u"lineedit_download_info") + self.lineedit_download_info.setReadOnly(True) + + self.gridlayout_progressbar.addWidget(self.lineedit_download_info, 6, 1, 1, 1) + self.label_progress_pornhub = QLabel(self.scrollAreaWidgetContents) self.label_progress_pornhub.setObjectName(u"label_progress_pornhub") sizePolicy2.setHeightForWidth(self.label_progress_pornhub.sizePolicy().hasHeightForWidth()) @@ -409,29 +415,6 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_progressbar.addWidget(self.label_progress_pornhub, 0, 0, 1, 1) - self.label_progress_xvideos = QLabel(self.scrollAreaWidgetContents) - self.label_progress_xvideos.setObjectName(u"label_progress_xvideos") - - self.gridlayout_progressbar.addWidget(self.label_progress_xvideos, 4, 0, 1, 1) - - self.label_progress_xnxx = QLabel(self.scrollAreaWidgetContents) - self.label_progress_xnxx.setObjectName(u"label_progress_xnxx") - - self.gridlayout_progressbar.addWidget(self.label_progress_xnxx, 3, 0, 1, 1) - - self.progressbar_xnxx = QProgressBar(self.scrollAreaWidgetContents) - self.progressbar_xnxx.setObjectName(u"progressbar_xnxx") - self.progressbar_xnxx.setValue(0) - - self.gridlayout_progressbar.addWidget(self.progressbar_xnxx, 3, 1, 1, 1) - - self.label_progress_hqporner = QLabel(self.scrollAreaWidgetContents) - self.label_progress_hqporner.setObjectName(u"label_progress_hqporner") - sizePolicy2.setHeightForWidth(self.label_progress_hqporner.sizePolicy().hasHeightForWidth()) - self.label_progress_hqporner.setSizePolicy(sizePolicy2) - - self.gridlayout_progressbar.addWidget(self.label_progress_hqporner, 1, 0, 1, 1) - self.progressbar_hqporner = QProgressBar(self.scrollAreaWidgetContents) self.progressbar_hqporner.setObjectName(u"progressbar_hqporner") sizePolicy1.setHeightForWidth(self.progressbar_hqporner.sizePolicy().hasHeightForWidth()) @@ -441,6 +424,15 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_progressbar.addWidget(self.progressbar_hqporner, 1, 1, 1, 1) + self.label_progress_xvideos = QLabel(self.scrollAreaWidgetContents) + self.label_progress_xvideos.setObjectName(u"label_progress_xvideos") + + self.gridlayout_progressbar.addWidget(self.label_progress_xvideos, 4, 0, 1, 1) + + self.verticalspacer_progress_bars = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) + + self.gridlayout_progressbar.addItem(self.verticalspacer_progress_bars, 7, 1, 1, 1) + self.progressbar_pornhub = QProgressBar(self.scrollAreaWidgetContents) self.progressbar_pornhub.setObjectName(u"progressbar_pornhub") sizePolicy1.setHeightForWidth(self.progressbar_pornhub.sizePolicy().hasHeightForWidth()) @@ -450,10 +442,6 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_progressbar.addWidget(self.progressbar_pornhub, 0, 1, 1, 1) - self.verticalspacer_progress_bars = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) - - self.gridlayout_progressbar.addItem(self.verticalspacer_progress_bars, 6, 1, 1, 1) - self.progressbar_eporner = QProgressBar(self.scrollAreaWidgetContents) self.progressbar_eporner.setObjectName(u"progressbar_eporner") self.progressbar_eporner.setValue(0) @@ -465,16 +453,39 @@ def setupUi(self, Porn_Fetch_Widget): self.gridlayout_progressbar.addWidget(self.label_progress_eporner, 2, 0, 1, 1) + self.label_progress_xnxx = QLabel(self.scrollAreaWidgetContents) + self.label_progress_xnxx.setObjectName(u"label_progress_xnxx") + + self.gridlayout_progressbar.addWidget(self.label_progress_xnxx, 3, 0, 1, 1) + + self.progressbar_xnxx = QProgressBar(self.scrollAreaWidgetContents) + self.progressbar_xnxx.setObjectName(u"progressbar_xnxx") + self.progressbar_xnxx.setValue(0) + + self.gridlayout_progressbar.addWidget(self.progressbar_xnxx, 3, 1, 1, 1) + self.label_info = QLabel(self.scrollAreaWidgetContents) self.label_info.setObjectName(u"label_info") - self.gridlayout_progressbar.addWidget(self.label_info, 5, 0, 1, 1) + self.gridlayout_progressbar.addWidget(self.label_info, 6, 0, 1, 1) - self.lineedit_download_info = QLineEdit(self.scrollAreaWidgetContents) - self.lineedit_download_info.setObjectName(u"lineedit_download_info") - self.lineedit_download_info.setReadOnly(True) + self.label_progress_hqporner = QLabel(self.scrollAreaWidgetContents) + self.label_progress_hqporner.setObjectName(u"label_progress_hqporner") + sizePolicy2.setHeightForWidth(self.label_progress_hqporner.sizePolicy().hasHeightForWidth()) + self.label_progress_hqporner.setSizePolicy(sizePolicy2) + + self.gridlayout_progressbar.addWidget(self.label_progress_hqporner, 1, 0, 1, 1) + + self.label_progress_spankbang = QLabel(self.scrollAreaWidgetContents) + self.label_progress_spankbang.setObjectName(u"label_progress_spankbang") + + self.gridlayout_progressbar.addWidget(self.label_progress_spankbang, 5, 0, 1, 1) + + self.progressbar_spankbang = QProgressBar(self.scrollAreaWidgetContents) + self.progressbar_spankbang.setObjectName(u"progressbar_spankbang") + self.progressbar_spankbang.setValue(0) - self.gridlayout_progressbar.addWidget(self.lineedit_download_info, 5, 1, 1, 1) + self.gridlayout_progressbar.addWidget(self.progressbar_spankbang, 5, 1, 1, 1) self.gridLayout_18.addLayout(self.gridlayout_progressbar, 1, 0, 1, 1) @@ -666,7 +677,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_treewidget.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") - self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1186, 363)) + self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1020, 289)) self.gridLayout_4 = QGridLayout(self.scrollAreaWidgetContents_3) self.gridLayout_4.setObjectName(u"gridLayout_4") self.verticallayout_treewidget_settings = QVBoxLayout() @@ -806,7 +817,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_settings.setWidgetResizable(True) self.scrollAreaWidgetContents_6 = QWidget() self.scrollAreaWidgetContents_6.setObjectName(u"scrollAreaWidgetContents_6") - self.scrollAreaWidgetContents_6.setGeometry(QRect(0, -24, 1006, 647)) + self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 1006, 647)) self.gridLayout_19 = QGridLayout(self.scrollAreaWidgetContents_6) self.gridLayout_19.setObjectName(u"gridLayout_19") self.gridlayout_settings = QGridLayout() @@ -1542,8 +1553,8 @@ def setupUi(self, Porn_Fetch_Widget): self.retranslateUi(Porn_Fetch_Widget) - self.stacked_widget_main.setCurrentIndex(1) - self.stacked_widget_top.setCurrentIndex(3) + self.stacked_widget_main.setCurrentIndex(0) + self.stacked_widget_top.setCurrentIndex(2) QMetaObject.connectSlotsByName(Porn_Fetch_Widget) @@ -1588,13 +1599,14 @@ def retranslateUi(self, Porn_Fetch_Widget): self.button_get_recommended_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get recommended videos", None)) self.label_password.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Password:", None)) self.lineedit_password.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter your PornHub Password", None)) + self.lineedit_download_info.setText("") self.label_progress_pornhub.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"PornHub:", None)) - self.label_progress_xvideos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XVideos", None)) - self.label_progress_xnxx.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XNXX", None)) - self.label_progress_hqporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"HQPorner:", None)) - self.label_progress_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Eporner", None)) + self.label_progress_xvideos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XVideos:", None)) + self.label_progress_eporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Eporner:", None)) + self.label_progress_xnxx.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"XNXX:", None)) self.label_info.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Info:", None)) - self.lineedit_download_info.setText("") + self.label_progress_hqporner.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"HQPorner:", None)) + self.label_progress_spankbang.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Spankbang:", None)) self.groupbox_tools.setTitle(QCoreApplication.translate("Porn_Fetch_Widget", u"HQPorner", None)) self.radio_top_porn_month.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Month", None)) self.radio_top_porn_all_time.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"All Time", None)) From f5a705d164496ba91c71397ef01bb576ca0468ff Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Sun, 4 Aug 2024 00:32:44 +0200 Subject: [PATCH 37/39] - added downloading support for spankbang in the ClI - fixed the CLI in general --- Porn_Fetch_CLI.py | 50 ++++++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/Porn_Fetch_CLI.py b/Porn_Fetch_CLI.py index ec839c5..8214cbb 100644 --- a/Porn_Fetch_CLI.py +++ b/Porn_Fetch_CLI.py @@ -15,6 +15,7 @@ class CLI: def __init__(self): + self.skip_existing_files = None self.threading_mode = None self.result_limit = None self.directory_system = None @@ -109,7 +110,6 @@ def menu(self): sys.exit(0) def load_user_settings(self): - self.language = self.conf.get("Video", "language") self.delay = int(self.conf.get("Video", "delay")) self.workers = int(self.conf.get("Performance", "workers")) self.timeout = int(self.conf.get("Performance", "timeout")) @@ -118,6 +118,7 @@ def load_user_settings(self): self.quality = self.conf.get("Video", "quality") self.output_path = correct_output_path(output_path=self.conf.get("Video", "output_path")) self.directory_system = True if self.conf.get("Video", "directory_system") == "1" else False + self.skip_existing_files = True if self.conf.get("Video", "skip_existing_files") == "true" else False self.result_limit = int(self.conf.get("Video", "search_limit")) self.threading_mode = self.conf.get("Performance", "threading_mode") @@ -135,19 +136,6 @@ def load_user_settings(self): self.ffmpeg_features = False def save_user_settings(self): - languages = f"""{Fore.WHITE} -de: German -en: English -fr: French -zh: Chinese -rt: Russian -nl: Dutch -es: Spanish -it: Italian -pt: Portuguese -cz: Czech -jp: Japanese -""" while True: settings_options = input(f""" {Fore.WHITE}--------- {Fore.LIGHTGREEN_EX}Quality {Fore.WHITE}---------- @@ -164,10 +152,8 @@ def save_user_settings(self): {return_color()}9) Enable / Disable directory system {Fore.WHITE}-------- {return_color()}Result Limit {Fore.WHITE}------- {return_color()}10) Change result limit -{Fore.WHITE}-------- {return_color()}Language (Video titles for PornHub){Fore.WHITE} -{return_color()}11) Change Language {Fore.WHITE}-------- {return_color()}Output Path {Fore.WHITE}-------- -{return_color()}12) Change output path +{return_color()}11) Change output path {Fore.LIGHTRED_EX}99) Exit {return_color()}------------->:""") @@ -214,15 +200,9 @@ def save_user_settings(self): self.conf.set("Video", "search_limit", limit) elif settings_options == "11": - print("Please enter a language code from the list below:") - print(languages) - language = input(f"Enter the new language code -->:") - self.conf.set("Video", "language", language) - - elif settings_options == "12": path = input(f"Enter a new output path -->:") if not os.path.exists(path): - raise FileNotFoundError("The specified output path doesn't exist!") + raise "The specified output path doesn't exist!" self.conf.set("Video", "output_path", path) @@ -237,7 +217,7 @@ def process_video(self, url=None): if url is None: url = input(f"{return_color()}Please enter the Video URL -->:") - video = check_video(url=url, language=self.language, delay=self.delay) + video = check_video(url=url, delay=self.delay) title = Core().strip_title(video.title) if isinstance(video, Video): @@ -258,10 +238,10 @@ def process_video(self, url=None): output_path = pathlib.Path(output_path + title + ".mp4") if os.path.exists(output_path): - logger_debug(f"{return_color()}File: {output_path} already exists, skipping...") + logger.debug(f"{return_color()}File: {output_path} already exists, skipping...") return - logger_debug(f"{return_color()}Trying to acquire the semaphore...") + logger.debug(f"{return_color()}Trying to acquire the semaphore...") self.semaphore.acquire() self.thread = threading.Thread(target=self.download, args=(video, output_path,)) self.thread.start() @@ -383,14 +363,15 @@ def download(self, video, output_path): self.threading_mode = resolve_threading_mode(mode=self.threading_mode, video=video, workers=self.workers, timeout=self.timeout) video.download(path=output_path, quality=self.quality, downloader=self.threading_mode, - display=Callback.text_progress_bar) + display=self.callback_wrapper(video.title, Callback.text_progress_bar)) elif isinstance(video, ep_Video) or isinstance(video, hq_Video): - video.download(path=output_path, quality=self.quality, callback=Callback.text_progress_bar) + video.download(path=output_path, quality=self.quality, callback=self.callback_wrapper(video.title, + Callback.text_progress_bar)) else: video.download(downloader=self.threading_mode, path=output_path, quality=self.quality, - callback=Callback.text_progress_bar) + callback=self.callback_wrapper(video.title, Callback.text_progress_bar)) finally: logger.debug(f"{return_color()}Finished downloading for: {video.title}") @@ -404,10 +385,17 @@ def download(self, video, output_path): print(f"\r\033[K[Converting: {progress}/100", end='', flush=True) os.remove(f"{output_path}_.tmp") - write_tags(path=output_path, video=video, ffmpeg_path=None) + write_tags(path=output_path, video=video) else: logger.debug("FFMPEG features disabled, writing tags and converting the video won't be available!") + @staticmethod + def callback_wrapper(title, callback): + def wrapped_callback(pos, total): + callback(pos, total, title) + + return wrapped_callback + @staticmethod def credits(): content = (requests.get("https://raw.githubusercontent.com/EchterAlsFake/Porn_Fetch/master/README/CREDITS.md") From afc1af80b1001904824988e48829516fd4a3b162 Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Sun, 4 Aug 2024 01:24:30 +0200 Subject: [PATCH 38/39] - fixed the translations once again - updated the german translations - updated all other translation string - updated credits and changelog --- README/CHANGELOG.md | 1 + README/CREDITS.md | 7 +- README/STATUS.md | 37 - README/WEBSITES.md | 16 +- main.py | 13 +- src/backend/class_help.py | 24 +- src/frontend/form_desktop.ui | 18 +- src/frontend/resources.py | 1389 ++++++++++++++++------------ src/frontend/translations/de_DE.qm | Bin 35590 -> 35455 bytes src/frontend/translations/de_DE.ts | 945 ++++++++++--------- src/frontend/translations/en.ts | 416 ++++++--- src/frontend/translations/fr.ts | 782 ++++++++-------- src/frontend/translations/zh_CN.ts | 794 ++++++++-------- src/frontend/ui_form_desktop.py | 12 +- 14 files changed, 2441 insertions(+), 2013 deletions(-) diff --git a/README/CHANGELOG.md b/README/CHANGELOG.md index fd0dba7..9eb3519 100644 --- a/README/CHANGELOG.md +++ b/README/CHANGELOG.md @@ -399,6 +399,7 @@ I tested it on Android 12 & 13 on two devices. - removed the progressbars at the bottom, but added a second widget for it (more space) - added a new button into the menu which can switch to the previous mentioned widget - fixed the whole layout for the desktop application. +- Video titles will now be shown in the progress report in the CLI ## Deprecations - removed internet checks, because it triggers AV diff --git a/README/CREDITS.md b/README/CREDITS.md index c7561c5..a790923 100644 --- a/README/CREDITS.md +++ b/README/CREDITS.md @@ -1,4 +1,4 @@ -# Porn Fetch V3.3 +# Porn Fetch V3.4 Copyright (C) 2023-2024 Johannes Habel (EchterAlsFake) @@ -42,6 +42,7 @@ but I didn't want to remove them. - [RonLar1132](https://github.com/RonLar1132) Enhancement [#20](https://github.com/EchterAlsFake/Porn_Fetch/issues/20) (Playlist Support), Enhancement [#28](https://github.com/EchterAlsFake/Porn_Fetch/issues/28) (Custom retry limit) - [xxIndirect](https://github.com/xxIndirect) Enhancement [#32](https://github.com/EchterAlsFake/Porn_Fetch/issues/32) - [efraxs](https://github.com/efraxs) Enhancement [#37](https://github.com/EchterAlsFake/Porn_Fetch/issues/37) (Range selecting and time sorting) +- [omar-st](https://github.com/omar-st) Pull Request / Enhancement [#46](https://github.com/EchterAlsFake/Porn_Fetch/issues/46) [#48](https://github.com/EchterAlsFake/Porn_Fetch/pull/48) # Libraries - [PHUB](https://github.com/EchterAlsFake/PHUB) (GPLv3) @@ -58,6 +59,7 @@ but I didn't want to remove them. - [XVideos_API](https://github.com/EchterAlsFake/xvideos_api) (LGPLv3) - [eaf_base_api](https://github.com/echteralsfake/eaf_base_api) (LGPLv3) - [pypresence](https://github.com/qwertyquerty/pypresence) (MIT) +- [spankbang_api](https://github.com/EchterAlsFake/spankbang_api) - [ffmpeg-progress-yield](https://github.com/slhck/ffmpeg-progress-yield) (MIT) - [Mutagen](https://github.com/quodlibet/mutagen) (GPLv2)
ANDROID: @@ -68,3 +70,6 @@ but I didn't want to remove them. - [FFMPEG](https://ffmpeg.org/) (GPL) ** All other libraries are built in to Python. + +Some libraries may not be used in the current release, but have been used in an older release. +For the fairness to these authors, I will still list them here, although they don't play a role anymore. diff --git a/README/STATUS.md b/README/STATUS.md index 15d7845..e69de29 100644 --- a/README/STATUS.md +++ b/README/STATUS.md @@ -1,37 +0,0 @@ -# 3.4 -- [] Fixing the completely broken and stupid Android layout -- [] Fixing the UI flickering issues on Android -- [] Fixing the low thread starting times on Android -- [x] Fixing searching for xvideos -- [] Huge code refactoring -- [] Splitting functions into other .py files -- [x] Trying to optimize the UI performance with more threading and slower UI repainting -- [] Supporting more websites -- [x] Writing the thumbnail into the video metadata -- [x] Improving the sorting mechanism, to be less confusing -- [] --Entirely reworking the progressbars and progress reporting in general-- (Won't do that fr) -- [x] Fixing the errors with the playlist -- [x] Fixing file progress -- [x] Fixing the tag writing function -- [x] Fixed the build scripts -- [] Entirely reworking the Layout, the UI design AND the Android Layout -- [] Adding support for Spankbang (easy) -- [] Adding support for Porntrex (even easier) (I don't know who tf wrote their JS code, but this guy should be fire) -- [] Adding support for Porngo (easy, but I am not so motivated, because the site is shit fr) -- [] Adding support for Youjizz - -""" -Update: - -Since the UI is a lot optimized for desktop systems I decided to make just a new UI file for Android devices, or to say -for smartphones. I will then use the same buttons, same connections, and same functions, but the design will be different. -This means that I don't have to rewrite this entire thing :) - - -In 2 weeks I have summer holidays (21th June) and then we can bring some 🔥 into this project :) -""""" - -# Maybe or maybe not: -- [] Enabling optional downloading over the tor network or proxies (Nope, won't do that, sorry) -- [] Distributing Porn Fetch over the p2p network too -- [] -- Supporting FFmpeg on Android -- (Nope, won't do that) diff --git a/README/WEBSITES.md b/README/WEBSITES.md index 16225d8..1a2f59c 100644 --- a/README/WEBSITES.md +++ b/README/WEBSITES.md @@ -6,6 +6,7 @@ - Eporner.com (3.0) - xnxx.com (3.0) - xvideos.com (3.0) +- spankbang.com (3.4) > Porn Fetch was built for PornHub in the first place, but I decided to support as many websites as possible @@ -13,10 +14,11 @@ ### Here's a list of all features and if the website (API) supports it -| Website | Downloading | Searching | Account Login | Metadata | Total Progress | Model | -|:---------|:-------------:|:---------:|:-------------:|:--------:|:--------------:|:-----:| -| PornHub | Yes | Yes | Yes | Yes | Yes | Yes | -| HQporner | Yes | Yes | No | Yes | No | Yes | -| Eporner | Yes | Yes | No | Yes | No | Yes | -| xnxx | Yes | Yes | No | Yes | Yes | Yes | -| xvideos | Yes | Yes | No | Yes | Yes | Yes | \ No newline at end of file +| Website | Downloading | Searching | Account Login | Total Progress | Model | +|:-----------|:-----------:|:---------:|:-------------:|:--------------:|:-----:| +| PornHub | Yes | Yes | Yes | Yes | Yes | +| HQporner | Yes | Yes | No | No | Yes | +| Eporner | Yes | Yes | No | No | Yes | +| xnxx | Yes | Yes | No | Yes | Yes | +| xvideos | Yes | Yes | No | Yes | Yes | +| Spankbang | Yes | No (v3.5) | No | No | No | diff --git a/main.py b/main.py index 5987099..889f1ff 100644 --- a/main.py +++ b/main.py @@ -58,12 +58,11 @@ __build__ = "desktop" # android or desktop __author__ = "Johannes Habel" __next_release__ = "3.5" -context = "Porn Fetch" # This is used to tell the Translator from what thing the translation actually comes total_segments = 0 downloaded_segments = 0 last_index = 0 stop_flag = Event() -invalid_input_string = QCoreApplication.translate(context, "Wrong Input, please verify the URL, category or" +invalid_input_string = QCoreApplication.translate("main", "Wrong Input, please verify the URL, category or" " actress!", None) ffmpeg_features = True ffmpeg_path = None @@ -190,7 +189,7 @@ def process_video(self, video, index): data = load_video_attributes(video) session_urls.append(video.url) title = data[0] - disabled = QCoreApplication.translate(context, "Disabled", None) + disabled = QCoreApplication.translate("main", "Disabled", None) duration = disabled author = disabled @@ -1878,7 +1877,7 @@ def load_stylesheet(path): def reset_pornfetch(): setup_config_file(force=True) - ui_popup(QCoreApplication.translate(context, "Done! Please restart.", None)) + ui_popup(QCoreApplication.translate("main", "Done! Please restart.", None)) def switch_stop_state_2(): @@ -1902,10 +1901,10 @@ def export_urls(): ui_popup(f"Success! Saved: {len(session_urls)} URLs") else: - ui_popup(QCoreApplication.translate(context, "No URLs in the current session...", None)) + ui_popup(QCoreApplication.translate("main", "No URLs in the current session...", None)) def ffmpeg_finished(): - ui_popup(QCoreApplication.translate(context, "FFmpeg has been installed. Please restart Porn Fetch :)", None)) + ui_popup(QCoreApplication.translate("main", "FFmpeg has been installed. Please restart Porn Fetch :)", None)) def check_for_updates_result(value): @@ -1920,7 +1919,7 @@ def check_for_updates_result(value): logger.error(f"Couldn't fetch changelog of version: {__next_release__}") changelog = f"Unknown Error: {e}" - ui_popup(QCoreApplication.translate(context, f""" + ui_popup(QCoreApplication.translate("main", f""" Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} diff --git a/src/backend/class_help.py b/src/backend/class_help.py index cee195e..1727b6c 100644 --- a/src/backend/class_help.py +++ b/src/backend/class_help.py @@ -1,11 +1,9 @@ from PySide6.QtCore import QCoreApplication from src.backend.shared_gui import ui_popup -context = "Porn Fetch" - def result_limit_help(): - text = QCoreApplication.translate(context, f""" + text = QCoreApplication.translate("main", f""" The result limit defines how many videos will be returned when performing a search or doing other operations which involves loading multiple videos. This also affects models / channels and your liked videos. The result limit is basically the number of videos which can be loaded into the tree widget (this thing where videos are displayed). @@ -14,7 +12,7 @@ def result_limit_help(): def pornhub_delay_help(): - text = QCoreApplication.translate(context, f""" + text = QCoreApplication.translate("main", f""" You can set a delay between requests from you to PornHub. If you are downloading a lot of videos or experiencing 'client.call' errors, you should enable a delay. By default the delay is turned off with the value 0 @@ -27,7 +25,7 @@ def pornhub_delay_help(): def maximal_workers_help(): - text = QCoreApplication.translate(context, f""" + text = QCoreApplication.translate("main", f""" The maximal workers define the amount of maximal threads which can be started when using the threaded download mode. One thread handles downloading one segment, so (in theory) 20 threads can download 20 segments at the same time. This can of course be helpful when you have a very fast internet connection, but when you have a poor PC or running on @@ -39,7 +37,7 @@ def maximal_workers_help(): def timeout_help(): - text = QCoreApplication.translate(context, f""" + text = QCoreApplication.translate("main", f""" The timeout handles the timeout for retrieving segments when using the threaded download mode. If you have a poor internet connection you can set this higher than 10. But this isn't required for most users! """, None) @@ -47,7 +45,7 @@ def timeout_help(): def button_semaphore_help(): - text = QCoreApplication.translate(context, f""" + text = QCoreApplication.translate("main", f""" The Semaphore is a tool to limit the number of simultaneous actions / downloads. For example: If the semaphore is set to 1, only 1 video will be downloaded at the same time. @@ -58,7 +56,7 @@ def button_semaphore_help(): def button_threading_mode_help(): - text = QCoreApplication.translate(context, """ + text = QCoreApplication.translate("main", """ The different threading modes are used for different scenarios. 1) High Performance: Uses a class of workers to download multiple video segments at a time. Can be really fast if you @@ -76,7 +74,7 @@ def button_threading_mode_help(): def button_directory_system_help(): - text = QCoreApplication.translate(context, """ + text = QCoreApplication.translate("main", """ The directory system will save videos in an intelligent way. If you download 3 videos form one Pornstar and 5 videos from another, Porn Fetch will automatically make folders for it and move the 3 videos into that one folder and the other 5 into the other. (This will still apply with your selected output path) @@ -87,7 +85,7 @@ def button_directory_system_help(): def open_file_help(): - text = QCoreApplication.translate(context, """ + text = QCoreApplication.translate("main", """ Create a .txt file and add URLs like this: url1 @@ -110,7 +108,7 @@ def open_file_help(): def max_retries_help(): - text = QCoreApplication.translate(context, """ + text = QCoreApplication.translate("main", """ The maximal retries defines how much attempts will be used for a network request. For example if an API calls a URL for a website there will be of attempts until an error is thrown. """, None) @@ -118,7 +116,7 @@ def max_retries_help(): def skip_existing_files_help(): - text = QCoreApplication.translate(context, """ + text = QCoreApplication.translate("main" """ If you fetch a video and the exact same filename already exists, usually Porn Fetch would just skip this file. If you set this option to No, then Porn Fetch instead download the video and append a random number to it. @@ -134,7 +132,7 @@ def skip_existing_files_help(): def model_videos_help(): - text = QCoreApplication.translate(context, """ + text = QCoreApplication.translate("main", """ User uploads and featured videos are two different things. User uploads are the videos which were really uploaded by the model and the featured videos are videos the model is part or featured in. diff --git a/src/frontend/form_desktop.ui b/src/frontend/form_desktop.ui index 06f599b..a15a423 100644 --- a/src/frontend/form_desktop.ui +++ b/src/frontend/form_desktop.ui @@ -106,7 +106,7 @@ 1 - 0 + 3 @@ -148,7 +148,7 @@ 1 - 2 + 1 @@ -612,7 +612,7 @@ - Username: + E-Mail:
@@ -650,7 +650,7 @@ - Enter your PornHub Username + Enter your PornHub E-Mail address (not your username, pornhub changed it)
@@ -746,8 +746,8 @@ 0 0 - 1020 - 246 + 391 + 237 @@ -1269,7 +1269,7 @@ 0 0 - 1020 + 1006 289 @@ -2305,6 +2305,7 @@ li.checked::marker { content: "\2612"; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com (supports total progress)</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Spankbang.com (supports total progress)</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All sites support *threaded* downloads and selectable quality!</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> @@ -2328,7 +2329,8 @@ li.checked::marker { content: "\2612"; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I am constantly working to support more websites.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If you want a specific site to be supported, just ask:<br /><br />Discord: echteralsfake</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">GitHub.com/echteralsfake/Porn_Fetch/issues</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> diff --git a/src/frontend/resources.py b/src/frontend/resources.py index 3e96af7..8a8f552 100644 --- a/src/frontend/resources.py +++ b/src/frontend/resources.py @@ -9212,107 +9212,117 @@ consistent mage\ nta */\x0a width\ : 20px;\x0a}\x0a\ -\x00\x00\x06&\ +\x00\x00\x06\xcd\ \x00\ -\x00\x18\x22x\xda\xddXko\xdb6\x14\xfd\xee_q\ -\x97\x00[\x5cTVcom\x17\xb4\x01\x1c;\x0f\xa7\ -N\xe7\xd5iP \x18\x02J\xba\x96\x18S\xa4BR\ -q\xdc_\xbfK:\xae\x93Ti\x1d\x0dC\x87}\xf1\ -C:\xe7\xdc\x07\xc9K^n\xc2Hi\x09\x07h\xe3\ -\x0c\xce:\xadN\xa3\xd1S\xc5\x5c\xf34\xb3\xb0\xd5k\ -B\xfbE\xbb\x13\xd0\xc7\xafp\xac2&%\x1a8b\ -\x11\x0a\xd8\xda\x8f3\x8b\xba+\xcc\x01\x9bb\xb3\xd1h\ -lnn\xc2i\xc6\x0d\x8c\xb4\xba\xc4\xd8\x02\xfdTR\ -\xcc\xa1P\xc6\xf0H XR\x98\x1a\xb0\x0a\xf6S\xc3\ -R%\x7f1p>:\xfa\xb8\xf7\xd7Vfmav\ -\xc20\xe56+\xa3V\xac\xf2\xf0\x9e\x81\xd0\xc1\x9a\xd0\ -\x1d\x0d\x9c!\x18\x09d\x06!\xce0\x9e\x82*-8\ -\xbb\xc5\xad]&\x13H\xf95\x02\xa7\xdf`,\xd3?\ -\x11\x09\xfax\x8dB\x159J\xdb\x08`\xc8dZ\xb2\ -\x14w\xc8\x83\xb9\xcd\x94\x5c\xf90\x9b\xcdZ\x85\x7f\xd6\ -R:\x0d\x9b\x84\x1e\xf4\xf7w\xe0\x18m\xa4\x19\x97\xce\ -\xe9y/c:w\xa1N\x90\xa2S\x92\x89\xfb\x02\x97\ -K\xb0\x8f\xa5\x98\xc7\x0e\xef\xb5F\x82\xd9\x89\xd29Y\ ->\xe4\xf6\xa8\x8c\xaa\xa2w\xc0C\xcd\x8a\x8c\xc7L\xc0\ -G\x83\x1a\x06\x92\xd21a\xf1\xc2\xe51O\xf0\xe5\x8a\ -\x99\xa8\xb8ue[\x5c\x85WN|\xe1~\xf0\xd2\x1b\ -<\xd0,\xc7\x99\xd2S\x22\xfeiW\x1c\x8f\xf7#\xb7\ -4e\x08\xfd\x86A\xa6q\xf2vc\x09\xe3\xb1\x92&\ -\xa6$\xfbH\xfc\xbfPpc7 \x16\xcc\x98\xb7\x1b\ -\x16olP\xca\x04\xb5\xe0\x12a\xa2\xa4\x0d\x0c\xff\x8c\ -\x81\xc97\x80\xb2\x9f\xa2}\xbbq\x11\x09\x1a\xfc\x8d\xdd\ -!1\xdf\x84l\x17\xa2\xf9\xf7L\xd1\x1f\xabyTZ\ -\xa5M\xc8\xe7|\xaad=\x9b\x03\xcf\x85V\xab\xe5,\ -\xaf\x1b#\x97n\x94\x98\xe5\xb5\xcd\xae\x04\xeaD\x5c\xa0\ -e<\xb8d\xf4\x88\x15jM'vG\x8e\x05\xc7_\ -X\xde2\x05\xffm\xcb\xebi\x0f\x882v\x94\xa7\xa4\ -\xb1\x94\x1aYR/\x83\x0bn\x9d\xe4E\xb4\xdc\x98\x0d\ -Fk\xb9L\x8d\x17|LdB\ -P?\xf8\xa1\xb9\x85\x07\xed\xd7\xbf\xbd\xfc}\xbb\xd3\x04\ -.\xdda3\xe1t\x0a\x87\xb1\x9d\x0bl\xec\x91WG\ -,f\xf4\xd7m7ky\x16)e\xac{\xdf\x5c\x7f\ -k\x91XwS\x91Xgv\xa4J\xa5\x82\xf2 \xe3\ -\xf5\xc6\xee\xd0\xe3\xe9\x98\x1f\xb7~x\xc9\xa0V*\xd5\ -\xd4\xd8DL\xd7K\xdah%P'w\xd7\x8c\xa6\x88\ -|\xca\xf1\xed\xcc3V5\xe3\xdfI_c\xa8R\x05\ -3f E\x89t^\xc4\xc4\x85\xd6\xef\x0e\x87\xc1>\ -5\xcc\x19\xb3\x87\xa3\xd3f\xe3M\xa4w\xc7*G \ -\x03h\x0d0\x8d\xf2\x17\x0b\xa5!<\x93\xf3\x5ci\x84\ -\x08cF\x0f`\x00\x19\xa3f5\xc1\x98Z\xba\xc4u\ -\xc7\xee\xa9\xc4\x19xw\x9f7('\x04Jx\xe2$\ -fT7\x1cFc\xae\xae]K\x8dy\xcb\xb7\xc4\xbd\ -;\xf9\xa3a>\xbfm\xb1\xab[\xeb\xc5\xbb&\xb8\xae\ -\xda5\xd5\xf0\xb3[\xdf2\xce\xe0T3i\x84oZ\ -\xbc\xcc\x87q\xbfwpxv\xb4w\xfc\xfe\xdd\xc9\xb0\ -R\xed>\xa4\x09;\xb0/\xa9\xd3\x8f\xd1\xb5\xdap\xbe\ -\xb9\xbd\xbdN\x7f\xaf\xb4\xbc\xf0\xf7\x10!7\xa6D\x13\ -no\xbb\xc5\xdd\xcbhL(\x1f[\x9d\xd6\x8b&\x9c\ -.o\x10\xa8\x95=V&+Y\xc0\xca\xcc\xa8\xcbJ\ -\x0b\xf7\x10M\x8a\xf1\x81_\xaf\xea\xf9\xf5\xaa\xe9\x13\xa3\ -\xe4\x90\xe9\xed\xedN\xbb:)_^7\x1f\x98m\xbf\ -\xa8e\xb6M\xe1o\x8d\x04\x9b\xbb\xde\x1b\xc6eQ(\ -*\xcc\xcf\x1f\x8a\xbf\xae'\xfe\x9a\xc4{\xa5\xb1*\xa7\ -\x99e\xf5\x1c\x04\xcf\xb9\xaf\xfb\xe777\x03\x99p\x8d\ -\xb1\xad\x94^\xbd~\x18\xe8#\x99\xf9\x9e/\x941g\ -\x16'\x9a\xdd\x98J\x85\xc5\xab\xaf\xcc\xd5\x1b\xce\xce+\ -\x0a\xfd\x03\x9d\xf1\x10\x0c\x0a\x0a\x83\xf6+\x7f\x85d9\ -\xad_CI\xa6\x07MwI2\xe4\x91f\x9a\xa3_\ -\x17O\xba\xb6\xda:\x1c\x0d\xaf;>,\x8dWd\xd5\ -V\x07V\x98I\xb8\x04\x10\xab[\xb08Ch\xd3\xcc\ -w\xd4\xec\x8a\x86\x9c\xaa\xce\x05+\xf8\x1a\xa6\xef\xc2I\ -l\xb8\xf2!+\xf1\xc2d|b\xd7QYb\xefK\ -\xac\x7f\x01\xe5\x83\x87\x10\x1c\xd9Sc\xea\x1c4\xcbY\ -\xa5q\xdaG\xac\xc0y\xb8\x04\x11}o\xdc\x87\x0e\xf4\ -\x84+\x96^ gz\xea:\xc5J\x81\xc5e^p\ -r\x8b\x09\x97\xe0*!\xcd\xe3\xacR\xe4\x94v\x84\x92\ -\x09\xda\x03B\x87!\xee\xc9\xe0\xd4S\xecU\x92W;\ -N/\xfc\xc7\x1d\xf0\xfe\xc8\x0f\x80+\xb0kd\x1a\x1f\ -\x1b\xaeO\xef?}ZS\xe3F\xde\xdcT\x08\x9c\xd1\ -X)s\xb1\xa6\xc6\xf5\x02\xfd\x95\x0c\xb2\xc9E\xc4\x0c\ ->:\xff\xd0\xeb0a&>\x9e;\xf0\xfbB\xc5\xbc\ -\xa0\xb3\x01m7X)s5Cm\xe7\xb4\x0a\xe83\ -\x5ca\xef$v2\xc9\x0bL\x83\xe5)%\x98s\x14\ -I\xa5\x96\x11Y<\x0d+\xf1w\xf4NJ\xcbhC\ -\xaf\xf6\xa6T\x89\xe0\x11\xda0_\xa0n\x97s{\xb1\ -\xcbw\xdf\xf7?\xfc1\xe8\xef8\x99\xbd\x92\x8bD}\ -F])4\xe5\xd7\xf30ZB\xeeX\xef=\xb8\x7f\ -\xbe\xc3\x89\xfd\xab\xdb\xaf\x07\x15\x81*R\xb7(\x04\x8f\ -W\x9b\xf5\xc1\xc1\xc9h\xffp\xa5\xb4\x88{q\x8b\xed\ -\xbd&\xd6\xb3g\xd0\x15\x02\x14\x9d\x1c4U\xf9\xdb\x92\ -\xe6N(\xe0\x9c\xb3\xee\x84N\xe7\x8b\xc5:j5\xfe\ -\x06u,k\xc3\ +\x00\x19\xe8x\xda\xddYmo\xdb8\x12\xfe\xee_1\ +\x97\x00\xb7qQ[\xcd\xcb\xa5\xdd\xa0-\xe0\xd8yq\ +\xd6\xe9z\xeblQ 8\x04#i,\xb1\x96H\x85\ +\xa4\xe2h\x7f\xfd\x0di\xbbNRu\xd7\xd1\xe2\xd0\xc3\ +}Q\x22\xf1\x99g^H\x0eg\xe8m\x18+-\xe1\ +\x94l\x94\xc2\xa7\xfd\xeeA\xab\xd5WE\xa5E\x92Z\ +\xd8\xe9\xb7a\xef\xd5\xde~\x87\x1f\x07p\xa1R\x94\x92\ +\x0c\x9ccH\x19\xec\x9cD\xa9%\xdd\xcb\xcc)\xce\xa8\ +\xddj\xb5\xb6\xb7\xb7\xe1*\x15\x06\xc6Z}\xa1\xc8\x02\ +\xff\xabdVA\xa1\x8c\x11aF`\x99af\xc0*\ +8I\x0c&J\xfed\xe0z|\xfe\xfb\xf1\xbfwR\ +k\x0bs\x14\x04\x89\xb0i\x19v#\x95\x07\x8f\x14\x04\ +\x0e\xd6\x86\xdex\xe8\x14\xc18#4\x04QJ\xd1\x0c\ +Ti\xc1\xe9-\x96zQ\xc6\x90\x88;\x02\xc1\xff\x83\ +\xb1\xa8\xff\xc1B0\xa0;\xcaT\x91\x93\xb4\xad\x0e\x8c\ +P&%&t\xc4\x16T6Urm\xc3|>\xef\ +\x16\xfe[W\xe9$h3z889\x82\x0b\xb2\xa1\ +F!\x9d\xd1U?E\x9d;W\xa7\xc4\xde)\x89\xd9\ +c\x82/+\xb0\xf7\xa5\xa8\x22\x87\xf7\x5c\xe3\x0c\xedT\ +\xe9\x9c5\x9f\x09{^\x86u\xde;\xe0\x99\xc6\x22\x15\ +\x11f\xf0\xbb!\x0dC\xc9\xe1\x98b\xb40y\x22b\ +:\x5cK\xc6*\xea\xde\xda\xaeP\xc1\xad#_\x98\xdf\ +9\xf4\x0aO5\xe64Wz\xc6\x82\xbf\xd9\xb5\x8c\xc7\ +\xfb\x99[\xa92\x8c~\x8b\x90j\x9a\xbe\xdbZ\xc1D\ +\xa4\xa4\x898\xc8\xde\x13\xff\x16d\xc2\xd8-\x8824\ +\xe6\xdd\x96\xa5{\xdb)eL:\x13\x92`\xaa\xa4\xed\ +\x18\xf1\x07uL\xbe\x05\x1c\xfd\x84\xec\xbb\xad\x9b0\xe3\ +\xc9\xdfz?b\xc9\xb7\x01\xbe\x87\xb0\xfa+U\xfcb\ +\xb5\x08K\xab\xb4\x09D%fJ6\xd39\xf4\xb2\xd0\ +\xedv\x9d\xe6M}\x14\xd2\xcd\x12Z\xd1X\xed\x9a\xa0\ +\x89\xc7\x05Y\x14\x9d/\xc8\x9f\xb0P\x1b\x1a\xf1~\xec\ +\xa4\xe0\xe2\xab\x94\xd7\xcc\xce\xff\xb9\xe6\xcd\xb8\x87,2\ +q\x22\xcf\x09c)5a\xdc,\x82\x0b\xd9&\xc1\x0b\ +y\xbb\xa1\xedx\xc4f\xce\x1d{\x09\xce\x12F$?\ +>jV\x15\x1d\xd4Z\xcd\x9b\x05\xeeJ\x15\xd0s\xe2\ +Mb\x17q\xd0-\xe7\xcf\x8e\xb1e,T3\x0b.\ +\x05J\x98 \x86\xcf\xf1:Vs\xf9w\xdc\x1e\xb0|\ +s\xbf1\xc6\xfc\x19\x0b\xa6\xc7p\x18x\x81\x1f\xbf\x5c\ +D4k\xb8RX\xb2I\xb0f*S\x9d\xd8o\x96\ +f\x8a\x7fA\x16J\x9f\xe3$F\xfcA6\ +\xfcr9\xaae{\x0ci\xc3\x11\x9cH\xee\xf4#r\ +\xad6\x5co\xef\xeen\xd2\xdf+-o\xfc=D \ +\x8c)\xc9\x04\xbb\xbbns\xf7S\x9e\x13\x8e\xc7\xce~\ +\xf7U\x1b\xaeV7\x08\xdc\xca^(\x93\x96\xd8\xc12\ +5\xeaK\xad\x86G\x886\xfb\xf8\xc4\xae\xd7\xcd\xecz\ +\xdd\xf6\x81Qr\x84zww\x7f\xaf>(_\x87\xdb\ +O\xd4\xee\xbdj\xa4v\x8f\xdd\xdf\x19gX\xb9\xde\x1b\ +&eQ(N\xcc/\x9f\x92\xbfiF\xfe\x86\xc9\xfb\ +\xa5\xb1*\xe7\x95eu\x05\x99\xc8\x85\xcf\xfb\xd7\xf7\xf7\ +C\x19\x0bM\x91\xad\xa5^\x0f?u\xf4;\x91\xf9+\ +[8bN-M5\xde\x9bZ\x86\xc5\xd07\xea\x9a\ +M\xe7\xfekv\xfd#\xd7x\x04\x862v\x83\xcf+\ +\x7f\x85d\x05\xef_\xc3A\xe6\x0f\xde\x22\x95\xa3\xe6\x9e\ +\xa8V\xcbr\x8cwT\x99e\xf0\x91n\x99\xdaB\xf0\ +\xc4\xc4\x83\xc3F&\x1e\x1c\xb6\x9d\xf03\xa7\xb6`K\ +\x82\x837mw\xbf3\x12\xa1F-\xc8o\xe9g\xdd\ +\xb8\xed\x9c\x8dGw\xfb\xde\x7f\xbd\xf0\xaa~N\x0a3\ +\x0dV\x00\x96\xea\x15\x18\xa5\x04{\xbci\x9dhz\xcb\ +\xab\x95\x13\xe6\x0d\x16b\x03\xd5\x0f\xe1L6Z\xdb\x90\ +\x96tcR1\xb5\x9b\xb0\xac\xb0\x8f)6\xbf;\xf3\ +\xce\xf3$:a/\x1aq\xd3\xa31\xc7Z\xe5|\x04\ +\xda\x8c\xaa`\x05b\xf1\xe3\xc9\x00\xf6\xa1\x9f\xb9<\xef\ +\x09x\x95\xcc\x5c\x93[K\xb0\xb8\x87\xec\x5c.1\xc1\ +\x0a\x5cG\xa4E\x94\xd6\x92\x5c\xf1aVb\xc6\xc7W\ +\xe00,{9\xbc\xf2\x22\xf66\xce\xeb\x0d\xe7\x01\xff\ +x\x00>\x19\xfb\x09pg\xc3\x06\x91\xa6\xefM\xd7\xe7\ +\x0f\x9f?o\xc8q/\xef\xefk\x08>\xf1\x5c)s\ +\xb3!\xc7\xdd\x02\xfd\x0d\x0d\xe1\xf4&DC\xdf]\x7f\ +\xe4y03S\xef\xcf\x03\xf8c\xa2\xa2*\xb8\xac\xe1\ +\x93\x92jin\xe7\xa4m\xc5\xbb\x80\x9f\xc1\x1a\xfb \ +\xb0\xa6\xe0\x13,\xe4t\xb3\xe1Vx\x84\xf7\x0c\xd3i\ +^P\xd2Y\x95h\x9dJP\x16\xd72\x99,\x8df\ +A-\xfe\x81E\x97\xa5E\xaef\xea\xfd)U\x9c\x89\ +\x90l\x90/P\xcb\x84\xb0\xb7(qz\x1f\x06\x1f\x7f\ +\x1d\x0e\x8e\x1c\xcdq)\xb2X\xfdA\xba\x96h&\xee\ +\xaa \x5cA\x1eh\xef?\xb9|\x7f \x13\xf9\xa1\xe5\ +\x9f'9\x85sZ\xaf(2\x11\xad+\x95\xd3\xd3\xcb\ +\xf1\xc9\xd9\x9ai\xe1\xf7\xe2\x0a\xdf[\xcdR/^@\ +\x8f\xf3\xb3\xe2\xb2I\xf3\x11\xb7L\x8a\xae<\x03g\x9c\ +u\xed\x09\x17W\x8b\x9d\xc8u\x95\xaf\xe1\xd6\xb8\x1c+\ +\x90\xcar\xe9\xb6(\xe5\x1c\x9a-\x8aJ\xad]\x82\xd7\ +\xe4\x7f\x96x\x09\xaeb\xf3E]H$\xbfBQ\x82\ +\xca\xb8\xca\x5c\xe1\xba\xadS\xa5=\xc1\x14\x05\xef\x1f\xe3\ +\x7f\x1a\xe1w.w\xb0d\x0b\xb4y\xc9\x85\xdf\x5c\xb0\ +\xc5\xdc\xed\xf0\xd3\x1f\xfd\xae\xe4\x03\xb6\x9f\xf5`\xc6\xa8\ +2I\xdd\xb7\x0a\xb8\xc5\xe1\x02\xb1\xe0\x12\x01\x10\xb4\xe2\ +^bYjv[\xff\x01\xe5*\x0b\xc8\ \x00\x00\x1a\xfc\ <\ \xb8d\x18\xca\xef\x9c\x95\xcd!\x1c\xbf`\xa1\xbd\xdd\xa7\ @@ -9747,516 +9757,667 @@ \x08\x00\x00\x00\x00\x06\x00\x00\x00\x03Yes\x07\x00\x00\ \x00\x11Porn_Fetch_Wid\ get\x01\x88\x00\x00\x00\x02\x03\x01\ -\x00\x00\x1f\xb3\ +\x00\x00)+\ \x00\ -\x00\x8b\x06x\xda\xed=\x0bp\x5cWu\xd7\xb6$\xdb\ -\xb2l\xe7CM~%\xd7\x8a'\x96\x82\xb4+\x7f\x02\ -d#\xdb\xc8\xfaX\x8a%[\x96\xe4/\x09\xca\xdb\xdd\ -\xbb\xbb/z\x9f\xcd\xfbh%9\x86\xf0k\x03\x13>\ --\x84_3Pf\x0aI\xa9\x1b\xa6\xa1i)\xdf)\ -\xa4\x01\x02\x14(\xe5\xd3\xb4\x84O\x92\x09\xa5LJ\xcb\ -L\x86\xb6\x9e\xb4\xe7\x9e{\xdf\xbb\xef\xed\xe7I\xa1\x0c\ -I\xccz\xc7\xda\xdd\xb7\xef\xde{\xce=\xf7|\xef\xb9\ -\xe7\xf5\x7f\x22\x7f\xc9\xc3\xff~\xf7]_\xdbz\xc5\xe7\ -n\xfe\xd0g\xbe\x7f\x0f!\xa45\xcff\x87\x86\xf7\x13\ -\xd2r3|9L\xc8\xab\xe0\xea\xec\x17\x08\x99\xbb\x8d\ -\xb4\xdc\xf9'\x84\x8c\xfc\x1biyp\x89\x90\xab&H\ -\xcbO\xae&\xe4\xd8\xe5\xa4\xe5g}\xf0~\x84\xb4\x16\ ->K\xc8\x8dS\xa4\xf5#\xffMH\xe1\x09\xd2\xfa\xad\ -\xefA\xbb\xcd\xa4\xf5\x9f?E\xc8-\xef%\xed\x1f\xbf\ -\x8c\x90SKd\xd7.\xb8\x1f\xfe\x8dV\xae#\xa4\xf3\ -5\xe4\xe0\x86\xf7\xc2\x97\xad\xe4\xe0\xc3\xf0~P#\x13\ -\xab\xdfB\xc8\xe4\x18\x99\xbe\xe9\x19BN~\x91\xcc\xb0\ -{\x01\x0e\x87\x9c\xba\xf7]\x84\xb02y\xb5\x0ep\xdc\ -\xf2Ur\xfa\xe7&!\xb7\x8f\x937\xc1g2\xf1#\ -\xf2\x9ew\xb7\x10\xe2?B\xeeM\xa7\x089\xf1\x1d\xf2\ -\xe4Sk\x08\xc9=\xb4\xaa\xf3\xde\xa7\x08y\xfd\xb9U\ -\xdd=\xbf\x80~\xcf\xad\xba\xed,\xc0\xf1\xea{V\xb7\ -\x9e\xcd\x00\x9c\xf9\xd5\x9b\x86\xdf\x09\xfdmY\xbdw\xdf\ -\xbf\x122NW\x1f4\xff\x83\x90\xa57\xaf>\xf5\xc5\ -\xe3\x84\x0c\xef]\xfd\x17\x1fx\x09@\xdb\xb5\xfa13\ -G\xc8\x91\xe9\xd5O\x9c}\x80\x90\xa1sk.\xdb\x03\ -\xf3p\xe3\xd7\xd6\x5c\xf9\x81\xc7\x08\xb9\xf9\xd3k\xf6~\ -\x10\xfa?\xfc\xda5\x93?\xbc\x8f\x90\xf9\xdf]\xf3\xc6\ -W\xc1\xfd\xd3\xa55\xbf\xdf\xd6\x03\xfd~b\xcd\x17w\ -\xee\x82\xf9\xdb\xb7\xe6\x07o\x85v\x9dg[Z/\x07\ -8_\xf3\xe7-\xd7\xfe\xf8\xe50\x9f^\xcb\xe4\xfd\xdb\ -\x09\xc9\xde\xd5r\xdb\x0f\x00\xefc\xdfn\xb9\xf3cY\ -\xb8\x7f}\xcb\xdb\xee\x7f\x1d!o\xfa\xdd\x96{\xbc\x7f\ -\x02x\xeej\xf9\xb3m\xef\x81q~\xdc\xf2\xbd\x07a\ -\xbe&oo\xf9\x97w\xbe\x06\xde?\xdf\xf2\xcb\xa7>\ -\x03\xf3\xfd\xa7-\xcf\xa4v\x10\xf2\xba\xd7\xb4~\xf4\xcd\ -\x9cN\x9fn\xfd\xab{8=\xfe\xa6\xf5\xa1O\xbe\x8f\ -\x90\xca\xa6\xd6\xaf,\xc0\xbcL=\xd4\xfa\xf5\xb3\x00\x9f\ -\xfeh\xdb\x9a\xff\xf9KBn{c\xdbF\x0f\xee/\ -}\xa9m\xe3\xdf\x01\xfc\x95G\xda.\xba\xf9\x9b\x84\xfc\ -^[\xdb%\xff\x00\xf3^\xba\xae\xed\xaas\x00Gq\ -s\xdb\x8e+\x19\xc0\xb9\xa7mG\xd7U\x84\xdc\xf4\xf7\ -m7\xfe\xf5k\xa1\xbfb\xdb\xfc;.\x22\xe4\xe8}\ -m\x7f\xf8\xcc50\x1f-m\x0f|\x06\xe6\xf5\x86\x91\ -\xb6/l9\x05t\xffI\xdb\x13;\x1e$d\xec\x99\ -\xb6'\xbe:\x0c\xedN\xad\xd5W\xc1\xfc\x1f\xfd\xd9Z\ -=\xfdc\xa0\x87\xb1\xf6n\xe3b\xf8\xbd\xb0\xf6\xee\xd7\ -q\xba\x8d\xae}\xcch%$\xdf\xbfn\xcd\x98\x0bt\ -\xff\xf0\xba\xd2\xd8]\xb0\x1e.]\xe7\xfe\xf4\x09Bf\ ->\xbb\xee\x97\xe6\xdba~/Z\xf7\xcc\xa6/\xc3\xfa\ -\xf8\xeez\xeb+@\xd7\xd1\x0f\xae\x7f\xfb\x03{\x09\xd9\ -\xb6c\xfd\xc3\x1f\x84\xf9\xd5\x1eX\xff\xf3\xf1o\x13r\ -\xe0\xa5\xeb\x7f\xb1\xe6QX\x07\xbd\xed\xeb\xbb\xd6C\xbb\ -G\xdb\xb7\xec|\x1c\xe6\xe5E\xed\xa7F`\xbc\xb1\xb5\ -\xed\xa5\xc9/\xc18\xbb\xda\xe7\xdf\xf5zX\x87\xf7\xb6\ -\xdf\xb7\x17\xe6\xed\xa6K\xdb?}\xa7\x07\xfdf\xdb\xbf\ -|\x05\xe0u\xe2\xae\xf6\x7f\x9c\xfb)\xcc\xf7\xa6\xf6\xef\ -\xbf\xf4$!gZ7\xbca\xd3\x0d\x80\xefm\x1b\xde\ -\xd9\x0dt\xb8\xea\xc9\x0d\x9f\xec\xfa\x16\xc0wl\xc3\xa7\ -\x1e\x06\xf8o\xde\xb9\xe1\x87\x8f\x01\xfe\xaf\xda\xdf\xd1\xf2\ -~\xc0\xfb\xc6;:\xd6\x1fy?\xd0\xff\xe9\x8e]\xaf\ -\x04\xfc\xb5\xff\xec8\xd4\x07|r\xf0\xb1\x8e\xe9w\x00\ -\xff\x1cy\xa0\x03\xc7?<\xd4q\xc7YX\xb7\x07\xbb\ -;\xder\x15\xe7\x9b\xd5\x1d\xef\xda\x07\xef\xfa\xfb:\xee\ ->\x03\xe3\xe7\x1f\xea\xf8\xe3\xfe[\x099=\xde\xf1\xb1\ -\xde+\xe1\xfd#\x1d\xdf\xf8\xd0-\x80\xe7w:\xbe\xb9\ -j\x1b!\x87\xf6w\xfc(\x07\xeb\xf4\xd8\x9b6^\xf7\ -\xb5'\x81\x0e\x0fn\xdc\xf7\xd6\x8f\xc2\xba|\xf3\xc6\xf1\ -\x0f\xc3\xfbM\x7f\xb4q\xe6\xbb\xb0\x9efOn\xfc\xb8\ -v-\xdc\xff\xb9\x8d_?\x0b\xebsn`\xe3\x0f\x9f\ -\xb4\x08Y\xf8\xea\xc6'\xd7\x00^ZvSK?\xe0\ -}\x94n\xca\x9d\xeb\x00\xfa?\xb9y\xd5\xfd\xff\x05\xe3\ -\x18\x9b_|%\xcc\xef\x1b\xcfl\x9e\xfc\xd0\x1b\x80.\ -'7\xe7\x7fp\x16\xf8\xf0\xa6\xcd\xf3\xc7\xde\x01p\xee\ -\xd8\xfc\x07\xbb\x01\xbf\xa9\xce\xcdw\xdd\xff\xb7\x84\xbc\xf6\ -\xb6\xcd\xdf\xbb\x0f\xf0[\xfc\xc6\xe6G\xde\xf7\x0dB\xac\ -w\xeb\xb0\xb8N\xc3\xcc\x93v\xd2\x17\xbc\xd6q\xb9\xd0\ -\xc6\xe5P\x1f\xff\xb7\x16>\xb5\x8c\xd8\x8e\xb9\x0a\xee\xdb\ -\xf2(\xe9'[\xc9\x109L\x06\xc9\x0c9I&\xc9\ -0\xa1d\x14>O\x90q\xf84I\x8e\x92\xfd\xf0i\ -\x0c~\xa7\xa4\x93\xf4\x924\xbc\x8e\x93]\xf0\x9d\x7f\x1a\ -\x82;\x87b-v\x93\x14\x8c\xca\x7f\x1b&\x87\xa0\x05\ -oU\x22\x1e\xbc\xca$\x83\xd7+\xf8J\xc1\xff]\xf0\ -\xd7&\x0e)\xc2\xd5\x192\x05\x7f\xa7\xa0\xd5 \x8c\xc2\ -[\x98\xc4\x80\xdex_.|s\x88Nr\xf0\x9e\x22\ -y\xf8\x9b\x87^\xf7\x02\x96\xfd\xe1\x9d{\xf13#\x1a\ -\xfc\xc6?\x9b\xf0\xd9\x83o\x94X\xf0\x97\x7f\xdb\x03m\ -n\x95\xfd\xf0V\x8c,\xc0_\x0ea\x0e\xa0\xb0\xf0\x0a\ -\xff\xcb\xef\xdb\x81\xd7\xd3\xd8\x13\x1f}\x11F`p\x85\ -\x7f*\xcb\xbe\x82\x1e\xd2\xd0\xde\x85\x97\x80\xa8Lz\xe0\ ->\x03F\xa1\xe44\xfc\xaf\xc0X:\xde\xdb\x0b\xf7\x94\ -\x01\x96\x1c|\xce\xc0/e\x80\x85_\xad\xc0\xbb\x06\xdf\ -\xae\x87kg\x10\xa7td\xcc\xbd\xf8=\x8aY\x16\xa0\ -\xcd\xc3\xaf4r\xd7\x1e\x84\xb7 \xf1\xe8\x85O\x1cg\ -\x1d~[\x84\xb1\xb6\x03%l\xb8n\xc3=\xd3\xf0\x8b\ -\x05-\xb7\xe3x\xaa\x85\x0bw/!d;\xc8N\x80\ -\xc6\xab\xfa\xbd\x02\xbf\xe9@)>s\x19\xa4K_M\ -\x0f\x014\x19\xb8\xc2\xe9j\xc2X\x06\xdc\x15\xd0\xaa\x5c\ -\x07f~\x0f_\x01:\xb4\xe9E\x18\xf9:\xe9\x83\xbf\ -\x0b\xd8\x7f\xfc\xf7,\xe2\xc1\xef2\x13\xee\xe2\xbd\x17\x10\ -\xceFw8\x11\x5c\xd4=\xbd\xb0><\x1c\xc5\x80\x11\ -rd\x0e>\xf3\xfb\xf3red$\xce\x01\xe5k\x7f\ -\x15=u\xcauS\xc6\xb9~6t\x9a\x86{\x8a\xf0\ -+_kG\x81\xeb\x1aS\xe9:I#>\xd6q\xf2\ -8\xe0\x22V\xa8\x80\x86\x02\xd72\x5c_b\xb5\x8b\xeb\ -\x0e\xbc\x1f\x83+\xfc\xb3\x0d}\xf5D\xaek\xc4\x97\xf3\ -\xaa\xc1\xbb\x0e\xbf\x8av\xfc\xba\x0b01X\x01b\x14\ -\x0fW5o\x15\x8c\xe5B;\x03^)\xb9v\x05\xde\ -b\xe5\x96\x1b\xd2>\x98\xed2RF\x831\x04\x1f\x94\ -p\x1d\x08>\xcb\xc0\x7f\x131]\xacC\xc5\xf3c\xb5\ -\xfc\xfa\xd7\x03\x97\x11N(\xbf\x92h\xd0\xe4\xbf_\xc7\ -|\xefG>\xe3\xe3\xe9\xf0\xc9@\xbe\xaa T\x16r\ -\x98\x0f\x7f\x97\xe0J\xc0U\x82k\xae\x85\xfev\x02\xcc\ -4\xe4,\x0e\xa7\xe0IM\xb6\x8d\xf3\x99\x86\x5c\xc6\xaa\ -\xb8\x98\x22\x06\x9e\xe4e\x13\xde\xc7\xe4\xac,\xc4F\xa9\ -\xcf\xc9\x19\xd2\xdd\xe4\xda&\xd7\xfe\x16r\xed\xe1P\xf7\ -U\x22\xfa\xd3B\x0b-\xaa1O!wsH3M\ -Nir\xcao!\xa7\x0c\xa0n\xa2+\xd2s\xf5u\ -\x94\xd0j:^\xaf\xd5\x84;P?\xf9\x88+\x95\xda\ -j\x02q\xf7\xa5WFQo\x95B=\xc85\x99\xe2\ -Z\x0b\xe7\xff\xe9\xd0\xaf\xab\xd5\xa3\x9c.Yxg\xd8\ -k\x93\x8f\x9b|\xfc\xdb\xc8\xc7\xd3\x18\x11q\x10\x06\x1a\ -F\x888\xf7=\x1b~h\xd2\xe2\xd7A\x8ba\x09\x85\ -\xa2\xc4\xcegI\x87\xa6\x5cj\xca\xa5\xf3\x83\x17\x8eJ\ -\xcd?\x87qS\x0e7C-oI\xebB@\xd8(\ -\xba\xc4\xdf\x83\x98h\x10-\x951\xe1 \xf6\xbda\xb6\ -\x7f\xeb\xd0\xe1\xc1\x99\x93\x93\xc3ttfb\x9cN\x1e\ -\xdd?>6H;{\xd3\xe9\xe3\xbb\x06\xd3\xe9\xa1\x99\ -!\xf1\xc3\xeeT_:=|\xa8\x93v\x96<\xaf\x9c\ -I\xa7+\x95J\xaa\xb2+e;\xc5\xf4\xccTzj\ -x\xb0\xb7\xe4\x99\xc6\xee\xbe\xb4\xeb9z\xceK\xe5\xbd\ -|\xe7\xde\xf6~~qo\x7f\x89i\xf9\xbd\xfd&\xf3\ -4ji&\xdb\xd3y+\xdcS\xf2\xd8\x82\xd7Is\ -\xb6\xe51\xcb\xdb\xd3\xb9\xa3\x93\xa6\xf7\xf6\xbb\xde\xa2\xc1\ -\xa8\xb7X\x86\xbb\xf8\x0d\xe9\x9c\xebBG\xe5\x1ej\xe8\ -\xf44\xad\x94t\x8f\xf5\xbae-\xc72\xb4\xec\xb0\xde\ -\x8a\xa3\x95\xaf\xa7g\xda\xfb\xd3\xd8ro\x7fZ\x0c\x96\ -\xb5\xf3\x8b\x14/\xed\xe9\xa4\x05\x18\xa3\xb7\xa0\x99\xba\xb1\ -\x98\xd9~\xc8\xf6l:\xadY\xee\xf6\xeb\xc5\x0f\xae\xbe\ -\xc42;v\x96=\xf9\xbd\xc2\xf4b\xc9\xcb\xec\xee\xeb\ -\x0bn\xe0\xddd,\xdb15\xe3z\x8eU9\xec\xd9\ -\xd4\x9c\xa2n\xf5zv9\xd3W^\xb8>\xf8\x9e\xb5\ -=\xcf6c\x97\x0cV\xf0b\x17\x1c\x1c\x05\xaf\xf4\xde\ -\xea\xf5f\x0d;7\xd7\xab[y\x98\x8c\x0c\x8c\xcc\x91\ -\x0f\xbf\xc2M\x9d07e\xcd\xaa\x8f\xd34+\xda\x8c\ -\x1e\x1d\x8b\xa1t\x1d`\xd4\xb9w\x9a\x19,\xe7Q\xaf\ -\xc4\xa8\xa3YEF\xed\x02\x9d\xd7\xf3\xccv)\xccC\ -\x96Q\xcd\x07P5O\xcfi\x86\x01S\x86\xb7\xb3|\ -\x0a&\x14\x86\x83\xf9,G\x11\xe6\x90\x965G+\xc2\ -\xb4\x97z9\x992\xcc,{\x8b\xd7\xff\x06gb\xc5\ -\xa8\xf7g\x1d\xbe\xa4\xe2\x18\xbc\x00H6b;\x94-\ -hf\xd9`=T/\xd0E\xdb\x07\xba\x08\x1a\xba\x9e\ -\xe6x\x9cr\xd7R\xcd\xca\xe3%\xc6\xdfm\xba\xb3\xaf\ -\x87\x7f\xb5(\xd01\xa0p\x96y\x15\x06\x97\xae\xed\xdd\ -\xd9G+:\xfc\x00\x04\xcf\x95Xn\x8e\xe5aX\x87\ -\xe6\xed\x8ae\xd8Z^\xb7\x8a4\xd3\xdd\xa4\xf9sF\ -\xf3\xc3\x8ed=\x9a]\xa4\x9adU\xdd\xa2\x9en\xb2\ -L\x93.\xcf\x07^\x0cX\xb1\xa2Y\xc8\x81\x01\xefD\ -\x19\x0e(\x16\xf0\xdc\x8e>\xe4P`\xa0\xcc\xa7\xc4b,\xffB\xda\x1b8\ -?\xd7\xf4\x84\x9dg\x06M\xd3\xc1\x92fY\xf0)\xb0\ -\x91\xdd&]\x9e?\x06r\xd3\x0c~^\x98\xc1\x93\xe7\ -\x97\x19|\xbe\x18\xbbMI\xf5\xdc\xc6\xb9\x98\xe6\xe4J\ -\xcd\x98JSe4UF\x8d\x94\x9a_FJ5#\ -@\xcf#\xd5\xd7\x94T\xbf!B\x8cQ\xcd\xe4;P\ -\xae\xa7Y\xe0\xf7\xd2\x8a\xed\xccq/\xd1\xb3\xc3\xb0\x88\ -\xc9\xfd\xc7\x8a\xdc89\x8f\x9d\xc4&\x0eM\x1c\x9a8\ -4qx^\xe0P\x9bpr!7\xc4fGx\xf4\ -r\xf6\xb8\x9e/2\x0f\x93\x22^D\x0e`\x0e\x06\xcf\ -L\xf70\xdb\x5c'^\x98\x08\xb1\x8eG\xb9gt\x93\ -%\xf4\xb0\x8dLc\xfd\x0a\x0fO\xac9\xf2\x84\x19\xff\ -d`^G6\x96\xcf\xb1\x11z\xb4+t\x1a4\x83\ -\xcc\xe5h\xd0\xed+\xaa\xd3b\xa0\xd3.\xd1\x19y\x1a\ -\x07+b\xa2\xca!\xb8\xe2c\xd2\xbdH\x02\xe9\x0e\x87\ -\xda\x22\xd2Th\x17\x8fO\xba\xd4a\x98%\xdb\x9d0\ -f;f\x85\xf0\x03\x07\x8eJ%\x19\xf0\xbd\x92\xed$\ -\xb4\xba9L\xc9\xf1\xea\x96\x86\x10\xd3\xe2\x85\x07\xea\xea\ -\x97\x9c\x98\xc7\xb4\xff\xea\xc3\xea\x98\x18\x13\xc2r\xf5@\ -,+\x1bSv\xdd0/4L\xe1N\x80u\x0b\x8e\ -\xebb\xca\xff\xd30\x83\xe2\x08AIe\xea\xec\x87Y\ -J\x5c.\x83X\xa2\xc5\xc2^\xe4\xc1\xc4\xb0\xf5\xdaA\ -\xf0\x1e\x99\x9b\xb4Z\xfa\xeau\x80\xa4\x9d\x0f'\xc4\xc2\ -\x93\x12\xe2|\xa2\x22\xe7\x8bd\xe7\xb4\xcb\xd5\xcd\xb2\xa1\ -\x17t\x96O\x22\xe6e\xe4 N\xe9\xbc\x9c~\xb5:\ -U\x9e\xd0\x86A\xdb\x9ag\xb8\x143\x89\xb36\x13\x1e\ -\xc1\xcc!\xf8q\xbc[\x07\x97X\xae\x94\xd0\xc1\x052\ -K\xc9\xc2S\x96\x0e\xc9\xab)\x1bb\x05\xcd7\x92\xe6\ -\xbc\x87\x0c\xc9\x11m,o@\xc9T\xb8j&\x11%\ -\x17\xd1\xca\xc5r\xae\xb6\x0c\xe9n\xcev\xf2tJ\xcf\ -\x95\xe8$\xac~f\xe5X\x12\x96WW\xad=+,\ -\xfeC1)KN_8\xc2\xc5C6\xb5l\x8f\xe6\ -\x0c\xa69\xcb/\xbd)\x9c\x03~\xe2\xa7\x8c]F\xbb\ -\xe7\xb3\xe2be$>\x88/\xeb\x0b\x09\x09\x120\x7f\ -\x1d\x06\x09A\xa1C6s\x11\x18\x17$r,\x7f}\ -Y\xb8.k<\xaa\x92\x83A0=\xa1\x9fW\x92q\ -\xd9\xae~\xf5\x88\xdaJ\x14\xa5\xf8\xb8\xe1h\x97\x04\xa3\ -\xd1iy\xee\x82\x1e[\x0e\x8b\xab\xc9\x08\xbcL<\xc7\ -V\x84\xbeu\xac[\xe4\xc9\x13\xc6z\x0d\xf1.\x0d\xc7\ -\xe0\x1b`\xd3\xcc\xf3\xcbtd\xc4,\xb3b\xa2|\x1c\ -\x07t,\x8eXdj|\x07$\x92m%\xb4\xbb\x02\ -\xa44\x07!/\xa7\xf7qd\x84\x1a.\x1a\xf2\xbdD\ -.\xdaD\x86a\xc1s&\xb0b\xf3\xb5V\xc6s\x13\ -\x19p\x18\xe16je\xd6\xb0U4t\xb7\x94\xb8r\ -\x0f\xc8\x13\xd1\x9d$E\xd2\xf2T\xd79\xcc\x98\x0cV\ -\xaeF\xe6`\xb6}<\xe9\x1d\x9c\xe8\xe6\xc8.\x85\x22\ -\xde\xc2\xa1\xa5\x12P+w\xd8\xf2\x98C;S\xe9N\ -\x081=\x8d\ -B\xc8\x91\xc2\x81#\xc8\x8b\x02\xee\x91\x9a^\x84\xa6t\ -0\xbe\x83\x9d\x88n\x19 \xa4X\x82hNj\xec\xb8\ -\x18\xeb\x0a\x9c\xff!\x06\x13O\xbb\xfa\xe8\x1e:\xa4\xbb\ -\xfc\x14C\xbe\x9bg\x81\xbb`\x84[\xf9D\xf1\xf6\xea\ -\x1a\x88\xab\x0d\xc9.\x14\xaa\x0eBH\xd1\xf5U\x85\xb4\ -\x0b1s\xd9\x8b\xf0\xb0\x08\xaf*\x1e\xdd\x1e\xc0\x1a\xd8\ -\x8f\xc0\xa9\xa0}s\x9e\xf4TA8\x02\xfb\xba\xdd+\ -Zh\xebdg\x99D&\x9b\x94\x0c\xe1c\x95\xa9z\ -\x9b!\xed\xd0\xd4\xf3\x8b~\xb2\x8a\xbc\x08\x8c$_j\ -i\x0f\x0c\xad(\x8b\xad;\x22N\x8bd\x12c\x80\xf5\ -W{0\x81\xc7\xa5\xf6r\xa5\x91\xa5b~Jwq\ -\x13\x8f\x0b\xcasXM\xca\x95z/*\xb9\xb6M1\ -^j&\xb2\xfey\xa5\x0b\xb1s\xc1\x8b\xd0\xf0\x0d\x94\ -d\x7frX\xfa}YiJ\xb8h\xe6\xea\xb2\x1as\ -\xc4\x9b\x86\x91x\xa7\xe3\xba\xa9{\xc9\xa2e\x0aWA\ -\x9d]\xa8)\xdfu\x93\x0d\x9bK`!\xfa8SY\ -4I\xb8A\xc2%o\x04\x0e\x91\x0cI\x8f\xf8\xccY\ -\xcc,\xb3\xfd\xe9\x87\xeb9:\xedY9\xe9Q\xcfa\ -\x93\xecV\x1e$N\xe8\xb7\x10\xebW\x1d\xf4\x8f:\x90\ -)\x1c)Z\xce^\x14\x0d\x9d\x0e\x15z`q{\x11\ -\xdb\xdc\x8b\x16\x06U<$!\xe3&\xaa\xcc\xc8\x95\xdb\ -\x0f\x01\xb0`\xe9\x1av%\xd1\x8a\x1a\x0f\x0d9\xe5#\ -*\xc3\xdcE\xab\x86\xaf\xad\x00\x84\xaai\x8a\x9a\x7f\xd3\ -\x8c\xd1\xda\x83\xd7\x89\xb6Tt*~\x95\xed\xd5K$\ -\xbe\xcffC\xf5P,|#\x84\xaa\x0f\xab\xba\x88\x96\ -\xa2\x83uX\x83\xc9\x9fBx\x84\x8f\x5c@\xfb\xb1(\ -k\xbc2\x19c\x89\xe2_\xb2+\x91\xfa1\x0e/\x80\ -\xb0\xcc\xce\xea\x01\xc4]`,w\xf2e\xbf\x5c\x11\xd8\ -\xb0\x14,\xacu\xc7\x8d\x017\xb2\xd6_<\xad\x9b\xc0\ -s`\xcd\xdb\xbe\xab\xce\xaee\x96\xd9\xd0\xac\xef\x17\xac\ -\x9d.sg\xa7\x94h\xfd\x855\x1b\x94\xf5\x87\x15\x1b\ -\x12\x1a\xbd,\xb2}\xc8\x22\x1b/\xe3+\xdc\x22\xbcx\ -\x9a\xef\x0c\xaexW\xf0\x0a\x18nQ\xaeeS\xee\xa4\ -\xd5\xee\xden\x9a^\x04S\xd0\x0cDa\xa2\x04\x9c\x91\ -V\xbc\x86l*\x14\xb5\xd8\xad\xf1c\xd4\xd8<\x13\x9e\ -\xb5\xe2\xb6\xf4\xca\xcc\xee\xb6\x19\xee\xc0\xae\xec\xde\x96e\ -\x0c\xa8\xdb#1x]\x16+V\xdbF\x22\xba\xcdK\ -,\x9eC\xe9\x1b\x14\x14\xd6c\x19\x0e\x0e\xca,\x86\x1b\ -bV\xe8\xd4\x08\xd6\xe4mD\x19N\x95\x19\x11-\xdd\ -\xbf5\x84t'\x0f\xebc\xbd+p\xd1\x0b`\xf7R\ -\xd3\x07\x030\xcb@\xe7\xf0\xb4\x1c.\x19*\xbaW\xa2\ -\x16\xabP\x83g\x07lM$A\xbc\xe6G \xadK\ -(\x84\xa2\xcc\xd7q\xd4\x92e\xb7\xc0\xf9L\x14x\xa3\ -\xd8\xd6\x8b\xc8\xde\xda1\xd4\x06[\xad\xf0)(\xf9\x1b\ -\x8c\xe9VU\x8e\xe2\xb8{\x0eH\xc3\x0a\x0e\xbc\x8c\xbb\ --v!5\xe9R\xeb1\xb3p^\xc6\xe4\xce\xc1\xb7\ -,\x12@\xad\xba\x0b\x8f\x96\xf30\x9fT\x9b\xd7t\x83\ -\x1by\x99\xc4\xd8\xfba\xa4V@\xe9(\xab\xc4c.\ -\xfb\x08U\x22\xed\xa8\xcb\xc0\x84\x94\xfb\x9a\xd4E\xd6\xd9\ -G\x13\x1d\xa2z{V\x11\x1f$\xd8\x98J\x0e\xe1\xd5\ -\x13\x07m\xcb\xc6\xc0_\x19\x09^\xd4\x0f\x8d\xb98\x8b\ -\x06V\xe0\x0cBW\xf5d\xf9\x15\xc7tX\x9f\x9c\xaa\ -6?Q\x19\x86\x99hVs\xdcD9y\x1c+\x93\ -F\xe3\xb7-\xc7\x19\x9b[\xc6\xb2\xc9I-\x18\xad\xf0\ -\xadzh=n;\x899>\xeb\xc8\x09\x98\xf7\x13\xe4\ -\x84\x1a\x94g[':5'\xeaN\xf2\xda\x13\xcb\xce\ -r\x0b\x0f1\x85\x0d\xd6\x9cLR\xf1\xab\x9e\x82)\xa1\ -\x0d^\x8d\xa3\x9d\xc3\xe1\x9eo \x91\x02\xcf\xc9\x95w\ -)\xcdQ\xdf\x98\xe6\xc9I\xa7\xc9,\xbc,Y\x0cv\ -\x16E\xb9\x81\xe2\x9c\xcb3\xfe\xdb\x19\xf4\xab*hJ\ -\x8b4\x10\xc1pO\xa3i)\xca\xc6\x1aa\xfc4\x85\ -0\x8b\xfeE\xd9\xe1\x02\x1a\x0b\xca\x92s\x1a\xc2\xb3$\ -\x8b\xc7\xd7cvQ\xfc\x95&\xcc\xd4\x01Y\x1c^\xf4\ -\x93\xc1\x08\xaax\xe4\x98+\x1f:V\xc4\x05^B\x9f\ --\x85yG&>\xa2,\x17\x1a3\xa2\xc8\xfd\x08\xc2\ -\xc0\xe0\xb7\x00\xce\xd9\x08\x9c\xe9\xaa9r\xe1\x8a\x87\x1b\ ->i|\xdc\xd7\xb2\xf3\x19.\x8bG\xdai\xe4_,\ -x;\x80\xb2\x9f\xdbF\xf0\x95[l\x11\x1f\xa5k\xfe\ -\xf4\xec\xac\xc5\x16\xbcY\x07$\xab\xe6\xb2\xd9\xd93\xdd\ -\xfc\x98\xb6\xed{):\xa6\xb6\x91\xb0\x80\x1fx4\xbe\ -\x90\x81\xaa\x8b\x14\x8d\x8d|\x00\xe6*\x09s2\x95J\xd1i\xdb\ -\x04o\x81i\x9e\x0fF\x16\xad`\xd5\x8el\xd4\xb2m\ -o\xef\xc5M?\xd9\xa3\xaama\x82\xbf\x05\xbf\xa9\xa4\ -`e\x86\x83v\xd0\xe8\xbcf\xe8y\x9a2\xcb\xbb\xa9\ -PAp\xf3qG\xc7;A\xbe\xbb4My\x8d>\ -P\x22\x9ah\xe2\x05\xc5A\xdc\xf6v\x18\xd1\x8d\xc0\xa5\ -9L\xd4\xce\xc8\x81%\xa8\x81=\xcc\x03/J\xf3\x88\ -\xba#9\x8dW\x8e\xa5\xbe\xcb\x0a\xbe\x81w\xb8\x1c\xb9\ -2\xb3\xcb\x06KA\x9fvU\xa1n9/\xb4P\xe0\ -\xa8\xf5\xd0[\xb8\xbf\xc4\x0b\xfaQ\x1bP\xa2\x12\xa4 \ -b\x87;\x99e4E\xf9eS+\xe2\xa6<\x8c\xec\ -\xd9V\x0f\x85\xe1\xe2\xfdqw\x84Ov\xbba\xf3\xfb\ -&\x07fFi\x17K\x15y\xa5\x10\xc7\xf6\x8b%A\ -\x0a\xf0\xc4\xfc\x05Z\xd6rs<\x14kj\x16\xbc9\ -\xd8]p\x1b\x1f\xed\xb8n\xe5\xed\x8a\x8b\xbdt\xf3\xe9\ -\x01\xc5\x5c\xd1\x1c,\xc0\x12\x12\xcd-\xd9\x15\x8bjE\ -M\xb7R1U\x1c\xfd\xd7P\x87\x82\x03Q7\x00\x1e\ -I^\x95\x11\xed\xc6]\xecD\xd1\xeaHa\xba\x15\x85\ -\x840\xff\x95E\xa9N\x1f\xc4\xf7\x99\x7fg\xc8\xb6\xd8\ -V:\x89\xca>8\x80\x90j<\xd6\xa1\x9a\xc6\x18\xdb\xe8\x8a\xf33\xb3\x07\x19\x1b\x99\x82\x0f\ +\xa7\x18;8\xcb\xd8\xf9\xcf3\xf6\xe0\x18\x1by\xdf\xaf\ +06\xf9,\x1b\xf9\x85\x8f3V\xbd\x95\x8d\xfc\xd7;\ +\x18;p\x13\x1b\xf9\x1f\xd0\xf6\xc0\x1c\xdb\xd8\xfa7\xd0\ +\xfe{l\xe3?\xf9\x01c'*l\xe3\x1f}\x95\xb1\ +\xf9\x06\xdb\xf8\xf5\xdfd\xec\xd4\x7fg\x95O\xdf\xc2\xd8\ +[\x9ee'\xd6\xff\x1cco\x9ea\xf3'\xee\x84\xf7\ +\xbe\xcc\x16\xde\xfeCx>\xce\x16\x05\xf4{\xf0zv\ +\xee\xe3\x1fb\xec\xf8\x13\xec\xed\x07\x9e\x81\xf7?\xc4\xde\ +\xe1\xc1\xb8\xf3od\xc1\xde?f\xec\xc7Cv\xe9{\ +]\xc6\xb6]b?\xfd\xae\xdfgl/g\xbf\xf8\x0b\ +#\x8c\xbd\xf7\x1d\xec\xa9\xa7\x9e`l\xc6g/|g\ +\x03c\xc7^\xb7n\xf4\xe3\xdfal\xfb\xeb\xd7\x8dO\ +\xfc9\x8c\xf7\x17\xeb\xde\xfd4\x8c?{\xe7\xbaO~\ +=`\xec\xa7>\xb3~\xe3\xd3u\xc6\xe6\xfe\xee\xfa\xfb\ +\xee\xffo\x8c\xed>\xbf\xfex\xf7\x7f2V\xf9\xe8\xfa\ +G\xda\x15\xc6N\xdf\xbb\xfe\x93\xef\x81v\xaf\xf9\x87\xeb\ +\xbf\xfe\xdac\x8c]\xf8\xf8\xfa\xe7\xbbM\xc6\xee>\xb9\ +\xfe[O\x7f\x86\xb1\x89\x99\x0d\xb7\x1c\xb8\xc8\xd8\xa1\xa5\ +\x0do\xfc\xe5\xe7\x19;\xfc\xc0\x86\xfb\xfe\x11\x8cs\xd7\ +\xfc\x86\xf9o~\x02\xe0yb\xc3O\xbd\x0d\xda\xd7\x9b\ +\x1b\xfe\xce\xa6\x09\xe8\xff/6\xfc\xbb\xdd{\x00\x7fS\ +#\xfb\x9e{3\xc0\xf7\xf3#\xf3\x9f\xda\xc9\xd8\x91\xff\ +2\xd2y\xfc\x9f1\xf6\xc0\xd7F\xde\xfd\x0d\xc0\xc3\x81\ +\xff;\xf2\xbeO6\xa0\xff\x1f\x8c\xbc\xffS\x8f3\xf6\ +\xd3\xf7\x8e|\xf4\x9a\xdfcl\x97;\xf2\xb1\xe4k\xf0\ +\xfcgF\xfe\xf9\xed\xbf\x08\xe3|z\xe4\xab_\xf80\ +\xcc\xeb\xd2\xc8\xb3\x1f\xfcq\xf8\xfd\xd9\x91\xe7\x8eC?\ +\xd1\xef\x8d\xfc\xb0\xba\x8b\xb1k?\xb6\xf1G\x9f\x03\xfc\ +\x1e\x17\x1b\xff\xe5\xc7`=\xe6\xfet\xe3\xbf}\xe6#\ +\x00\xd7\xff\xde\xf8\xef/\x00~\xee\xf9\xdc\xc6?x\x1a\ +\xe0;\xf5\xe9M7\xbc\xf3+0\xcf\xea\xa6\x9b\xff\x10\ +\xf0~\xf2\x1d\x9bn{\x09\xc6=\xb1w\xd3\xae7\x0a\ +\x80\xef\xfd\x9bv\x8d\x01\xdc3Omz\xe47\xde\x03\ +\xef56-\x7f\xe0\x06\xc6\xf6\xff\xd3M\xff\xe0\x87\xd0\ +\xff\xec\xb3\x9b>\xf3\xd9\x0f26\xf5\xf8\xa6\xcf\xdft\ +\x8e\xb1\xe9\x076}k\xd7\x17\xe0\xf3=\x9b\xbe\xf5\xfb\ +\xb0w\x0e}\x7f\xf3\x8f\xc0\xd7\xa1\xdf\xa8\xfc\xfa\x0a\xfc^\ +\xbe\xa3\xf2[\xefK\xe0\xfb\x8d\x95?\xf9\xca\x97\x81\x0e\ +N_\xf3\xde\xeb`\xbc\xc3\x95k\x9e\x19\xfb#\x80\xe7\ +\xc1k\xbe\xf9<\xce\xfbW\xb6\x8d\xfc\x12\xce\xf7\x8em\ +{\xde\x02\xf3\x8ft\xf0\x83k\xef\xf9\xd2\x0b\x80\xd7\xbf\xbc\xf6\ +\xfe\x9f\x87u\xde|\xf2\xda\xb9_\x85\xdf3\xf7\x5c\xfb\ +\x07O\xc3\xfa\xcc\xff\xf6\xb5\xdf|\x01\xf6\xeb\x96\xef^\ +\xfb\xc2\x06\x84\xef{\xd7\x8d\xec\x87\xf5\xd9\xff\x86\xeb\x9a\ +/m\x83u\xddv\x9d\x1f\xc2\xf8\xc1#\xdb\xd7}\xea\ +\xff\xc08\xf3\xdb_\xf7\xc6*c\xd7\x7fh\xfb\xfcS\ +\xefe\xec\xfe\xdf\xdc\xee~\xe3i\xc6\xf6<\xb9=\xee\ +~\x1a\xd6\xe5\x1b\xdb\x97\xcf|\x00\xde\xfb\xb3\xed\x7f\x7f\ +/\xcc\xe7\x9e\x1f\xdd\xfe\xc4\xa7>\x07\xf0\xfe\x8b\xed_\ +\xfd\x04\xccg\xeb\x9fm\xff\xe3\x8f\x00>\x80\xc2\xfe\xd7\ +\xf30\x9f3\xcfy\x8c\xfd\xcc\xed\x80\xc9\x8d7\xb2\x0a\ +;\x0c\xff\xba\xac\xc7\x04k3\xce<\x16\xb3\x04~\x07\ +\xf0W\x93u\xe8o\x87\xf5Y\x0b~\xbb\xd0\xc6\x83o\ +\x04\xb4\xe7l\x81\xadP[\xf9\x09\x9f\xe3'\x87\xf9\xf0\ +\xcf\x83\xa7\x11|\xaa\xd2?\xcef\xe9{\x0fF\x10\xf0\ +\xe90\xf4\x17\xb0%\xf8\xdec!\xf5\x17\xc0\xd3\x01\xbd\ +\xe3\xaaO\xf6\xf8\xcb\xf4M\x8b\xbd\x04\xef7`\x84\x08\ +\x9e\xc5\x0a\x96:\xcc\xa0\xc2&\xe1\xc9\x0c\xb5\xe2\xb9\xf9\ +$\xd0G\x04\x7f;\xd03\xb6\xc7g'`T\x17`\ +\x88\xcd\x9b\x0e\xfc\xcd\xd9q\x82fY\xc1.\xe7 \xa1\ +Y\xa6o8;\x03O\x11\xc2\x90\xda{\xf4L\xa8\xdf\ +\xcb4w\xf9}L\xa3\xcc\xb3\xbd\x04O\x08\xfdt\xe1\ +\xdbD\x8dw\x02Z$\x04\x91C\xf8\xc3\xb7k\xf0\xff\ +\x22|n[=\xbb\x0a\xaetT\x9cwS\xcd\xc8\x03\ +\x5c\xe0\xbb8\xff\x19\x826\xfe+a\xb7\x0d\xcf\xf1\x0d\ +\x17\xa0\x17\xb4B\xf8w:\xe7y\x82?\xa0\x9e\x11n\ +|\x8f\xab\xb1_\xa4Q\xda\xf0s\x82\xf6IC\xad\x81\ +\xc8\xac\xf7<=\x8d-h\x96\xe0\xcd\x00\xfe\xe9\xd9\xbb\ +\x16\xfc\x01@\x93\xb0\x8b\x06\xee\x90v\x94\x9e\xe9i\xda\ +m\xd95v\xe8\x8dP\xe1\xd8S8\xe2\xd0G\x7f\x95\ +\x9d\x89\xbdM\xd0\xdc\x05\xb4\x14\x06\xe2\x16\xb4\x92\xefz\ +\x16\x5cz\xff\xca\xdd\x8e\xbd\xf4i'I\x08\xfb\x0a_\ +K\xd4{\x13~s\x83\xe7.\xad\xa8\x86H>;H\ +\xd0&\x0a\xbb!\xb5\x8dV\x853?W\x1f\xdeX\xa2\ +6\xe9\xc8\x922\xb8\xdaw\x1arM\xabA\x8eV{\ +4K|\xafC-\x10K\x156\x06\xbf\xab\x00\x1bR\ +\xebKf\x1d\xb3\xbd\xcc\xd1\xdf}v\x81\xd6\xd4\x018\ +p?\xe0\x1c\x03\x9a'\xbe3\x91\x99S\xb6'\xec\xe3\ +,\xf5\xe1B\x9b\x01A;\xcf\xa6a\xdf\x1fe\xe3C\ +\xfb\xf8,Qz\xa0p\x8d;\xc1\xa3\x1d\x9c\xdd\xbd\x82\ +\xda\x08\xc2)'H\x10\x8e\x8b\x04w\x9b8P\x05\x9e\ +\xbf\xac\x7f[\x90Unbl\xfd\x1b*\x87\x0fw{\ +\xa2\xcd\xbd8\xd8\x99p/\x88\x13\xc7\xf7\x85\xcb\xc3\x80\ +\xaf\x84\xfd\x88\xc7+q\x22\xba\xd5j\x95/\x84]\xc1\ +[\xc2I\xfa\x91\x88\xf9 \xc4\xf6\x0d\xc1\x9de\xc7\xf3\ +\x9d\x86/\xea\x95\xca$_\xec\x08\xaezL:\x91p\ +\x5c/h\xf3n\xe8\x0a\xf8\xeeP\x18,\x8b(\xc1'\ +\xcb\x9e+\xc2\x18\x86KB\xee\xf0e\xc7\xf7\x5c^\xed\ +\xf6\xf6\xf2V\x18u\x9d\x04\x1a\x9f\x8dd7\xcc\x06\x09 \xb2\x09x\x0d\xbb|\ +\xdeI:\xf5\xa2\xe1\x9fa\xc7\x88\x85\xa5\xe2F\x0a\x80\ +:\x898O\x11\x95\x00\x80\xa4\xf0L\xe8\xc9%\x12\x0d\ +\xf8L>y\x8cHX3\xbe\x94\x99 \x11\x9f\x86\x9f\ +sJ`&\xd4GJrm\xea%e\xda\xa9\xb0\x91\ +*\xc5\x84\xa5\x5cH\x92~\x09\x98\x98\x14\x1fU3\xd5\ +c\xc7\x02\xb9\xcb\xbd0\xa8\x13\xc1\x9c\x15\x8d\xd8K\x04\ +\xbf4\x90\x7f<\xc6\xe3\x9ehz-\x0f\xe8\x10\xb6\x06\ +\xae\xea\xe9\x87\xe6x\xcb\xf3\x85\xa2S\xa2\x98j\x11\x86\ +\x9e\x84\x19dG\x16$\xf6\xe5l\xda\x045\xce\xbbJ\ +s\x8c\xa0]\x93\x98\x1cg\xa3\x05\xad\x02\xa3\x1a\xf9j\ +f\xf8l\x94\xe6\xd7\xa5\xef\xa4\xe0B1\xf0\x22\xbc\xe7\ ++\xb6%\xdf\x94\xc2)V\x02(\xb0pp\xe8X \ +\x89\xfe\x90\x93\x88v\x18\xadT\xf9<\xd1\xcbN\xdf\x8b\ +\x91>\xe9\xa9'\xe2\x9dH[\xb1\x006\x03\xd4\xd2\x0b\ +\xe3\xd8\x03N\x03\xccI\xc4\x85\xb3\xef\x14\xcc>\xb26\ +^\xd5\xda'\xd3\xd0r\xa0T\x81\x22\x06\xdc\xa79\xb4\ +\x89Y\xe3\x9c|R\x89\xe2\xdcL&\xf4Lz\xb0g\ +\xab\xb4\x9cN\xaf\xe7\x03\xc1\xe3\xfa\xf2\x81\x07p\x07\xe1\ +\x80\x8b\x0b^R\x08\xb2\x0b\xdb-$\x09\x9a\x1dNo\ +\xdfHm\xac\x06}\x96\x1bZ\xcb\x9c\x1e-`\x8b\x9e\ +\xa5rL\xcb\xf2\xb6\xd2V\x02\xb6\xc3\x80[\x9f\x0b\xdb\ +\xb0\xa5\x0e\x03\xcf\x16\xee\x04\x07v\xe7\x00\xf7lvD\ +sI2\x99f$\x5c\x11$\x9e\xe3K6\x96\x00\x0b\ +%>\xb1\xa3\x08\xf8\xdb3\xc0K\x15\x16\x95\x99\xb6R\ +\xdfp\x22\xe9\xe0\xaf\x91\x83/\xf4\x9b\xc8\x9c\x81\xf5\x16\ +\xf6\xf9\xeeRUd\x00\x9fR\xba\x93\xe8\xea\x99\xb1\xb4\ +J\x8e*H\x8a.\xa9rD\xeaS\xb1\xb2'\x05l\ +\x0akm\xc1Y\x06\xf2;\x1d\x03WZP|\xdd\xe0\ +\x0b\xb6j\xe2D\x89%W\x0ag\xf2\xbbj&\x92\x1b\ + l\x03\x03GbTyA{K~J\xe0\xa7C\ +\xfc\xa3As\xea\x92J\xe2\x98\xf9j\xc5;\xab\xa4K\ +\x0a\xd5\xb3\xf6\xe9\x1b\xa4Ha\xfe\xd6j\xb6^\x1d\xb9\ +\xeb\x05\xf1\xcdK4vDX9Oo\xe1.\x97\xca\ +\xcec\x06\x1f\xc7I\xfc\x8b(\x02q\x136\x9b\xfd(\ +\x92\xcc\xc9\x0f\xa5\x8cw\xa4@\x06:\xd6(\xea\x85\x80\ +\xa1\x04\xc4O\x9d_\xa2\xf7\xcewQ$\xb7\xc5cE\ +\xb8z\x04p\x95\xee\x1e\x09\x17\xe2\xe8\x02\xfc|,C\ +\x99\xa8\x0aF9\x85z\x81V\xfb\xa2\xa1\xe3\xb6%\x90\ +\x12kU\xabj\xef\x01H\x89\xb8\x90<&\xe9S\xaa\ +\x02.)\x02\x0800\x1c`4a\xf1\x96\xbf`\xac\ +\xb0i\xb2\xaf4\x95\xf5,\xd9vA1K-\xfd\xb2\ +\xfa\x9c\xad\x0f\x0f[\xa2\x0d\xc3\x01\xb4\x05$\xed\xc1\x94\ +\xe5\xecF&\x13\xf6\x93\x1eh2\xc8u\xb8\x1b\x82\xe2\ +\x13\x84\x092\x19\xe0\x9e\xa8_\xc8\xcf\x03P\xa2P5\ ++d<\x97\x01\xe31\xe1\x0a\x07I,3o\x9ev\ +C\x83ve\x97v\x92G\xdf\xbb\xeasJ\xf3yJ\ +\xf3\xe9\x9b\xb6\xdas\x9e\xa2-i\x1a\xd9#\xf4\x8d\x01\ +&\xbf\xeb+\xea\x95;5(0D\xb5\xa9\x965\xd0\ +\xa7\xe1\xbd&|\xd3'CKK\x1c\xdfPL\x8a\xb4\ +\x0b\x80\xb4H\xec\x04\xa6\x06\x9aY\x088\xe9\xc2\xda'\ +Re\xf2\x91-\x99\x9d\xdbu\x96@A\x02e\x12\x19\ +\xa2\xfc\x0eDo\x04\x88%~\xd8\x11\xa4\xac\x11c\x04\ +\xd9\xd4\x16\x89\xd6f\x1bNl)\xceN\xb3\x19\xf6\x83\ +b\x9e?\x9f\xb1\x02\xce\x01\xd0m\xa5d\xc4\x19\x8b9\ +\x15\x9d\xc3\x0a\x85$\xfbX\xfa\x1f\xcc4\xdf\xb4\xd8\x09\ +\x91\xa1[\x5c\xdc%\xa5\x0fdh\x17\xe1\x85\xbd.\x95\ +\x87j!dw\x01d}%mb\xb3\x1f#%\x8d\ +b\xb3\x84mb.r\xb1m\x02\xbb\xe5\xad\x80\x1a\xd0\ +\xc1A^\xa3\xf6\xbf\x82\xf8k\x13\xa7\x18&\xa6\xbf\x84\ +\xff\xf4\x8b\xb7<\xbe\x7f\xc7\xcc\xa9C\x8bo\x9d\x9f\xe5\ +G\x17O\xcc\xf1\xf9\xd3\x07\xe7\x8e\x1d\xe2\xa3\x93\xb5\xda\ +\xd9=\x87j\xb5\x99\xc5\x19\xf9\xc5\xde\xeaT\xad6{\ +r\x94\x8fv\x92\xa4W\xaf\xd5\x06\x83Au\xb0\xa7\x1a\ +F\xed\xda\xe2C\xb5\x87f\x0fMv\x92\xae\xbfw\xaa\ +\x16'\x91\xd7L\xaan\xe2\x8e\xdeW\xd9\x8f\x0f\xef\xdb\ +\x8f:\xfb}\xfb\xd1\x9a\xe0\x81\xd3\x15\x07F\x1f\x856\ +\x1d\xe4\x05\xa3\xbc\x19\x82\x0e\x1a$\x07Fw\x8d\xf2\x9a\ +j\xd4\xec8\x11\xa8\xf5\x07F\xfbIk\xf2nz\x1e\ +'+\xa0\x82$+=x\x1b_\xac5\xe3\x18\x06\xe8\ +M\x80\x82\xce/\xf1A\x074\xb8\xc9\x18\xd4tQG\ +#`r\x109\xbd{\xf9c\x95N\x04\xdfv\x84\xd7\ +\xee$u\xbe\xabw\xe1^\xde\x08#WD\x93\x03\xcf\ +\x05u\x97Oa#\xdf\xab\xf6\x03\x12\xc7\xc2\xad\xd7\xbb\ +N\xb4$\xf05\x05Z\x9d\x8f>\xb2\xfb\xae]S\xa3\ +\xaa\xe9\x95\x1a\xee\xa6\x86\xfbk\x04\xf2}\xfbkr\xf6\ +\x8d\x10\xd6\x85\x1e\x1d\x18\x05\x9e\x17$\x93-\xa7\xeb\xf9\ ++\xf5\x9d\x0bN\x10\x83\xb4\x8b\xbc\xd6\xce{\xe57\xb1\ +wQ\xd4\xef\xe9%\xea\xe3@\x82\xbfwjJ\x7f\x8f\ +\xdd\xd4\x03\xd4g\xfd{\x11\xcd=\xd33\xc0\x04\xa43\ +\x99\x84\xbd\xfa\x14\xceV}n\x84`\x05u3\x8f|\ +\xd1J2\x0f\x22\x1a\x85\x9eL>\x9aL6\xc0.Z\ +\x9a\x04\xbb\x06g\x06##\xd6\xcdGh4z\xdfB\ +\xbf\x87\xe2\x066\x9a\xd2\xa5\xe3\xfa\xfeZ\xcf\x06\x07\xfb\ +\xe99\x91\xd3\x86\xd5\xe8L\xe2\xea\xd5E\xb7\x97\xac\xdc\ +\xfb7\x0a\xe7\xfeF\x84[(\x0b\xda\xdf(\x043`\ +\xf8)\x99}\x15E\xc5\x10L\x92^w\xb4\xdf\xa86\ +\xc1\x16\x1d\x8b\xe5\xde\x02[>\x04\x9b\x1d\xa5G\x1bM\ +\x95\xf1W\x16\xc4\xa3\x0f\x22\x90\x22B\x18_YHf\ +{\xaf\x12@\x1e>\xf9\xf0\xc3\xaf\xe6%{\xf8\x0c\xe9\ +\x09\xaff\x10\x17zN\xb0\xd4p\x82\xf6\xcb\x02\xf2*\ +\xe3\x90\x10L\x83-A\xc2\x87+\xc4\xf1;\xa5\x13T\ +\xb8w\x82\x1a&\x19\xaf4\xabc\xe1\x8b&\xe9\xe6\xfc\ +\xd1>\xe8c\xc9\xca\x8e\xabH-\x84\xe0N\xdeyT\ +r\x18B\x9cP\x7fG\xfd\x80\x5c\x9a\xa0\x9c?\xb8H\ +H\x8e\xa5o\x17\x14\xf4\x15\xa5\xf3\xb6P\xcf\x04T\xb7\ +\xbb\xd0],\x9d3\xa4\xab\xa3}\xe4z\x11\xac\x80\xbf\ +\xf2J\xceM\xef\x09t\xc5$h\x9f\x80\x05*,\xc7\ +9L\xce\xd1\xf0+\xcf_ @\xb3w\xabW7K\ +!\x04'BW\xf8\xbc\xc6\x0fu\x9c \x80\xbf\xb4\xb6\ +\x13_\xc5\xd7\x95U\x9d\xab\x0a\x8dRh\xe6_e\x0a\ +\xcd\xabFm\xb9JE\xc5\xd6\xa7p\xa2f\xe7\xaaE\ +u\x95\xcd\xbc,\xbaZ^\x8d\xae\xfe\xb6\x1bpW\xa9\ +\xa8\x10\x82c\xdc\xe9\xa2\x83/N\x9c\x00\x14W>\x08\ +\xa3%J\x91\x08\x8d\xbd\xd1E\xfdQE\x91\xe3\xea+\ +\x0al\x8b\xbc\xe4\x03\x00\x15uX\x19\xcfn\x92y\xa4\ +\xdc\xd0\xb1\xf6\xd9\xa9t\x0a'^\xaa+$\xd3\xcf\x19\ +/n\x86\x91[\xe7\x02\x1d\xb4\x91\xe3\xc7-gI\xbc\ +\x92s:\xe2%\x8a\x87\xd520\xd5R\xafv\xcd\x8b\ +\xe3\xbe\xf8\xffH\xdd\xbc\x0a\xdaU\xd0\xfe\xb6\x82\xb6\xbf\ +\x86\xa1\x10\x8c\x8b`l\x08\xe3S\xafI)\xf9\xfcY\ +\xcfm\x8b\x84\xa2b7\xb2#\x14\xadsXW\xe58\ +y,11\xaf-\xe8\xf7Y\xf4\xba\xa2\xa4\x87\xbb3\ +\xe9&2\xa276\x94a\xca\xd9IJCH\x13\x16\ +\xc6\xcd(7M\xf7z\xc0\xf4\xf9\x18z\x00b\x9d\x82\ +0^2f\x85\x22\xd4\x98\x85\x19\x99^6M\xf7\x93\ +N\x18\x95\xbc\xf5Nv\x96]\xa6\x94\x84\xa40\xef4\ +\x8di\xdb\x19`\x07M\x94P\x86|\x8b\xb3\x89)b\ +i`\xb9c:\x93cG\xc1,\x8c\xcfFN\xd0\x16\ +\xe5w\x95\xad\xdf-\xabfk\xa7ys\xd7\ +\xa4I\x95\xf5\x92\xae\xaeg\x0b\xb4\xa5\x02\x0a/G\xcc\ +5\x1dl\x9e\x11-\xa7\xef\x97a\xe9\x8e\xdc*\xda\xd9\ +\x0a\x98\x22\xa0\xa02]\xbev&\xa4\xec\x83\xa6\x0fv\ +\xd1\x95\x17\xf1!\x82-d=\xf8\x97O\x86\xd0y+\ +Gi\x90\xbeJ\xa7\x8e\xac\x08\x7f\xe1V3\xa0\xf0\x19\ +\x9d\x1a\x11\x03o1>\xd84\x05\xb5\x14\xfd\xab\x8e\x9a\ +\x92\xbev0\x95\xf4\xf3\x16\x93\xc1\xa3C\xf6\x18<\x1f\ +\x18\x22\x13Cd\xd2\xc9\x8ekF\xbbY\x8f\xc6\x17\xc8\ +},\x5c~\xe6J\xb3\xb8c\xe8\xf0Ca\xaa\xb8\x19\ +\xe3\xf5f\x0c\xf4\xb6.\x88\xa4\xdfS\x09\xbd%\x83\xfc\ +\x18L\xf1\xb2\xca\x0a@J\xe8\xaa,j\x99\xc7\x90R\ +\xc0\x0d3\xfdH\xe6\xc5\x8du\xbd\xa0\x0f:\xea\xaa\xfb\ +\xdfN\x0e`\x9bg'O8\x9e_\xb6\xc3\xafc\xb3\ +&\xb3\xcb\xc6\xd9f\xe5\xcd)%\x8eY\x82\xdd\xd7\xd4\ +l\xbd\x1c\xb4}/\xee\x94\xee^\x9d\x10;\xca\xaa\xac\ +F\xb9\x91i\x86\x92\xa3\xd8\x1e\x1eU\xe8\xabl6\xb9\ +\xde\x88\xf7\x8b\x86a\x064\xb4b\xa9\xe9\xee\x95I\xb1\ +\xa3\xd5\xda(\xe5&Q\xd6\x15\xe8\xd3\xd2u\x1dF+\ +%p=2\x94\xa8\xab\x0f\x85\x08J\xac\xaf\xa9\xac\xd0\ +@%\xda\xa7II3\xc4!\xd2\xec;\x9d\x17\xfb\x10\ +\xe5\xc5f!\xbcMB\x98w\xbb\xd6\xf8t3\xa1|\ +\xce\xd3\x0f\xcd\x95\x00y\xb0\x00H\xbd\x88G\x01a\x0d\ +\xfa\x8cd\xb7b\x12PW\x03\xe5V\x09\x8a\xa3]\x0d\ +|\xdewV(\x9b\xb4\x1c\x86\x89\x02\x18\xec\xd3(\xc5\ +\xa3m\x97\xa3\xc9hB\xf9\x00\xbfn\x06pK\xa69\ +\xcb&a}\x1c\xca\xdf\xc3\xbc&\x97\xe82V)B\ +:oj,\xc7\x1dm\x11|\xd2J\xc0\x0eHU\xd1\ +G@\xf2cuT\x8e\xa1\xde\x9fH\xb6\x97\x95bB\ +JGz@\x80= 'J)M\x1a\xb3\x92\x1a\xb9\ +\xe3\xba\xb4\xc6c\xc8_\xa9A?\x16\x11\xa6\xd5Lp\ +t)t\xa0i\xb3\x83\xc2\xdc\xe5^2\xceKp\xb4\ +\x7f\x08G)\xd4\xf6Vp\x08#2\xf7:\x19Z\x94\ +7\x14\xc0:\xef\xc41\x18\xca\xee\x9a\xf8\xcc\x16\xe5\x0a\ +\xa9\x97\xee\x97\xe1\xdd\x11\xab\xac\xbf\x9e\x02l\x98\xad\xbe\ +f\xf6\x02\x19\xe8f\xc3\xc4k\x02h\xd3\xe1\xc3'\xe6\ +g\x8f\x94\xaa#Y\xd9\xa1s\xf5\x0e\xd3\x81\xb0\x84\xb2\ +eq\x07\xf5\x94B\x99\xca\xc6\xed\x87\xe5\x99\x09\xf7\xca\ +\xa2p\x9b\x95\x0e\x9f\xea\x1e\x1b\x0f{\xbe\xa8\x97\xaag\ +\x87)\x9f\x15\x0f\xe0\xbc\x98*K\xd6\xec\x80\x9d5;\ +\xa5\x5c}F\x1d|\xc9\xbdyDD]'(\x15I\ +\x07i\xec\x8b\x8a\x22\xe2U4\x84\xd7\x1e\x11\x09?\x18\ +9\x17/\x8a(\xbe2&&\xc8\x12@^\xb4T(\ +\xba1\x174\xa2t\x5c{\xf5\xaf\xc7A\xe6\xbc\xa5\xb5\ +\xe0z\x82-\xaa\xcco\x9f\x88\xd7\xe8\xf0V\xda\xa4\x91\ +\xb6\xe9\xd6\xc7\x11\x16\xbd\xc4\x07\xda\x93*\xfe\x04\xd7\xc2\ +\xb6d\xb0\x1b`0\xd4\xbcRjK\x97\xf7Z\xea\x12\ +\xb4&|\xb5^\xba\x05\xcf\xd1\x8c/+\x95\xa2=\x94\ +\xa4\xbc\x1a^\xb6\xe2\x10\xa4\xc2\x94t\x7f\xeb\x9aP\x5c\ +1]\x95!\x97_\x09\xd4\xec\x92\x81%\xe2\x86]\xb9\ +f%\xbd\xd6I\x07\x8d2g\x05\x1c\x95\x83\xbc\xd6-\ +r\x13\x8d'\x9aa\xb7+\xc0Z]\xc3F\xd9O\x19\ +\xd3\x1d\x92\xdfE[Q\xcb\x86\xa8\xe8\xfcGv\x5c\x9d\ +\xc0\xba\xa2O^\xac\x94.w:OG)yk\x9b\ +\xe3\x0d8\xd6\xc0\x81\xfe\xd62\xbf\xdb\xc98\xb3\x8f\x15\ +\x85*\x19\x15O\xa3\x5c\x96\x19\xc3\xa9n|\x04\x9d\x0a\ +t\xce\x8ar\xf6\x8f\xa1(h9\xcd2\xa3\xfc0X\ +\x1e=\xe2\x12i\xf6\xb1\xc4W\x9b\x9e\xf6\xc8\xd0\xb3\x0f\ +6\x9e\x1a\x86\xc0\xa2\x98\xd1\xd5`\xe0s \x05\xfbN\ +[\x94\xdbhG\xd9\x83\x85:\xec\x16\x1d\xb4X\x93\xcc\ +\xd8\xaa[\xd7K9\xfaQ\x22\x82\x16._j\xfb\x1e\ +u\xfcV\xa9\xbd|\x94\x14\x94V\xe6\x1d\xe1\xf7\xae`\ +F\x85\x0a\xbds\xb4)c\x12K\xc0\xbfRb;\xea\ +\xb5;|\x1e\x90\x85\x89\xa4\xc1\xea\x8b\x96\x99\xe8F<\ +HU2\xc9u7\x94\x9e\x16\xd3'.Be\x0d\x09\ +s\x9091\x09\xf82\xb3\x1d\xf3\xcaS\x97\x88\xad\x81\ +iM\x7fV\x89~Mo\x9aQ\xe7V\x94\x18\xfa\x80\ +\x90\xe0\xe7N0\xd8\x9a\x9cct1\xf9\x19\x0fSK\ +j\x93vB\x97\xacH=z\x81\xc5\x98\xb1\x8f\xed\xc3\ +\xc6i\xa2\xf8\xcf\x0e\x9dB\xcb\xe6x5\xc0t7\xe7\ +\x0a(\x93\x9dL\x90Y+\x15G\xef\xb3\x09\xde\x10M\ +\x07t?\x99{\x83\xd9\xdf\xfd\x18Ml\xd7k\xb5\x04\ +Y,]\x81\x8a\xa0\x17wc\xea\xc5\xb2\xc3\xab%[\ +g7\x08?m1\xad\xf1lZ\xca\xd7\xe6\xe8(D\ +\x8b\x0e\x8e\xa5\xe7\xc9J\xe9\x0f]t\xe9\xa9\x99\xb4\xaf\ +\x8dtn\xa9\xd4\x8eA\xd5\xfd\x02\x1d\xd8\xd1[\xe9$\ +\x1d\xf2\xb9\xa8N\xa5/\xa9#,B-l\x87\x0e\xba\ +\xa4\x07\x9bR&r\xfd\x09\xe7\x82\xd7\x85\x95\x88D\x82\ +\x10\xd7K\xbd\x8a\xc3\xe3\x9eS\xb9\xfa\xfa\x8c\x98}\x96\ +D\xd1]\xd1h\x89\xd7\x15a?\xa9\x972\xe4\xe1\xd1\ +\xa6\xa1\xe7\x86uV\xad\xa0g\x0cS\x81nU_\x13\ +MW\xa4)\x09\x0a\xf2\xda\xda\xdf$\xdb+\x016\xa6\ +\xb4\xfer\xaf\xe8\x09b\x02\x8e\xe5\xc1\xddx\x22\x0cJ\ +\x9d~[h9m[c\xfd\xc9\xb0T6\x9f$\xcd\ +\x9b[\xca\x1cZo\xae\xd2f}\xe3(\x8d\x95\xfd\x9f\ +\xda\xda\xa9\xbb\xe4\xf5\xa7\x02\x7fEju|\xcc\xe1>\ +Pb\xcb\x89A\xa6\x8c\x97r\xf6\xff\x04$\xd1\x92\xcc\ +$\xe5\xd2\xa7z\x22(U\xd5\xd3\xb7\xac\xc3\xaf\xa9P\ +\xc1\xf79*\xfc\xa5\xac>{$*=w\x99n\x8b\ +m\xa7\xd2\x83K\xf5R\xcd4o\xed\xa5}l\xd5F\ +]\xb98]M\xda\x5c\xf3r\x05\xcd\xb5\xb6+am\ +\xfbr{z4\x90\x9f\x10A\x7fM/\x8dY/\x9d\ +\xd9S\xdd\xcb\xc7\x0e\x8d\xf3\x07Br\xaa\xc4\xfc\xa8\xd3\ +\x80\x9d~d~\x8e\xef)\xb5\x982\xd6~\xea\xcaR\ +\xa4Q\xf2\xaa;\xe4(\xd0n\xaa\x17\xd5AZ}\xbc\ +n\x0c\x94@\xce\x0e(1\xea\xa8J\x1c\xcb&60\ +n\x8eU/\xc0\x93%%\x0e\xb3|N\xd3*\x9f\x11\ +\x80]>6\xc5\x0f\xf0\x19/\xc6\x94Xw\x1c3\x1f\ +cP\x86\x03w\x8d|c\x8b\xea\xad|K=\x08\x90\ +\xc8\x0a&\x09\x08t{KmyPf\xe1\xd6K]\ +j\xc5GGu\xed\x98\xb3\x8a\xd3\xeb\xba-\xc5\x07X\ +/\x12c\x90\xc7\xaec%#lJ\xbd\xfd!\x11\x0b\ +\xfbh)\x86\xcb]\xe9\xa47\x15\x06JM\x9cYe\ +\x8a4\x94\xba\x10\xab\xba\x16\xd25`\x19x0\x12v\ +:\xe7u\xbdR\xc6\x7f3,\xa3<\xa1\xd7 \x09\x8c\ +\xf2\x17\x99\x85\xd5\x95L\x81\xe2\x0f\xf6E\xb4R.C\ +\x16\xac\xc3~6\xe6\xac#\xfb\xa6\xdb\xebT\xb7\xeaP\ +OI\xbf\xadL\xbf\x81\xa9qb\x9b%U\x1a\xe9\xb2\ +:n\x9b\x16\x00X\xb0J\x05\x0c,Y\xc6\x8dB\x15\ +\x0c\xc5\xaev*\xc8P\x9bQ\xf9q\xca)oN\xf3\ +\x03\xb5\x86\x83R\xa5a\xce\xe8-\xa9\xe5\x91\xeap1\ +\x09qy\x82U\x17\x16\xc9V6\xb0\xb4\x9d\x05!\xf8\ +\xf0!\xa8R\xd5\xc1F\xc5_%|w\xb3\x9a\xef\xcb\ +\x09\xd8\xfd\x98\xd1\xe8L\x7f&\x12\x92q\x97\xa9\xbe\xc5\ +2\xec\xa7\x04S\xebJ:=\x99\xf14\xe8\x03\xa6]\ +\xa2\x01\xe9F\xed\x98\x15}\x88&)\xcd\xb9\xf404\ +7\xd5T\xb2H\xed\x84\x83\xb4T\x09(d\x00M,\ +JM\xe3#4\x11\x89F\x15'6E\x18f\xa8\x22\ +L@\xe7&Q(\xc6\x16\x01\xbdn\xc1\xeb\x02-:\ +\x01(aqzV\xa0^\x1ayx\xd6\xa8x=\xa2\ +I\x1d\x80\x19>\xb2\x99=\x90\xac\x83\xd0v\x95\x8b,\ +s\xbeqa\xc9\xeb\xc9\xe3\xc4\xa8\xc8c\xe5\x89\xb5*\ +p\xe6\x08I\xbdT\x09[\xd0!\xeeT\x09[\xc0\x80\ +v\xc9KwY\x81B\xfbP\xfb\xdc\x1a\x83\x81\xaf]\ +\xc0\x18\xe0\x9a\xe3\x7f\xb7fJ\x0a\xc5\xab\xc4O\xaf[\ +\xa0\x029\x9aC\x972\xe6\xc5\xd2B])\xf6\xb7/\ +\x9a\x13\x00\xa8\xde\xae\x0d\xf1\x9b\x16\xd1~[[\xdb\x91\ +2=\x06\x1e\xff\x84\xe5\xd7\xce\x96G\xb1\xcb\xa2t\x81\ +=\xe9\x82\x18\xa9\xe3\xd9v;\xc9\xa2\x0a\xf2\xfbs\xca\ +\xec\x15\xea\x5c\xb3tH\xa7\xd9\x04v\xf5\xae\xf4<\xf1\ +nt\x95\xeb\x22(T\x00\xa5\x8b\xb9b\x98>&0\ +\x95\x04\xb9\x1d\x9d\xe3\x0e\xc4\x00\x0b\xe4\x88xG\xe9\x12\ +L+\x96\xe3\x10\xcb\xd1\x12\xa8\xa3\x0b\xbb\xa4j\xea\xe9\ + V\xec\xcd\xf7K\x99\xf8Qz7\xb1\xe4\xc9\xf0\x18\ +i\x18\xad\xa0pC*S\xf4\x981\x19\xad)\xe3\xc1\ +\xb9'\x11p\xf8\x01\x0d\x5c\xea<>EH\xd4\x0b\x90\ +-`g{\x02\xee\xb7b<7\x9d\x06\xdb}F\x07\ +\x15U\xc9\xa7\xfb\xf9\x15\x82 !\xf5iG\x9d8\x99\ +\xb5\xc8\xfa\xe4\xf1\xf0|\xb4|\x1by\xc5\xfa=bm\ +\xa5&L\x11\xf9n\xba\xa2w\xb7\x022-\xcc\xf9\x05\ +G\xce\x0a\xb1t\x05\xdd\xa6\xa9\xe4OS\x09\x8a8\xa3\ +\x84l<\x1bF\xa5Y$[\xd8\xc3\x80\x86\x87\xd9\xc3\ +\xe9\xa0\x98\xc9\xba6\x1f\x16\xb6,\x8fk?\x5c\x88\x8d\ +\xcd\x0f\x97\xa3#\xab\x1d\xab\xc6e\x03\x8d\xb0\x07\x98c\ +\xde\xd8\xf0\xd62\xeda\xfd?.)9\xb6\xba\xcfm\ +\xd6D?5c\xd0&F\xacZ]\xa9$\x1f&\xd9\ +\x5cb\xe7\xe1_\xa0j\x83\x9c'\x8e\xea\x13WE\xb6\ +\x82\xdf=F\x06HZ)F\xd7\x99x\x91\xb4VA\ +\x1a\x96o\xbcxU\x82YW\xaa\x90\xc5\xe3DFI\ +\x8c2Q\xd4,D\xb2\xe2\x84\x8e\xf0;\xca\x17\x95\xca\ +Y\xec}u\x5c\x1d\xa1\x91d/u\xa2\x1f\xf47\xf6\ +P\x1a\xb0\x1a\xfck\x13S\xed\x909V\xa5J\x17]\ +x:kvjD\xfaT\x0c\x10\xc9Ru5\x03\xe5\ +y\x0b\xcaZ\x0eG1\ +GA\xbbJ\x1f\xf87f{\xd6\x02'h\xaeL:\ +\x15k\x99\x80U\x9f3U%\xa5-\xdbU\xa1\xabP\ +\x85\xfe}c\xfb{V=\xb1\x81zCzm$\xb3\ +k\xbf,\xebE\x17\xd6B\x96\xd5R5/%\xcb\xab\ +P\xee\xa9Om\x0e*/\x5cO\x8d\xa3C A\xa6\ +\xfah\x11\xdc\x0d\xa5g\x8e\xb2]\x94V%\xd3\xd5t\ +%\xd6\xb4PPZ\x1aJ\xa7\x8e\xd8\xf6`7\xe3\xb3\ +\xd6\xfe\x17\xa9\x83\xfa\xa6\x9c\x9f\xf6\x9a\x0f\x87R2\xaa\ +\x0c\xcd\xed\xec\xcb\x82~o\x09\xe4K\xea\xafX\xe9\x8f\ +}\xd5>\xab%\xae\xb6*ea\x9f\xaa\xc1\xbc\xae\x22\ +\x14Y\x85\xd0\x96\xd4\xac\x8f\x997\x03\x12\x16RL6\ +\xd4Z\xda^\xab\xae\xc9gM\xed\xae\x05j'S\x8c\ +*\x96\x96\xab\x8d\x9b\xd8\x08\xde\x06\x85S\xfb\xa6\x87b\ +Q\x9a\xc2\xa9\xf7$g\x87\xa0\xed\xe9\xe1\xc8\xa1\xc1c\ +'WIK\xef\x80\xb3\xc6\xae\xe8\x80\xd8\xd7\xad\x1c\xb5\ +'\xf7\xa8\x96\xed\x9c2\xc0\xd9\xa3$\xc4u\x00\xb0b\ +\x18\xe0\xdb\xb0\xce(_\x10]\xa7\xd7\xc136\x1e&\ +*'a\xe8#\xe7\xf7\xd1\x81F|*\xe8w\x1b\xa0\ +\xe2\x82$\x89m{\xdei\xa2\xbc\xc1:\xa6\xc6\xb2\x07\ +\x96x\x18\xb8\x90\xe2Hu~\xac\xa5J\x88Z#\xa0\ +\x1f\x10\xba\xdf5\xc1C\x0c\x04\xecR\xd9C\xbafY\ +zz\x9c;I\xca&1\x92S\xad\x94\xf4\xb7w\x82\ +\xef\xd5\xd6\xc5Z\xfa\x92\x82\x85N\x1aaq4\x14\x81\ +\x08\x8e\xac\x9e:\xc1\xbdV\x05%`\xc7YF\xf1\x00\ +b\x02\x93\xb9\xdba\x88E\x9f@\xac\x05\x02\xe3\x87A\ + \x08\x07Rh\xc8\xafUi\xd9,7\xdb\xf4\xfd\xd5\ +\xe3\xc5\xa4\x22\x9dQ\x85\xf4\xb4\x13#\xc9d\xee\x1d'\ +\x1a\xd0isZ\x99\xccG\xa9\xe4\x9e\xed\xab\xe2fB\ +\x99\xe5Q.\x91a\x92\xe8\xba\xad\x12\xe9\x92R\x0e9\ +L\x8b\xc8g\xb2\xf4x\xdc\xd0\xbdM\x91v\xf8'\xad\ +\xf9\x9d\xe7\x92\xfd\xcc,\x8b)zm\xf4,\xd3\xffb\ +\xa5\xf8\x9eQ\x94\x96\xce*\x1f\xe2\x96\xd8\x90\xbcS\x87\ +\xbb%\xd4\x03+q\xc264\x85\x92\x00\x98x\x8c\x15\ +\xc2gA\xcd\xad\xd3\xdb\xad\x82*\xec\x9ab1\x11)\ +4\x1c\xba\xbb\xa6Z\xe5'\xc8\xc3\xe7\xa9\xbd`\xbb\xb2\ +\xaaC\xe3\xa5R\xe2]*\x0a\x1b\x97\xaevyP]\ +\x07\xf8\xa5y H\xfd\xcfW\xd4N\xfbv-\xaf\x89\ +>\x1f\xf0\x92\xe2>iIR\xe9\xaa\x0bH\x9a\xca5\ +\xcc\x9f\xb2\xb8H\x9e\x85\xcbdpgK\xad.\xe4\x12\ +\x16\x1c\x95\x22\xe0\x1aG@\xc6}E\xb3LHZI\ +\x03I\xcf\xc73\xb2(\xe5\xad)7\x1e\x0eVfk\ +\xa2\xa3\x94\xed\x1a\xdfOhJk\xa6\xbb)&\x99\xdc\ +V\xb5\xac\xb5\x0e\xd2Y\x95\xe2\xe5N\xcaCo'p\ +\xe4\xbf\x9b\x1c\xd2T&-'\x1b\xa7\xc4\x1d\xd7\xc2l\ +Z\x0f}X{\x18\xde\x13idA\x17C\xcc'k\ +\xe4wMUI#\x9b\x92m\x9dk\x91\xb0&\xa8\x88\ +\xa1t\xd76h?\x85\x84K]Vx\xc9\xf0\x0e\xd7\ +\xec\x15\xd7TUFs\xeb\xa2J\x17\xd6;}\xc9\x92\ +j\xcbf\xffJ\xb9l'\x07#\xde\xf4;\x5caQ\ +\xc7e\xd2r\xa5A\xce\xdf7a\xf4\x80\xb8 \xc1x\ +\x98\x02\x8ax\xa9\x1d\x09\xd3E(\xabD\xd5i\xb9\xc9\ +\x88\x92hB\xe3\xa2\xb1\xf7F<\xb4\x8bu\xcd}a\ +\xe9\x85\x5c\x05\x18\x22S\xf5_\xd3\xfeYkvq\xc1\ +~\xb0W\x96\x17\xc0\xbf:\x7f\x98P\xb8\x93:\xb2\xa7\ +xvX\xc0\xefS\xbd\xca\xa4\xe6lh\x90\xae\x91&\ +\xcfd\x0b\xa9\xc7*\xc1F\xd5+M\x9b\xc5M\x118\ +\x91\x87\x91\xa8Je\xd78\xcf\xe7T\xd59f\xa5\xa1\ +\xde\xd2\xf4\x9d8F%E\xa5fP\x84Q\x1f\xfb0\ +\xf6\x97T6t\xf5\x1cT\x0b\x1c\xad\x0f\xc8\xf2\xe9J\ +\xd4cJ\x02(\x01h\x06W\x94\x12\x80Q\x1b\x1e'\ +QH5l\x86\x94\x80*?\xe1\xac@\x07h\xee\xb5\ +\xd1\xae\xa4\x99\xf8X%9\xd0j\x01*H\xbb\xc7\xb9\ +\xcc\x7f\x06\xd0u\xa5t\xa3w\xd1\x81\x88\xb4\xa2|W\ +\xb8\x9e4\xe9`\xfe\xaa1)7fb\x14K\xca\xce\ +\x8a\xb4\x91\xae\x88\xda\xa0\x1e%\xa6\x22P%[c\x9e\ +:\xc5\xe2A\x1e\x9e\xba\xeb\x86\xcb\x88C\xb4%\x93\xc8\ +\x81I\x8a\x1eoEa\x97\xda\xeb0mW$\x9dP\ +\x9e\xa0\xf1b\xab\xb2\x8f\x9d\xc3!\xab\x15\xc5\x89,\x10\ +\x8d\xc7\x9fy\x85\xd4\x22\xf8\xa3\x83K\xd7K\x97\x0ep\ +\xb1g\x9c\xab\x93Z\x80\x8cEk\xact\xe1`s\xc8\ +)\xd3qj\xf3<\x0cD~\xd6-L\x93'}\x15\ +f\x81\x0d\xaa\x5c\x9d\xd7\xc6r\xa6\x12J\xd8\x1e\x15\x95\ +\x14\x14K\xc5\x0f\xadn\xb5\xe61.\x16\x8e@\xbd\xf4\ +\xa2\x10\x8b\xeaN \xe8\x03A%\x8apK\x0d\x1c/\ +1\xe5\xf71\xd2\x0f\xcf\x22\x91\xf4\xa3\xc0B\xae\xa9\xce\ +T9\xab\xcb\xb1\xe67\xaeB\xe7\x04\xf6\x8d0\xe4\xa6\ +\x87\xe8M\xb7\xe9\xa0CV\xbd#o\x0f\x80O\xcd\x0e\ +Ut\x8dq\x85\xe3\x90\x90\x9fS97\xfc\xa1\xb9\x1e\ +\xa5\xf8\x5cN\x9c\xf1\xa2\x0f\xd7\x9b.\xae\xc7,\xd5\x01\ +\x9d\x02\x90\x1a\x1b\xbaF\xbdG\xac\xb4H<\xecY\xb5\ +\xfa\xad]\xfbV3\xdd\xd0(\x81\xa9\x18\xdf\xb7\xa6\x1e\ +\xae$\xba\xa4\xa8\xd4\x22HdN\x05\xadn\xc6\xadv\ +UI62\x81\xc2C\xab\x93\xf9j\xc0M\xca\xbb\xcd\ +\x87U\xf6\xacr9\x8d\x16\x83\xb6\xa2\x94\x1d\xcbV\xd6\ +D\xc1\xbc\xf7\x0d\xf5\x95mQ%\xcfs\xaa\xa4\xb5)\ +\x90\x95\xe4\xd2\x05:\xaa\x8f\xf4\xf4W6\xa7\xb3\xe8\xe4\ +_\xb0j\x19\xe9\xaa\xb9.D\xee\xccT\x01\xe8\xa8\x14\ +\x5c;^o\x9b\x0dRy\x9e\xb1\xe2\xc1\xd2G-3\ +\xd4u\x0ei\xf6\x92\x18\xad\xf6\xe5\xaf\xb7\x11\xaaf8\ +\xee\xf2\xb6U\x98ZW|\x0e\x0a\xaf\xe3\xb1oW\xd0\ +\xbfO(\x93\xa5c\x1c-Z\xbcg#H2l\x16\ +YE\xf0\x03K\x91\x19\xbe2){\xa4Z+\xf9F\ +\x98\xae\xfb\xb4\x12\xa6\xd9\xe0\x96\xe4\x931J\xab4\xcc\ +\x06\xac\x05\x85\x95\xef{m\xe4\x92\x03g\xc5\xb0E\xc3\ +m\xf6\xe8\xf6\xc8\x9c\x88\xb5\xce+\xe7\x1cq\xfb}\xfa\ +\xeb\x0a\xc9\x04' \xee4a\xfb\x95i\xe4\xec\xed\x22\ +Tq\xba\x15\xfa.\xcabd\x98\x9e\x92L k\x88\ +#\xee\xc9\x5c\x98\x92t\x1cb\xda\xea\x15]\x96Zr\ +\xc2\xca\xbe\xf4\x8a\x14zP\xe5c\xf2\x0e\x10\x9a1\x89\ +\x1b\x87N\x92\x93\x1bV\xde\xf1\xa2O\x93ZE\xc5\xf5\ +\xd5!\xea\xaa\x94\x8e\xf0{\xfa\xae\x940j;\x81w\ +\x11\xf9k\x9c\xf4[-)\xc9H2S\xfd\x11\xc7]\ +F\xb6\xed\xeaKY&\x90\xef\xca\x8bP\xde\x15F^\ +\xb2\x82\xb2\x05\x8f\x8a\xe9[d0u\x18\xa6\x8cu\xb9\ +\x9d\x06\xc8\xdf\x0cw^\xf7\xbb\xc6\xb9\xd9\xcd\xa5\x9f\xea\ +\xcbvVK\xaa\xe5C\x17\x91\xa4\xca\xd9\xb0\xf3\xf3\xcc\ +P-rM\xc9)-\xe4\x93z')g\xb8E*\ +s\xdb\x18R\xda\x04\x0f\x959\x94\xbf\x9c*\xcb\xf3\xb5\ +\xb9\x9bw\x94\xda\xe3N\x03\xaf=\x96y\xa2\x8f%\x0e\ +\xc3x6s\xd7\x89\x96F\xf24F\xea\xfa\xd5\x0eS\ +\xe4-\xfb\xa1\xff\x93\xec\x1c\xfc<\x0a}\xdeW\x88\x8b\ +\xf4\xee\x93\x09S\x1e<5\x99\xb2\xb7\x188j,\xcd\ +'\xd2\xac\xf3\xdf!j\xecf3\x9cQ\x95\xc1H\x00\ +\xc7t\x9bn\x1fh\xc4I\x12,\x0c\x11\x0f\x97\xe7w\ +@\xbbHPm\x85\x97\x1f\xed\x0b\x90\xe5\xdcr\xa3\xa1\ +\x1a\x0a\xfbuz\xfe\x18G\xca\x8a+\x8e\xbc8\x85^\ +Teq\xa4:fz\xde?}\xe2\xd4\xe9\x93\x8b\xf7\ +Q\xaa\xb8\x1e\xb6\x1f$x\xbe1P\xf7\x1d\x90\x0e\x17\ +a\x04%\xbb5\xd7_(\xdd\x9a\xa3C~\xa7\xd1U\ +\xb6d\xca&\xcf\x99\xac\x01\xcd\x1e\x8bz\xb6\x13Ib\ +\xe3+\xf2\xcdb\xe9-Uvl\xde-\xc8H\xc8[\ +8\x8d\xcc5\x0a\xf9M\x5c1\xd7[\xd8\xf0\xd8\xa2J\ +XY\xa0k\xf3\xac\xe0\x5cvSvi1\xf6\xb2\x16\ +\x9e\xf4\xe7\x86\xe6\x9d\xbf\x8e\xbf\xce\xc6\xcd\x98\xc2\xa0\x8e\ +i\xc4\x19\xef\x8eP\x89\xdd\x1d\xc2Zz\x9d\xceqE\ +\xf0\xdaO\x90\x10i\xa6\xc2k\xf8\x8e\xc1a\x8f]*\ +d\x07jt\x84v\xc9\x08M\xc4\xec\xb8\xe5\x97~6\ +CP\xda\x9e\x93\x04E<\xd7\xe9\xd2\xd9\x0d\xd8\xdd\xba\ +\x914'c\xa5\x1b+\xfeN\xc5D0\x97\x06\xaf7\ +\x90\xa77(\xebD\x95\xaf\xcdZ\x19\xd5\xca\xa9@\x7f\ +\xc7; ~|\x11gj+\xa0pR\x1a91\xff\ +1\x19\xc6\x03\xf9;\xcewO\x19\x08pl\xd31<\ +\xb7m\xcd\x9c;\xdb\xc8\x22\x98H\x13dV,l\xa9\ +4\xd0\x972\xd8\xf6\xa7\xb4K\x87\xadO)\xae\xf2\xaf\ +\xf4B4T\x0e\xe1\xe5\x19\xba\xb4l\x18T\xa6\x037\ +\x0a=0=\xb0e\xdc\xa1X!y\xd1\x11\x1c\xba\xbb\ +\x0c\x0c!<\x07\xee\xf8}\xb4\xd2\xec\xb0\xf0\xce=;\ +\x89\xf3\xa8>\x94~\xa0-\xdd\x06|\xa4\xc2\xff\x16d\ +1\xdf\xcfw\xed\x9b\x9a\x9a\xe2\x0d/\xa9\xc599\xf8\ +\x1dK\x1b\x1cN\xf1\x9d\xb4R|y\xc1\x05\x5c\xabK\ +=[\xa3\xce\xbad\xf27^\xa5\xc4\x9fuO\xa7\xdb\ +\xd9N\xc2M+\x0a\xc8\xd0P[9\x87\xb3\x17?\x16\ +%\xefe]\xf2\xc3y\xa8.A\xa9\xf3\x8cP\x02v\ +L\x12\x99\xd2\xff\x00Wg\x0a\xcb\xb1\xd8\x8e\xe7\xb8\x80\ +\xf1\xae\x0dO\xf9\xa0bvN\x8b4\xaeP\xda\x89K\ +P&J\x86\xdal&{a\xa5K\xec\xa2\xa5\x99\xab\ +!\xf13D\xe2\x91\xcc\xd5\x96\xa1\xa6\x8c\xc0t\x82\x95\ +|4GZ\xd9\x9a\x9c\x95#A\xde\xd2\x13\xcb\xbce\ +:\x84E\x9b\x9c\xcc\xe7\x10\xda8r\x0b\x12[\xa8x\ +\xc1r\xe8\xa3\xa7C\x93t\xd6-\x14+\x7f\x88\x0c\xc2\ +\xb7Z\x94\xb4F1l\x0cr5e\x19\x08Y\xe9Z\ +]]\x97\x9e}\x96u\x983\xf3\xf1\xe2J\xc3\x89\x95\ +6\x9c\x8d\xa3\xe9\x99\xd9\xccJ\x05\xaa\x8c\x9ek\xe5\xc6\ +\xf11I\x9a\x1di\xfd\xa3\xa4W=\xa0\xd7\xcc\xf5\xe2\ +\x9e\xef\xac\x08w<'\xc9\xd7}\x98\x88K\x98#;\ +\xa9G\xf6J\xc4\xe4\x9b\xb4\x94\x94\xc3\xaf&\xf7\x8a\x8c\ +p;V-\xcd\xc3\xf4\x8a\xa8\xfc\x16\x89U:\x8d\xad\ +\x82\xa5r\xdcV\xd9\xa4)'\xc97\xd2IqY\x13\ +)\x13!\xce\xa7\xc0E\x14\xd3-\xba\xb9\xb3\xa1\xb28\ +\xa35\xc7\x9b\x86\xf5\x01\x19\x93\xd5\x04\x1e\xe5\xe2\xb5B\ +\x9e0\xc5<\xd0\x94\x0c\xd8W\x88\x0c\x94G\xcaH\x9d\ +\xc4z\x86\xacU\xaa\x94\xcbd\x9b\xa4.\xa1\xb5\xc84\ +m\xea\xd9\xf2\xa0R\x14\xc1\x5cQ\x09(F\x0e\xa0\xb7\ +\x8e\xfci\xf0p\xd7T\x95\x1f\xec':R\x8a\xd6\x0d\ +*\xaa^\xa4\xf4\xd7n\x18'\xd2\xf6\xd9\x91sB}\ +'c\x08O\x82\x82\xdf\xcb\xe4Zh'F\xb6\xb0\x83\ +;\xc4\x9ab\x85}\xae\xcc\x14\xaf\xc0\xb1\xe2\x1a\xd3=\ +u\x13Ts\xa6\xf80\x04i\xcf\xc3\xfe\xfd8c\xf4\ +\x17E d\xba\xa8]\x82\xa60Y4w\xc5\xdbD\ +\x81\xfb&\x8b\x81IS\xdabuL\xe4\xe1\xb4\x9d=\ +\x22\xc3\xbam\xf8\xba*\x81^\x1bd\xf26$\xc4j\ +5\x13\xb7\xd4\xc7y5u{*\xba\x8a\xee\x9bs\xab\ +\x1aw\xf9\x22,\xf6\xc8'\x89b\x9alE]q%\ +\xcc\xfdO\x82\x8a\x17\xc8\xd8\xef.\xd2yu\x1eK\xac\ +\xa8\xa7\x08\xa7ek\x95\xc6'\xec~\xda*\xa3E\x0b\ +M\x09m6\xda\x17\x9b\x0b4m\xfd8Q\xae.\xdb\ +-\xb3\xdaq\x92\xd4\xc9\xa6#y}\x82+UF2\ +\xd7G\x12F\xf3\xce\xd2\xd1\xd2];j\xe2?\xbeq\ +d\xe6\xef\x89\xce\xe6\x03\xbd\x1c<\xa6\x5c\xd6\x14;\xc8\ +\xec\xd8t\x86\xb1\xb17p7\xd4\xd3C\x9e\xeb~\xa7\ +bgE\x93\xc8le\x0b\xb3\x90\xe8\x02\xa37\x13\x12\ +\xc2S`U\x9e}5\x12\xd6\xcd\xb8Jd\x0eP\x04\ +*\xaf\xbdl(\xdcJCJY\x999\xa7\xddGE\ +\xa3\xaa?\xd3\xc6\xc0\xd5zx\xf3!\xb02\xd3\x1e\xef\ +\x90\xb5\x93Y\xac\xe6'1a\x8dO7AUwT\ +z\xde.\xd4\xf3\xfd\x96\x01F\xc1\x19\x93\x19\xe3\x0a,\ +B\xd1\xc1c6\xbe\xf2+\xe1\x17zT\xbcoP\xa6\ +\xf8\x85\xfd\x18\xe0\x8e+\xa9\x86@\x0e7\x15\x0cH\xfa\ +.\xc6\xc1*\x15\xc5\xd3\x9b\x9d\x10oE\x1b%t\x9d\ +\x96\xe8\x1aUY5Y`r\x8a\x14\xdd \x81\x15j\ +3>6t\x0d\x02z\xc0\xb0ry}<\xcb\xc6\x0f\ +\x93\x22\xd1\x1fJ\xee\xb2\x8bK\x15\x1f\xaa\xbcHl3\ +\x15\xd4\xae\xa9\xeb\x94?H\x9e\xf59\x05\xe6\xdd8\xf3\ +\xb6\x97\xf3}\xa7\x82\xd6\xf6\x0e\xe5\x8f*\x0e\xfb\xa7\x86\ +C\xd6\xa5\xd5\xea\xac\xa8\x81=\xbac\x12\xe2\xb2\xb7\x0b\ +\x8a\xc2\x80w\xc5\xba\xaa[3H\xfb>\xc1\xd5|]\ +\xfa\xfa\xef\x90\xb2\xbd#\xea\xdb'R^\xca(o\xa9\ +bS\xe4\xb9\x1a\x98@s\xb50u\xe22\xfb\x86r\ +\x22\xa4\xe9\x12^\xe9\xda\xe6oPL\xd5\x9d)\xf5t\ +\xf8\x10m\xc58X\xe4\x95\xaevfzz_\xede\ +\x15\x9e\x1e\xde\x01S\x00=F6&IT\xe0\xdf\xd8\ +\xe3\x03Ji\xd5\xe5\xfa\xa25@\x9f\xden\xac\x9d!\ +\xe1P\x1fY\xa6\x9a\xde\x0b\x9c\xdf\xbd\xce\xd0\xde\xb5\x93\ +\x03\xe5\x13K\xed[\xf7\x01\x93\xf0\x1bSh\xd2\xa5\xd3\ +\xc2\x0d\x91\x0c\x84\x08\xb4\x13PQ\xbfJ\xc4\xd6\xb5\xe6\ +\xb5FG\x9a\xbf\xe5\x9d0\xf1ME\xec\xc4\xb9\xc0\x00\ +\xf2D\xd0\xc4\xef+;\x9b>\xfc\x9dT\xd1\x1e\xd9)\ +}\x80q\xc6\x05 \x02\xba\xb9GA\x03\x1a\xdf\x8a\x09\ +\xc7\xca00\xc2\x88f\x88\xb4\xc2\xc2V+\xbdl\x92\ +\x5c\x05|\xaaR\x99VYp\xe8y\xc1a{`\x8f\ +\x91\x1b]On\xaa\xba\x8fO\xf2]\xd5}t\xc99\ +\x00\x1d\xb4U\xd8V\x0f0\xa1\xae\xaf\xa4/\xc0\x8e\x22\ +\xb6\x95`4\xc1\x8e\xe8\xcbiNp\xeb\x03\xf1\xb3\xb6\ +\x08\xb0\x84\xb5\x8f\xd7\xe5HO\xbe\xf2\xb3P\xdd\x8f\x93\ +\xa7\x16\x95e\xa7\xb9*\x9e(\xcdi\xad\xec\xa6\xe2\x13\ +\xe0V\x81Lu\xa4;\xfb\xdan\xa2\xbbH9\xe3&\ +r\xb7\x88\x06\xb9\x22\xb8\xd9\xca%?2\x13\x06bG\ +z\xcf,!\xb0\x9a\xed\xbf\x97\xabzi\x9f\x05)\xaa\ +\x80\xf9\xd7\xb938#\xce\xd9\x9be\xb1L\x92w\x0d\ +\x5cEu\xd5\xbbp\xab9\x90\xed\xa0PN\x8a\xb09\ +v|\xc8\xd7?|\x18/_WR\x9b\x9c\xb19O\ +\x93\xbd\x1ct\xc7\xc90\x93U\xaf\xebI\xaa\xebn\xd5\ +\x95\xa0)\x14\x1f\xa6s%\xbe\xe1*\xf9\x8b\xa5\xf3\xd7\ +RK3\xc3#c\xf9\xa2qo\xa7\xfcE\xcec\xa2\ +\xb0\x9a\x8b\xcd\x93u\xfb\xa2J\x94^\xe6x\xe0\xddg\ +)\xc7\xe4X\xd0\xeb'\xe6v\xe6e\xbc\xc0rE_\ +\x9b>ajZ!\xa1;\xb2.\xe5\x8et\xa2?\x8b\ +\xc5<\xd6\xad\xfb\x7f\x8a\xf7i,\ \x00\x00\x16\xb8\ <\ \xb8d\x18\xca\xef\x9c\x95\xcd!\x1c\xbf`\xa1\xbd\xdd\xa7\ @@ -10818,16 +10979,16 @@ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x06\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x05\xbe\x00\x00\x00\x00\x00\x01\x00\x02Ay\ +\x00\x00\x05\xbe\x00\x00\x00\x00\x00\x01\x00\x02B \ \x00\x00\x01\x90\xc8\x93\xd8O\ -\x00\x00\x05\xce\x00\x01\x00\x00\x00\x01\x00\x02\x5cy\ -\x00\x00\x01\x90\xc8\x93\xd8L\ -\x00\x00\x05\xe4\x00\x00\x00\x00\x00\x01\x00\x02|0\ +\x00\x00\x05\xce\x00\x01\x00\x00\x00\x01\x00\x02] \ +\x00\x00\x01\x91\x1a\x8ec\xe2\ +\x00\x00\x05\xe4\x00\x00\x00\x00\x00\x01\x00\x02\x86O\ \x00\x00\x01\x90\xc8\x93\xd8O\ \x00\x00\x05\x92\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0a\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x05\xa4\x00\x01\x00\x00\x00\x01\x00\x02;O\ -\x00\x00\x01\x90\xfa;(\x8b\ +\x00\x00\x01\x91\x1an*\xd6\ \x00\x00\x00T\x00\x02\x00\x00\x00\x0d\x00\x00\x00\x0c\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x01\xbc\x00\x01\x00\x00\x00\x01\x00\x02\x1d\x8a\ diff --git a/src/frontend/translations/de_DE.qm b/src/frontend/translations/de_DE.qm index 51f3b11a72613ac51348d4866b9f60b6160fe40b..0037880649365ee651fb77b3f18deb4d97d02d5c 100644 GIT binary patch literal 35455 zcmeHweRLexb>9OCfaD7N&_`%lR_sSeM+9YH0e;C61X3mmfTY9^NFYU7mQ4?KXLm=~ z-C51d5`<{RQJthoj^ntsmDo9IYV{m zKl>L?DWwL=?%C;?gG%*J;LAy+4$dfb_VY^JJEHnO@M}tqJ*WDA=@Uv7Z&dyNGN*yn#fj|4IQgaJx;OoDm)XD#*3eVi2)Z3p^$JhM4 zQg549bH{JRb6-~T@A@IG?@*^)jC*j4dhin;QR<$@)w}jRi|0S0-tA%Dxwok1oYy^qt!3}QomB~f46$_$;XwNuB#WnyH=^AZ|EET#CMh2{Kmc= zqkoP0{-*D}PhTl+rs^`=rk^_evTPfsd!?B~|(zw5s$wd?Gfdm8^kslvzCJX9?x zb^6XVpL!qeyZRrk`TDg-l{){4HQ#EKl)C-Inr}b-8Kp+2*WR%2QKb$ou6@g|eoLv@ zyVvgj$C&4~xwUiO{3PIceC03P=JpZ*VgY60WF-2cH(Kc>`A-`W51tNuu-o#pJBNO-?#CXw1K0n!|R@? zU#ryklk1*%3~(L!*t&1k2Y{dF*RMSq0{$wnPrMc{Sg z`X6orUJkZ5_}AU7)H{E3!;^3QqEeNcHaz(q+`ss_4Zr*0&trY3H~jk>e^se>0}BOCDi*9u#Ay#T!2QFw3`^Nt@ZocqY%!#pn*KDqy8!2R2W-&)4sbGHp`sV*M|Ckh3ma#X!qMEfwx0L zCniAuyM~A6KlFQ`o8KJz`I~M4otKB6xcD9HcYWyNQ;#Th)w_nC@>-zd$A-TALkR8N$8}ZL0g2zxmMSzEA&e%rm$7 z4R0wbwdEt5=bn7OQg{8%=JGe5R%-VXo5RL4*q3i?K6n3z@Z4W*{s()oo;!Yg^W&fX z9N_&Io4@)=tY^btZT|C*0UzM7|M{)&D0Tnyo>D(^GcY-DohqnV{MS$|<*KUE%2T0= z@VALiB~>$@9o1G9Tr1-q55Ks$U#oewZ0?nByv`>bRmXoG?g{X%X#Ue`#ysa?1{Y7x zV!WnW#P6Q+&3H{*T{6#b4t~qdf6n|;QLo_n1d=XNe7>`y2n5xvk^9~L7+Kje$ncFTqT6Qxu4@{e3QTD%-ZF5 zj&@wlsXh2Ri@O70%)xpE(&KoBm@1oVGQ&9TJcaMo%*gzmBc-!)-P{$zE|kzX@m}^=SOd5}qPO*_EC)w3pvw(r1MG1jnRc;z(nR zHvXTx(@B{ejSzFSH8ZO~T)`UTS=m#8%hE4LaSb%YmtacAxYM9#(tQbkg;R(zLR7_7 zfk@VR&_GLgc?T(x*jWwEPI|86iA9WB#}l$^8oWu)Al6AO7IImU%$eoY7VanQX{?<0 z5=#X&g1<#|5dSnrBV`dL!p3`Klw;;|Tb;)*a~NY0*CVsWrdcPSAy(5h`ER$RiPEks%5N%ot|iasrotHQkaM zhEA}|5%ruOH1(_-m1?7Up&jXx(|7@u?m6|x)EUxwbLx?7O)hW%MGW>VK{T-H%B!9it!wehpz_N zg}TrC<_?@XqDR~!<^c}p&v~qVB9gT_3cmI-w4O>J~t4S*{T&ZDkrM z*aZiYtE`q3?wU*ZQl6f)bf~VGX+}U~33&Azdd`Vzlij9&RvpEl6|k07H=a6$mk^*{UigOFeqDDOB$H%}K*BXWWI*i(GwSNj_ZEVaqLf6%Tv}(%`P1 zzVDc>cy%}CQ^PUEZWww3E1-Z#XC?;jf!N?`ss?Iq3WeY_R`7}u=e%dQ%UxWXm_`)* zq8ysIlY*HBl9)n#x&d`pjnxCy4WAU{#GQ~UDGm-DZ3@#Law50t2g^l0XZU4%-2-Qp zy{se9wZHflN)wjeXYytxvQ4&WYt{1hEQ%Ax}Yi0O#t(ns83OC zR7;_ut7c|5N9{^lpxL6?PN&tXgW)6WuU_&1chg_e?s+fj3UV3b<^y#?h9ohoNrhNx zW0J5Ia7Sb|G1Xozvw;<}oK%llU0%iZ2)S-ch;QD^1f`pp*>-oxpZtY#^8)?`_>c1Jta*x5PNU9M7Zbv{$Ebfd2%x?EQmGw) zPAHt}zUX*paq4vNv5-{YwtQeHg8G@%7tC{K8&t_v_hL6ndI-2msYl=4_Jw?3f)Pd2tgGO80T?IsQ1mPqnj;rc=FJ&uSTIycDc>;I6&=a%slc){ zX9W{wWYtg(?-rh{Zq8r_fOHA&`qb|?i+pt_tYp0hIPq@4cd(M4euP*tVDE6C_%0;b}fNUJ64@&>GcsPhZeWHJEZ^Al;1?~9!LPyYOk!qYJ^6~EhxgC7TU0k7wAhvoC#S|+S#UT` z%L$w+cB3}N-J5h9t!O!c>otLMY9SzL?{aNg?zkOxjY@WAVN%O1GjM7>_m zAkMd(=Hi0WtiCEBugF%as^R?y;OjGx0|!E6hQ3vTplfIDyz7=&q=1kSNI$HE^+{+cf0Gv#6j z)K`c_h~+pk4Rt-P57nGz6Q8WL6JEhrSGzf9>U7}fHRXiYl|l1*v8=2?^P}CEjM>rw z$Q7w0QfJI3$wksahWq4E_MD+iyn0Y`l*jF4l6Z#q6Kc-iacUQ!Wh?%3>X)qFq z+*1>VE3)~)BD4C;kjDN-gZ5*bMGiZS#MhM5j#fzKK&fOd(fch_k06|7x0)~3dp3SnM^xglnyuTDAn>>00&IGAhAk~I4LRxp4=Co}hmYK?fNtRG*OKrL~ zt?RXg3Sk1vEr2CcV`q|C%+CghKO(_hiSw#GVBKowCAM=9R&14Rq|zO{?ht$g7AuZ~UIQgUtnccze>bdJ zt)14*U6mG9nu57i2zU!h*;xa_tUD`V%E@xqO}iDRUGIgZTQb$z+{J9Q0t;6pKio`) zyms0*)d(e2f&`b|#QO|vKFaf3CWoIL-qx)gF_TD^pVOro{<0 zU2kVYj+WtLq&p?0&|~&nP+^okEI`5)@sb{5fH+F#cw;gLs~u4J)NaKEy*(y*GnV** zsbAn?Mohtol;2R&r5te0bUTo`xRC~mSrI8;mHxBE0czdM*l|>>^`h`isAjR1UBF(l zo^>-4&FKOC7Cg$@3n_7g{K`DstfC;XmpHgDDTp0LA;!3=jZ7<)r0R-gGg~$iXASFGfy9&Iu=z|u%{(-jjG8Wi+U)5%Zh1xD1=aGKq^(C zENkcYv?yuXNC?u1g;(lg@53g?0flTNE{pxh{+I5v5ULNsUDRFn3GVYCYjDLbw<+h&_^o7uw04Qh zV!d4xGDem;g9ARtfqBpD#sSD_7Trj_sV%x8YvrY*-CL^Q6BtR16OKz$h0Mp&(ayPQ z_?3vX(v|Xv>`VAqCAmZCWQXsTg_^SfzosYaFoldO`el8>*HK@ zFF`Y!5!RMEgmuqDfpJqa=c*FWuAVs$l*FZCtmY0c3!uT-+2eCFhgZ877VAU?9D-qM z^;lQRU1qf`B~A<92wG}>ZJw309OX-^!XZ?JNmZJsQrlx-7DdFpP_-4BhxM#Hfb$ae zEjE@CqzukNoRxY>*G;C_l5}m%tn|slE-H?iJ@E2on0B1|Q6ptpf0)y<$w=28MgiZ! zzgi9f2Xvh9JTYcLrtuaw);?cHdGgw;g0@3qYniWQ6%h!8O; zC{FU|rs2~KFB>?8F=2YZcw+~JcOR;d47Dm}fm`&YKur*8whW#~86`kw&w4;OX{u8L zQ}-(F0PRzvfpw}my2H2b@NXsj$VmGQB&(6(y)>arnTl!3a-K0+Igiy1)ZQ!3e$v_f3;WDDD^s(7l%`V!MVLMIZ5Eyfk5I^gNMcYlAZwy|wPhSV*-`GLRwq|NkP(Q( ztHGd;K?}A~`reC;w!jv+H__Eu8+N@d_F8Q%IVHBi-rZ}mAxuVot#JDiB=#S1>Xp?d z0s9p26b%$ex6Ctcz18Cxx>3GyX;?T;qNHg_Nmfn9*m48~pLz}(#zNBO>YJ8Z=l~B= z^;l%zH9b#@k)kv}@$rv5#Qm3p%(1q??{bEOb>(SDBx`|LOMeEmBKDk&Y6W%2jv9f^ zL*QcN$q6($5^TAZR3?5pM-r;zVQNx4uM>R@ppODpX6L64j}fb}74US|tzDR{hyU3X zr_l1{jSFzylXC^8lHIrDxWg404sL9|1<*k!L$K~W1lmImVG zPSXn;p&6x|7NMFd^i`r3yP*8!V00G=X84ivhtfcZDywq09y3QFD(2u=dY-HYp>Dx! zO=C67shL!L514aHJsv%1On098V4O@yiIF^-<8tPoC#HFX#f?Qw4dhZ6E-;&%s@*Ne zo%0^5si6!|zwU-T2wdIXW!?ud9?908OBV5EEBFoHWkgmoTZH%}&Xn|;?dC4C9RQK? zgn(EqLAQ~arh;v?>c}~sE{H1$1Nrjq-zxXV3T!0yP*#m97#YUi2y~Fr2=2gfRKfSM zL)V+YEMg~#$Xav4??Dh##v7x2NsT#rZ`3d3Mp7&}+BQ3&ogkDRWWptHJlRCV*I0FW z#KBPtl(acGjve$`-;nx`V2KJ=m}Q6llP$NGxx6*=6c2{R)_$_w4SZhH;P0{O8;r4< z9*Lq=DF^XW@*X;w9$Z>=i?L1D;Mu&lmyWT)I(5AU*s`j&x$4y_nvK~|!m4xT=y)?J zQI4GJ<8HIP8rE_T8S;%Ex_@_Zj~+R+L*MP2TDDLhaTZX~c6jcX-o4srz}u$8f-sSV zWCPd5tkL7qa{f^e=l!4|hN*b8m!Cv>kdPpuLO#&rpAc`$-)ZU6xUe5NX!$M1{g zIg&nlnIr&NUe(hs0yTPMLhsW^`SQ40c?VAxhA@Vk<;#>C>*M9Ex;uuX?gb>2&y-d# z;9m;O`g^4cx7YIzCHTqr2@xeE2hRhnmI~d5S%s|yZ=%e3M9m(%=ACgLkOVI`--i@I z_Gl^7DIPXH)YD_tmE5?L?jl~(NFGnh zagW516JwwBDl{tki#j^hW#Vtsy%D1fMppva_82mTWsL)i@?r_f+Y?AIit7GS50DR< zO_4Zj>Uoehl;;T`tJI8y{{%=_vXZ+ zBT;hu8O^g>lCJ0Kcx)HlHI{KCw^{A6loOc%ft5RKPe7R^VN~{bB1$zP$J}3<%hE=I zN7YFKwwnsBCwshg9$hkGKb!(7AT(hw1vr7|5UoE^?lPvdf8ZR`usfD8FV9WVJP$MS z=MD2-1H9-oVT7SJ-JTWb#Y*?7=VEU(G+r!4jx2^;Y7IW(x${6W7f*4VQS|th70%bq zFM2IGPE13dohL3+5EqgoB)woSfL-G=`3brQ=6R;R$3EX?9+E^Mfw$pnn_eTAcF8*@ z6I?sb9H2e0E+%7->2AbyY5OnosrY62{OP87(;&x6=pN(I7VOoiE0w03` zIpb9vN{OaYk#Ui7KP!WklJhv-L!TCtQU6~xuRz%ET zd+|IBl8SN5r@MOPYnTLKGqQZviE#+uC|=5;BnFWzaL7dF+AXqRuPE(MMxduEcTn_f zkIg7Rr^)=8@YEUCUF`7;Z5x^jBuxILqA)r+fqLMKkHh~xhFGs2fV=mAdLVhEpOvhu zJ(1(u0p7VP(;9pJfv(tC7nkK<)-3Den|n>vukKb(vVyhmaC_{~nt#%x<=9bBU-u48 zGe($DbX&n-T@2=iq*)0a{*mS&YBU}8|19fblg39i>~?YA~Tp^a@#3} zYJvRllCfGTj#3X?y2Tug%|&*VU?UIPlZ8r#E!nbJ)I3Deal&T!#kt^WI3H&!0+Q9+ zvmG`wN#6?gJR$u>fB>ceGW6rn=QK=fSjhrLVyBA+uFfQs8W?*jMBGwZ)r}`E%2`~a zb3vLO@4!)rE7WFH{AK@_OXHIb7*}gB_XVs{)PuM=VvR7W$~Jz|+K??QS9|^f)Ms}btOb@s$DfhiK*WfG{_B?<-aj@`U)v;F-D$X)q`^dQq zXU{g#Y2a)CMc{<)*|Qhnmxk=TQq)J&T#c!7hL6^6p+TLS8KS6jGap8iIDb;JYek5* z6;*T}kt62gGp4}#Ks}sAfpfN)IG#BiM;E+ty%L^6ZUP>9tHSB1PUbFOU>6Bmltuet zM6&X@bH~N}5R@kU4RnR;TbmVAeIG0wLOTzv&e6r_Ji<^g2u%zaH2@}?4c&{bDW=;` zq0kQMJNbXR_!9!s-2&mYIkJc) zzg;iGoi{$-4`HI&$%Su2Znsbl&vNn~C`ElndT zi@I2S_-3Q#D^n>sQwBnqM#igweh)@p4RUrlCJXy0f*C} zNl@aO`tweS%>dcQH1X^q5@#WWVu>`VabAXIewdwsaX<{e6Foke2-qpHh@@wk9Sbgy zBhwo($xKeM&||zkqk4}GYnc9o@TPi=WlmG0l@CrDu{j!5Ai+Vx4=wygwO1*i_)FK& zFOS9BE*z$1UG@Dk+&1JYnpgw^xoF608X~f))RCX#*0OnNHu!_p^TnoJoy4RWrxUY- zdn~(7S$7Y1SkeakW{t_tES1o#w6J8EoVev8EmPhbgKI!}BZYM2lUKuwGz|0n$RZ4p zSSh6ooss*q?9GHVvNe^)d1~dzq*E6A$Skxo$Ss_)iLnV2Kc$q#4(a5gwpp9CK?sM?(J?$NFo^aM zO6r83)HJ=y%Es_ZKF-R*TCP)yCRjRD&S2J_)UZ2~-M5uAk!BW%SyCx^TCglTAy`Yp z_}t&D#XwHB7$uc3K}?*ni6QllwEm>yL|l?jiDPRiaA!zeypOYT@1mHPYglv>yz;1Q;Hs zzy?~MZcKVxSaO?A;Q7cz6$(3d=+2s|NzHDyv|CDb6h+fWiAytRWLN`0C;pdld0>!8 z_Z*rSuy|-&=tFS7U^B$3o+Sw|0_X-8Vk3ZA8}tDTeAo78Aq=ElJ8<-b_0IrZIBHfm*1Sk^a{WeXD z{*pD=KeTo55Ppd}`($f4q+3xKNrPx0H`E1VHQ_^z<#4UE91ghHy#tAIb5aY)IF*?z zSs#f*Y(sOLI=PN!*`2Gdz%DZYGrqxY+6ZXKd2NK3vCXVB0eKYSq985->!8;i?|I10 z;tXaKw8UdW=TWX<3EPSTiX^Ee2T0{M#kqN2Ls3&3g%K%oEqxUWXKXvxPQqpLf1q=e zV-tpsi9N{Zpt6VOB9NC2>c#v^GeibYyu+Du_8i@j}xsbv7vas1T^;qz`+idf1ISQZtkzT0@pk(O9J7u|k(! z$;Ajv)%f1a8X+s-DBxELG^$Fgf~eN{S=K`VZ6U}b^|8nspRr$m6cc_E<~L3uf+{N=jXEHTeZ}=ZelAxR{oA6ejmvgX;fCMxu%fk zti(xRVCLL*Ra7&wTf8a;8BIQ$?-s>lQ&OF6q>IVxLWD9?1Aw?;2`&|y7*?c7nTv`? z+?r`KH|G;Y%M)HK3*pMRC&aI)L_Q-XSJsrXuyZ|pGBW0>?4>m`sW>@)=gW@7I1nS) z;+&>Bl`v^6uimrgmPBpxKAB0Nu%>R_loX?eJ0J!av22a}M49$I6D!kva!cf7NSD>f zct{6C6q`m_)$3lBHLFVw-bxUQ#YC9yw)aD>H7GfaaAR=JNc+9^=Yr7*4m2F3(`Y6r zEHmfdE@C=PSNuAf0ZV->L=|-hb&U~~$*i$vg2v?3@`$;W0@ch_*vmyA)NC&l^@vej zMj48_;R_1TK7{ht9NUsiCxmvUsknW02n8-wbqz({_FXCHw2WHbM=4*!s9mXuCWC@- z05NP6r+khz+^|pNfYB)BF5zi75BumyzD(VM=m8chFC@WdN@w=vM)}urUOM;vVa$1* zp*%72&KOD-Q;}{&wy0KQL-s`^d`65jq0X!!F0wxa|4{yrt}Q30yl?{7vqimQ2y-&q z6@agV*HXiu4v@G*LYd?@!YR&aD)VUuQ=Ut>E)A5X5{)uq4#B$Y6?+JBC5#+7eb`uB^lbS4THb@F(rTEj%Ls)3+Fi{^Pq0$mto= zR{eqD#zwxvnPw9+_nPH4jW!gv6XBghtqAl%>j>lr3K4VHfprnlY=tH92pX**6*CJ9 z!v^*})O$Defw`kF6zcV`;4m*>Y!Jt`#UUkvNbSf|2acaSed5%9(qu9%`nG#@jwJ6p zFg9Gk3`(9f*YI5cLP%70+4^s8`7jWguZ|wZRgyp_N%E?U^B~5N$^;?l?nHmeh*G9J zsh)+Psg^C_T9P_~xiSaIaYuSAz>c3aG&-YQvf)(ckK&)GyOf9vi0p{k%)*oPRfTan zeWz}QhJ}l3*=4FryJIi!;YmD~ew92kkM-t#w7*O2oXTD>$kh=~G<&ip0zGA}nO-}I zT+BGetH|)Y*VLDr7geOn%bJB8Q4E8X5j(P(s6H|&XQ$!F=$#VzJ-9)ZMja|N${4jjbr&v4Q6U-_<935y+MgB_k#Bl1xPQWSU3soBflZ; z+bp9xEV+Yffyya1?2Ygrku)BPOLpj86Y-PcP$UE6y7dLRgtLtbBdk~mPNSd`NK4{-^k*D?`wtt~wuS`E*nc@#Pt|wXEMn&afQ#9$XJbxbe~~<_b+zp8gQDEM27~ zxF2|>LYprRI|{KBAK}y6cW*b6CmzG7>AmI(ohLL|E}O>xnc#S+r}WOf6B849!HdSj zys+u}E<&o-PniMPiA1&@%2=kvccqX?E*ocMN=?yWI7Z_p3F{uH0w+JYCfgZz# zqQhi98`Kdt7Iqfh*C}{cw+^y+%8UC{G{~Ax0UEYNp`XX62qkCc->e9x?P|p-_l)ng zVd$3@LdxRz8y3e&d)8`8swt;1o#wK&I;~O@FB@!Ys5}lNkTDUkFuf{C=4IcoD%GL( zagS-t5sL+cK+gGfMmlV{WIilpnkm!bGf8-y@+v`Dn;bTiTr4j@_g#ib%3@)%I=~)j zl|Ib5^>|?cFHeczwMV&==FwvFJSVIO6NXFd+)Qnp9xgY!HDAS*Bf&BE8W+U@&WwwM&th`YeWc~U_$vR3JIk`Al!eK(WE;l%>3#~Pj^e7^ zO-HbM{NM->#VW+;14aT@WH6};sEHCiz-XO`r{UtxiK0G;_c9qOly_>NQpcHQ0KKeUR7;P`2Hc1tQSVuq+BBThx&F(;V=85no*!lg z8*ofl7-G*jtGN1;=^@X)KPa5$I|k#bXrnUYxQSJmCgB68HFJuX>|QqAXE(S{AWPD}mya9mZB2gc$qjysq)NU%dKEg51#CO~Kqn*ztG ztS8M`+_+{E#dx#EkRV~&h^;WDm;}OzB!rcRDk)g9DSgX4oiQhhglx=-;!B>jF;fv} zw1iW&Va!e-|H8}H~8CEc8Pn>EPJE@FeqDF1drj>j-VKH*)! zitMYpt*1c2KyhS6FQ4pO4OhVu6T0Ounf3E6hEy|)27amuih$Ixp)%==T+uGKLcCk) z#0%;h_&r<1Vuh*r94q%$REek@szJgnDvKhVd$aNoElX%-Fpnte8M7{W2ZWXahVxUj zQG9lzfC*rbnT;|0+i5;?#JkPiEP@cVPa3%t^nwfGjgXR77;?#vL7b(&jCg#6tCM;u z64Q7oDK%RhD9Siv_Vs-zDfp$m>> zC+frriu0Q>vqP4-=ivZ(Xhy}~3)@R|e2$8YA#Rr#Ad;Jz5C9VGd<}674JY zOCcdJGD3h{CnTI-L8{$mH%+KOPoN$-u7YFah10g+k0FsBCX1UW?$u*@XK}B2$vHeR zRCfnP3fT$FTVw1Gh@cz)FXHARh);|alV(Wq zG$ACb$!m~F$&f!bjquX8^gXjCbYAm8;edlrNoC1XooR^XsXmxUoa`)Zj^ zfm5TnEp2i6w%J*}BHrk`1(Im|s&~Azrvv0{Qm8|VAS!YXR&9A-V*QMkh>2xoxjl7~ zN^S|YvM5K+(-gt?Ddx7J(ms2h&i0dxUw4Z-{roO{6j+oHE9EYCM&yyrRdV0x4%&Sa zH-l%xJ;-nB3z1D$zQ{WG6iXqwuj%{9vohJ<&uCXR=gjelf%JIb?PpAl$g*$5B nW{r{%uOb!>Ryzu3P2Mq1qXm_?h&;$4K_Qo)#gT_KeSQBIiuY+O literal 35590 zcmeHw3vgW5dEOxjfFuY$M7xMgDfS_xF-aM~f)6DY1d#>_@FDR565vC$Z0ch70=VYx z-POH!34#>;NbJ_mIEhrWrMD zW;ChGQTu)8zvn)H-AhSzWJv)r#4hgMd(MCU_y3>&{5$gNm7BlvKOTMLYg=#qtp`8( z`9J-%QmV7!UKktSuT;l__~V39Z^zXOzoXQ}hgHXi|EW?3|GVn=;uWQCJEl7R{LM<8 zxkYvSI)%i!?#B&=}=YRQ4rQY=ms{7ZrD0Tjd+Pxe1 zb|ew^*%=(TlrH;O&n2^?|5FR`@gKF+{XY%pw2(`F{Rvw zdZ!0C-t|>=^{;A5z4xg40N$%(f2Mx^=Q@;XeoH-88dU1sH`FuFu2QP}r4@aTJ*(7D zTwk%H|F1Fb^%W044mjTV>6M+24+GB1$_?Wm#dy6d_wM^|N*&cJ@2mY!rLKHv<@qn4 zRcd_i%76JwZv?d4S3X%QD|K>m<QK7@I0`&{S0{`B{;&VSqa zrQi6tQu7-+fB!P@a_UQ+fABcq^S<4+>i_&Jr5=8N*ZK(e&;4%K`hO4j=fBmp`N2O_ z>hE`T-TWVc_qn^eZo3XRW;b^2e3J_}@9EmP{WhiE@gKS#_&4vtc(YxXKC)S<)1T@3 zN6+5@d~|d@@p<6&-h*Ag(|aCt|MRY=cYaZ+BhPm|{nc?icYd|EVi@=TWdCu{xR-vU1R#M+;IVy{xS?_B$pPXNEp6KntK=pQR}=q+pideyhV2Ls(} zx39%>-|p_+^%U^(`tI`wG2fBZ-E$Mai+Of;U;5ZjfDa$*{>>q3zkPpC$1h^t4}7p^?a5yR{h#aE{kCDi_rH3M4?#}ud$MQpBVPc2J<((4 zKQY$x!N;G)^&LGwb=wx;Z)MNN_Tkn0c+aEPFn{GsJ^y6nA*HS!?fKP#H{tb{d%ph3 zcVV61==sAHw<~pgf6t$l!KY_Fu>P*EJp(#?as9rZ{uS`$ht?nc6kgx)kJnHA3Ha&4 z{p)|txfA#Q*7`qqd^h-Kbp3aq@s+y#)%DM;x)<g z)CqM!O{x3Ugc?^`9me}(>L}h#sMBgc-W|c`TJ@;`Rl?6%wHtr)-5Bm1%RRA24Ps_~ zHm;822|hKaBK$Peu(>|3_%n$AyYaiO0yT^4Q|c6cpTbiIFbkiksjAvz#tQLQpgdK^ z>!7OOcLk&F#VSXVJNKIRu5$1h-`A9j`y9;g<2V1h2hThdkHhg@bs4`2VHr^P<_drF zzMbZJ$&AF=7XXWkJNd2=k7Y+F;rS3h0#QTtpWf^{B<|3T{CMc;Z8dz*HXe5>B^=7Z3S@X%w2?8tC@Hm19-KL((dnWOTk0-a8`O+ss+{ZAnc~!XFH#jH(N|Dp0w71x%Oi%)5&F==FB_D{K4P%~~S?NLx zZXmp`er_p}+n2@D4YZ;6viw;+`O@%BS);@>@Y{tPP_8H;K7J@+P5i!s zD^{xbiB@-l&v!wi@LrKDYEY3$>S*4RmosWpk@Bn*lZLb~BFiKGe>&tkb&eB?v zht-Z{sg3dVVs!kn)LIK|_4upJYMw}JpOrsaU3!aoi+SEiH?9BhvZO3a3bgj$HUDxH zD-IzWFT~EZwozi$XdPQw!kxwnHVtp-*d`u>P4kUUD%O%7D5D@+MX_Y5)bd(QJ!j;W zzWGu+%J^a$chOG!%W`b6Ko4Qr;{9EU6DQ#%GS;Fk(~vp&q4d3&xNSLR$mdpGTFfvG z*`oxelwd6IV(4J~uI2do2c1t@j-OxN{MBhA3mW-0=1rM*qo2SSSfXgLRPC}$lo^{7 zwb@e19`Cie?{ybOwvL@RFm?aLxIR2}?5LhNz5nQu1G;aZR64u+K&dn~H6|bI85}B= z#*g>uzPTuB43|pt^YerAy9evRY-#FL>D2gvfw`zw-7{1QqrfXigO#Y#x3_zQ7x#|L zxlU#8NX?BL?K?I1p1y~0&s^kQj{0=D?nka4-P5&?zZ!+VB?>t8O{c(VVLT$Deg|eMVpMDsDa0z{9kw zohCqaBCqUJt3a8#-K`7)p_mT%Y-ATqNE=Sz%mVFm10>V1TWdrM$;w{_OytQ~u=J7X zfGm|?fhEz)0O(648MdLcd)cWqs&2pbX7ob63AzXk!^jEnuCDLYj$bikb@^J?yN3Gt zr>{XrOW|oZns;&O&VgM+dfvkaAb5GsEnjpiKx3dQ^?AQqcPgGgtA}?i(|q8EC8j5W zSoHMtf_7q2^?V(9HFtQKE}CCJ`c$K^xaF!>zNkkVjp{Shw~#1 zq0XUQ_P$ltFdcV8GOn>h`C+?JloAK)2_PNh&-`s~#HwX~j=9n$Im+bGn_^GZz2pW9 z(HuOI{5UovVS6j@;!A#$on#?)s6Hw@bZk*^rns(6KmPjZcJ zz$L!IeZ=C0j6;vT7S?g@__=ehVSYPj{EzUZtnd}+=@+r&tJegLB5h`T0UfJ6eMdAG zAf@eA?nn}7p$YaSd+JOhh5b;|sd~}E*4A2NnRraG|A3O;MQnG6o_k1Cp&^hPzYm(e z&zvXnH7BPGF~fd6-84DY1rXKW7U>x`D$gM_n5`it9}em%q|i;~TzkmncmdMt)rHpN zeN|XHo4;}^CUG3NNC;!=#b6`GjboROB@-pS>w@dE@or`_WSOU5CZ0Z4ueeoR(g)@o z-^V-aBZsY-ahWbJ6J2r+a%)<=Dip(je(kuyuMv0Ny1}n%uF5#Ot=F-vsa_^cHR(D* znJL!goXRUGr_x#|mQ4n-UO&)cnWA`MK%bN9nB@#mrk?4CnRF~Reaj}}WilB@v{PfT z9tx0r#JzgH9$aLUh{_|I7O63QoR2q7Uc*7+Yk}vM*C3Uf|G%1TQ88kXX=#}OU8ch_ z9Zbb9t!=)h_l5D&(t?wl81r5@$n52XvtDJ^jo8yfy{}O? z#bD6wC|&0(+AHLM=B-f>*K+($Lyg9+MDs*N)a))sQU~`W!x-xrj<vbH3!`|ZtdgQ^%$;$X)gqkt zqiK-LNHMDbS*P%~9J`({C<}o$A6IZdDjB$U%nQr)prTLVP=%fV_q#rhM-%}0=0&{c z$Fq=gd5AX_?qr77jn%bZk5Kc5yg^)BUNHPAg9G*;VZR)n9hXJ$J+Z<%u)}5&o^9pH zRM8-Eo<)N{mIz1!3XK;e;W2p7!$W_1uh?Eb=@I2yQR-y$kSR@o(* zIho@P$s9Z|FzH6khCX<()^Lk-ayORv6b8oe;$)yTW6c2PMCyJ4aJNEB69giMMCBM2 zT*+&X&aozpQ^7DBP+B-a<&4KMPy)j0amnWvJi5tLC5pbw&$@ctpRIaf(Y&W%BjrSN zAIbzvarda}fFtEx2j{RN(2^ZZY}XMkRxB!omHbW~HySR1U613SQ=t0>OFWPi=yEd% zVEN;n#Cot$u&4(TxU6B(=tRbTSA>EcZ8UTsPlk~Tbo>dS9>bNu@P~z$S5HH+9K~xM z!rKJG#oJ3IJz9=f+M`dOI$8ka{uV%5A|3|9rZM3Jz;n>Vh>S|6Z3oJ&0*Yfxj`T#; zSpe~(8^F-t0)|u++s(F7W|Pg`;zf=m6A<^5JuXT()rWqu%cPcL(J4RSGV_?eMJB|- zo*-SJ6NU(?D+L%HTQa$L7#09K{c(UHE*=Gl4xik2V<1k4ZongY1wc?X8}W+svMGD( z1&{V;)S{(@2+HMn$c*t$1m~vl%NRL|_ufICu-z2df?d^h@ZhnD@k8zIg`2w}r%6+T zx?0p@kp=BBf<@EiWh`;$K@SH73uf%ajO^*Zf5zo+xW8be|fC1Z# z$>_PHQl0X}dNU-v4jQ2%G7qWqX2nkdFT@O+bmY;^=%E!})^ZBt0u*r3tr;=mu&syc zPKIhLFOUI!BT(}s!x7R7ia!m_3LqRdJ{Np@q?7J1^fm&(&M-NEaM9Hwp3`;Qe28asd8}7ctK(z{+>aR? zoGzf-L3r-$zbP>pS0Rp^#tM0rT?k{Hg?VZFPAr8WqY(Sr!Jv=gEOOJCE!38qU{6mb z))nhacyWy_P-wT7oF!Om?=F(r9!y4gW#f|+i5-WX>P)*yAU@rAitR+9-4ftB4!hMx z!7~g)>LeA=cND+H6QU-YO~%-C7^lPa1PI1c=LqN8kGEp8X>7-457JtcHk1JrTWHW& zklm>-B}Cw?2hF{)3Bl*ou5?na00R_NzRw12GfG_GoZ-hkR{Jg@Q_|>~->B4Fg2 z&x_Cu3VR7F9m5@DVO}RrY8apDO=jo2MPU?1moSWsn2Lp;Ip6caBfh~P!kM;yqOu-xbijR1{~iD zYoQsXlAc{K$BNqI9E5&UMiTCz4NbxaYmLo|HC-orADc z4Xca&N{O@Sm~+`fPY75kG`+xCp@Mne+G1YYLGOC3L&Z``W{eRg!|xWe@hD!sS;!H$ zx0r1d>_uxKu2j%!WbWy~>1(@=oL23YI1&DM+xv}zWSq(%B+WH<9z#ElqA+}o$@L<* zN_b@D@p=JrM{s}B=(*HWWTKJUg}x%Wj+%undHG5wM7TA`q#fUI!pFX*aT)b?M^}+! znsGuH&7$06kNO4_)QlN21-Iiw!!6>%-po@Hqf=nKWVvhkyk;~}u<9))hs`F$bS|h} zCjbaFV#+i4JFPd{A z@eOFwD8oYJGp2+3ZXjeka?m^QdM|iT3=2t5Q*t;)8V%GTjKgfm?gana>EUa$g`&^w z9^9?BAK0Pqt($t=P#<=tQFVK0;;7zTK%NZ=bS5lM#$L^_af+(o(MtYNfOZC8GsVPA zKHrIQ-~!nw_a6MGrI*x{2j`pWi-`v=UXm1S$92&>N2!2!kN{*B3xM>PizJKQKBVu_ zNGbCaLuCgm7y`I+ z>?XxKB~6rSuG>#x6_JT>WBx~hM@4onzz7jHP>M{mHZd5PbQ(-XOi|j7;+=G3PT6if zX2Ny|vH&%&(3ovPvXY+QQpB%5)eOU8$L3~4G)JjYr+&8;$h>1#0AnmlN*<&(yB2l5h0S%I@x>V?BY}NYYVJFm!{a( zxQlO2DYCv-m_W8IhK!D`Nj2bXOMLb|1{R(!wr&eR=67FMM=p&K$!DBW^3B%`Z&?t? zof$M`OndL7>*~oR2d@iee`^jE`^}6*gP^U&?omvx6a_cO>wPgBs>d@~7pqj8;A--E z1#4y>R#`o_?FbLU74C4-f8<>Zuy~#CQ;F-HoWnMGoN$1)4cGwT20N>VFrro!;OnNoQ9K88@ll^F<`BR~0=Y}R*DYghJCJ`1C@27O*;dr|~ zVZTn(v7vyxKV}}1?L*;p*)p`7Zsh0|L{27n-6VGgZC5KnY{7K5V!8!jiL|SkR|!n> zySE!A7vKuktST%RPa}gkXZV5GrzYkuo$S_7jis7rqntcr3`t+Qt?tPgt*$8^w|-&w zcHF=@e{Z}IL=`Pwg2dw)mlU7WU@oYAMVHv7`eZ*kQ_L>#l^bHDj080jSn(NY!)g7I zeCz(L3C(sftxsQred=c5_v%^`K_R-8g)aNeac6Yii{@|wZ62Kf5shvwB*Cb$7`Eq! z)z%b9nt@dKdQSUtW|P5Z!HE0eF!EVuMy&2#I){xZ7AGE!tw`3o&CVGv>Kw(jW1|f< zl%{H@033$fvI{Bx1WhAJVckNhgka)i7C@7eQ?9$|bfW@%YUh&URq5olJ&|t9&oC}jvL$uQ6x1RC9pUh*_LChd&ilC8aD)O4TVbS=_I$+QQ zi5+KM_hJFm^lbP9MUAi2Uq*{1BXpjv2Zc30Yt%X5{hT_NJkr5x>w-x);O=xkHAV93 z_-s$Xqa92!B@?Z>zbM1A;#p)?b(^0fKz{3N=Xk7>QjKIICkluZl~~JR_e}H7G>en2 zstfob$McJ@E`a~(Ml-siKI3QCOk6b&aieU|Mv1^ZXIx9NNSbrtS99^JN5naiukGPp zm=I3133X^|c<8QEd$kgF&cm_WW9pEZM;wo)$p@27_?2TYLns<3K|Ro8oWm^B7>i%{ zRm0WsgrNc>8X>}K!rTRXqut}(;)_R zZstRE6t)j*HoFbc?RFNXNBW+W#@V$!;w09Ls;wAHOyMdTuMVgIL$gWfPd)7QFBio9# zRPEU`B3Hy}A!3f}AH!dql>+x-vCGJm*1KX zjivVl{$^xGH7K;ch;$OaPsy%c92xYXVl@(kMw!DUD!F8f0%F}Qni7hJF(K_*LySoR>re8c_+S{UrcnhDUMZswR z4(s6POV}{0=)qcJ4|np=9ve5G4LoMQH1vC@OPcM>;Yd4(TJQ*ccL_DSyQk)mLrdYp zPNDS9D5HkXfj`W|OKN$f??@S~y#YG57iXGPb4SR=*8Ji2`i`dG?s6Ji-Gn~DRvz{>7R#Yj{`GC7&4j`CK-`3zBPb&FDNsEFIbxt+P z;6i-M86!~El*@f~pT{c9G)~$qg@t7>1IlzJ?5|qn!&Y zh|_R5(+d9|j|Fnh3BmQ)>Pn=1a1jnOf`SI+?TPm@NvQ*iD`M}k};yp8bb&!G@TP#}Y#8X2`nSzX-WsH4`3ppr2kWwm=8g^TxqQDD7 z>>g0Vp|xyKhw7=gmptf;0v37{$s20r>sV=;{ad>EJ_y*x0KMe=$;y4ER+y_xs-MgX zOqv3t+03qQ>Yth8q;8kwhJ2$`a-777fyD?t2io!M`VSoOMVB6k>!?6rqlUJbYF>E3 ztggc5`8IQs6v+=p&y70r`s|_wsVc(3TnijXFeTPi)=uFOD$=_pErla!-#jB`6mMP= zUqt)_+IXAxN(H^&u7^9S(i6%_-FfM;?<1ep(xnEITQ+fv}x?<>j>b zn^!alNc|8XdLuE(ep%PRy7zWB*jH(GZP-*r=z~c3u-OwV3bm9uR3v)59H6h0A9+p{ zIVpaf0IZZz#U{(vT6^4{TLJ;InQrlmDT65pHwg%n%`&YZY+S*}?*)HawMY-xZi8e? zhUqiT7@A3}LP}2>bW%bss<`Ld1j6XAr2f13XXI*re>RW12q#oP5c*R4619HU@w!-b zmYuVxr|DM)^{8o+g_57tX)snble^p3UQ>-3?~BSkA76>|E!8%uCZaBjcU2MyZ^qY| z*aO(&BgGn|EdVQeOvz`u6&4y^5``(QW0vbeppV2LIZ0&UIuWTcpqISKFZC8qCNcPq zc@Cb~OKsWWb8vM0Qy2Ax7!sR#9tG<7o^C0hV__m4c?v$^Bcz0ilC|C3C0A%Id2EJk zDy#J~CTSjJ3N`3qCKtwopbj@CmJ^#Gmb~;#0K;mWANXp4HeW^45B~`r<+8TQB&(eY zTK~g`vjc}Xp$Kwiidwf8n6yhtt|cGzEmc~Ubzb}yFd3d|n;u7;C`edqPwJzldJVc8 z+r#iKJ#4uz-WQJBXSdcD56Afjl5FX|bn1Jg3Ng=kl1R(CWG{qi#QR9~P-)V+1UX?k z8JnK6ot;oR_S-UaEYMQF9j`}x1&W45OI#iQlO5?$TEP-+Lspg8i96zq<`@MEv)Y_R zUQ-Eiso%JEDR`q5CJy-ojeulMto{`nC*PrV6?X*qp?F*{Ptm4HoOmrE^?fFia>@3( zUN$F_DhvVaCK>`F_DRn;XAPdnK$rG#SYI{IU8pg-nRTzVRXpkeU@Wx~EKj{^FvT?M zHT;z_wkjB@2sR=kBkKhOzMQy} zqnI?Uvr0pEW{5=xS^qq*(o_8=cjZ5&H5XSy4CXZKJ7bH~+1Q0hk||7E!IhS(!o6V4 zB*M1P9EO}nY|6cy0+-_{V4s$cPKRt{iK?dGPX6Hc6pPxnik93ZJZfDP%Y`;5qK`Cd ztR}foj0DxJQ~=oUB+ZdX4lx8e#heK5ipQPjdYh&v45>jG#dAzji%qnCXIciFqV6(K z7r5Kt&Ttb3n5lseuz$#Sw8|RMgqLf`Ae7=n_Hg%|iQ0 zoR2-7Fq4&V%BFm{fB+NVC-R9T*v?}S^wsFXhem|0%}U*9L0s0wmozZzLGY7^?^~wk z>U8KbUYxWr4PC4oP=ou87hb5KKMZw6H{Yho7JHPm*jdj&h{ZEpHyML^=wc_taQYO5G0Bk84hm-^Z+s8nDyJL;RQ;BBZn0W1pCK8 z2yUxzF|;9~k3|Ss6mR*K8pd*XR>N$$AN;`jZ>P#oZh=fQ3s&&_Hj{o3ssEKLR{THP Cs*>mc diff --git a/src/frontend/translations/de_DE.ts b/src/frontend/translations/de_DE.ts index f987dac..9e2dc52 100644 --- a/src/frontend/translations/de_DE.ts +++ b/src/frontend/translations/de_DE.ts @@ -2,843 +2,896 @@ - Form + Porn_Fetch - - Video selector... - Video Auswahl... + + Saved User Settings, please restart Porn Fetch! + Einstellungen wurden gespeichert. Bitte starte Porn Fetch neu! - - Apply by Index: - Wähle nach Index: + + +FFmpeg isn't installed on your system... Some features won't be available: + +- The FFmpeg threading mode +- Converting videos into a valid .mp4 format +- Writing tags / metadata into the videos + +These features aren't necessary for Porn Fetch, but can be useful for some people. + +To automatically install ffmpeg, just head over to the settings and press the magical button, or install ffmpeg in your +local PATH (e.g, through your linux package manager, or through the Windows PATH) + +This warning won't be shown again. + + +FFmpeg ist nicht auf deinem System installiert... Einige Funktionen werden nicht verfügbar sein: + +- Der FFmpeg threading Modus +- Das Konvertieren von Videos in ein valides MP4 Format +- Metadaten / Tags in das Video schreiben + +Diese Funktionen werden nicht grundlegend von Porn Fetch benötigt, aber einige Personen könnten diese nutzen wollen + +Um FFmpeg automatisch zu installieren, gehe einfach in die Einstellungen und klick den magischen Button oder installiere FFmpeg lokal und füg es in deinen Systempfad hinzu +(z.B. über deinen Linux Paketmanager, oder über den Windows PATH) + +Diese Warnung wird nicht erneut angezeigt. + - - - Start: - Start: + + The output path does not exist or is not writable. + Der Ausgabepfad existiert nicht oder ist nicht beschreibbar. - - - 00000 - 00000 + + Enter custom Path: + Gib einen benutzerdefinierten Pfad ein: - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Select the range of videos to be automatically selected.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">For example, if you set the start to 5 and the end to 20, then all videos between 5-20 will be checked for downloading :)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Or select by a range in time:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">For example if you want to download all videos in between 10 and 20 minutes do:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Start: 000010</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">End: 00020</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">And click Apply.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Wähle den Bereich der Videos, der automatisch ausgewählt werden soll.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Beispiel, wenn du zwischen 5-20 wählst, dann werden alle Videos mit dem Index 5-20 ausgewählt :)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Oder wähle nach der Zeit::</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Als Beispiel, wenn du alle Videos, die zwischen 10 und 20 Minuten gehen auswählen möchtest, dann gib ein:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Start: 000010</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Ende: 00020</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Und klicke anwenden.</span></p></body></html> + + Success: {text} will be used for this session! + Erfolg: {text} wird für diese Sitzung genutzt! - - - End: - Ende: + + Invalid path. The application will now exit. + Ungültiger Pfad. Die Anwendung wird nun geschlossen. - - Apply by time: - Nach der Zeit auswählen: + + Some error occurred in loading a video. Please report this: {error_message} + Ein unerwarteter Fehler trat beim Laden des Videos auf. Bilde melde das folgende: {error_message} - - - Apply - Anwenden + + Information: The Website {website} specified in the URL file isn't valid. + Information: Die Webseite {website}, die in der UrL Datei angegeben worden ist, ist ungültig. - - Select everything - Alles auswählen + + Those credentials don't seem to be valid... + Diese Zugangsdaten sehen ungültig aus... - - - Porn_Fetch_Widget - - Total: - + + Login Successful! + Login erfolgreich! - - PornHub: - + + Login Failed, please check your credentials and try again! + Login gescheitert, bitte überprüfe deine Eingaben! - - HQPorner: - + + You are already logged in! + Du bist bereits eingeloggt! - + + There's a problem with the login. Please make sure you login first and then you try to get videos based on your account. + Es gibt ein Problem mit dem Login. Bitte logge dich erst ein und versuche dann Videos von deinem Account zu laden. + + + + Invalid Category. Press 'list categories' to see all possible ones. + Ungültige Kategorie. Drücke "Kategorien auflisten" um alle möglichen zu sehen. + + + + Porn_Fetch_Widget + + File: Datei: - + Open File Öffne Datei - - - - - - + + + + + + Get Videos Videos abrufen - - Model URL: - - - - + Download Herunterladen - + Search Query: Suchbegriff: - - URL: - - - - + Get recommended videos vorgeschlagene Videos abrufen - + Password: Passwort: - + Start Start - + URLs in the file must be separated with new lines! URLs in der Datei müssen mit einer neuen Zeile separiert werden! - + Get Liked videos Gelikte Videos abrufen - - Username: - Nutzername: - - - + Get watched videos geschaute Videos abrufen - + Login Anmelden - + Enter your PornHub Password Gib dein PornnHub Passwort ein - - Enter your PornHub Username - Gib deinen PornHub Nutzernamen ein - - - + Only Title (a lot faster) Nur Titel (deutlich schneller) - + Get Title, Author, Duration Titel, Autor und Länge - + Show videos in reverse Video in umgedrehter Reihenfolge zeigen - + Author Autor - - Duration - Länge - - - + Download Selected Videos Lade ausgewählte Videos herunter - + Unselect all Auswahl aufheben - + High Performance Hohe Leistung - + Default Standard - - FFMPEG - - - - - - - - - - - - - + + + + + + + + + + + Help Hilfe - - + + No Nein - - + + Yes Ja - - - German - Deutsch + + Porn Fetch V3.4 (C) Johannes Habel GPL 3 + - - - English - Englisch + + Total: + - - - French - Französisch + + URL: + - - Use Directory system? - Ordner System nutzen? + + Playlist URL: + - - Enter "./" for current directory - Gib "./" für das aktuelle Verzeichnis ein + + Model URL: + - - PornHub Language (affects video titles) - PornHub Sprache (wirkt sich auf Videotitel aus) + + E-Mail: + - - Spanish - Spanisch + + PornHub: + - - Portuguese - Portugiesisch + + XVideos: + - - Dutch - Niederländisch + + Eporner: + - - Italian - Italienisch + + XNXX: + - - Czech - Tschechisch + + Info: + - - Japanese - Japanisch + + HQPorner: + - - Output path: - Ausgabe Pfad: + + Spankbang: + - - Chinese - Chinesisch + + Duration (minutes) + Länge (minuten) - - Russian - Russisch + + Select everything + Alles auswählen + + + + FFMPEG + + + + + Skip existing files: + Überspringe bereits existierende Dateien: + + + + Model videos (PornHub) + + + + + User uploads + Vom Nutzer hochgeladen - + + Featured videos + Videos mit Feature parts + + + + Both + Beide + + + + German + Deutsch + + + + English + Englisch + + + + French + Französisch + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +hr { height: 1px; border-width: 0; } +li.unchecked::marker { content: "\2610"; } +li.checked::marker { content: "\2612"; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Supported Websites:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Downloading:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Spankbang.com (supports total progress)</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All sites support *threaded* downloads and selectable quality!</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">downloaded, therefore threading in a segment isn't needed.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Model / Channel Downloads</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- EPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Searching:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Xvideos.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I am constantly working to support more websites.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If you want a specific site to be supported, just ask:<br /><br />Discord: echteralsfake</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">GitHub.com/echteralsfake/Porn_Fetch/issues</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + + + Porn Fetch Menu + + + + + Use Directory system? + Ordner System nutzen? + + + + Enter "./" for current directory + Gib "./" für das aktuelle Verzeichnis ein + + + + Output path: + Ausgabe Pfad: + + + Half Hälfte - + Best Bestmöglich - - + + Get videos by category Erhalte Videos einer Kategorie - - + + List of all categories Alle Kategorien auflisten - + Get Top Porn: Top Porn: - + Week Woche - + + Enter your PornHub E-Mail address (not your username, pornhub changed it) + Gib deine PornHub E-Mail Adresse ein (nicht deinen Nutzernamen, PornHub hat das geändert) + + + Month Monat - + All Time Gesamtzeit - + Get random video Zufälliges Video - + Get Video Zufälliges Video abrufen - + Get Brazzers videos Brazzers Videos - + Threading Mode: Threading Modus: - + Worst Schlechteste - + Quality: Qualität: - + Graphical User Interface Language: Sprache der graphischen Oberfläche: - + System default Systemstandard - + Chinese (simplified) Chinesisch (vereinfacht) - + Open Öffnen - + Result Limit: Ergebniss Limit: - - Eporner - Eporner - - - - + XNXX XNXX - - + XVideos XVideos - + Enter video URL Gib eine Video URL ein - + Search Website Suche auf Webseite - + See Supported Websites Liste der unterstützten Webseiten - + Search for Videos. Select Website below Suche nach Videos. Wähle die Seite weiter unten aus - + Enter Model / Channel / Actress URL Gib eine Model / Kanal oder Darsteller URL ein - + PornHub PornHub - - + + HQPorner HQPorner - - + + EPorner EPorner - - Playlist URL: - - - - - Porn Fetch V3.3 (C) Johannes Habel GPL 3 - Porn Fetch V3.3 (C) Johannes Habel GPL 3 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Supported Websites:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Downloading:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com (supports total progress)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Eporner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com (supports total progress)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XVideos.com (supports total progress)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">All sites support *threaded* downloads and selectable quality!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">downloaded, therefore threading in a segment isn't needed.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Model / Channel Downloads</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- EPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XVideos.com</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Searching:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Xvideos.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Eporner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">I am constantly working to support more websites.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> - - - - + Information: The total progressbar does not count for Eporner and HQPorner, because they are using different mechanisms for downloading. Information: Der totale Fortschritt zählt nicht für Eporner und HQPorner, weil diese einen anderen Mechanismus fürs herunterladen nutzen. - - View all other progress bars - Alle Fortschrittsbalken anzeigen - - - + Converting: Konvertieren: - + Export video URLs Video URLs exportieren - + Do not clear videos Videos nicht leeren - + Enter a PornHub Playlist URL Gib eine PornHub Playlist URL ein - + Graphical User Interface Benutzeroberfläche - + Videos Videos - + Performance Leistung - - Allow Sorting - Sortieren erlauben - - - + Unselects all videos in the tree widget Hebt die Auswahl aller Videos auf - + Does not stop downloading videos Stoppt nicht das Herunterladen von Videos - + Stop loading videos Stoppe das Laden von Videos - + Automatically checks a range of videos Wählt automatisiert einen Bereich von Videos aus - + Select a range of videos Wähle Bereich von Videos aus - - Internet: - Internet: - - - - FFmpeg: - FFmpeg: - - - - Update available: - Aktualisierung verfügbar: - - - + Simultaneous downloads: Gleichzeitige Downloads: - + Maximal workers: Maximale Arbeiter: - + PornHub Delay (0 = Disabled) in seconds: PornHub Verzögerung (0 = Deaktiviert) in Sekunden: - + Maximal timeout: Maximale Zeitüberschreitung: - + Maximal retries: Maximale Netzwerk wiederholungen: - - Discord Rich Presence: - Discord Rich Presence: - - - + Apply (needs restart) Anwenden (benötigt Neustart) - + Reset Porn Fetch to default settings Porn Fetch auf Werkseinstellungen zurücksetzen - + Download and Setup FFmpeg FFmpeg installieren - QCoreApplication - - - Disabled - Deaktiviert - - - - Saved User Settings, please restart Porn Fetch! - Einstellungen wurden gespeichert. Bitte starte Porn Fetch neu! - - - - Login Failed, please check your credentials and try again! - Login gescheitert, bitte überprüfe deine Eingaben! - + main - - Login Successful! - Login erfolgreich! + + +The result limit defines how many videos will be returned when performing a search or doing other operations which +involves loading multiple videos. This also affects models / channels and your liked videos. The result limit is +basically the number of videos which can be loaded into the tree widget (this thing where videos are displayed). + + +Das Ergebniss-Limit definiert, wie viele Videos zurückgegeben werden, wenn eine Suche oder allgemein das Laden von mehreren Videos durchgeführt wird. +Vereinfacht ist es die Zahl, wie viele Videos maximal in das Tree Widget geladen werden dürfen. + - + -FFmpeg isn't installed on your system... Some features won't be available: - -- The FFmpeg threading mode -- Converting videos into a valid .mp4 format -- Writing tags / metadata into the videos - -These features aren't necessary for Porn Fetch, but can be useful for some people. +You can set a delay between requests from you to PornHub. If you are downloading a lot of videos or experiencing +'client.call' errors, you should enable a delay. By default the delay is turned off with the value 0 -To automatically install ffmpeg, just head over to the settings and press the magical button, or install ffmpeg in your -local PATH (e.g, through your linux package manager, or through the Windows PATH) +A good starting point is between 0.5 - 1.5 -This warning won't be shown again. - +The longer the delay is, the longer it will take to download videos, load videos and generally do stuff. +This does NOT affect other sites! + -FFmpeg ist nicht auf deinem System installiert... Einige Funktionen werden nicht verfügbar sein: +Du kannst eine Verzögerung zwichen den Netzwerk Anfragen zwischen dir und der Website einstellen. Wenn du viele Videos herunterlädst und dabei Probleme bekommst, +z.B. das dich eine Website temporör blockiert, oder Fehler aufweist. Standardmäßig ist die Verzögerung mit dem Wert 0 deaktiviert -- Der FFmpeg threading Modus -- Das Konvertieren von Videos in ein valides MP4 Format -- Metadaten / Tags in das Video schreiben - -Diese Funktionen werden nicht grundlegend von Porn Fetch benötigt, aber einige Personen könnten diese nutzen wollen - -Um FFmpeg automatisch zu installieren, gehe einfach in die Einstellungen und klick den magischen Button oder installiere FFmpeg lokal und füg es in deinen Systempfad hinzu -(z.B. über deinen Linux Paketmanager, oder über den Windows PATH) +Eine Empfehlung wäre zwischen 0.5 - 1.5 -This warning won't be shown again. - - - - - Enter custom Path: - Gib einen benutzerdefinierten Pfad ein: - - - - Success: {text} will be used for this session! - Erfolg: {text} wird für diese Sitzung genutzt! - - - - Not supported on Android - Wird nicht auf Android unterstützt - - - - Some error occurred in loading a video. Please report this: {error_message} - Ein unerwarteter Fehler trat beim Laden des Videos auf. Bilde melde das folgende: {error_message} +Je länger die Verzögerung ist, desto länger werden alle Netzwerkanfragen brauchen ! + - - Wrong Input, please verify the URL, category or actress! - Falsche Eingabe, bitte verifiziere die URL, Kategorie oder Darsteller! + + +The maximal workers define the amount of maximal threads which can be started when using the threaded download mode. +One thread handles downloading one segment, so (in theory) 20 threads can download 20 segments at the same time. +This can of course be helpful when you have a very fast internet connection, but when you have a poor PC or running on +Android, you should set this to a lower value. + +I recommend '3' for Android and 5 for low bandwidth connections < 15000 bit/s + + Die maximalen "Arbeiter" definieren die Zahl der maximalen Threads, welche zum Herunterladen der Videosegmente benutzt werden. +Ein Thread kann ein Segment herunterladen, 20 "Arbeiter" können also 20 Segmente gleichzeitig herunterladen (zumindest in der Theorie. Kommt natürlich auf deine Internetgeschwindigkeit an) + - + - Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. - Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} +The timeout handles the timeout for retrieving segments when using the threaded download mode. If you have a poor +internet connection you can set this higher than 10. But this isn't required for most users! + - Information: Eine neue Version von Porn Fetch (v{__next_release__}) wurde veröffentlicht. Ich empfehle dir Porn Fetch zu aktualisieren. - Gehe zu: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} +Der Timeout definiert, wie lange auf ein Segment von einem Video gewartet werden soll, bis der Versuch abgebrochen wird. Bei schlechter +oder instabiler Internetverbindung kann ein höhrerer Wert helfen! + - - FFmpeg has been installed. Please restart Porn Fetch :) - FFmpeg wurde installiert. Bitte starte Porn Fetch neu :) + + +The Semaphore is a tool to limit the number of simultaneous actions / downloads. + +For example: If the semaphore is set to 1, only 1 video will be downloaded at the same time. +If the semaphore is set to 4, 4 videos will be downloaded at the same time. Changing this is only useful, if +you have a really good internet connection and a good system. + + +Die Semaphore limitiert, wie viele gleichzeitige Downloads stattfinden. + +Als Beispiel, wenn die Semaphore bei "1" liegt, dann wird ein Video maximal zur selben Zeit heruntergeladen. +Wenn die Semaphore bei 4 liegt, dann kannst du 4 Videos gleichzeitig herunterladen. Bei sehr starken Internetverbindungen macht das Sinn, +allerdings verbraucht Porn Fetch sehr viel CPU Leistung, daher ist ein Wert höher als 3 eigentlich quatsch + - - The output path does not exist or is not writable. - Der Ausgabepfad existiert nicht oder ist nicht beschreibbar. + + +The different threading modes are used for different scenarios. + +1) High Performance: Uses a class of workers to download multiple video segments at a time. Can be really fast if you +have a very strong internet connection. Maybe not great for low end systems. + +2) FFMPEG: ffmpeg is a tool for converting media files. ffmpeg will download every video segment and merge it directly +into the video file. This removes an extra step from the default method and is therefore a lot faster, but still not as +good as high performance. + +3) Default: The default download mode will just download one video segment after the next one. If you get a lot of +timeouts this can really slow down the process, as we need to wait for PornHub to return the video segments. +With the High Performance method, we can just download other segments while waiting which makes it so fast. + + Hohe Leistung: Verwendet eine Klasse von Arbeitern, um mehrere Video-Segmente gleichzeitig herunterzuladen. Kann sehr schnell sein, wenn du eine sehr starke Internetverbindung hast. Vielleicht nicht ideal für schwache Systeme. + +FFMPEG: ffmpeg ist ein Tool zum Konvertieren von Mediendateien. ffmpeg wird jedes Video-Segment herunterladen und direkt in die Videodatei einfügen. Dies entfernt einen zusätzlichen Schritt aus der Standardmethode und ist daher viel schneller, aber immer noch nicht so gut wie hohe Leistung. + +Standard: Der Standard-Download-Modus lädt einfach ein Video-Segment nach dem anderen herunter. Wenn du viele Timeouts bekommst, kann dies den Prozess wirklich verlangsamen, da wir darauf warten müssen, dass PornHub die Video-Segmente zurückgibt. Mit der Hochleistungsmethode können wir während des Wartens einfach andere Segmente herunterladen, was sie so schnell macht. - - Invalid path. The application will now exit. - Ungültiger Pfad. Die Anwendung wird nun geschlossen. + + +The directory system will save videos in an intelligent way. If you download 3 videos form one Pornstar and 5 videos +from another, Porn Fetch will automatically make folders for it and move the 3 videos into that one folder and the other +5 into the other. (This will still apply with your selected output path) + +This can be helpful for organizing stuff, but is a more advanced feature, so the majority of users won't use it probably + + Das Verzeichnissystem speichert Videos auf intelligente Weise. Wenn du 3 Videos von einem Pornostar und 5 Videos von einem anderen herunterlädst, erstellt Porn Fetch automatisch Ordner dafür und verschiebt die 3 Videos in den einen Ordner und die anderen 5 in den anderen. (Dies gilt weiterhin für deinen ausgewählten Ausgabepfad.) + +Das kann hilfreich sein, um Dinge zu organisieren, ist aber eine fortgeschrittene Funktion, die die Mehrheit der Nutzer wahrscheinlich nicht verwenden wird. - - High Performance threading may cause issues on Android devices. - Der Hochleistungs-threading Modus kann unter Android zu fehlern führen. + + +Create a .txt file and add URLs like this: + +url1 +url2 +url3 +... + +Split them with new lines. No comma, not multiple URLs in the same line! +You can also add model URLs like this: + +model#MODEL_URL + +An example for a file would be: + +https://de.pornhub.com/view_video.php?viewkey=ph5be76343323ff +https://de.pornhub.com/view_video.php?viewkey=ph5946e5f19585a +model#https://de.pornhub.com/pornstar/nancy-a + + - - Porn Fetch will now reset to its default settings... - Porn Fetch wird nun auf Werkseinstellungen zurückgesetzt... + + +The maximal retries defines how much attempts will be used for a network request. For example if an API calls +a URL for a website there will be <AMOUNT> of attempts until an error is thrown. + + Die maximalen Wiederholungen definieren, wie viele Versuche für eine Netzwerk-Anfrage unternommen werden. Wenn zum Beispiel eine API eine URL für eine Website aufruft, wird es <ANZAHL> Versuche geben, bis ein Fehler auftritt. - - Done! Please restart. - Fertig! Bitte neustarten. + + +User uploads and featured videos are two different things. User uploads are the videos which were really uploaded +by the model and the featured videos are videos the model is part or featured in. + +For example the model Nancy Ace has like 10 self uploaded which she made by herself, but she is part in like thousands +of videos from other studios. + +If you choose "User Uploads", only self uploaded videos will be fetched, and the other way around :) + Nutzer-Uploads und Featured Videos sind zwei verschiedene Dinge. Nutzer-Uploads sind die Videos, die wirklich vom Model hochgeladen wurden, und die Feature-part Videos sind Videos, in denen das Model mitspielt bzw. ein Teil von ist. + +Zum Beispiel hat das Model Nancy Ace ungefähr 10 selbst hochgeladene Videos, die sie selbst gemacht hat, aber sie ist in tausenden von Videos anderer Studios zu sehen. + +Wenn du "Nutzer-Uploads" wählst, werden nur selbst hochgeladene Videos abgerufen, und andersherum :) - - No video URLs found. Are there videos in the tree widget? - Keine video URLs gefunden. Sind überhaupt Videos im tree widget? + + Wrong Input, please verify the URL, category or actress! + Falsche Eingabe, bitte verifiziere die URL, Kategorie oder die Darstellerin! - - Permission Error, please select a file from your user space,or run Porn Fetch with admin permissions (not recommended!) - Zugriffsfehler, bitte speichere die Datei in deinem Nutzer Bereich, oder starte Porn Fetch mit Administrator rechten (nicht empfohlen) + + Disabled + Deaktiviert - - Those credentials don't seem to be valid... - Diese Zugangsdaten sehen ungültig aus... + + Done! Please restart. + Fertig, Bitte neustarten. - - You are already logged in! - Du bist bereits eingeloggt! + + No URLs in the current session... + Keine URLs in der aktuellen Session... - - There's a problem with the login. Please make sure you login first and then you try to get videos based on your account. - Es gibt ein Problem mit dem Login. Bitte logge dich erst ein und versuche dann Videos von deinem Account zu laden. + + FFmpeg has been installed. Please restart Porn Fetch :) + FFmpeg wurde installiert. Bitte starte Porn Fetch neu :) - - Invalid Category. Press 'list categories' to see all possible ones. - Ungültige Kategorie. Drücke "Kategorien auflisten" um alle möglichen zu sehen. + + + Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. + Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} + + Changelog: + {markdown.markdown(changelog)} + + + + Information: Eine neue Version von Porn Fetch (v{__next_release__}) wurde veröffentlicht. Ich empfehle dir, Porn Fetch zu aktualisieren. + Geh zu: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} + + Änderungsprotokoll: + {markdown.markdown(changelog)} + + diff --git a/src/frontend/translations/en.ts b/src/frontend/translations/en.ts index 86006cf..7003628 100644 --- a/src/frontend/translations/en.ts +++ b/src/frontend/translations/en.ts @@ -4,12 +4,12 @@ Porn_Fetch - + Saved User Settings, please restart Porn Fetch! - + FFmpeg isn't installed on your system... Some features won't be available: @@ -27,62 +27,62 @@ This warning won't be shown again. - + The output path does not exist or is not writable. - + Enter custom Path: - + Success: {text} will be used for this session! - + Invalid path. The application will now exit. - + Some error occurred in loading a video. Please report this: {error_message} - + Information: The Website {website} specified in the URL file isn't valid. - + Those credentials don't seem to be valid... - + Login Successful! - + Login Failed, please check your credentials and try again! - + You are already logged in! - + There's a problem with the login. Please make sure you login first and then you try to get videos based on your account. - + Invalid Category. Press 'list categories' to see all possible ones. @@ -95,63 +95,63 @@ This warning won't be shown again. - + PornHub: - + HQPorner: - + Info: - + Duration (minutes) - + Only Title (a lot faster) - + Select everything - + Unselect all - + Download Selected Videos - + Author - + Get Title, Author, Duration - + Show videos in reverse - + EPorner @@ -160,11 +160,6 @@ This warning won't be shown again. URLs in the file must be separated with new lines! - - - Enter your PornHub Username - - Get Liked videos @@ -190,11 +185,6 @@ This warning won't be shown again. Get recommended videos - - - Username: - - Enter your PornHub Password @@ -203,10 +193,10 @@ This warning won't be shown again. - - - - + + + + Get Videos @@ -241,102 +231,95 @@ This warning won't be shown again. - - + + No - - + + Yes - + High Performance - + Default - + FFMPEG - - - - - - - - - - + + + + + + + + + + Help - + Half - + Best - + Worst - + Use Directory system? - + Enter "./" for current directory - + Output path: - + German - - + + Get videos by category - - - Eporner - - - XNXX - XVideos @@ -372,93 +355,123 @@ This warning won't be shown again. - + HQPorner - - + + List of all categories - + Get Top Porn: - + Week - + Month - + All Time - + Get random video - + Get Video - + Get Brazzers videos - + + E-Mail: + + + + + Enter your PornHub E-Mail address (not your username, pornhub changed it) + + + + + XVideos: + + + + + Eporner: + + + + + XNXX: + + + + + Spankbang: + + + + Threading Mode: - + Quality: - + Skip existing files: - + Model videos (PornHub) - + User uploads - + Featured videos - + Both - + French - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -475,6 +488,7 @@ li.checked::marker { content: "\2612"; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com (supports total progress)</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Spankbang.com (supports total progress)</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All sites support *threaded* downloads and selectable quality!</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> @@ -498,7 +512,8 @@ li.checked::marker { content: "\2612"; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I am constantly working to support more websites.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If you want a specific site to be supported, just ask:<br /><br />Discord: echteralsfake</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">GitHub.com/echteralsfake/Porn_Fetch/issues</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> @@ -508,37 +523,37 @@ li.checked::marker { content: "\2612"; } - + Porn Fetch Menu - + English - + Graphical User Interface Language: - + System default - + Chinese (simplified) - + Open - + Result Limit: @@ -563,12 +578,12 @@ li.checked::marker { content: "\2612"; } - + Export video URLs - + Do not clear videos @@ -578,82 +593,82 @@ li.checked::marker { content: "\2612"; } - + Graphical User Interface - + Videos - + Performance - + Unselects all videos in the tree widget - + Does not stop downloading videos - + Stop loading videos - + Automatically checks a range of videos - + Select a range of videos - + Simultaneous downloads: - + Maximal workers: - + PornHub Delay (0 = Disabled) in seconds: - + Maximal timeout: - + Maximal retries: - + Apply (needs restart) - + Reset Porn Fetch to default settings - + Download and Setup FFmpeg @@ -663,4 +678,169 @@ li.checked::marker { content: "\2612"; } + + main + + + Wrong Input, please verify the URL, category or actress! + + + + + Disabled + + + + + Done! Please restart. + + + + + No URLs in the current session... + + + + + FFmpeg has been installed. Please restart Porn Fetch :) + + + + + + Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. + Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} + + Changelog: + {markdown.markdown(changelog)} + + + + + + + +The result limit defines how many videos will be returned when performing a search or doing other operations which +involves loading multiple videos. This also affects models / channels and your liked videos. The result limit is +basically the number of videos which can be loaded into the tree widget (this thing where videos are displayed). + + + + + + +You can set a delay between requests from you to PornHub. If you are downloading a lot of videos or experiencing +'client.call' errors, you should enable a delay. By default the delay is turned off with the value 0 + +A good starting point is between 0.5 - 1.5 + +The longer the delay is, the longer it will take to download videos, load videos and generally do stuff. +This does NOT affect other sites! + + + + + + +The maximal workers define the amount of maximal threads which can be started when using the threaded download mode. +One thread handles downloading one segment, so (in theory) 20 threads can download 20 segments at the same time. +This can of course be helpful when you have a very fast internet connection, but when you have a poor PC or running on +Android, you should set this to a lower value. + +I recommend '3' for Android and 5 for low bandwidth connections < 15000 bit/s + + + + + + +The timeout handles the timeout for retrieving segments when using the threaded download mode. If you have a poor +internet connection you can set this higher than 10. But this isn't required for most users! + + + + + + +The Semaphore is a tool to limit the number of simultaneous actions / downloads. + +For example: If the semaphore is set to 1, only 1 video will be downloaded at the same time. +If the semaphore is set to 4, 4 videos will be downloaded at the same time. Changing this is only useful, if +you have a really good internet connection and a good system. + + + + + + +The different threading modes are used for different scenarios. + +1) High Performance: Uses a class of workers to download multiple video segments at a time. Can be really fast if you +have a very strong internet connection. Maybe not great for low end systems. + +2) FFMPEG: ffmpeg is a tool for converting media files. ffmpeg will download every video segment and merge it directly +into the video file. This removes an extra step from the default method and is therefore a lot faster, but still not as +good as high performance. + +3) Default: The default download mode will just download one video segment after the next one. If you get a lot of +timeouts this can really slow down the process, as we need to wait for PornHub to return the video segments. +With the High Performance method, we can just download other segments while waiting which makes it so fast. + + + + + + +The directory system will save videos in an intelligent way. If you download 3 videos form one Pornstar and 5 videos +from another, Porn Fetch will automatically make folders for it and move the 3 videos into that one folder and the other +5 into the other. (This will still apply with your selected output path) + +This can be helpful for organizing stuff, but is a more advanced feature, so the majority of users won't use it probably + + + + + + +Create a .txt file and add URLs like this: + +url1 +url2 +url3 +... + +Split them with new lines. No comma, not multiple URLs in the same line! +You can also add model URLs like this: + +model#MODEL_URL + +An example for a file would be: + +https://de.pornhub.com/view_video.php?viewkey=ph5be76343323ff +https://de.pornhub.com/view_video.php?viewkey=ph5946e5f19585a +model#https://de.pornhub.com/pornstar/nancy-a + + + + + + +The maximal retries defines how much attempts will be used for a network request. For example if an API calls +a URL for a website there will be <AMOUNT> of attempts until an error is thrown. + + + + + + +User uploads and featured videos are two different things. User uploads are the videos which were really uploaded +by the model and the featured videos are videos the model is part or featured in. + +For example the model Nancy Ace has like 10 self uploaded which she made by herself, but she is part in like thousands +of videos from other studios. + +If you choose "User Uploads", only self uploaded videos will be fetched, and the other way around :) + + + diff --git a/src/frontend/translations/fr.ts b/src/frontend/translations/fr.ts index 6ce725f..d77409a 100644 --- a/src/frontend/translations/fr.ts +++ b/src/frontend/translations/fr.ts @@ -2,812 +2,844 @@ - Form + Porn_Fetch - - Video selector... + + Saved User Settings, please restart Porn Fetch! + + + + + +FFmpeg isn't installed on your system... Some features won't be available: + +- The FFmpeg threading mode +- Converting videos into a valid .mp4 format +- Writing tags / metadata into the videos + +These features aren't necessary for Porn Fetch, but can be useful for some people. + +To automatically install ffmpeg, just head over to the settings and press the magical button, or install ffmpeg in your +local PATH (e.g, through your linux package manager, or through the Windows PATH) + +This warning won't be shown again. + - - Apply by Index: + + The output path does not exist or is not writable. - - - Start: + + Enter custom Path: - - - 00000 + + Success: {text} will be used for this session! - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Select the range of videos to be automatically selected.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">For example, if you set the start to 5 and the end to 20, then all videos between 5-20 will be checked for downloading :)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Or select by a range in time:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">For example if you want to download all videos in between 10 and 20 minutes do:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Start: 000010</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">End: 00020</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">And click Apply.</span></p></body></html> + + Invalid path. The application will now exit. - - - End: + + Some error occurred in loading a video. Please report this: {error_message} - - Apply by time: + + Information: The Website {website} specified in the URL file isn't valid. - - - Apply + + Those credentials don't seem to be valid... - - Select everything + + Login Successful! + + + + + Login Failed, please check your credentials and try again! + + + + + You are already logged in! + + + + + There's a problem with the login. Please make sure you login first and then you try to get videos based on your account. + + + + + Invalid Category. Press 'list categories' to see all possible ones. Porn_Fetch_Widget - + Total: Total : - + + E-Mail: + + + + + Enter your PornHub E-Mail address (not your username, pornhub changed it) + + + + PornHub: Pornhub : - + + XVideos: + + + + + Eporner: + + + + + XNXX: + + + + + Info: + + + + HQPorner: HQPorner : - + + Spankbang: + + + + + Duration (minutes) + + + + Only Title (a lot faster) Titre seulement (plus rapide) - + + Select everything + + + + Unselect all Déselectionner tout - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +hr { height: 1px; border-width: 0; } +li.unchecked::marker { content: "\2610"; } +li.checked::marker { content: "\2612"; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Supported Websites:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Downloading:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Spankbang.com (supports total progress)</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All sites support *threaded* downloads and selectable quality!</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">downloaded, therefore threading in a segment isn't needed.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Model / Channel Downloads</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- EPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Searching:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Xvideos.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I am constantly working to support more websites.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If you want a specific site to be supported, just ask:<br /><br />Discord: echteralsfake</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">GitHub.com/echteralsfake/Porn_Fetch/issues</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + + + Porn Fetch Menu + + + + Information: The total progressbar does not count for Eporner and HQPorner, because they are using different mechanisms for downloading. - - View all other progress bars - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Supported Websites:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Downloading:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com (supports total progress)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Eporner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com (supports total progress)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XVideos.com (supports total progress)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">All sites support *threaded* downloads and selectable quality!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">downloaded, therefore threading in a segment isn't needed.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Model / Channel Downloads</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- EPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XVideos.com</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Searching:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Xvideos.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Eporner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">I am constantly working to support more websites.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> - - - - + Converting: - + Download Selected Videos Télecharger la sélection - + Export video URLs - + Do not clear videos - + Author Auteur - - Duration - Durée - - - + Get Title, Author, Duration Trouver Titre, Auteur, Durée - + Show videos in reverse Inverser l'ordre des videos - + URLs in the file must be separated with new lines! Les URLS du fichier doivent être séparées par des lignes! - - Enter your PornHub Username - Entrer un nom de compte PornHub - - - + Get Liked videos Trouver les vidéos aimées - + Get watched videos Trouver les vidées regardées - + Password: Mot de passe : - + Login Identifiant - + Get recommended videos Trouver les recommendations - - Username: - Identifiant : - - - + Enter your PornHub Password Entrer le mot de passe PornHub - - - - - - + + + + + + Get Videos Trouver les vidéos - + Search Query: Recherche : - + Download Télecharger - + File: Fichier : - + Open File Ouvrir - + Model URL: URL du model : - + URL: URL : - - + + No Non - - + + Yes Oui - + High Performance Performance haute - + Default Défaut - + FFMPEG FFMPEG - - - - - - - - - - + + + + + + + + + + + Help Aide - + Half Moitié - + Best Meilleur - + Worst Pas ouf - + Use Directory system? Utiliser le système de fichier ? - + Enter "./" for current directory Entrer "./" pour utiliser le dossier courant - + Output path: Chemin de sortie : - - + German Allemand - - + + Get videos by category Trouver les vidéos par catégorie - - Eporner - EPorner - - - - + XNXX XNXX - - + XVideos XVideos - + + Porn Fetch V3.4 (C) Johannes Habel GPL 3 + + + + Enter video URL Entrer l'URL de la vidéo - + Search Website Chercher un site - + See Supported Websites Chercher un site supporté - + Search for Videos. Select Website below Chercher une vidéo : Sélectionner un site ci-dessous - + PornHub PornHub - + Playlist URL: - - + + HQPorner HQPorner - - + + EPorner - + Enter Model / Channel / Actress URL - + Enter a PornHub Playlist URL - - + + List of all categories Liste des catégories - + Get Top Porn: Récupérer les tendances Porn : - + Week Semaine - + Month Mois - + All Time Toujours - + Get random video Prendre une vidée aléatoire - + Get Video Trouver la vidéo - + Get Brazzers videos Trouver les vidéos Brazzers - + Threading Mode: Mode de thread : - + Quality: Qualité : - - - French - Français - - - - - English - Anglais + + Skip existing files: + - - Graphical User Interface Language: - Language de l'application : + + Model videos (PornHub) + - - System default - Langue système + + User uploads + - - Chinese (simplified) - Chinois (simplifié) + + Featured videos + - - PornHub Language (affects video titles) - Language PornHub (affecte les titres des vidéos) + + Both + - - Spanish - Espagnol + + French + Français - - Portuguese - Portuguais + + English + Anglais - - Chinese - Chinois + + Graphical User Interface Language: + Language de l'application : - - Dutch - Pays-Bas + + System default + Langue système - - Italian - Italien + + Chinese (simplified) + Chinois (simplifié) - Russian - Russe - - - - Czech - Czech - - - - Japanese - Japonais - - - Open Ouvrir - + Result Limit: Limite de résultats : - + Graphical User Interface - + Videos - - Porn Fetch V3.3 (C) Johannes Habel GPL 3 - - - - - Allow Sorting - - - - + Unselects all videos in the tree widget - + Does not stop downloading videos - + Stop loading videos - + Automatically checks a range of videos - + Select a range of videos - - Internet: - - - - - FFmpeg: - - - - - Update available: - - - - + Performance - + Simultaneous downloads: - + Maximal workers: - + PornHub Delay (0 = Disabled) in seconds: - + Maximal timeout: - + Maximal retries: - - Discord Rich Presence: - - - - + Apply (needs restart) - + Reset Porn Fetch to default settings - + Download and Setup FFmpeg - + Start Démarrer - QCoreApplication + main - - Disabled - - - - - Saved User Settings, please restart Porn Fetch! - - - - - Login Failed, please check your credentials and try again! - - - - - Login Successful! + + Wrong Input, please verify the URL, category or actress! - - Enter custom Path: + + Disabled - - Success: {text} will be used for this session! + + Done! Please restart. - - Not supported on Android + + No URLs in the current session... - - Wrong Input, please verify the URL, category or actress! + + FFmpeg has been installed. Please restart Porn Fetch :) - + Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. - Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} - - - - - -FFmpeg isn't installed on your system... Some features won't be available: + Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} -- The FFmpeg threading mode -- Converting videos into a valid .mp4 format -- Writing tags / metadata into the videos + Changelog: + {markdown.markdown(changelog)} -These features aren't necessary for Porn Fetch, but can be useful for some people. - -To automatically install ffmpeg, just head over to the settings and press the magical button, or install ffmpeg in your -local PATH (e.g, through your linux package manager, or through the Windows PATH) - -This warning won't be shown again. - + - - FFmpeg has been installed. Please restart Porn Fetch :) - - - - - The output path does not exist or is not writable. - - - - - Invalid path. The application will now exit. - - - - - High Performance threading may cause issues on Android devices. + + +The result limit defines how many videos will be returned when performing a search or doing other operations which +involves loading multiple videos. This also affects models / channels and your liked videos. The result limit is +basically the number of videos which can be loaded into the tree widget (this thing where videos are displayed). + - - Porn Fetch will now reset to its default settings... + + +You can set a delay between requests from you to PornHub. If you are downloading a lot of videos or experiencing +'client.call' errors, you should enable a delay. By default the delay is turned off with the value 0 + +A good starting point is between 0.5 - 1.5 + +The longer the delay is, the longer it will take to download videos, load videos and generally do stuff. +This does NOT affect other sites! + - - Done! Please restart. + + +The maximal workers define the amount of maximal threads which can be started when using the threaded download mode. +One thread handles downloading one segment, so (in theory) 20 threads can download 20 segments at the same time. +This can of course be helpful when you have a very fast internet connection, but when you have a poor PC or running on +Android, you should set this to a lower value. + +I recommend '3' for Android and 5 for low bandwidth connections < 15000 bit/s + - - No video URLs found. Are there videos in the tree widget? + + +The timeout handles the timeout for retrieving segments when using the threaded download mode. If you have a poor +internet connection you can set this higher than 10. But this isn't required for most users! + - - Permission Error, please select a file from your user space,or run Porn Fetch with admin permissions (not recommended!) + + +The Semaphore is a tool to limit the number of simultaneous actions / downloads. + +For example: If the semaphore is set to 1, only 1 video will be downloaded at the same time. +If the semaphore is set to 4, 4 videos will be downloaded at the same time. Changing this is only useful, if +you have a really good internet connection and a good system. + - - Some error occurred in loading a video. Please report this: {error_message} + + +The different threading modes are used for different scenarios. + +1) High Performance: Uses a class of workers to download multiple video segments at a time. Can be really fast if you +have a very strong internet connection. Maybe not great for low end systems. + +2) FFMPEG: ffmpeg is a tool for converting media files. ffmpeg will download every video segment and merge it directly +into the video file. This removes an extra step from the default method and is therefore a lot faster, but still not as +good as high performance. + +3) Default: The default download mode will just download one video segment after the next one. If you get a lot of +timeouts this can really slow down the process, as we need to wait for PornHub to return the video segments. +With the High Performance method, we can just download other segments while waiting which makes it so fast. + - - Those credentials don't seem to be valid... + + +The directory system will save videos in an intelligent way. If you download 3 videos form one Pornstar and 5 videos +from another, Porn Fetch will automatically make folders for it and move the 3 videos into that one folder and the other +5 into the other. (This will still apply with your selected output path) + +This can be helpful for organizing stuff, but is a more advanced feature, so the majority of users won't use it probably + - - You are already logged in! + + +Create a .txt file and add URLs like this: + +url1 +url2 +url3 +... + +Split them with new lines. No comma, not multiple URLs in the same line! +You can also add model URLs like this: + +model#MODEL_URL + +An example for a file would be: + +https://de.pornhub.com/view_video.php?viewkey=ph5be76343323ff +https://de.pornhub.com/view_video.php?viewkey=ph5946e5f19585a +model#https://de.pornhub.com/pornstar/nancy-a + - - There's a problem with the login. Please make sure you login first and then you try to get videos based on your account. + + +The maximal retries defines how much attempts will be used for a network request. For example if an API calls +a URL for a website there will be <AMOUNT> of attempts until an error is thrown. + - - Invalid Category. Press 'list categories' to see all possible ones. + + +User uploads and featured videos are two different things. User uploads are the videos which were really uploaded +by the model and the featured videos are videos the model is part or featured in. + +For example the model Nancy Ace has like 10 self uploaded which she made by herself, but she is part in like thousands +of videos from other studios. + +If you choose "User Uploads", only self uploaded videos will be fetched, and the other way around :) diff --git a/src/frontend/translations/zh_CN.ts b/src/frontend/translations/zh_CN.ts index 744d578..b639e88 100644 --- a/src/frontend/translations/zh_CN.ts +++ b/src/frontend/translations/zh_CN.ts @@ -2,813 +2,845 @@ - Form + Porn_Fetch - - Video selector... - + + Saved User Settings, please restart Porn Fetch! + 已保存用户设置,请重新启动 Porn Fetch! - - Apply by Index: + + +FFmpeg isn't installed on your system... Some features won't be available: + +- The FFmpeg threading mode +- Converting videos into a valid .mp4 format +- Writing tags / metadata into the videos + +These features aren't necessary for Porn Fetch, but can be useful for some people. + +To automatically install ffmpeg, just head over to the settings and press the magical button, or install ffmpeg in your +local PATH (e.g, through your linux package manager, or through the Windows PATH) + +This warning won't be shown again. + - - - Start: + + The output path does not exist or is not writable. - - - 00000 - + + Enter custom Path: + 输入自定义路径: - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Select the range of videos to be automatically selected.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">For example, if you set the start to 5 and the end to 20, then all videos between 5-20 will be checked for downloading :)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Or select by a range in time:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">For example if you want to download all videos in between 10 and 20 minutes do:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">Start: 000010</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">End: 00020</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Segoe UI'; font-size:9pt;">And click Apply.</span></p></body></html> - + + Success: {text} will be used for this session! + 成功: {text} 将用于此会话! - - - End: + + Invalid path. The application will now exit. - - Apply by time: + + Some error occurred in loading a video. Please report this: {error_message} - - - Apply + + Information: The Website {website} specified in the URL file isn't valid. - - Select everything + + Those credentials don't seem to be valid... + + + Login Successful! + 登陆成功! + + + + Login Failed, please check your credentials and try again! + 登录失败,请检查您的凭据并重试! + + + + You are already logged in! + 您已经登录! + + + + There's a problem with the login. Please make sure you login first and then you try to get videos based on your account. + 登录有问题。请确保您先登录,然后尝试根据您的帐户获取视频。 + + + + Invalid Category. Press 'list categories' to see all possible ones. + 类别无效。按“列出类别”查看所有可能的类别。 + Porn_Fetch_Widget - + Total: 合计: - + + E-Mail: + + + + + Enter your PornHub E-Mail address (not your username, pornhub changed it) + + + + PornHub: PornHub: - + + XVideos: + + + + + Eporner: + + + + + XNXX: + + + + + Info: + + + + HQPorner: HQPorner: - + + Spankbang: + + + + + Duration (minutes) + + + + Only Title (a lot faster) 仅标题(可加快速度) - + + Select everything + + + + Unselect all 全不选 - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +hr { height: 1px; border-width: 0; } +li.unchecked::marker { content: "\2610"; } +li.checked::marker { content: "\2612"; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Supported Websites:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Downloading:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com (supports total progress)</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Spankbang.com (supports total progress)</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All sites support *threaded* downloads and selectable quality!</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">downloaded, therefore threading in a segment isn't needed.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Model / Channel Downloads</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- EPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XVideos.com</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Searching:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PornHub.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- HQPorner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Xvideos.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Eporner.com</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- XNXX.com</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I am constantly working to support more websites.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If you want a specific site to be supported, just ask:<br /><br />Discord: echteralsfake</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">GitHub.com/echteralsfake/Porn_Fetch/issues</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + + + Porn Fetch Menu + + + + Information: The total progressbar does not count for Eporner and HQPorner, because they are using different mechanisms for downloading. - - View all other progress bars - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Supported Websites:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Downloading:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com (supports total progress)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Eporner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com (supports total progress)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XVideos.com (supports total progress)</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">All sites support *threaded* downloads and selectable quality!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">* hqporner and eporner running in QThreads, but they don't fetch segments. The video is directly</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">downloaded, therefore threading in a segment isn't needed.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Model / Channel Downloads</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- EPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XVideos.com</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Searching:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- PornHub.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- HQPorner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Xvideos.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- Eporner.com</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">- XNXX.com</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">I am constantly working to support more websites.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> - - - - + Converting: - + Download Selected Videos 下载选择视频 - + Export video URLs - + Do not clear videos - + Author 作者 - - Duration - 时长 - - - + Get Title, Author, Duration 获取标题,作者,时长 - + Show videos in reverse 以相反顺序显示视频 - + URLs in the file must be separated with new lines! 文件中的URL必须用换行符隔开! - - Enter your PornHub Username - 请输入你的PornHub用户名 - - - + Get Liked videos 获取以点赞视频 - + Get watched videos 获取已观看视频 - + Password: 密码: - + Login 登录 - + Get recommended videos 获取推荐视频 - - Username: - 用户名: - - - + Enter your PornHub Password 请输入你的PornHub密码 - - - - - - + + + + + + Get Videos 获取视频 - + Search Query: 搜索: - + Download 下载 - + File: 文件: - + Open File 打开文件 - + Model URL: 模特链接: - + URL: URL: - - + + No - - + + Yes - + High Performance 高性能 - + Default 默认 - + FFMPEG FFMPEG - - - - - - - - - - + + + + + + + + + + + Help 帮助 - + Half 中等 - + Best 最好 - + Worst 最差 - + Use Directory system? 是否使用路径系统? - + Enter "./" for current directory 输入"./"以使用当前目录 - + Output path: 输出路径: - - + German 德语 - - + + Get videos by category 获取分类视频 - - Eporner + + XNXX - - - XNXX + + XVideos - - - XVideos + + Porn Fetch V3.4 (C) Johannes Habel GPL 3 - + Enter video URL - + Search Website - + See Supported Websites - + Search for Videos. Select Website below - + PornHub - + Playlist URL: - - + + HQPorner - - + + EPorner - + Enter Model / Channel / Actress URL - + Enter a PornHub Playlist URL - - + + List of all categories 列出所有类别 - + Get Top Porn: 获取最最热视频: - + Week 本周 - + Month 本月 - + All Time 至今 - + Get random video 获取随机视频 - + Get Video 获取视频 - + Get Brazzers videos 获取Brazzers视频 - + Threading Mode: 线程模式: - + Quality: 质量: - - - French - 法语 - - - - - English - 英语 + + Skip existing files: + - - Graphical User Interface Language: - 用户界面语言: + + Model videos (PornHub) + - - System default - 系统默认 + + User uploads + - - Chinese (simplified) - 中文(简体) + + Featured videos + - - PornHub Language (affects video titles) - PornHub语言(会影响视频标题) + + Both + - - Spanish - 西班牙语 + + French + 法语 - - Portuguese - 葡萄牙语 + + English + 英语 - - Chinese - 中文 + + Graphical User Interface Language: + 用户界面语言: - - Dutch - 荷兰语 + + System default + 系统默认 - - Italian - 意大利语 + + Chinese (simplified) + 中文(简体) - Russian - 俄语 - - - - Czech - 捷克语 - - - - Japanese - 日语 - - - Open 打开 - + Result Limit: 结果限制: - + Graphical User Interface - + Videos - - Porn Fetch V3.3 (C) Johannes Habel GPL 3 - - - - - Allow Sorting - - - - + Unselects all videos in the tree widget - + Does not stop downloading videos - + Stop loading videos - + Automatically checks a range of videos - + Select a range of videos - - Internet: - - - - - FFmpeg: - - - - - Update available: - - - - + Performance - + Simultaneous downloads: - + Maximal workers: - + PornHub Delay (0 = Disabled) in seconds: - + Maximal timeout: - + Maximal retries: - - Discord Rich Presence: - - - - + Apply (needs restart) - + Reset Porn Fetch to default settings - + Download and Setup FFmpeg - + Start 开始 - QCoreApplication - - - Disabled - 关闭 - - - - Saved User Settings, please restart Porn Fetch! - 已保存用户设置,请重新启动 Porn Fetch! - - - - Login Failed, please check your credentials and try again! - 登录失败,请检查您的凭据并重试! - - - - Login Successful! - 登陆成功! - + main - - Enter custom Path: - 输入自定义路径: + + Wrong Input, please verify the URL, category or actress! + - - Success: {text} will be used for this session! - 成功: {text} 将用于此会话! + + Disabled + - - Not supported on Android - Android 上不支持 + + Done! Please restart. + - - Wrong Input, please verify the URL, category or actress! + + No URLs in the current session... - - - Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. - Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} + + FFmpeg has been installed. Please restart Porn Fetch :) - + -FFmpeg isn't installed on your system... Some features won't be available: - -- The FFmpeg threading mode -- Converting videos into a valid .mp4 format -- Writing tags / metadata into the videos - -These features aren't necessary for Porn Fetch, but can be useful for some people. + Information: A new version of Porn Fetch (v{__next_release__}) is out. I recommend you to update Porn Fetch. + Go to: https://github.com/EchterAlsFake/Porn_Fetch/releases/tag/ {__next_release__} -To automatically install ffmpeg, just head over to the settings and press the magical button, or install ffmpeg in your -local PATH (e.g, through your linux package manager, or through the Windows PATH) + Changelog: + {markdown.markdown(changelog)} -This warning won't be shown again. - + - - FFmpeg has been installed. Please restart Porn Fetch :) + + +The result limit defines how many videos will be returned when performing a search or doing other operations which +involves loading multiple videos. This also affects models / channels and your liked videos. The result limit is +basically the number of videos which can be loaded into the tree widget (this thing where videos are displayed). + - - The output path does not exist or is not writable. + + +You can set a delay between requests from you to PornHub. If you are downloading a lot of videos or experiencing +'client.call' errors, you should enable a delay. By default the delay is turned off with the value 0 + +A good starting point is between 0.5 - 1.5 + +The longer the delay is, the longer it will take to download videos, load videos and generally do stuff. +This does NOT affect other sites! + - - Invalid path. The application will now exit. + + +The maximal workers define the amount of maximal threads which can be started when using the threaded download mode. +One thread handles downloading one segment, so (in theory) 20 threads can download 20 segments at the same time. +This can of course be helpful when you have a very fast internet connection, but when you have a poor PC or running on +Android, you should set this to a lower value. + +I recommend '3' for Android and 5 for low bandwidth connections < 15000 bit/s + - - High Performance threading may cause issues on Android devices. + + +The timeout handles the timeout for retrieving segments when using the threaded download mode. If you have a poor +internet connection you can set this higher than 10. But this isn't required for most users! + - - Porn Fetch will now reset to its default settings... + + +The Semaphore is a tool to limit the number of simultaneous actions / downloads. + +For example: If the semaphore is set to 1, only 1 video will be downloaded at the same time. +If the semaphore is set to 4, 4 videos will be downloaded at the same time. Changing this is only useful, if +you have a really good internet connection and a good system. + - - Done! Please restart. + + +The different threading modes are used for different scenarios. + +1) High Performance: Uses a class of workers to download multiple video segments at a time. Can be really fast if you +have a very strong internet connection. Maybe not great for low end systems. + +2) FFMPEG: ffmpeg is a tool for converting media files. ffmpeg will download every video segment and merge it directly +into the video file. This removes an extra step from the default method and is therefore a lot faster, but still not as +good as high performance. + +3) Default: The default download mode will just download one video segment after the next one. If you get a lot of +timeouts this can really slow down the process, as we need to wait for PornHub to return the video segments. +With the High Performance method, we can just download other segments while waiting which makes it so fast. + - - No video URLs found. Are there videos in the tree widget? + + +The directory system will save videos in an intelligent way. If you download 3 videos form one Pornstar and 5 videos +from another, Porn Fetch will automatically make folders for it and move the 3 videos into that one folder and the other +5 into the other. (This will still apply with your selected output path) + +This can be helpful for organizing stuff, but is a more advanced feature, so the majority of users won't use it probably + - - Permission Error, please select a file from your user space,or run Porn Fetch with admin permissions (not recommended!) + + +Create a .txt file and add URLs like this: + +url1 +url2 +url3 +... + +Split them with new lines. No comma, not multiple URLs in the same line! +You can also add model URLs like this: + +model#MODEL_URL + +An example for a file would be: + +https://de.pornhub.com/view_video.php?viewkey=ph5be76343323ff +https://de.pornhub.com/view_video.php?viewkey=ph5946e5f19585a +model#https://de.pornhub.com/pornstar/nancy-a + - - Some error occurred in loading a video. Please report this: {error_message} + + +The maximal retries defines how much attempts will be used for a network request. For example if an API calls +a URL for a website there will be <AMOUNT> of attempts until an error is thrown. + - - Those credentials don't seem to be valid... + + +User uploads and featured videos are two different things. User uploads are the videos which were really uploaded +by the model and the featured videos are videos the model is part or featured in. + +For example the model Nancy Ace has like 10 self uploaded which she made by herself, but she is part in like thousands +of videos from other studios. + +If you choose "User Uploads", only self uploaded videos will be fetched, and the other way around :) - - - You are already logged in! - 您已经登录! - - - - There's a problem with the login. Please make sure you login first and then you try to get videos based on your account. - 登录有问题。请确保您先登录,然后尝试根据您的帐户获取视频。 - - - - Invalid Category. Press 'list categories' to see all possible ones. - 类别无效。按“列出类别”查看所有可能的类别。 - diff --git a/src/frontend/ui_form_desktop.py b/src/frontend/ui_form_desktop.py index fc0a39e..4224f81 100644 --- a/src/frontend/ui_form_desktop.py +++ b/src/frontend/ui_form_desktop.py @@ -391,7 +391,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1020, 246)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 391, 237)) self.gridLayout_18 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_18.setObjectName(u"gridLayout_18") self.gridlayout_progressbar = QGridLayout() @@ -677,7 +677,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_treewidget.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") - self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1020, 289)) + self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 1006, 289)) self.gridLayout_4 = QGridLayout(self.scrollAreaWidgetContents_3) self.gridLayout_4.setObjectName(u"gridLayout_4") self.verticallayout_treewidget_settings = QVBoxLayout() @@ -817,7 +817,7 @@ def setupUi(self, Porn_Fetch_Widget): self.scrollarea_settings.setWidgetResizable(True) self.scrollAreaWidgetContents_6 = QWidget() self.scrollAreaWidgetContents_6.setObjectName(u"scrollAreaWidgetContents_6") - self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 1006, 647)) + self.scrollAreaWidgetContents_6.setGeometry(QRect(0, 0, 696, 647)) self.gridLayout_19 = QGridLayout(self.scrollAreaWidgetContents_6) self.gridLayout_19.setObjectName(u"gridLayout_19") self.gridlayout_settings = QGridLayout() @@ -1554,7 +1554,7 @@ def setupUi(self, Porn_Fetch_Widget): self.retranslateUi(Porn_Fetch_Widget) self.stacked_widget_main.setCurrentIndex(0) - self.stacked_widget_top.setCurrentIndex(2) + self.stacked_widget_top.setCurrentIndex(1) QMetaObject.connectSlotsByName(Porn_Fetch_Widget) @@ -1593,9 +1593,9 @@ def retranslateUi(self, Porn_Fetch_Widget): self.button_help_file.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Help", None)) self.button_get_liked_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get Liked videos", None)) self.button_get_watched_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get watched videos", None)) - self.label_username.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Username:", None)) + self.label_username.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"E-Mail:", None)) self.button_login.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Login", None)) - self.lineedit_username.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter your PornHub Username", None)) + self.lineedit_username.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter your PornHub E-Mail address (not your username, pornhub changed it) ", None)) self.button_get_recommended_videos.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Get recommended videos", None)) self.label_password.setText(QCoreApplication.translate("Porn_Fetch_Widget", u"Password:", None)) self.lineedit_password.setPlaceholderText(QCoreApplication.translate("Porn_Fetch_Widget", u"Enter your PornHub Password", None)) From 22dbe310ebfdd01940bf2d1f7e5642e58aad4dbe Mon Sep 17 00:00:00 2001 From: Johannes Habel Date: Sun, 4 Aug 2024 01:29:50 +0200 Subject: [PATCH 39/39] - pov: me being stupid as usual :skull: --- src/build/pysidedeploy_android_aarch64.spec | 2 +- src/build/pysidedeploy_android_armv7.spec | 2 +- src/build/pysidedeploy_android_i686.spec | 2 +- src/build/pysidedeploy_android_x86_64.spec | 2 +- src/build/pysidedeploy_linux.spec | 2 +- src/scripts/install.sh | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/build/pysidedeploy_android_aarch64.spec b/src/build/pysidedeploy_android_aarch64.spec index 0aa3770..64fc87e 100755 --- a/src/build/pysidedeploy_android_aarch64.spec +++ b/src/build/pysidedeploy_android_aarch64.spec @@ -11,7 +11,7 @@ exec_directory = . # path to .pyproject project file project_file = # application icon -icon = /home/asuna/PycharmProjects/Porn_Fetch/src/frontend/graphics/android_app_icon.png +icon = src/frontend/graphics/android_app_icon.png [python] # python path diff --git a/src/build/pysidedeploy_android_armv7.spec b/src/build/pysidedeploy_android_armv7.spec index d966880..e9086fa 100755 --- a/src/build/pysidedeploy_android_armv7.spec +++ b/src/build/pysidedeploy_android_armv7.spec @@ -11,7 +11,7 @@ exec_directory = . # path to .pyproject project file project_file = # application icon -icon = /home/asuna/PycharmProjects/Porn_Fetch/src/frontend/graphics/android_app_icon.png +icon = src/frontend/graphics/android_app_icon.png [python] # python path diff --git a/src/build/pysidedeploy_android_i686.spec b/src/build/pysidedeploy_android_i686.spec index 735c51d..32fe4c0 100755 --- a/src/build/pysidedeploy_android_i686.spec +++ b/src/build/pysidedeploy_android_i686.spec @@ -11,7 +11,7 @@ exec_directory = . # path to .pyproject project file project_file = # application icon -icon = /home/asuna/PycharmProjects/Porn_Fetch/src/frontend/graphics/android_app_icon.png +icon = src/frontend/graphics/android_app_icon.png [python] # python path diff --git a/src/build/pysidedeploy_android_x86_64.spec b/src/build/pysidedeploy_android_x86_64.spec index ccd8a2a..d04a52d 100755 --- a/src/build/pysidedeploy_android_x86_64.spec +++ b/src/build/pysidedeploy_android_x86_64.spec @@ -11,7 +11,7 @@ exec_directory = . # path to .pyproject project file project_file = # application icon -icon = /home/asuna/PycharmProjects/Porn_Fetch/src/frontend/graphics/android_app_icon.png +icon = src/frontend/graphics/android_app_icon.png [python] # python path diff --git a/src/build/pysidedeploy_linux.spec b/src/build/pysidedeploy_linux.spec index ef9ec41..e13f151 100755 --- a/src/build/pysidedeploy_linux.spec +++ b/src/build/pysidedeploy_linux.spec @@ -11,7 +11,7 @@ exec_directory = . # path to .pyproject project file project_file = # application icon -icon = /home/asuna/Porn_Fetch/src/scripts/Porn_Fetch/src/frontend/graphics/logo_transparent.png +icon = src/frontend/graphics/logo_transparent.png [python] # python path diff --git a/src/scripts/install.sh b/src/scripts/install.sh index 861656d..55f1805 100644 --- a/src/scripts/install.sh +++ b/src/scripts/install.sh @@ -83,4 +83,4 @@ pyside6-deploy main.py -c src/build/pysidedeploy_linux.spec -f -v deactivate echo "Deleting the temporary created virtual environment..." rm -rf /tmp/.venv -echo "Porn Fetch is now installed in $(pwd)/main.bin" \ No newline at end of file +echo "Porn Fetch is now installed in $(pwd)/main.bin"