Merge branch 'main' into test-support-2

This commit is contained in:
Vele George
2024-05-11 21:30:15 +03:00
committed by GitHub
15 changed files with 252 additions and 426 deletions

1
.gitignore vendored
View File

@@ -250,5 +250,4 @@ compile_commands.json
# TagStudio
.TagStudio
TagStudio.ini
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,python,qt

69
Build_MacOS_app.sh Executable file
View File

@@ -0,0 +1,69 @@
#! /usr/bin/env bash
# GETTING BASE DIR
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# SETTING UP CONSTANTS
TAGSTUDIO_NAME="TagStudio"
TAGSTUDIO_DIR="$SCRIPT_DIR/tagstudio"
TAGSTUDIO_DIR_RESOURCES="$TAGSTUDIO_DIR/resources"
TAGSTUDIO_ICON="$TAGSTUDIO_DIR/resources/icon.ico"
TAGSTUDIO_SRC="$TAGSTUDIO_DIR/src"
TAGSTUDIO_MAIN="$TAGSTUDIO_DIR/tag_studio.py"
DIST_PATH="$SCRIPT_DIR/dist"
BUILD_PATH="$SCRIPT_DIR/build"
LOGS_PATH="$BUILD_PATH/logs"
printf -- "🏁 Starting Script \n"
# CREATE VENV AND INSTALL REQUIREMENTS
printf -- "🐍 Creating Python virtual env\n"
python3 -m venv .venv
source .venv/bin/activate
if [ ! -d $LOGS_PATH ]; then
printf -- "📁 Creating Logs folder\n"
mkdir -p $LOGS_PATH;
fi
printf -- "💻 Installing Requirements \n"
pip install -r requirements.txt > "$LOGS_PATH/pip.log" 2>&1
pip install PyInstaller > "$LOGS_PATH/pip.log" 2>&1
if [[ "$OSTYPE" == "darwin"* ]]; then
printf -- "🍏 MacOS Detected \n"
SYS_CMD="--windowed"
OS=0
fi
SECONDS=0
# CREATE COMMAND
printf -- "⏳ Building App \n"
COMMAND=$( python -m PyInstaller \
--name "$TAGSTUDIO_NAME" \
--icon "$TAGSTUDIO_ICON" \
--add-data "$TAGSTUDIO_DIR_RESOURCES:./resources" \
--add-data "$TAGSTUDIO_SRC:./src" \
--distpath "$DIST_PATH" \
-p "$TAGSTUDIO_DIR" \
--noconsole \
--workpath "$BUILD_PATH" \
-y "$SYS_CMD" "$TAGSTUDIO_MAIN" \
> "$LOGS_PATH/pyinstaller.log" 2>&1 )
duration=$SECONDS
if $COMMAND; then
printf -- "✅ Build Successfull \n"
printf -- "$((duration)) seconds of build\n"
if [[ "$OS" == 0 ]]; then
printf -- "📁 Opening App folder \n"
open $DIST_PATH
fi
else
printf -- "❌ Error Building the app\nPlease read the logs\navailable at build/logs\n"
fi
printf -- "🏁 END OF TRANSMISSION"

31
Build_win.bat Normal file
View File

@@ -0,0 +1,31 @@
@echo off
set TAGSTUDIO_NAME=TagStudio
set TAGSTUDIO_DIR=tagstudio
set TAGSTUDIO_DIR_RESOURCES=%TAGSTUDIO_DIR%/resources
set TAGSTUDIO_ICON=%TAGSTUDIO_DIR%/resources/icon.ico
set TAGSTUDIO_SRC=%TAGSTUDIO_DIR%/src
set TAGSTUDIO_MAIN=%TAGSTUDIO_DIR%/tag_studio.py
set BUILD_MODE=--onedir
if "%1" == "--help" (
echo run "%~nx0" for normal Build
echo run "%~nx0 --portable" for Build packaged into one file
goto end
)
if "%1" == "--portable" (
echo Building portable executable...
set BUILD_MODE=--onefile
goto run
)
if not "%1" == "" (
echo Invalid argument run "%~nx0 --help" for help
goto end
)
:run
echo Building executable...
set COMMAND=PyInstaller --name "%TAGSTUDIO_NAME%" --icon "%TAGSTUDIO_ICON%" --add-data "%TAGSTUDIO_DIR_RESOURCES%:./resources" --add-data "%TAGSTUDIO_SRC%:./src" -p "%TAGSTUDIO_DIR%" --console %BUILD_MODE% "%TAGSTUDIO_MAIN%" -y
call .venv\Scripts\activate.bat
%COMMAND%
deactivate
:end

View File

@@ -7,3 +7,4 @@ PySide6_Addons>=6.5.1.1,<=6.6.3.1
PySide6_Essentials>=6.5.1.1,<=6.6.3.1
typing_extensions>=3.10.0.0,<=4.11.0
ujson>=5.8.0,<=5.9.0
Pyinstaller==6.6.0

View File

@@ -15,11 +15,11 @@ class ColorType(Enum):
_TAG_COLORS = {
"": {
ColorType.PRIMARY: "#1E1A33",
ColorType.PRIMARY: "#1e1e1e",
ColorType.TEXT: ColorType.LIGHT_ACCENT,
ColorType.BORDER: "#2B2547",
ColorType.LIGHT_ACCENT: "#CDA7F7",
ColorType.DARK_ACCENT: "#1E1A33",
ColorType.BORDER: "#333333",
ColorType.LIGHT_ACCENT: "#FFFFFF",
ColorType.DARK_ACCENT: "#222222",
},
"black": {
ColorType.PRIMARY: "#111018",

View File

@@ -38,54 +38,29 @@ class Ui_MainWindow(QMainWindow):
# # self.setStyleSheet(
# # 'background:#EE000000;'
# # )
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
MainWindow.resize(1300, 720)
# self._createMenuBar(MainWindow)
# print(type(MainWindow))
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.gridLayout = QGridLayout(self.centralwidget)
self.gridLayout.setObjectName(u"gridLayout")
# self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
# tb = StandardTitleBar(MainWindow)
# tb.setObjectName('TitleBar')
# # # self.setTitleBar(tb)
# hor = QVBoxLayout()
# self.gridLayout.setContentsMargins(0,0,0,0)
# self.gridLayout.addLayout(hor, 0, 0, 1, 1)
# hor.addWidget(tb)
self.splitter = QSplitter()
self.splitter.setObjectName(u"splitter")
self.splitter.setHandleWidth(12)
self.frame_container = QWidget()
# self.frame_container.setStyleSheet('background:red;')
self.frame_layout = QVBoxLayout(self.frame_container)
# self.frame_container.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum)
self.frame_layout.setSpacing(0)
self.scrollArea = QScrollArea()
# self.scrollArea.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
# self.scrollArea.setStyleSheet('background:green;')
self.scrollArea.setObjectName(u"scrollArea")
self.scrollArea.setFocusPolicy(Qt.WheelFocus)
self.scrollArea.setFrameShape(QFrame.NoFrame)
@@ -102,12 +77,6 @@ class Ui_MainWindow(QMainWindow):
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.frame_layout.addWidget(self.scrollArea)
self.scrollArea.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground)
# self.scrollArea.setWindowFlag(Qt.WindowType.FramelessWindowHint)
self.scrollArea.setAttribute(
Qt.WidgetAttribute.WA_TranslucentBackground)
self.scrollArea.setStyleSheet('background:#00000000;')
# self.page_bar_controls = QWidget()
# self.page_bar_controls.setStyleSheet('background:blue;')
# self.page_bar_controls.setMinimumHeight(32)
@@ -118,7 +87,6 @@ class Ui_MainWindow(QMainWindow):
# self.frame_layout.addWidget(self.page_bar_controls)
# self.frame_layout.addWidget(self.page_bar_controls)
# self.horizontalLayout.addWidget(self.scrollArea)
self.horizontalLayout.addWidget(self.splitter)
self.splitter.addWidget(self.frame_container)
self.splitter.setStretchFactor(0, 1)
@@ -154,13 +122,6 @@ class Ui_MainWindow(QMainWindow):
self.searchField = QLineEdit(self.centralwidget)
self.searchField.setObjectName(u"searchField")
self.searchField.setMinimumSize(QSize(0, 32))
self.searchField.setStyleSheet(
'background:#55000000;'
'border-radius:6px;'
'border-style:solid;'
'border-width:1px;'
'border-color:#11FFFFFF;'
)
font2 = QFont()
font2.setPointSize(11)
font2.setBold(False)
@@ -174,7 +135,6 @@ class Ui_MainWindow(QMainWindow):
self.searchButton.setFont(font2)
self.horizontalLayout_2.addWidget(self.searchButton)
self.gridLayout.addLayout(self.horizontalLayout_2, 3, 0, 1, 1)
self.comboBox = QComboBox(self.centralwidget)
@@ -213,7 +173,6 @@ class Ui_MainWindow(QMainWindow):
self.frame_layout.addWidget(menu_bar)
self.retranslateUi(MainWindow)
# self.dumpObjectTree()
QMetaObject.connectSlotsByName(MainWindow)
# setupUi

View File

@@ -165,25 +165,26 @@ class FoldersToTagsModal(QWidget):
self.count = -1
self.filename = ""
self.setWindowTitle(f"Folders To Tags")
self.setWindowTitle(f"Create Tags From Folders")
self.setWindowModality(Qt.WindowModality.ApplicationModal)
self.setMinimumSize(500, 800)
self.setMinimumSize(640, 640)
self.root_layout = QVBoxLayout(self)
self.root_layout.setContentsMargins(6, 6, 6, 6)
self.title_widget = QLabel()
self.title_widget.setObjectName("title")
self.title_widget.setWordWrap(True)
self.title_widget.setStyleSheet(
"font-weight:bold;" "font-size:14px;" "padding-top: 6px"
)
self.title_widget.setText("Create Tags From Folders")
self.title_widget.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.desc_widget = QLabel()
self.desc_widget.setObjectName("descriptionLabel")
self.desc_widget.setWordWrap(True)
self.desc_widget.setStyleSheet(
# 'background:blue;'
"text-align:left;"
# 'font-weight:bold;'
"font-size:18px;"
# 'padding-top: 6px'
""
)
self.desc_widget.setText(
"""Creates tags based on the folder structure and applies them to entries.\n The Structure below shows all the tags that would be added and to which files they would be added. It being empty means that there are no Tag to be created or assigned"""
"""Creates tags based on your folder structure and applies them to your entries.\n The structure below shows all the tags that will be created and what entries they will be applied to."""
)
self.desc_widget.setAlignment(Qt.AlignmentFlag.AlignCenter)
@@ -216,14 +217,18 @@ class FoldersToTagsModal(QWidget):
self.apply_button = QPushButton()
self.apply_button.setText("&Apply")
self.apply_button.setMinimumWidth(100)
self.apply_button.clicked.connect(self.on_apply)
self.showEvent = self.on_open
self.root_layout.addWidget(self.title_widget)
self.root_layout.addWidget(self.desc_widget)
self.root_layout.addWidget(self.open_close_button_w)
self.root_layout.addWidget(self.scroll_area)
self.root_layout.addWidget(self.apply_button)
self.root_layout.addWidget(
self.apply_button, alignment=Qt.AlignmentFlag.AlignCenter
)
def on_apply(self, event):
folders_to_tags(self.library)

View File

@@ -133,6 +133,10 @@ class Pagination(QWidget, QObject):
# self.update_buttons(page_count=9, index=0)
def update_buttons(self, page_count: int, index: int, emit: bool = True):
# Guard
if index < 0:
raise ValueError("Negative index detected")
# Screw it
for i in range(0, 10):
if self.start_buffer_layout.itemAt(i):
@@ -140,6 +144,8 @@ class Pagination(QWidget, QObject):
if self.end_buffer_layout.itemAt(i):
self.end_buffer_layout.itemAt(i).widget().setHidden(True)
end_page = page_count - 1
if page_count <= 1:
# Hide everything if there are only one or less pages.
# [-------------- HIDDEN --------------]
@@ -172,7 +178,7 @@ class Pagination(QWidget, QObject):
# self.start_buffer_layout.setContentsMargins(3,0,3,0)
self._assign_click(self.prev_button, index - 1)
self.prev_button.setDisabled(False)
if index == page_count - 1:
if index == end_page:
self.next_button.setDisabled(True)
# self.end_buffer_layout.setContentsMargins(0,0,0,0)
else:
@@ -181,201 +187,22 @@ class Pagination(QWidget, QObject):
self.next_button.setDisabled(False)
# Set Ellipses Sizes
if page_count == 8:
if index == 0:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 2 + 3)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 2 + 3)
else:
self.end_ellipses.setMinimumWidth(self.button_size.width())
self.end_ellipses.setMaximumWidth(self.button_size.width())
if index == page_count - 1:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 2 + 3
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 2 + 3
)
else:
self.start_ellipses.setMinimumWidth(self.button_size.width())
self.start_ellipses.setMaximumWidth(self.button_size.width())
elif page_count == 9:
if index == 0:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 3 + 6)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 3 + 6)
elif index == 1:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 2 + 3)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 2 + 3)
else:
self.end_ellipses.setMinimumWidth(self.button_size.width())
self.end_ellipses.setMaximumWidth(self.button_size.width())
if index == page_count - 1:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 3 + 6
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 3 + 6
)
elif index == page_count - 2:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 2 + 3
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 2 + 3
)
else:
self.start_ellipses.setMinimumWidth(self.button_size.width())
self.start_ellipses.setMaximumWidth(self.button_size.width())
elif page_count == 10:
if index == 0:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 4 + 9)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 4 + 9)
elif index == 1:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 3 + 6)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 3 + 6)
elif index == 2:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 2 + 3)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 2 + 3)
else:
self.end_ellipses.setMinimumWidth(self.button_size.width())
self.end_ellipses.setMaximumWidth(self.button_size.width())
if index == page_count - 1:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 4 + 9
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 4 + 9
)
elif index == page_count - 2:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 3 + 6
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 3 + 6
)
elif index == page_count - 3:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 2 + 3
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 2 + 3
)
else:
self.start_ellipses.setMinimumWidth(self.button_size.width())
self.start_ellipses.setMaximumWidth(self.button_size.width())
elif page_count == 11:
if index == 0:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 5 + 12)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 5 + 12)
elif index == 1:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 4 + 9)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 4 + 9)
elif index == 2:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 3 + 6)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 3 + 6)
elif index == 3:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 2 + 3)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 2 + 3)
else:
self.end_ellipses.setMinimumWidth(self.button_size.width())
self.end_ellipses.setMaximumWidth(self.button_size.width())
if index == page_count - 1:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 5 + 12
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 5 + 12
)
elif index == page_count - 2:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 4 + 9
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 4 + 9
)
elif index == page_count - 3:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 3 + 6
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 3 + 6
)
elif index == page_count - 4:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 2 + 3
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 2 + 3
)
else:
self.start_ellipses.setMinimumWidth(self.button_size.width())
self.start_ellipses.setMaximumWidth(self.button_size.width())
# I do not know where these magic values were derived from, but
# this is better than the chain elif's that were here before
if 8 <= page_count <= 11:
end_scale = max(1, page_count - index - 6)
srt_scale = max(1, index - 5)
elif page_count > 11:
if index == 0:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 7 + 18)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 7 + 18)
elif index == 1:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 6 + 15)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 6 + 15)
elif index == 2:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 5 + 12)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 5 + 12)
elif index == 3:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 4 + 9)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 4 + 9)
elif index == 4:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 3 + 6)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 3 + 6)
elif index == 5:
self.end_ellipses.setMinimumWidth(self.button_size.width() * 2 + 3)
self.end_ellipses.setMaximumWidth(self.button_size.width() * 2 + 3)
else:
self.end_ellipses.setMinimumWidth(self.button_size.width())
self.end_ellipses.setMaximumWidth(self.button_size.width())
if index == page_count - 1:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 7 + 18
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 7 + 18
)
elif index == page_count - 2:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 6 + 15
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 6 + 15
)
elif index == page_count - 3:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 5 + 12
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 5 + 12
)
elif index == page_count - 4:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 4 + 9
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 4 + 9
)
elif index == page_count - 5:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 3 + 6
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 3 + 6
)
elif index == page_count - 6:
self.start_ellipses.setMinimumWidth(
self.button_size.width() * 2 + 3
)
self.start_ellipses.setMaximumWidth(
self.button_size.width() * 2 + 3
)
else:
self.start_ellipses.setMinimumWidth(self.button_size.width())
self.start_ellipses.setMaximumWidth(self.button_size.width())
end_scale = max(1, 7 - index)
srt_scale = max(1, (7 - (end_page - index)))
if page_count >= 8:
end_size = self.button_size.width() * end_scale + (3 * (end_scale - 1))
srt_size = self.button_size.width() * srt_scale + (3 * (srt_scale - 1))
self.end_ellipses.setMinimumWidth(end_size)
self.end_ellipses.setMaximumWidth(end_size)
self.start_ellipses.setMinimumWidth(srt_size)
self.start_ellipses.setMaximumWidth(srt_size)
# Enable/Disable Ellipses
# if index <= max(self.buffer_page_count, 5)+1:

View File

@@ -16901,17 +16901,10 @@ qt_resource_struct = b"\
\x00\x00\x01\x8a\xd2\x83?\x9d\
"
def qInitResources():
QtCore.qRegisterResourceData(
0x03, qt_resource_struct, qt_resource_name, qt_resource_data
)
QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources():
QtCore.qUnregisterResourceData(
0x03, qt_resource_struct, qt_resource_name, qt_resource_data
)
QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources()

View File

@@ -13,6 +13,7 @@ import math
import os
import sys
import time
import webbrowser
from datetime import datetime as dt
from pathlib import Path
from queue import Empty, Queue
@@ -132,19 +133,20 @@ class NavigationState:
class Consumer(QThread):
MARKER_QUIT = "MARKER_QUIT"
def __init__(self, queue) -> None:
self.queue = queue
QThread.__init__(self)
def run(self):
self.active = True
while self.active:
while True:
try:
job = self.queue.get(timeout=0.2)
# print('Running job...')
# logging.info(*job[1])
job = self.queue.get()
if job == self.MARKER_QUIT:
break
job[0](*job[1])
except (Empty, RuntimeError):
except RuntimeError:
pass
def set_page_count(self, count: int):
@@ -179,7 +181,7 @@ class QtDriver(QObject):
# self.title_text: str = self.base_title
# self.buffer = {}
self.thumb_job_queue: Queue = Queue()
self.thumb_threads = []
self.thumb_threads: list[Consumer] = []
self.thumb_cutoff: float = time.time()
# self.selected: list[tuple[int,int]] = [] # (Thumb Index, Page Index)
self.selected: list[tuple[ItemType, int]] = [] # (Item Type, Item ID)
@@ -264,8 +266,11 @@ class QtDriver(QObject):
self.splash.show()
menu_bar = self.main_window.menuBar()
menu_bar.setNativeMenuBar(False)
# menu_bar.setStyleSheet('background:#00000000;')
# Allow the use of the native macOS menu bar.
if sys.platform != "darwin":
menu_bar.setNativeMenuBar(False)
file_menu = QMenu("&File", menu_bar)
edit_menu = QMenu("&Edit", menu_bar)
tools_menu = QMenu("&Tools", menu_bar)
@@ -354,13 +359,13 @@ class QtDriver(QObject):
edit_menu.addSeparator()
manage_file_extensions_action = QAction("Ignore File Extensions", menu_bar)
manage_file_extensions_action = QAction("Ignored File Extensions", menu_bar)
manage_file_extensions_action.triggered.connect(
lambda: self.show_file_extension_modal()
)
edit_menu.addAction(manage_file_extensions_action)
tag_database_action = QAction("Tag Database", menu_bar)
tag_database_action = QAction("Manage Tags", menu_bar)
tag_database_action.triggered.connect(lambda: self.show_tag_database())
edit_menu.addAction(tag_database_action)
@@ -410,11 +415,18 @@ class QtDriver(QObject):
self.sort_fields_action.setToolTip("Alt+S")
macros_menu.addAction(self.sort_fields_action)
folders_to_tags_action = QAction("Folders to Tags", menu_bar)
folders_to_tags_action = QAction("Create Tags From Folders", menu_bar)
ftt_modal = FoldersToTagsModal(self.lib, self)
folders_to_tags_action.triggered.connect(lambda: ftt_modal.show())
macros_menu.addAction(folders_to_tags_action)
# Help Menu ==========================================================
self.repo_action = QAction("Visit GitHub Repository", menu_bar)
self.repo_action.triggered.connect(
lambda: webbrowser.open("https://github.com/TagStudioDev/TagStudio")
)
help_menu.addAction(self.repo_action)
self.set_macro_menu_viability()
menu_bar.addMenu(file_menu)
@@ -545,10 +557,14 @@ class QtDriver(QObject):
self.settings.setValue("last_library", self.lib.library_dir)
self.settings.sync()
logging.info("[SHUTDOWN] Ending Thumbnail Threads...")
for _ in self.thumb_threads:
self.thumb_job_queue.put(Consumer.MARKER_QUIT)
# wait for threads to quit
for thread in self.thumb_threads:
thread.active = False
thread.quit()
thread.wait()
QApplication.quit()
def save_library(self, show_status=True):
@@ -630,7 +646,7 @@ class QtDriver(QObject):
def show_tag_database(self):
self.modal = PanelModal(
TagDatabasePanel(self.lib), "Tag Database", "Tag Database", has_save=False
TagDatabasePanel(self.lib), "Library Tags", "Library Tags", has_save=False
)
self.modal.show()

