-
-
Notifications
You must be signed in to change notification settings - Fork 465
feat(ui): expanded thumbnail and preview features #390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 48 commits
34f347b
3c27b37
7ce3519
6b892ce
ff17b93
c1cd96f
3144440
d339f86
dc135f7
10d81b3
087176e
cee4254
127fed7
32257f6
3e00a77
1529714
d2b5e31
05a4860
c582f3d
c0e56dc
598aa4f
ffdfd6c
3bfeb3c
086fc1e
ef8cc6c
ad53f10
91ee242
196c1ba
3932414
c6a5202
ad12d64
8d2e67d
6883f9e
447b5e6
c070f84
a244098
f91861d
e4f7055
387baae
81dfb50
a658fc4
ccf3d78
148f792
9f688cd
c377b9d
12d69ba
5c4a3c5
a037a3b
2796db6
dd90add
ad0f472
2faed27
69e1b20
992aa82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,6 +55,5 @@ | |
| "cool gray", | ||
| "olive", | ||
| ] | ||
|
|
||
| TAG_FAVORITE = 1 | ||
| TAG_ARCHIVED = 0 | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,7 +13,7 @@ class ColorType(int, Enum): | |||||||||||||||||
| DARK_ACCENT = 4 | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| _TAG_COLORS = { | ||||||||||||||||||
| _TAG_COLORS: dict = { | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are other dict like mapping structures that might be more suitable. like defaultdict. This can solve the keyerror solution from
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Custom user-defined tag colors is also a feature I've been wanting to add in the near future (post-#332) that would see this getting shaken up once more. Still, it's good to be aware of |
||||||||||||||||||
| "": { | ||||||||||||||||||
| ColorType.PRIMARY: "#1e1e1e", | ||||||||||||||||||
| ColorType.TEXT: ColorType.LIGHT_ACCENT, | ||||||||||||||||||
|
|
@@ -277,6 +277,45 @@ class ColorType(int, Enum): | |||||||||||||||||
| }, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| _UI_COLORS: dict = { | ||||||||||||||||||
| "": { | ||||||||||||||||||
| ColorType.PRIMARY: "#333333", | ||||||||||||||||||
| ColorType.BORDER: "#555555", | ||||||||||||||||||
| ColorType.LIGHT_ACCENT: "#FFFFFF", | ||||||||||||||||||
| ColorType.DARK_ACCENT: "#1e1e1e", | ||||||||||||||||||
| }, | ||||||||||||||||||
| "green": { | ||||||||||||||||||
| ColorType.PRIMARY: "#28bb48", | ||||||||||||||||||
| ColorType.BORDER: "#43c568", | ||||||||||||||||||
| ColorType.LIGHT_ACCENT: "#DDFFCC", | ||||||||||||||||||
| ColorType.DARK_ACCENT: "#0d3828", | ||||||||||||||||||
| }, | ||||||||||||||||||
| "purple": { | ||||||||||||||||||
| ColorType.PRIMARY: "#C76FF3", | ||||||||||||||||||
| ColorType.BORDER: "#c364f2", | ||||||||||||||||||
| ColorType.LIGHT_ACCENT: "#EFD4FB", | ||||||||||||||||||
| ColorType.DARK_ACCENT: "#3E1555", | ||||||||||||||||||
| }, | ||||||||||||||||||
| "red": { | ||||||||||||||||||
| ColorType.PRIMARY: "#e22c3c", | ||||||||||||||||||
| ColorType.BORDER: "#e54252", | ||||||||||||||||||
| ColorType.LIGHT_ACCENT: "#f39caa", | ||||||||||||||||||
| ColorType.DARK_ACCENT: "#440d12", | ||||||||||||||||||
| }, | ||||||||||||||||||
| "theme_dark": { | ||||||||||||||||||
| ColorType.PRIMARY: "#333333", | ||||||||||||||||||
| ColorType.BORDER: "#555555", | ||||||||||||||||||
| ColorType.LIGHT_ACCENT: "#FFFFFF", | ||||||||||||||||||
| ColorType.DARK_ACCENT: "#1e1e1e", | ||||||||||||||||||
| }, | ||||||||||||||||||
| "theme_light": { | ||||||||||||||||||
| ColorType.PRIMARY: "#FFFFFF", | ||||||||||||||||||
| ColorType.BORDER: "#333333", | ||||||||||||||||||
| ColorType.LIGHT_ACCENT: "#999999", | ||||||||||||||||||
| ColorType.DARK_ACCENT: "#888888", | ||||||||||||||||||
| }, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| def get_tag_color(type, color): | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I try not to PEP-8 people, but don't overwrite builtins, it never leads to a good place.
Suggested change
|
||||||||||||||||||
| color = color.lower() | ||||||||||||||||||
|
|
@@ -287,3 +326,9 @@ def get_tag_color(type, color): | |||||||||||||||||
| return _TAG_COLORS[color][type] | ||||||||||||||||||
| except KeyError: | ||||||||||||||||||
| return "#FF00FF" | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| def get_ui_color(type: ColorType, color: str): | ||||||||||||||||||
| """Returns a hex value given a color name and ColorType.""" | ||||||||||||||||||
| color = color.lower() | ||||||||||||||||||
| return _UI_COLORS.get(color).get(type) | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I try not to PEP-8 people, but don't overwrite builtins, it never leads to a good place.
Suggested change
|
||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # Copyright (C) 2024 Travis Abendshien (CyanVoxel). | ||
| # Licensed under the GPL-3.0 License. | ||
| # Created for TagStudio: https://github.com/CyanVoxel/TagStudio | ||
|
|
||
|
|
||
| import ffmpeg | ||
| from pathlib import Path | ||
|
|
||
|
|
||
| def is_readable_video(filepath: Path | str): | ||
| """Test if a video is in a readable format. Examples of unreadable videos | ||
| include files with undetermined codecs and DRM-protected content. | ||
|
|
||
| Args: | ||
| filepath (Path | str): | ||
| """ | ||
| try: | ||
| probe = ffmpeg.probe(Path(filepath)) | ||
| for stream in probe["streams"]: | ||
| # DRM check | ||
| if stream.get("codec_tag_string") in [ | ||
| "drma", | ||
| "drms", | ||
| "drmi", | ||
| ]: | ||
| return False | ||
| except ffmpeg.Error: | ||
| return False | ||
|
Comment on lines
+27
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this an exception that is also raised if ffmpeg is not installed on the system? or otherwise not available via
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a great question - If so, it wasn't my intention to catch that with this method |
||
| return True | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,21 +2,21 @@ | |
| # Licensed under the GPL-3.0 License. | ||
| # Created for TagStudio: https://github.com/CyanVoxel/TagStudio | ||
|
|
||
| from PIL import Image, ImageEnhance, ImageChops | ||
| from PIL import Image | ||
|
|
||
|
|
||
| def four_corner_gradient_background( | ||
| image: Image.Image, adj_size, mask, hl | ||
| def four_corner_gradient( | ||
| image: Image.Image, size: tuple[int, int], mask: Image.Image | ||
| ) -> Image.Image: | ||
| if image.size != (adj_size, adj_size): | ||
| if image.size != size: | ||
| # Old 1 color method. | ||
| # bg_col = image.copy().resize((1, 1)).getpixel((0,0)) | ||
| # bg = Image.new(mode='RGB',size=(adj_size,adj_size),color=bg_col) | ||
| # bg = Image.new(mode='RGB',size=size,color=bg_col) | ||
| # bg.thumbnail((1, 1)) | ||
| # bg = bg.resize((adj_size,adj_size), resample=Image.Resampling.NEAREST) | ||
| # bg = bg.resize(size, resample=Image.Resampling.NEAREST) | ||
|
|
||
| # Small gradient background. Looks decent, and is only a one-liner. | ||
| # bg = image.copy().resize((2, 2), resample=Image.Resampling.BILINEAR).resize((adj_size,adj_size),resample=Image.Resampling.BILINEAR) | ||
| # bg = image.copy().resize((2, 2), resample=Image.Resampling.BILINEAR).resize(size,resample=Image.Resampling.BILINEAR) | ||
|
|
||
| # Four-Corner Gradient Background. | ||
| # Not exactly a one-liner, but it's (subjectively) really cool. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are these lines commented out when there are code changes being made to them?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might've gotten caught in a find-and-replace |
||
|
|
@@ -29,26 +29,31 @@ def four_corner_gradient_background( | |
| bg.paste(tr, (1, 0, 2, 2)) | ||
| bg.paste(bl, (0, 1, 2, 2)) | ||
| bg.paste(br, (1, 1, 2, 2)) | ||
| bg = bg.resize((adj_size, adj_size), resample=Image.Resampling.BICUBIC) | ||
|
|
||
| bg = bg.resize(size, resample=Image.Resampling.BICUBIC) | ||
| bg.paste( | ||
| image, | ||
| box=( | ||
| (adj_size - image.size[0]) // 2, | ||
| (adj_size - image.size[1]) // 2, | ||
| (size[0] - image.size[0]) // 2, | ||
| (size[1] - image.size[1]) // 2, | ||
| ), | ||
| ) | ||
|
|
||
| bg.putalpha(mask) | ||
| final = bg | ||
| final = Image.new("RGBA", bg.size, (0, 0, 0, 0)) | ||
| final.paste(bg, mask=mask.getchannel(0)) | ||
|
|
||
| # bg.putalpha(mask) | ||
| # final = bg | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can these be removed? |
||
|
|
||
| else: | ||
| image.putalpha(mask) | ||
| final = image | ||
| # image.putalpha(mask) | ||
| # final = image | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can these be removed? |
||
|
|
||
| final = Image.new("RGBA", size, (0, 0, 0, 0)) | ||
| final.paste(image, mask=mask.getchannel(0)) | ||
|
|
||
| if final.mode != "RGBA": | ||
| final = final.convert("RGBA") | ||
|
|
||
| hl_soft = hl.copy() | ||
| hl_soft.putalpha(ImageEnhance.Brightness(hl.getchannel(3)).enhance(0.5)) | ||
| final.paste(ImageChops.soft_light(final, hl_soft), mask=hl_soft.getchannel(3)) | ||
| return final | ||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # Based on the implementation by eyllanesc: | ||
| # https://stackoverflow.com/questions/54230005/qmovie-with-border-radius | ||
| # Licensed under the Creative Commons CC BY-SA 4.0 License: | ||
| # https://creativecommons.org/licenses/by-sa/4.0/ | ||
| # Modified for TagStudio: https://github.com/CyanVoxel/TagStudio | ||
|
|
||
| from PySide6.QtGui import QPixmap, QPainter, QBrush | ||
| from PySide6.QtWidgets import ( | ||
| QProxyStyle, | ||
| ) | ||
|
|
||
|
|
||
| class RoundedPixmapStyle(QProxyStyle): | ||
| def __init__(self, radius=8): | ||
| super().__init__() | ||
| self._radius = radius | ||
|
|
||
| def drawItemPixmap(self, painter, rectangle, alignment, pixmap): | ||
| painter.save() | ||
| pix = QPixmap(pixmap.size()) | ||
| pix.fill("#00000000") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. woulndt it be better to use something like |
||
| p = QPainter(pix) | ||
| p.setBrush(QBrush(pixmap)) | ||
| p.setPen("#00000000") | ||
| p.setRenderHint(QPainter.RenderHint.Antialiasing) | ||
| p.drawRoundedRect(pixmap.rect(), self._radius, self._radius) | ||
| p.end() | ||
| super(RoundedPixmapStyle, self).drawItemPixmap( | ||
| painter, rectangle, alignment, pix | ||
| ) | ||
| painter.restore() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see no update to the README to tell the user to install ffmpeg.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can confirm, video thumbnails/previews do not work without ffmpeg installed. (Fails to find ffprobe). Could this be something looked into being bundled into pyinstaller? Ffmpeg will be an incredibly useful tool for the future (could probably look into dropping opencv potentially)