Skip to content

Commit 9e4ae27

Browse files
committed
feat: fix review items
1 parent 4afdc4e commit 9e4ae27

File tree

13 files changed

+96
-69
lines changed

13 files changed

+96
-69
lines changed

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ ujson>=5.8.0,<=5.9.0
1919
vtf2img==0.1.0
2020
toml==0.10.2
2121
appdirs==1.4.4
22-
pydantic==2.10.4
22+
pydantic==2.10.4

tagstudio/src/core/library/alchemy/library.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
TextField,
5151
_FieldID,
5252
)
53+
from ...settings import LibSettings
5354
from .joins import TagField, TagSubtag
5455
from .models import Entry, Folder, Preferences, Tag, TagAlias, ValueType
5556
from .visitors import SQLBoolExpressionBuilder
@@ -137,6 +138,7 @@ class Library:
137138
engine: Engine | None
138139
folder: Folder | None
139140
included_files: set[Path] = set()
141+
settings: LibSettings | None = None
140142

141143
SQL_FILENAME: str = "ts_library.sqlite"
142144
JSON_FILENAME: str = "ts_library.json"
@@ -200,8 +202,8 @@ def migrate_json_to_sqlite(self, json_lib: JsonLibrary):
200202
)
201203

202204
# Preferences
203-
self.set_prefs(LibraryPrefs.EXTENSION_LIST, [x.strip(".") for x in json_lib.ext_list])
204-
self.set_prefs(LibraryPrefs.IS_EXCLUDE_LIST, json_lib.is_exclude_list)
205+
self.settings.extension_list = [ x.strip(".") for x in json_lib.ext_list]
206+
self.settings.is_exclude_list = json_lib.is_exclude_list
205207

206208
end_time = time.time()
207209
logger.info(f"Library Converted! ({format_timespan(end_time-start_time)})")
@@ -220,6 +222,9 @@ def open_library(self, library_dir: Path, storage_path: str | None = None) -> Li
220222
return self.open_sqlite_library(library_dir, is_new)
221223
else:
222224
self.storage_path = library_dir / TS_FOLDER_NAME / self.SQL_FILENAME
225+
settings_path = library_dir / TS_FOLDER_NAME / "libsettings.toml"
226+
227+
self.settings = LibSettings.open(settings_path)
223228

224229
if self.verify_ts_folder(library_dir) and (is_new := not self.storage_path.exists()):
225230
json_path = library_dir / TS_FOLDER_NAME / self.JSON_FILENAME
@@ -547,10 +552,9 @@ def search_library(
547552
SQLBoolExpressionBuilder(self).visit(search.ast)
548553
)
549554

550-
extensions = self.prefs(LibraryPrefs.EXTENSION_LIST)
551-
is_exclude_list = self.prefs(LibraryPrefs.IS_EXCLUDE_LIST)
555+
extensions = self.settings.extension_list
552556

553-
if extensions and is_exclude_list:
557+
if extensions and self.settings.is_exclude_list:
554558
statement = statement.where(Entry.suffix.notin_(extensions))
555559
elif extensions:
556560
statement = statement.where(Entry.suffix.in_(extensions))
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
from .tssettings import TSSettings
2+
from .libsettings import LibSettings
23

3-
__all__ = ["TSSettings"]
4+
__all__ = ["TSSettings", "LibSettings"]
Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,40 @@
1-
from pydantic import BaseModel
1+
from pathlib import Path
2+
from pydantic import BaseModel, Field
3+
import toml
4+
import structlog
25

6+
logger = structlog.get_logger(__name__)
37

48
class LibSettings(BaseModel):
5-
# Cant think of any library-specific properties lol
6-
test_prop: bool = False
9+
is_exclude_list: bool = Field(default=True)
10+
extension_list: list[str] = Field(default = [".json", ".xmp", ".aae"])
11+
page_size: int = Field(default=500)
12+
db_version: int = Field(default=2)
13+
filename: str = Field(default="")
14+
15+
@staticmethod
16+
def open(path_value: Path | str) -> "LibSettings":
17+
path: Path
18+
if not isinstance(path_value, Path):
19+
path = Path(path_value)
20+
else:
21+
path = path_value
22+
23+
if path.exists():
24+
with open(path, "r") as settings_file:
25+
filecontents = settings_file.read()
26+
if len(filecontents.strip()) != 0:
27+
settings_data = toml.loads(filecontents)
28+
settings_data["filename"] = str(path)
29+
return LibSettings(**settings_data)
30+
31+
#either settings file did not exist or was empty - either way, use default settings
32+
settings = LibSettings(**dict(filename=str(path)))
33+
return settings
34+
35+
def save(self):
36+
if not (parent_path := Path(self.filename).parent).exists():
37+
parent_path.mkdir()
38+
39+
with open(self.filename, "w") as settings_file:
40+
toml.dump(dict(self), settings_file)

tagstudio/src/core/settings/tssettings.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,35 +21,27 @@ class TSSettings(BaseModel):
2121
filename: str = Field()
2222

2323
@staticmethod
24-
def read_settings(path: Path | str, **kwargs) -> "TSSettings":
24+
def read_settings(path: Path | str) -> "TSSettings":
2525
path_value = Path(path)
26-
settings_data: dict[str, Any] = dict()
2726
if path_value.exists():
28-
with open(path, "rb") as file:
27+
with open(path, "r") as file:
2928
filecontents = file.read()
3029
if len(filecontents.strip()) != 0:
31-
settings_data = toml.loads(filecontents.decode("utf-8"))
30+
settings_data = toml.loads(filecontents)
31+
settings = TSSettings(**settings_data)
32+
return settings
3233

33-
settings_data["filename"] = str(path)
34-
settings = TSSettings(**settings_data)
35-
return settings
36-
37-
def to_dict(self) -> dict[str, Any]:
38-
d = dict[str, Any]()
39-
for prop_name, prop_value in self:
40-
d[prop_name] = prop_value
41-
42-
return d
34+
return TSSettings(**dict(filename=str(path)))
4335

4436
def save(self, path: Path | str | None = None) -> None:
4537
path_value: Path
4638
if isinstance(path, str):
4739
path_value = Path(path)
48-
49-
if path is None:
40+
else:
5041
path_value = Path(self.filename)
42+
5143
if not path_value.parent.exists():
5244
path_value.parent.mkdir(parents=True, exist_ok=True)
5345

5446
with open(path_value, "w") as f:
55-
toml.dump(self.to_dict(), f)
47+
toml.dump(dict(self), f)

tagstudio/src/core/tscacheddata.py

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,27 @@ class TSCachedData(BaseModel):
2121
path: str = Field()
2222

2323
@staticmethod
24-
def open(path: str | None = None) -> "TSCachedData":
25-
file: str | None = None
26-
if path is None:
27-
if not Path(cache_dir).exists():
28-
logger.info("Cache directory does not exist - creating", path=cache_dir)
29-
Path.mkdir(cache_dir)
30-
if not Path(cache_location).exists():
31-
logger.info("Cache file does not exist - creating", path=cache_location)
32-
open(cache_location, "w").close()
33-
file = str(cache_location)
24+
def open(path_value: Path | str | None = None) -> "TSCachedData":
25+
path: Path | None = None
26+
default_cache_location = Path(user_cache_dir()) / "ts_cache.toml"
27+
if isinstance(path_value, str):
28+
path = Path(path_value)
29+
elif isinstance(path_value, Path):
30+
path = path_value
3431
else:
35-
if not Path(path).exists():
36-
logger.info("Cache file does not exist - creating", path=path)
37-
open(path, "w").close()
38-
file = str(path)
39-
40-
data = toml.load(file)
41-
data["path"] = str(path) if path is not None else str(cache_location)
42-
cached_data = TSCachedData(**data)
43-
return cached_data
32+
logger.info("no cache location was specified, using ", default_cache_location=default_cache_location)
33+
path = default_cache_location
34+
35+
if path.exists():
36+
with open(path, "r") as cache_file:
37+
filecontents = cache_file.read()
38+
if len(filecontents.strip()) != 0:
39+
cache_data = toml.loads(filecontents)
40+
cache_data["path"] = str(path)
41+
logger.info("opening cache file at ", cache_location=path)
42+
return TSCachedData(**cache_data)
43+
44+
return TSCachedData(**dict(path=str(default_cache_location)))
4445

4546
def save(self):
4647
with open(self.path, "w") as f:

tagstudio/src/qt/modals/file_extension.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def __init__(self, library: "Library"):
4343
self.root_layout.setContentsMargins(6, 6, 6, 6)
4444

4545
# Create Table Widget --------------------------------------------------
46-
self.table = QTableWidget(len(self.lib.prefs(LibraryPrefs.EXTENSION_LIST)), 1)
46+
self.table = QTableWidget(len(self.lib.settings.extension_list), 1)
4747
self.table.horizontalHeader().setVisible(False)
4848
self.table.verticalHeader().setVisible(False)
4949
self.table.horizontalHeader().setStretchLastSection(True)
@@ -74,7 +74,7 @@ def __init__(self, library: "Library"):
7474
lambda text: self.mode_combobox.setItemText(1, text), "ignore_list.mode.exclude"
7575
)
7676

77-
is_exclude_list = int(bool(self.lib.prefs(LibraryPrefs.IS_EXCLUDE_LIST)))
77+
is_exclude_list = int(bool(self.lib.settings.is_exclude_list))
7878

7979
self.mode_combobox.setCurrentIndex(is_exclude_list)
8080
self.mode_combobox.currentIndexChanged.connect(lambda i: self.update_list_mode(i))
@@ -97,10 +97,10 @@ def update_list_mode(self, mode: int):
9797
mode (int): The list mode, given by the index of the mode inside
9898
the mode combobox. 1 for "Exclude", 0 for "Include".
9999
"""
100-
self.lib.set_prefs(LibraryPrefs.IS_EXCLUDE_LIST, bool(mode))
100+
self.lib.settings.is_exclude_list = bool(mode)
101101

102102
def refresh_list(self):
103-
for i, ext in enumerate(self.lib.prefs(LibraryPrefs.EXTENSION_LIST)):
103+
for i, ext in enumerate(self.lib.settings.extension_list):
104104
self.table.setItem(i, 0, QTableWidgetItem(ext))
105105

106106
def add_item(self):
@@ -114,4 +114,4 @@ def save(self):
114114
extensions.append(ext.text().strip().lstrip(".").lower())
115115

116116
# save preference
117-
self.lib.set_prefs(LibraryPrefs.EXTENSION_LIST, extensions)
117+
self.lib.settings.extension_list = extensions

tagstudio/src/qt/modals/settings_modal.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ def __init__(self, settings: TSSettings):
5555
self.show_filenames_Row = QHBoxLayout()
5656
self.show_filenames_Row.addWidget(self.show_filenames_Label)
5757
self.show_filenames_Row.addWidget(self.show_filenames_Value)
58-
# TODO: use value from translations
59-
self.show_filenames_Label.setText("Show filenames in grid")
58+
self.show_filenames_Label.setText("Show filenames in grid (requires restart)")
6059
self.show_filenames_Value.setChecked(self.tempSettings.show_filenames_in_grid)
6160

6261
self.show_filenames_Value.stateChanged.connect(

tagstudio/src/qt/ts_qt.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,6 @@ def start(self) -> None:
272272
Translations.translate_qobject(file_menu, "menu.file")
273273
edit_menu = QMenu(menu_bar)
274274
Translations.translate_qobject(edit_menu, "generic.edit_alt")
275-
view_menu = QMenu(menu_bar)
276-
Translations.translate_qobject(view_menu, "menu.view")
277275
tools_menu = QMenu(menu_bar)
278276
Translations.translate_qobject(tools_menu, "menu.tools")
279277
macros_menu = QMenu(menu_bar)
@@ -346,9 +344,7 @@ def start(self) -> None:
346344
# Edit Menu ============================================================
347345
settings_menu_action = QAction("&Settings", menu_bar)
348346
settings_menu_action.triggered.connect(lambda: self.open_settings_menu())
349-
edit_menu.addAction(settings_menu_action)
350-
351-
edit_menu.addSeparator()
347+
file_menu.addAction(settings_menu_action)
352348

353349
new_tag_action = QAction(menu_bar)
354350
Translations.translate_qobject(new_tag_action, "menu.edit.new_tag")
@@ -476,7 +472,6 @@ def create_folders_tags_modal():
476472

477473
menu_bar.addMenu(file_menu)
478474
menu_bar.addMenu(edit_menu)
479-
menu_bar.addMenu(view_menu)
480475
menu_bar.addMenu(tools_menu)
481476
menu_bar.addMenu(macros_menu)
482477
menu_bar.addMenu(help_menu)
@@ -629,6 +624,7 @@ def close_library(self, is_shutdown: bool = False):
629624

630625
self.cache.last_library = str(self.lib.library_dir)
631626
self.settings.save()
627+
self.lib.settings.save()
632628

633629
self.lib.close()
634630

@@ -1289,7 +1285,7 @@ def init_library(self, path: Path, open_status: LibraryStatus):
12891285

12901286
self.init_workers()
12911287

1292-
self.filter.page_size = self.lib.prefs(LibraryPrefs.PAGE_SIZE)
1288+
self.filter.page_size = self.lib.settings.page_size
12931289

12941290
# TODO - make this call optional
12951291
if self.lib.entries_count < 10000:

tagstudio/src/qt/widgets/migration_modal.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,12 +417,12 @@ def update_sql_value_ui(self, show_msg_box: bool = True):
417417
)
418418
self.update_sql_value(
419419
self.ext_row,
420-
len(self.sql_lib.prefs(LibraryPrefs.EXTENSION_LIST)),
420+
len(self.sql_lib.settings.extension_list),
421421
self.old_ext_count,
422422
)
423423
self.update_sql_value(
424424
self.ext_type_row,
425-
self.sql_lib.prefs(LibraryPrefs.IS_EXCLUDE_LIST),
425+
self.sql_lib.settings.is_exclude_list,
426426
self.old_ext_type,
427427
)
428428
logger.info("Parity check complete!")
@@ -680,7 +680,7 @@ def check_subtag_parity(self) -> bool:
680680
return self.subtag_parity
681681

682682
def check_ext_type(self) -> bool:
683-
return self.json_lib.is_exclude_list == self.sql_lib.prefs(LibraryPrefs.IS_EXCLUDE_LIST)
683+
return self.json_lib.is_exclude_list == self.sql_lib.settings.is_exclude_list
684684

685685
def check_alias_parity(self) -> bool:
686686
"""Check if all JSON aliases match the new SQL aliases."""

0 commit comments

Comments
 (0)