View File

@@ -23,7 +23,8 @@ from PySide6.QtWidgets import (
QCheckBox,
)
from src.core.library import ItemType, Library
from src.core.library import ItemType, Library, Entry
from src.core.constants import AUDIO_TYPES, VIDEO_TYPES, IMAGE_TYPES
from src.qt.flowlayout import FlowWidget
from src.qt.helpers import FileOpenerHelper
@@ -32,11 +33,14 @@ from src.qt.widgets import ThumbRenderer, ThumbButton
if typing.TYPE_CHECKING:
from src.qt.widgets import PreviewPanel
ERROR = f"[ERROR]"
WARNING = f"[WARNING]"
INFO = f"[INFO]"
DEFAULT_META_TAG_FIELD = 8
TAG_FAVORITE = 1
TAG_ARCHIVED = 0
logging.basicConfig(format="%(message)s", level=logging.INFO)
@@ -62,7 +66,7 @@ class ItemThumb(FlowWidget):
tag_group_icon_128.load()
small_text_style = (
f"background-color:rgba(0, 0, 0, 128);"
f"background-color:rgba(0, 0, 0, 192);"
f"font-family:Oxanium;"
f"font-weight:bold;"
f"font-size:12px;"
@@ -74,7 +78,7 @@ class ItemThumb(FlowWidget):
)
med_text_style = (
f"background-color:rgba(17, 15, 27, 192);"
f"background-color:rgba(0, 0, 0, 192);"
f"font-family:Oxanium;"
f"font-weight:bold;"
f"font-size:18px;"
@@ -453,91 +457,40 @@ class ItemThumb(FlowWidget):
self.show_check_badges(False)
return super().leaveEvent(event)
def on_archived_check(self, value: bool):
# logging.info(f'Archived Check: {value}, Mode: {self.mode}')
def on_archived_check(self, toggle_value: bool):
if self.mode == ItemType.ENTRY:
self.isArchived = value
DEFAULT_META_TAG_FIELD = 8
temp = (ItemType.ENTRY, self.item_id)
if (
list(self.panel.driver.selected).count(temp) > 0
): # Is the archived badge apart of the selection?
# Yes, then add archived tag to all selected.
for x in self.panel.driver.selected:
e = self.lib.get_entry(x[1])
if value:
self.archived_badge.setHidden(False)
e.add_tag(
self.panel.driver.lib,
0,
field_id=DEFAULT_META_TAG_FIELD,
field_index=-1,
)
else:
e.remove_tag(self.panel.driver.lib, 0)
else:
# No, then add archived tag to the entry this badge is on.
e = self.lib.get_entry(self.item_id)
if value:
self.favorite_badge.setHidden(False)
e.add_tag(
self.panel.driver.lib,
0,
field_id=DEFAULT_META_TAG_FIELD,
field_index=-1,
)
else:
e.remove_tag(self.panel.driver.lib, 0)
if self.panel.isOpen:
self.panel.update_widgets()
self.panel.driver.update_badges()
self.isArchived = toggle_value
self.toggle_item_tag(toggle_value, TAG_ARCHIVED)
# def on_archived_uncheck(self):
# if self.mode == SearchItemType.ENTRY:
# self.isArchived = False
# e = self.lib.get_entry(self.item_id)
def on_favorite_check(self, value: bool):
# logging.info(f'Favorite Check: {value}, Mode: {self.mode}')
def on_favorite_check(self, toggle_value: bool):
if self.mode == ItemType.ENTRY:
self.isFavorite = value
DEFAULT_META_TAG_FIELD = 8
temp = (ItemType.ENTRY, self.item_id)
if (
list(self.panel.driver.selected).count(temp) > 0
): # Is the favorite badge apart of the selection?
# Yes, then add favorite tag to all selected.
for x in self.panel.driver.selected:
e = self.lib.get_entry(x[1])
if value:
self.favorite_badge.setHidden(False)
e.add_tag(
self.panel.driver.lib,
1,
field_id=DEFAULT_META_TAG_FIELD,
field_index=-1,
)
else:
e.remove_tag(self.panel.driver.lib, 1)
else:
# No, then add favorite tag to the entry this badge is on.
e = self.lib.get_entry(self.item_id)
if value:
self.favorite_badge.setHidden(False)
e.add_tag(
self.panel.driver.lib,
1,
field_id=DEFAULT_META_TAG_FIELD,
field_index=-1,
)
else:
e.remove_tag(self.panel.driver.lib, 1)
if self.panel.isOpen:
self.panel.update_widgets()
self.panel.driver.update_badges()
self.isFavorite = toggle_value
self.toggle_item_tag(toggle_value, TAG_FAVORITE)
# def on_favorite_uncheck(self):
# if self.mode == SearchItemType.ENTRY:
# self.isFavorite = False
# e = self.lib.get_entry(self.item_id)
# e.remove_tag(1)
def toggle_item_tag(self, toggle_value: bool, tag_id: int):
def toggle_tag(entry: Entry):
if toggle_value:
self.favorite_badge.setHidden(False)
entry.add_tag(
self.panel.driver.lib,
tag_id,
field_id=DEFAULT_META_TAG_FIELD,
field_index=-1,
)
else:
entry.remove_tag(self.panel.driver.lib, tag_id)
# Is the badge a part of the selection?
if (ItemType.ENTRY, self.item_id) in self.panel.driver.selected:
# Yes, add chosen tag to all selected.
for _, item_id in self.panel.driver.selected:
entry = self.lib.get_entry(item_id)
toggle_tag(entry)
else:
# No, add tag to the entry this badge is on.
entry = self.lib.get_entry(self.item_id)
toggle_tag(entry)
if self.panel.isOpen:
self.panel.update_widgets()
self.panel.driver.update_badges()

View File

@@ -38,9 +38,7 @@ class PanelModal(QWidget):
self.title_widget.setObjectName("fieldTitle")
self.title_widget.setWordWrap(True)
self.title_widget.setStyleSheet(
# 'background:blue;'
# 'text-align:center;'
"font-weight:bold;" "font-size:14px;" "padding-top: 6px" ""
"font-weight:bold;" "font-size:14px;" "padding-top: 6px"
)
self.title_widget.setText(title)
self.title_widget.setAlignment(Qt.AlignmentFlag.AlignCenter)

View File

@@ -136,19 +136,20 @@ class PreviewPanel(QWidget):
self.dimensions_label.setWordWrap(True)
# self.dim_label.setTextInteractionFlags(
# Qt.TextInteractionFlag.TextSelectableByMouse)
self.dimensions_label.setStyleSheet(ItemThumb.small_text_style)
# small_text_style = (
# f'background-color:rgba(17, 15, 27, 192);'
# f'font-family:Oxanium;'
# f'font-weight:bold;'
# f'font-size:12px;'
# f'border-radius:3px;'
# f'padding-top: 4px;'
# f'padding-right: 1px;'
# f'padding-bottom: 1px;'
# f'padding-left: 1px;'
# )
properties_style = (
f"background-color:#65000000;"
f"font-family:Oxanium;"
f"font-weight:bold;"
f"font-size:12px;"
f"border-radius:6px;"
f"padding-top: 4px;"
f"padding-right: 1px;"
f"padding-bottom: 1px;"
f"padding-left: 1px;"
)
self.dimensions_label.setStyleSheet(properties_style)
self.scroll_layout = QVBoxLayout()
self.scroll_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
@@ -157,20 +158,14 @@ class PreviewPanel(QWidget):
scroll_container: QWidget = QWidget()
scroll_container.setObjectName("entryScrollContainer")
scroll_container.setLayout(self.scroll_layout)
# scroll_container.setStyleSheet('background:#080716; border-radius:12px;')
scroll_container.setStyleSheet(
"background:#00000000;"
"border-style:none;"
f"QScrollBar::{{background:red;}}"
)
info_section = QWidget()
info_layout = QVBoxLayout(info_section)
info_layout.setContentsMargins(0, 0, 0, 0)
info_layout.setSpacing(6)
self.setStyleSheet("background:#00000000;" f"QScrollBar::{{background:red;}}")
scroll_area = QScrollArea()
scroll_area.setObjectName("entryScrollArea")
scroll_area.setSizePolicy(
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding
)
@@ -178,15 +173,15 @@ class PreviewPanel(QWidget):
scroll_area.setWidgetResizable(True)
scroll_area.setFrameShadow(QFrame.Shadow.Plain)
scroll_area.setFrameShape(QFrame.Shape.NoFrame)
# NOTE: I would rather have this style applied to the scroll_area
# background and NOT the scroll container background, so that the
# rounded corners are maintained when scrolling. I was unable to
# find the right trick to only select that particular element.
scroll_area.setStyleSheet(
"background:#55000000;"
"border-radius:12px;"
"border-style:solid;"
"border-width:1px;"
"border-color:#11FFFFFF;"
# f'QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {{border: none;background: none;}}'
# f'QScrollBar::left-arrow:horizontal, QScrollBar::right-arrow:horizontal, QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {{border: none;background: none;color: none;}}'
f"QScrollBar::{{background:red;}}"
f"QWidget#entryScrollContainer{{"
"background:#65000000;"
"border-radius:6px;"
f"}}"
)
scroll_area.setWidget(scroll_container)
@@ -207,29 +202,6 @@ class PreviewPanel(QWidget):
self.add_field_button.setMinimumSize(96, 28)
self.add_field_button.setMaximumSize(96, 28)
self.add_field_button.setText("Add Field")
self.add_field_button.setStyleSheet(
f"QPushButton{{"
# f'background: #1E1A33;'
# f'color: #CDA7F7;'
f"font-weight: bold;"
# f"border-color: #2B2547;"
f"border-radius: 6px;"
f"border-style:solid;"
# f'border-width:{math.ceil(1*self.devicePixelRatio())}px;'
"background:#55000000;"
"border-width:1px;"
"border-color:#11FFFFFF;"
# f'padding-top: 1.5px;'
# f'padding-right: 4px;'
# f'padding-bottom: 5px;'
# f'padding-left: 4px;'
f"font-size: 13px;"
f"}}"
f"QPushButton::hover"
f"{{"
f"background: #333333;"
f"}}"
)
self.afb_layout.addWidget(self.add_field_button)
self.afm = AddFieldModal(self.lib)
self.place_add_field_button()
@@ -398,7 +370,7 @@ class PreviewPanel(QWidget):
if extension in IMAGE_TYPES:
image = Image.open(filepath)
if image.mode == "RGBA":
new_bg = Image.new("RGB", image.size, color="#222222")
new_bg = Image.new("RGB", image.size, color="#1e1e1e")
new_bg.paste(image, mask=image.getchannel(3))
image = new_bg
if image.mode != "RGB":

View File

@@ -52,10 +52,10 @@ class TagBoxWidget(FieldWidget):
self.add_button.setText("+")
self.add_button.setStyleSheet(
f"QPushButton{{"
# f'background: #1E1A33;'
# f'color: #CDA7F7;'
f"background: #1e1e1e;"
f"color: #FFFFFF;"
f"font-weight: bold;"
# f"border-color: #2B2547;"
f"border-color: #333333;"
f"border-radius: 6px;"
f"border-style:solid;"
f"border-width:{math.ceil(1*self.devicePixelRatio())}px;"
@@ -67,7 +67,8 @@ class TagBoxWidget(FieldWidget):
f"}}"
f"QPushButton::hover"
f"{{"
# f'background: #2B2547;'
f"border-color: #CCCCCC;"
f"background: #555555;"
f"}}"
)
tsp = TagSearchPanel(self.lib)

View File

@@ -19,11 +19,13 @@ from PIL import (
ImageFont,
ImageEnhance,
ImageOps,
ImageFile,
)
from PySide6.QtCore import QObject, Signal, QSize
from PySide6.QtGui import QPixmap
from src.core.constants import PLAINTEXT_TYPES, VIDEO_TYPES, IMAGE_TYPES
ImageFile.LOAD_TRUNCATED_IMAGES = True
ERROR = f"[ERROR]"
WARNING = f"[WARNING]"
@@ -140,7 +142,7 @@ class ThumbRenderer(QObject):
# image = self.thumb_debug
if image.mode == "RGBA":
# logging.info(image.getchannel(3).tobytes())
new_bg = Image.new("RGB", image.size, color="#222222")
new_bg = Image.new("RGB", image.size, color="#1e1e1e")
new_bg.paste(image, mask=image.getchannel(3))
image = new_bg
if image.mode != "RGB":
@@ -171,7 +173,7 @@ class ThumbRenderer(QObject):
text: str = extension
with open(filepath, "r", encoding="utf-8") as text_file:
text = text_file.read(256)
bg = Image.new("RGB", (256, 256), color="#222222")
bg = Image.new("RGB", (256, 256), color="#1e1e1e")
draw = ImageDraw.Draw(bg)
draw.text((16, 16), text, file=(255, 255, 255))
image = bg
@@ -323,7 +325,7 @@ class ThumbRenderer(QObject):
# image = self.thumb_debug
if image.mode == "RGBA":
# logging.info(image.getchannel(3).tobytes())
new_bg = Image.new("RGB", image.size, color="#222222")
new_bg = Image.new("RGB", image.size, color="#1e1e1e")
new_bg.paste(image, mask=image.getchannel(3))
image = new_bg
if image.mode != "RGB":
@@ -353,7 +355,7 @@ class ThumbRenderer(QObject):
text: str = extension
with open(filepath, "r", encoding="utf-8") as text_file:
text = text_file.read(256)
bg = Image.new("RGB", (256, 256), color="#222222")
bg = Image.new("RGB", (256, 256), color="#1e1e1e")
draw = ImageDraw.Draw(bg)
draw.text((16, 16), text, file=(255, 255, 255))
image = bg