diff --git a/.gitignore b/.gitignore index e8383c6..7a56971 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,3 @@ dist/ __pycache__/ .flatpak-builder/ flatpak-build-dir/ -*.jpg diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..12386d8 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,69 @@ +--- +include: + - local: .gitlab-ci/versioning/gitversion.yml + - local: .gitlab-ci/git/create_tag.yml + +stages: + - build + - release + +gitversion: + extends: .versioning:gitversion + stage: .pre + tags: + - gitlab-org-docker + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch + +build: + stage: build + image: python:3.9.21 + tags: + - gitlab-org-docker + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch + needs: + - job: gitversion + artifacts: true + script: + - sed -i "s/0.0.1/${GitVersion_MajorMinorPatch}/" src/OptimaLab35/__init__.py + - cat src/OptimaLab35/__init__.py + - python3 -m pip install build + - python3 -m build + artifacts: + paths: + - dist/* + expire_in: 1 day + +publish: + stage: release + image: python:3.9.21 + tags: + - gitlab-org-docker + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch + variables: + TWINE_USERNAME: "__token__" + TWINE_PASSWORD: $TWINE_API + needs: + - job: build + artifacts: true + script: + - python3 -m pip install twine + - python3 -m twine upload dist/* + +create_tag: + extends: .git:create_tag + stage: release + tags: + - gitlab-org-docker + variables: + VERSION: $GitVersion_SemVer + TOKEN: $GITLAB_TOKEN + needs: + - job: gitversion + artifacts: true + rules: + - if: $CI_COMMIT_TAG + when: never # Do not run this job when a tag is created manually + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch diff --git a/.gitlab-ci/git/create_tag.yml b/.gitlab-ci/git/create_tag.yml new file mode 100644 index 0000000..2c1afd7 --- /dev/null +++ b/.gitlab-ci/git/create_tag.yml @@ -0,0 +1,15 @@ +--- + +.git:create_tag: + image: alpine:3.21 + variables: + GIT_STRATEGY: clone + GIT_DEPTH: 0 + GIT_LFS_SKIP_SMUDGE: 1 + VERSION: '' + TOKEN: '' # Token with push privileges + script: + - apk add git + - git remote set-url origin https://oauth2:$TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH + - git tag $VERSION + - git push origin tag $VERSION diff --git a/.gitlab-ci/versioning/gitversion.yml b/.gitlab-ci/versioning/gitversion.yml new file mode 100644 index 0000000..dbbc149 --- /dev/null +++ b/.gitlab-ci/versioning/gitversion.yml @@ -0,0 +1,31 @@ +--- +.versioning:gitversion: + image: + name: mcr.microsoft.com/dotnet/sdk:9.0 + variables: + GIT_STRATEGY: clone + GIT_DEPTH: 0 # force a deep/non-shallow fetch need by gitversion + GIT_LFS_SKIP_SMUDGE: 1 + cache: [] # caches and before / after scripts can mess things up + script: + - | + dotnet tool install --global GitVersion.Tool --version 5.* + export PATH="$PATH:/root/.dotnet/tools" + + dotnet-gitversion -output buildserver + + # We could just collect the output file gitversion.properties (with artifacts:report:dotenv: gitversion.properties as it is already in DOTENV format, + # however it contains ~33 variables which unnecessarily consumes many of the 50 max DOTENV variables of the free GitLab version. + # Limits are higher for licensed editions, see https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportsdotenv + grep 'GitVersion_LegacySemVer=' gitversion.properties >> gitversion.env + grep 'GitVersion_SemVer=' gitversion.properties >> gitversion.env + grep 'GitVersion_FullSemVer=' gitversion.properties >> gitversion.env + grep 'GitVersion_Major=' gitversion.properties >> gitversion.env + grep 'GitVersion_Minor=' gitversion.properties >> gitversion.env + grep 'GitVersion_Patch=' gitversion.properties >> gitversion.env + grep 'GitVersion_MajorMinorPatch=' gitversion.properties >> gitversion.env + grep 'GitVersion_BuildMetaData=' gitversion.properties >> gitversion.env + artifacts: + reports: + # propagates variables into the pipeline level + dotenv: gitversion.env diff --git a/.woodpecker/woodpecker_ci.yml b/.woodpecker/woodpecker_ci.yml deleted file mode 100644 index ba24276..0000000 --- a/.woodpecker/woodpecker_ci.yml +++ /dev/null @@ -1,92 +0,0 @@ -steps: - - name: gitversion - depends_on: [] # nothing start emititly - when: - event: push - branch: main - image: mcr.microsoft.com/dotnet/sdk:9.0 - environment: - CI_TOKEN: - from_secret: CI_TOKEN - commands: - - git remote set-url origin https://CodeByMrFinchum:$CI_TOKEN@code.boxyfoxy.net/$CI_REPO.git - - git fetch --unshallow --tags - - apt-get update && apt-get install -y jq - - dotnet tool install --global GitVersion.Tool --version 5.* - - export PATH="$PATH:/root/.dotnet/tools" - - dotnet-gitversion -output json > version.json - - ls - - cat version.json - - | - echo "GitVersion_SemVer=$(jq -r '.SemVer' version.json)" >> gitversion.env - echo "GitVersion_LegacySemVer=$(jq -r '.LegacySemVer' version.json)" >> gitversion.env - echo "GitVersion_FullSemVer=$(jq -r '.FullSemVer' version.json)" >> gitversion.env - echo "GitVersion_Major=$(jq -r '.Major' version.json)" >> gitversion.env - echo "GitVersion_Minor=$(jq -r '.Minor' version.json)" >> gitversion.env - echo "GitVersion_Patch=$(jq -r '.Patch' version.json)" >> gitversion.env - echo "GitVersion_MajorMinorPatch=$(jq -r '.MajorMinorPatch' version.json)" >> gitversion.env - echo "GitVersion_BuildMetaData=$(jq -r '.BuildMetaData' version.json)" >> gitversion.env - - - name: tagging - depends_on: [gitversion] - when: - event: push - branch: main - image: alpine/git - environment: - CI_TOKEN: - from_secret: CI_TOKEN - commands: - - ls - - cat gitversion.env - - git config --global user.email "ci@noreply.boxyfoxy.net" - - git config --global user.name "CI Bot" - - git remote set-url origin https://CodeByMrFinchum:$${CI_TOKEN}@code.boxyfoxy.net/$${CI_REPO}.git - - . gitversion.env - - git tag $GitVersion_SemVer - - git push origin tag $GitVersion_SemVer - - - name: build - depends_on: [gitversion, tagging] - when: - event: push - branch: main - image: python:3.9.21 - commands: - - ls - - cat gitversion.env - - export $(cat gitversion.env | xargs) - - sed -i "s/0.0.1/$GitVersion_SemVer/" src/OptimaLab35/__init__.py - - cat src/OptimaLab35/__init__.py - - python3 -m pip install build - - python3 -m build --wheel --sdist -s src - - - name: publish_pypi - depends_on: [gitversion, tagging, build] - when: - event: push - branch: main - image: python:3.9.21 - environment: - TWINE_PASSWORD: - from_secret: TWINE_API - TWINE_USERNAME: "__token__" - commands: - - ls - - python3 -m pip install twine - - python3 -m twine upload src/dist/* - - - name: publish_forgejo - depends_on: [gitversion, tagging, build] - when: - event: push - branch: main - image: python:3.9.21 - environment: - TWINE_PASSWORD: - from_secret: PKG_TOKEN - TWINE_USERNAME: "CodeByMrFinchum" - commands: - - ls - - python3 -m pip install twine - - python3 -m twine upload --repository-url https://code.boxyfoxy.net/api/packages/CodeByMrFinchum/pypi src/dist/* diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b2781..c103ff4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,213 +1,11 @@ # Changelog -## 1.5.x -### 1.5.0: Feature - Time of dateEdit now today -- Changes that instead of the dateEdit elements being always set to a last day of 2024 it is the current day. -## 1.4.x -### 1.4.2: Fix links -- Fixed that changelog was linked to GitLab, not it is to code.boxyfoxy.net -- Fixed Changelog - -### 1.4.1: Fix CI -- Fixed pipline -### 1.4.0: New CI -- Migrated repo from GitLab to my forgejo instance, therefore switching to woodpecker CI - ---- - -## 1.3.x -### 1.3.4: Fix - Spelling (25.04.01) -- Fixed misspelling in preview window. - -### 1.3.3: Patch - Increased Preview Performance x2 (25.04.01) -- Reduced preview stutter: Previously, the image was updated twice when changing brightness or contrast. Now, it updates only once, improving performance by 100%. -- There is still room for improvement. Analysis shows that image processing takes the most time, while displaying in Qt is relatively fast. Reducing the image size impacts performance, so resizing to 50% is a good idea. -- There is an issue where `QRunner` does not always finish in the correct order when brightness or contrast values are changed rapidly. ATM I do not know how to fix this easly. -- The "Preview" watermark now displays the brightness and contrast levels of the shown image. - -### 1.3.2: Fix - Fixed problem with app folders (25.03.30) -- Fixed a problem that the app folder path was not generated correctly. - -### 1.3.1: Fix - Fixed insert exif not working (25.03.27) -- Fixed the feature that inserted exif into images without modifying them. - -### 1.3.0: Feature - Write Adjustments into EXIF (25.03.24) -- Changes to contrast and brightness are now recorded in the EXIF comment section (labeled *Scanner* in the program). -- This allows users to track what adjustments were made to an image. - ---- - -## 1.2.x -### 1.2.2: Patch - Pyproject file (25.03.23) -- Fixed `Development Status` Classifier -- Added <4.0 python version - -### 1.2.1: Patch - Changelog file (25.03.23) -- Patches formation in changelog file. - -### 1.2.0: Refactor - Splitting Classes into Separate Files (25.03.23) -- Refactored `gui.py`, which previously contained almost all the code, into multiple files. -- Each window's logic is now in its own file, improving code organization. -- Window layouts remain in `.ui` folder, while their logic is now properly separated. - -## 1.1.x -### 1.1.0: Feature - New Function in Preview Window (25.03.23) -- Added a new feature to the preview window: **Hold a button to temporarily view the original (unedited) image.** This makes it easier to compare changes. -- Minor UI adjustments. - ---- - -## 1.0.x (25.03.06) -### 1.0.1: Fixed spelling -- Fixes spelling some places - -### 1.0.0: Fix version bump -- Version was not bumped correctly - ---- - -## 0.15.1: Final Polish (25.03.06) -- Fixed a bug where the GPS field being empty but selected caused issues. -- EXIF insertion is now canceled if any image in the folder does not end with a number. -- Minor GUI adjustments for a more polished experience. -- Disabled preview adjustment controls until an image is loaded to prevent errors. - -## 0.15.0: Preview Image Resizing Update (25.02.12) -- Added the ability to change the preview image size dynamically. -- Previously, the image was processed and displayed at its original size, causing lag or unresponsiveness when adjusting the slider. -- Reducing the processed image size should help improve performance. -- Default preview image size is now **25%**, but users can adjust it between **10% and 100%**. - ---- - -## 0.14.x -### 0.14.1: Patch changelog (25.02.12) -- Updated the changelog to include missing entries. - -### 0.14.0: Code refactor (by Mr. Finch) (25.02.11) -- Introduced constants and optimized the code. - -## 0.13.x (25.02.11) -### 0.13.1: Fixed image processing -- Fixed a bug that made it impossible to process images. - -### 0.13.0: Requirements file (by Mr. Finch) -- Added a requirements file. - ---- - -## 0.12.x -### 0.12.6: Disabled app restart on Windows (25.02.11) -- The app can not restart properly on Windows, so the restart button has been hidden when the OS is `nt`. -- Also updated tool tip to indicate that changing theme requeres are restart. - -### 0.12.5: Fixed EXIF File Generation Bug (25.02.10) -- Fixed a bug where the application failed to generate a new default EXIF file if none was available. Now, the file is correctly created when missing. - -### 0.12.4: Updated README (25.02.10) -- The README file (project description) now includes updates description and screenshots. - -### 0.12.3: UI Adjustments (25.02.10) -- Minor changes to maintain a unified layout across all windows. -- Added option to sync app theme with OS (if supported). -- Set auto theme as the default value. - -### 0.12.2: Minor UI Improvements for Theme Compatibility (25.02.10) -- Fixed text clipping issues when using the new theme options. - -### 0.12.1: Removed Unnecessary Debug Prints (25.02.09) -- Removed leftover debug statements. - -### 0.12.0: New Settings Menu & Patches (25.02.09) -- **New Settings Window:** - - The updater window has been reworked into a settings window. - - **Initial settings (first tab) include:** - 1. Option to change the theme (with an optional dependency installation). - 2. Reset selectable EXIF data to default. - - The updater UI has been moved to the second tab. - - Added a link to the changelog for easier access to update details. - -- **Patches:** - - Fixed an issue where links in labels (About window) did not open a browser. - - Added a changelog link in the About window. - - Minor changes to `utility.py` to handle settings. - ---- - -## 0.11.x (25.02.05) -### 0.11.1: Fixed pipeline -- Fixed pipeline publish error - -### 0.11.0: Refactor and Patches -- Fixed an issue with the updater: The updater window wouldn't start if the `updater_log.json` file was missing or lacked a valid last `time.time()` float value. -- Corrected layout issues in the preview window, repositioning elements to their proper places. -- Added an application icon (may not work on all desktop environments). -- Refactored code to reduce the size of the PyPi package by removing unnecessary folders. - ---- - -## 0.10.x (25.02.04) -### 0.10.1: Fixed Updater -- Fixed an issue where the updater was permanently disabled. - -### 0.10.0: Multithreading for Preview Window -- The preview window now processes images in a separate thread, and live update preview is enabled by default. - - This improves UI responsiveness. - - The image now resizes dynamically to fit the window when the window size changes. -- Minor UI improvements. - ---- - -## 0.9.x -### 0.9.2: Enhanced updater -- Minor enhancments for the updater - -### 0.9.1: Patch for Unsuccessful Successful Update -- Addressed a rare issue where the package did not update correctly using the updater. - - Unable to reproduce, but it may have been related to an older version and the restart process. -- Added developer functions to test the updater without requiring a published release. - -### 0.9.0: UI Enhancements and Language Refinements -- Changed text, labels, buttons, and checkboxes for clearer understanding. -- Improved UI language to make the interface easier to navigate. -- Added tooltips for more helpful information and guidance. -- Updates applied across the main window (both tabs) and the preview window. - ---- - -## 0.8.x -### 0.8.5: Patch for New PyPiUpdater Version -- **PyPiUpdater 0.5** introduced breaking changes; adjusted code to ensure compatibility with the new version. - -### 0.8.4: Minor Enhancements & Cleanup -- Updated window titles. -- Improved error handling for updater: now displays the specific error message instead of just **"error"** when an issue occurs during update checks. -- Ensured all child windows close when the main window is closed. - -### 0.8.3: Fix - OptimaLab35 Not Closing After Update -- Fixed an issue where **OptimaLab35** would not close properly when updating, resulting in an unresponsive instance and multiple running processes. - -### 0.8.2: Patch for New PyPiUpdater Version -- Updated to support **PyPiUpdater 0.4.0**. -- Now stores version information locally, preventing an "unknown" state on the first updater launch. - - Users still need to press the **Update** button to verify the latest version, ensuring an internet connection is available. - -### 0.8.1: Fix -- Fixed a misspelling of `PyPiUpdater` in the build file, which prevented v0.8.0 from being installed. - -### 0.8.0: Updater Feature -- Added an updater function utilizing my new package [PyPiUpdater](https://gitlab.com/CodeByMrFinchum/PyPiUpdater). -- New updater window displaying the local version and checking for updates online. -- Added an option to update and restart the app from the menu. - ---- - -## 0.7.0: Enhanced Preview +## 0.7.x +### 0.7.0: Enhanced Preview - Images loaded into the preview window are now scaled while maintaining aspect ratio. - Added live updates: changes to brightness, contrast, or grayscale are applied immediately. - - This may crush the system depending on image size and system specifications. + - ⚠ This may crush the system depending on image size and system specifications. - Removed Settings from menuBar, and extended the about window. - --- ## 0.6.0: Initial Flatpak Support diff --git a/README.md b/README.md index 22efff4..f489d04 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,22 @@ # **OptimaLab35** -Developed on my [forgejo instance](https://code.boxyfoxy.net/CodeByMrFinchum), [GitLab](https://gitlab.com/CodeByMrFinchum) is used as backup. +_Last updated: 28 Jan 2025_ ## **Overview** **OptimaLab35** enhances **OPTIMA35** (**Organizing, Processing, Tweaking Images, and Modifying scanned Analogs from 35mm Film**) by offering a user-friendly graphical interface for efficient image and metadata management. -It serves as a GUI for the [optima35 library](https://code.boxyfoxy.net/CodeByMrFinchum/optima35), providing an intuitive way to interact with the core functionalities. +It serves as a GUI for the [OPTIMA35 library](https://gitlab.com/CodeByMrFinchum/optima35), providing an intuitive way to interact with the core functionalities. --- ## **Current Status** -The program has reached a stable release. All functions have been tested, and there should be *no* bugs. -While there is always room for additional features and optimizations, the core functionality is complete and reliable. +### **Alpha Stage** + +OptimaLab35 is built using **PySide6** and **Qt**, offering a modern and flexible interface for **OPTIMA35**. + +The program is under **active development**, and while versions released on PyPI should not contain major bugs, occasional issues may arise. + +For the most accurate and detailed update information, please refer to the well-maintained [**CHANGELOG**](https://gitlab.com/CodeByMrFinchum/OptimaLab35/-/blob/main/CHANGELOG.md), as this README may occasionally lag behind the latest updates. --- @@ -23,8 +28,8 @@ While there is always room for additional features and optimizations, the core f - Adjust brightness and contrast - Add customizable text-based watermarks -### **Image Preview** -- Load a single image and see how changes in brightness and contrast affect the image +### **Image preview** +- Load a single image and see how change in brightness and contrast changes the image ### **EXIF Management** - Add EXIF data using a simple dictionary @@ -34,10 +39,6 @@ While there is always room for additional features and optimizations, the core f - Automatically adjust EXIF timestamps based on image file names - Add GPS coordinates to images -### **Settings** -- Option to use `PyQtDarkTheme` and select Dark, Light, or auto theme -- Checks for updates on PyPI, automatically downloads and installs the latest version - --- ## **Installation** @@ -49,45 +50,31 @@ pip install OptimaLab35 --- -## GUI Preview -The layout remains consistent with v1.0.0. -The UI is OS-dependent, but a custom theme can be enabled in the settings. +## Preview GUI +**PREVIEW** might be out of date. **Main tab** -![main](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35/raw/branch/main/media/mainwindow_light.png){width=40%} -![main](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35/raw/branch/main/media/mainwindow_dark.png){width=40%} - -**Exif tab** - -![main](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35/raw/branch/main/media/mainwindow_exif_light.png){width=40%} -![main](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35/raw/branch/main/media/mainwindow_exif_dark.png){width=40%} +![main](https://gitlab.com/CodeByMrFinchum/OptimaLab35/-/raw/main/media/main_tab.png){width=40%} **Preview window** -![main](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35/raw/branch/main/media/previewwindow_light.png){width=40%} -![main](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35/raw/branch/main/media/previewwindow_dark.png){width=40%} +![main](https://gitlab.com/CodeByMrFinchum/OptimaLab35/-/raw/main/media/preview_window.png){width=40%} -**Settings** +**Exif tab** -![main](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35/raw/branch/main/media/settingswindow_light.png){width=40%} -![main](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35/raw/branch/main/media/settingswindow_dark.png){width=40%} +![main](https://gitlab.com/CodeByMrFinchum/OptimaLab35/-/raw/main/media/exif_tab.png){width=40%} -**Updater** +**Exif editor** -![main](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35/raw/branch/main/media/settingswindow_updater_light.png){width=40%} -![main](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35/raw/branch/main/media/settingswindow_updater_dark.png){width=40%} +![main](https://gitlab.com/CodeByMrFinchum/OptimaLab35/-/raw/main/media/exif_editor.png){width=40%} --- -# Contribution - -Thanks to developer [Mr Finch](https://gitlab.com/MrFinchMkV) for contributing to this project. - -## Use of LLMs +# Use of LLMs In the interest of transparency, I disclose that Generative AI (GAI) large language models (LLMs), including OpenAI’s ChatGPT and Ollama models (e.g., OpenCoder and Qwen2.5-coder), have been used to assist in this project. -### Areas of Assistance: +## Areas of Assistance: - Project discussions and planning - Spelling and grammar corrections - Suggestions for suitable packages and libraries @@ -99,7 +86,7 @@ In cases where LLMs contribute directly to code or provide substantial optimizat - mradermacher gguf Q4K-M Instruct version of infly/OpenCoder-1.5B - unsloth gguf Q4K_M Instruct version of both Qwen/QWEN2 1.5B and 3B -#### References +### References 1. **Huang, Siming, et al.** *OpenCoder: The Open Cookbook for Top-Tier Code Large Language Models.* 2024. [PDF](https://arxiv.org/pdf/2411.04905) diff --git a/media/demo_v041.gif b/media/demo_v041.gif new file mode 100644 index 0000000..d5398b2 Binary files /dev/null and b/media/demo_v041.gif differ diff --git a/media/exif_editor.png b/media/exif_editor.png new file mode 100644 index 0000000..81fa4b0 Binary files /dev/null and b/media/exif_editor.png differ diff --git a/media/exif_tab.png b/media/exif_tab.png new file mode 100644 index 0000000..723c814 Binary files /dev/null and b/media/exif_tab.png differ diff --git a/media/info_window.png b/media/info_window.png new file mode 100644 index 0000000..dea48ac Binary files /dev/null and b/media/info_window.png differ diff --git a/media/main_tab.png b/media/main_tab.png new file mode 100644 index 0000000..3c0ebf6 Binary files /dev/null and b/media/main_tab.png differ diff --git a/media/mainwindow_dark.png b/media/mainwindow_dark.png deleted file mode 100644 index 8ccda0d..0000000 Binary files a/media/mainwindow_dark.png and /dev/null differ diff --git a/media/mainwindow_exif_dark.png b/media/mainwindow_exif_dark.png deleted file mode 100644 index f759fe2..0000000 Binary files a/media/mainwindow_exif_dark.png and /dev/null differ diff --git a/media/mainwindow_exif_light.png b/media/mainwindow_exif_light.png deleted file mode 100644 index 2b3f1ab..0000000 Binary files a/media/mainwindow_exif_light.png and /dev/null differ diff --git a/media/mainwindow_light.png b/media/mainwindow_light.png deleted file mode 100644 index 197874b..0000000 Binary files a/media/mainwindow_light.png and /dev/null differ diff --git a/media/preview_window.png b/media/preview_window.png new file mode 100644 index 0000000..2057ce4 Binary files /dev/null and b/media/preview_window.png differ diff --git a/media/previewwindow_dark.png b/media/previewwindow_dark.png deleted file mode 100644 index 618340c..0000000 Binary files a/media/previewwindow_dark.png and /dev/null differ diff --git a/media/previewwindow_light.png b/media/previewwindow_light.png deleted file mode 100644 index aaf3d4d..0000000 Binary files a/media/previewwindow_light.png and /dev/null differ diff --git a/media/settingswindow_dark.png b/media/settingswindow_dark.png deleted file mode 100644 index 9c791b8..0000000 Binary files a/media/settingswindow_dark.png and /dev/null differ diff --git a/media/settingswindow_light.png b/media/settingswindow_light.png deleted file mode 100644 index 67f5fb0..0000000 Binary files a/media/settingswindow_light.png and /dev/null differ diff --git a/media/settingswindow_updater_dark.png b/media/settingswindow_updater_dark.png deleted file mode 100644 index fbe003c..0000000 Binary files a/media/settingswindow_updater_dark.png and /dev/null differ diff --git a/media/settingswindow_updater_light.png b/media/settingswindow_updater_light.png deleted file mode 100644 index 6a3e124..0000000 Binary files a/media/settingswindow_updater_light.png and /dev/null differ diff --git a/pip_README.md b/pip_README.md index 576c8bf..f36b255 100644 --- a/pip_README.md +++ b/pip_README.md @@ -1,11 +1,4 @@ -**[OptimaLab35](https://code.boxyfoxy.net/CodeByMrFinchum/OptimaLab35)** is a graphical interface for the [optima35 library](https://code.boxyfoxy.net/CodeByMrFinchum/optima35), designed for efficient image and metadata management. +OptimaLab35 is in active development, and even *stable* versions may produce errors in unexpected situations. It is a GUI for optima35. +Please visit [OptimaLab35](https://gitlab.com/CodeByMrFinchum/OptimaLab35/-/blob/main/media/exif_editor.png?ref_type=heads) gitlab page for more information. -Developed on my [forgejo instance](https://code.boxyfoxy.net/CodeByMrFinchum), [GitLab](https://gitlab.com/CodeByMrFinchum) is used as backup. - -### **Features** -- Resize, adjust brightness/contrast, and convert images to grayscale -- Add customizable text-based watermarks -- Manage EXIF data: add, copy, remove, and adjust timestamps -- Preview image adjustments in real time -- Theme selection (light, dark, auto) -- Automatic updates via PyPI +Uses [optima35](https://gitlab.com/CodeByMrFinchum/optima35) to modify images. diff --git a/flatpak/pyproject.toml b/pyproject.toml similarity index 79% rename from flatpak/pyproject.toml rename to pyproject.toml index 4e3097a..b9e2577 100644 --- a/flatpak/pyproject.toml +++ b/pyproject.toml @@ -7,8 +7,9 @@ name = "OptimaLab35" dynamic = ["version"] authors = [{ name = "Mr Finchum" }] description = "User interface for optima35." +readme = "pip_README.md" requires-python = ">=3.8" -dependencies = ["optima35>=1.0.0, <2.0.0", "PyYAML", "PyPyUpdater"] +dependencies = ["optima35>=1.0.0, <2.0.0", "pyside6", "PyYAML"] classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)", @@ -22,7 +23,7 @@ Source = "https://gitlab.com/CodeByMrFinchum/OptimaLab35" OptimaLab35 = "OptimaLab35.__main__:main" [tool.hatch.build.targets.wheel] -packages = ["OptimaLab35"] +packages = ["src/OptimaLab35"] [tool.hatch.version] -path = "OptimaLab35/__init__.py" +path = "src/OptimaLab35/__init__.py" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index b5901cc..0000000 --- a/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -optima35 -PyPiUpdater -pyside6 -PyYAML diff --git a/src/OptimaLab35/__main__.py b/src/OptimaLab35/__main__.py index 512c7b3..557cfbf 100644 --- a/src/OptimaLab35/__main__.py +++ b/src/OptimaLab35/__main__.py @@ -1,30 +1,7 @@ -import sys -from PySide6 import QtWidgets -from .utils.utility import Utilities -from .mainWindow import OptimaLab35 -from .const import ( - CONFIG_BASE_PATH -) +from OptimaLab35 import gui, __version__ def main(): - u = Utilities(CONFIG_BASE_PATH) - app_settings = u.load_settings() - app = QtWidgets.QApplication(sys.argv) - - try: - import qdarktheme - app_settings["theme"]["theme_pkg"] = True - except ImportError: - app_settings["theme"]["theme_pkg"] = False - - if app_settings["theme"]["use_custom_theme"] and app_settings["theme"]["theme_pkg"]: - qdarktheme.setup_theme(app_settings["theme"]["mode"].lower()) - - u.save_settings(app_settings) - - window = OptimaLab35() - window.show() - app.exec() + gui.main() if __name__ == "__main__": main() diff --git a/src/OptimaLab35/const.py b/src/OptimaLab35/const.py deleted file mode 100644 index 2dcfd9c..0000000 --- a/src/OptimaLab35/const.py +++ /dev/null @@ -1,2 +0,0 @@ -APPLICATION_NAME = "OptimaLab35" -CONFIG_BASE_PATH = "~/.config/OptimaLab35" diff --git a/src/OptimaLab35/mainWindow.py b/src/OptimaLab35/gui.py similarity index 78% rename from src/OptimaLab35/mainWindow.py rename to src/OptimaLab35/gui.py index c299689..1194845 100644 --- a/src/OptimaLab35/mainWindow.py +++ b/src/OptimaLab35/gui.py @@ -1,67 +1,59 @@ +import sys import os from datetime import datetime + from optima35.core import OptimaManager - +from OptimaLab35.utils.utility import Utilities +from OptimaLab35.ui.main_window import Ui_MainWindow +from OptimaLab35.ui.preview_window import Ui_Preview_Window +from OptimaLab35.ui.exif_handler_window import ExifEditor +from OptimaLab35.ui.simple_dialog import SimpleDialog # Import the SimpleDialog class from OptimaLab35 import __version__ -from .const import ( - APPLICATION_NAME, - CONFIG_BASE_PATH -) -from .ui import resources_rc -from .previewWindow import PreviewWindow -from .settingsWindow import SettingsWindow - -from .utils.utility import Utilities -from .ui.main_window import Ui_MainWindow -from .ui.exif_handler_window import ExifEditor -from .ui.simple_dialog import SimpleDialog # Import the SimpleDialog class - -from PySide6 import QtWidgets, QtCore - -from PySide6.QtCore import ( - QRunnable, - QThreadPool, - Signal, - QObject, - QRegularExpression, - Qt, - QDate -) +from PySide6.QtCore import QRunnable, QThreadPool, Signal, QObject, QRegularExpression, Qt +from PySide6 import QtWidgets from PySide6.QtWidgets import ( QMessageBox, QApplication, QMainWindow, - QFileDialog + QWidget, + QVBoxLayout, + QLabel, + QLineEdit, + QPushButton, + QCheckBox, + QFileDialog, + QHBoxLayout, + QSpinBox, + QProgressBar, ) -from PySide6.QtGui import QRegularExpressionValidator, QIcon +from PySide6.QtGui import QPixmap, QRegularExpressionValidator class OptimaLab35(QMainWindow, Ui_MainWindow): def __init__(self): super(OptimaLab35, self).__init__() - self.name = APPLICATION_NAME + self.name = "OptimaLab35" self.version = __version__ self.o = OptimaManager() - self.u = Utilities(os.path.expanduser(CONFIG_BASE_PATH)) - self.app_settings = self.u.load_settings() + self.u = Utilities() + self.u.program_configs() self.thread_pool = QThreadPool() # multi thread ChatGPT # Initiate internal object - self.exif_file = os.path.expanduser(f"{CONFIG_BASE_PATH}/exif.yaml") + self.exif_file = os.path.expanduser("~/.config/OptimaLab35/exif.yaml") self.available_exif_data = None self.settings = {} # UI elements self.ui = Ui_MainWindow() self.ui.setupUi(self) self.sd = SimpleDialog() - + self.preview_window = PreviewWindow() # Change UI elements - self.change_statusbar(f"{self.name} v{self.version}", 10000) - self.set_title() + self.change_statusbar(f"Using {self.o.name} v{self.o.version}", 5000) + self.setWindowTitle(f"{self.name} v{self.version}") self.default_ui_layout() self.define_gui_interaction() - self.setWindowIcon(QIcon(":app-icon.png")) # Init function def default_ui_layout(self): @@ -69,13 +61,6 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): self.ui.png_quality_Slider.setVisible(False) self.ui.quality_label_2.setVisible(False) - def set_title(self): - if self.version == "0.0.1": - title = f"{self.name} DEV MODE" - else: - title = self.name - self.setWindowTitle(title) - def define_gui_interaction(self): self.ui.input_folder_button.clicked.connect(self.browse_input_folder) self.ui.output_folder_button.clicked.connect(self.browse_output_folder) @@ -91,23 +76,19 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): self.ui.actionAbout.triggered.connect(self.info_window) self.ui.preview_Button.clicked.connect(self.open_preview_window) - self.ui.actionSettings.triggered.connect(self.open_updater_window) regex = QRegularExpression(r"^\d{1,2}\.\d{1,6}$") validator = QRegularExpressionValidator(regex) self.ui.lat_lineEdit.setValidator(validator) self.ui.long_lineEdit.setValidator(validator) - self.ui.dateEdit.setDate(QDate.currentDate()) + #layout.addWidget(self.ui.lat_lineEdit) + #layout.addWidget(self.ui.long_lineEdit) + # UI related function, changing parts, open, etc. def open_preview_window(self): - self.preview_window = PreviewWindow() self.preview_window.values_selected.connect(self.update_values) self.preview_window.showMaximized() - def open_updater_window(self): - self.updater_window = SettingsWindow(self.version, self.o.version) - self.updater_window.show() - def update_values(self, value1, value2, checkbox_state): # Update main window's widgets with the received values # ChatGPT @@ -119,7 +100,7 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): info_text = f"""

{self.name} v{self.version}

(C) 2024-2025 Mr Finchum aka CodeByMrFinchum

-

{self.name} is a GUI for {self.o.name} (v{self.o.version}), enhancing its functionality with a user-friendly interface for efficient image and metadata management.

+

{self.name} is a GUI for {self.o.name} (v{self.o.version}), enhancing its functionality with a\nuser-friendly interface for efficient image and metadata management.

Features: