@@ -323,6 +323,9 @@ def __init__(self) -> None:
323
323
# That filename can then be used to provide quick lookup to image metadata entries in the Library.
324
324
# NOTE: On Windows, these strings are always lowercase.
325
325
self .filename_to_entry_id_map : dict [str , int ] = {}
326
+ # A list of file extensions to be ignored by TagStudio.
327
+ self .default_ext_blacklist : list = ['json' , 'xmp' , 'aae' ]
328
+ self .ignored_extensions : list = self .default_ext_blacklist
326
329
327
330
# Tags =================================================================
328
331
# List of every Tag object (ts-v8).
@@ -612,6 +615,10 @@ def open_library(self, path: str) -> int:
612
615
self .verify_ts_folders ()
613
616
major , minor , patch = json_dump ['ts-version' ].split ('.' )
614
617
618
+ # Load Extension Blacklist ---------------------------------
619
+ if 'ignored_extensions' in json_dump .keys ():
620
+ self .ignored_extensions = json_dump ['ignored_extensions' ]
621
+
615
622
# Parse Tags ---------------------------------------------------
616
623
if 'tags' in json_dump .keys ():
617
624
start_time = time .time ()
@@ -850,6 +857,7 @@ def to_json(self):
850
857
Used in saving the library to disk.
851
858
"""
852
859
file_to_save = {"ts-version" : ts_core .VERSION ,
860
+ "ignored_extensions" : [],
853
861
"tags" : [],
854
862
"collations" : [],
855
863
"fields" : [],
@@ -858,6 +866,9 @@ def to_json(self):
858
866
}
859
867
860
868
print ('[LIBRARY] Formatting Tags to JSON...' )
869
+
870
+ file_to_save ['ignored_extensions' ] = [i for i in self .ignored_extensions if i is not '' ]
871
+
861
872
for tag in self .tags :
862
873
file_to_save ["tags" ].append (tag .compressed_dict ())
863
874
@@ -925,6 +936,7 @@ def clear_internal_vars(self):
925
936
self .missing_files .clear ()
926
937
self .fixed_files .clear ()
927
938
self .filename_to_entry_id_map : dict [str , int ] = {}
939
+ self .ignored_extensions = self .default_ext_blacklist
928
940
929
941
self .tags .clear ()
930
942
self ._next_tag_id : int = 1000
@@ -950,7 +962,7 @@ def refresh_dir(self):
950
962
# p = Path(os.path.normpath(f))
951
963
if ('$RECYCLE.BIN' not in f and ts_core .TS_FOLDER_NAME not in f
952
964
and 'tagstudio_thumbs' not in f and not os .path .isdir (f )):
953
- if os .path .splitext (f )[1 ][1 :].lower () in ts_core . ALL_FILE_TYPES :
965
+ if os .path .splitext (f )[1 ][1 :].lower () not in self . ignored_extensions :
954
966
self .dir_file_count += 1
955
967
file = str (os .path .relpath (f , self .library_dir ))
956
968
@@ -1416,102 +1428,104 @@ def search_library(self, query:str=None, entries=True, collations=True,
1416
1428
# non_entry_count = 0
1417
1429
# Iterate over all Entries =============================================================
1418
1430
for entry in self .entries :
1431
+ allowed_ext : bool = False if os .path .splitext (entry .filename )[1 ][1 :].lower () in self .ignored_extensions else True
1419
1432
# try:
1420
1433
# entry: Entry = self.entries[self.file_to_library_index_map[self._source_filenames[i]]]
1421
1434
# print(f'{entry}')
1422
1435
1423
- # If the entry has tags of any kind, append them to this main tag list.
1424
- entry_tags : list [int ] = []
1425
- entry_authors : list [str ] = []
1426
- if entry .fields :
1427
- for field in entry .fields :
1428
- field_id = list (field .keys ())[0 ]
1429
- if self .get_field_obj (field_id )['type' ] == 'tag_box' :
1430
- entry_tags .extend (field [field_id ])
1431
- if self .get_field_obj (field_id )['name' ] == 'Author' :
1432
- entry_authors .extend (field [field_id ])
1433
- if self .get_field_obj (field_id )['name' ] == 'Artist' :
1434
- entry_authors .extend (field [field_id ])
1435
-
1436
- # print(f'Entry Tags: {entry_tags}')
1437
-
1438
- # Add Entries from special flags -------------------------------
1439
- # TODO: Come up with a more user-resistent way to 'archived' and 'favorite' tags.
1440
- if only_untagged :
1441
- if not entry_tags :
1442
- results .append ((ItemType .ENTRY , entry .id ))
1443
- elif only_no_author :
1444
- if not entry_authors :
1445
- results .append ((ItemType .ENTRY , entry .id ))
1446
- elif only_empty :
1447
- if not entry .fields :
1448
- results .append ((ItemType .ENTRY , entry .id ))
1449
- elif only_missing :
1450
- if os .path .normpath (f'{ self .library_dir } /{ entry .path } /{ entry .filename } ' ) in self .missing_files :
1451
- results .append ((ItemType .ENTRY , entry .id ))
1452
-
1453
- # elif query == "archived":
1454
- # if entry.tags and self._tag_names_to_tag_id_map[self.archived_word.lower()][0] in entry.tags:
1455
- # self.filtered_file_list.append(file)
1456
- # pb.value = len(self.filtered_file_list)
1457
- # elif query in entry.path.lower():
1436
+ if allowed_ext :
1437
+ # If the entry has tags of any kind, append them to this main tag list.
1438
+ entry_tags : list [int ] = []
1439
+ entry_authors : list [str ] = []
1440
+ if entry .fields :
1441
+ for field in entry .fields :
1442
+ field_id = list (field .keys ())[0 ]
1443
+ if self .get_field_obj (field_id )['type' ] == 'tag_box' :
1444
+ entry_tags .extend (field [field_id ])
1445
+ if self .get_field_obj (field_id )['name' ] == 'Author' :
1446
+ entry_authors .extend (field [field_id ])
1447
+ if self .get_field_obj (field_id )['name' ] == 'Artist' :
1448
+ entry_authors .extend (field [field_id ])
1449
+
1450
+ # print(f'Entry Tags: {entry_tags}')
1451
+
1452
+ # Add Entries from special flags -------------------------------
1453
+ # TODO: Come up with a more user-resistent way to 'archived' and 'favorite' tags.
1454
+ if only_untagged :
1455
+ if not entry_tags :
1456
+ results .append ((ItemType .ENTRY , entry .id ))
1457
+ elif only_no_author :
1458
+ if not entry_authors :
1459
+ results .append ((ItemType .ENTRY , entry .id ))
1460
+ elif only_empty :
1461
+ if not entry .fields :
1462
+ results .append ((ItemType .ENTRY , entry .id ))
1463
+ elif only_missing :
1464
+ if os .path .normpath (f'{ self .library_dir } /{ entry .path } /{ entry .filename } ' ) in self .missing_files :
1465
+ results .append ((ItemType .ENTRY , entry .id ))
1458
1466
1459
- # NOTE: This searches path and filenames.
1460
- if allow_adv :
1461
- if [q for q in query_words if (q in entry .path .lower ())]:
1462
- results .append ((ItemType .ENTRY , entry .id ))
1463
- elif [q for q in query_words if (q in entry .filename .lower ())]:
1464
- results .append ((ItemType .ENTRY , entry .id ))
1465
- elif tag_only :
1466
- if entry .has_tag (self , int (query_words [0 ])):
1467
- results .append ((ItemType .ENTRY , entry .id ))
1467
+ # elif query == "archived":
1468
+ # if entry.tags and self._tag_names_to_tag_id_map[self.archived_word.lower()][0] in entry.tags:
1469
+ # self.filtered_file_list.append(file)
1470
+ # pb.value = len(self.filtered_file_list)
1471
+ # elif query in entry.path.lower():
1468
1472
1469
- # elif query in entry.filename.lower():
1470
- # self.filtered_entries.append(index)
1471
- elif entry_tags :
1472
- # For each verified, extracted Tag term.
1473
- failure_to_union_terms = False
1474
- for term in all_tag_terms :
1475
- # If the term from the previous loop was already verified:
1476
- if not failure_to_union_terms :
1477
- cluster : set = set ()
1478
- # Add the immediate associated Tags to the set (ex. Name, Alias hits)
1479
- # Since this term could technically map to multiple IDs, iterate over it
1480
- # (You're 99.9999999% likely to just get 1 item)
1481
- for id in self ._tag_strings_to_id_map [term ]:
1482
- cluster .add (id )
1483
- cluster = cluster .union (
1484
- set (self .get_tag_cluster (id )))
1485
- # print(f'Full Cluster: {cluster}')
1486
- # For each of the Tag IDs in the term's ID cluster:
1487
- for t in cluster :
1488
- # Assume that this ID from the cluster is not in the Entry.
1489
- # Wait to see if proven wrong.
1490
- failure_to_union_terms = True
1491
- # If the ID actually is in the Entry,
1492
- if t in entry_tags :
1493
- # There wasn't a failure to find one of the term's cluster IDs in the Entry.
1494
- # There is also no more need to keep checking the rest of the terms in the cluster.
1495
- failure_to_union_terms = False
1496
- # print(f'FOUND MATCH: {t}')
1497
- break
1498
- # print(f'\tFailure to Match: {t}')
1499
- # If there even were tag terms to search through AND they all match an entry
1500
- if all_tag_terms and not failure_to_union_terms :
1501
- # self.filter_entries.append()
1502
- # self.filtered_file_list.append(file)
1503
- # results.append((SearchItemType.ENTRY, entry.id))
1504
- added = False
1505
- for f in entry .fields :
1506
- if self .get_field_attr (f , 'type' ) == 'collation' :
1507
- if (self .get_field_attr (f , 'content' ) not in collations_added ):
1508
- results .append ((ItemType .COLLATION , self .get_field_attr (f , 'content' )))
1509
- collations_added .append (self .get_field_attr (f , 'content' ))
1510
- added = True
1511
-
1512
- if not added :
1473
+ # NOTE: This searches path and filenames.
1474
+ if allow_adv :
1475
+ if [q for q in query_words if (q in entry .path .lower ())]:
1476
+ results .append ((ItemType .ENTRY , entry .id ))
1477
+ elif [q for q in query_words if (q in entry .filename .lower ())]:
1478
+ results .append ((ItemType .ENTRY , entry .id ))
1479
+ elif tag_only :
1480
+ if entry .has_tag (self , int (query_words [0 ])):
1513
1481
results .append ((ItemType .ENTRY , entry .id ))
1514
1482
1483
+ # elif query in entry.filename.lower():
1484
+ # self.filtered_entries.append(index)
1485
+ elif entry_tags :
1486
+ # For each verified, extracted Tag term.
1487
+ failure_to_union_terms = False
1488
+ for term in all_tag_terms :
1489
+ # If the term from the previous loop was already verified:
1490
+ if not failure_to_union_terms :
1491
+ cluster : set = set ()
1492
+ # Add the immediate associated Tags to the set (ex. Name, Alias hits)
1493
+ # Since this term could technically map to multiple IDs, iterate over it
1494
+ # (You're 99.9999999% likely to just get 1 item)
1495
+ for id in self ._tag_strings_to_id_map [term ]:
1496
+ cluster .add (id )
1497
+ cluster = cluster .union (
1498
+ set (self .get_tag_cluster (id )))
1499
+ # print(f'Full Cluster: {cluster}')
1500
+ # For each of the Tag IDs in the term's ID cluster:
1501
+ for t in cluster :
1502
+ # Assume that this ID from the cluster is not in the Entry.
1503
+ # Wait to see if proven wrong.
1504
+ failure_to_union_terms = True
1505
+ # If the ID actually is in the Entry,
1506
+ if t in entry_tags :
1507
+ # There wasn't a failure to find one of the term's cluster IDs in the Entry.
1508
+ # There is also no more need to keep checking the rest of the terms in the cluster.
1509
+ failure_to_union_terms = False
1510
+ # print(f'FOUND MATCH: {t}')
1511
+ break
1512
+ # print(f'\tFailure to Match: {t}')
1513
+ # If there even were tag terms to search through AND they all match an entry
1514
+ if all_tag_terms and not failure_to_union_terms :
1515
+ # self.filter_entries.append()
1516
+ # self.filtered_file_list.append(file)
1517
+ # results.append((SearchItemType.ENTRY, entry.id))
1518
+ added = False
1519
+ for f in entry .fields :
1520
+ if self .get_field_attr (f , 'type' ) == 'collation' :
1521
+ if (self .get_field_attr (f , 'content' ) not in collations_added ):
1522
+ results .append ((ItemType .COLLATION , self .get_field_attr (f , 'content' )))
1523
+ collations_added .append (self .get_field_attr (f , 'content' ))
1524
+ added = True
1525
+
1526
+ if not added :
1527
+ results .append ((ItemType .ENTRY , entry .id ))
1528
+
1515
1529
# sys.stdout.write(
1516
1530
# f'\r[INFO][FILTER]: {len(self.filtered_file_list)} matches found')
1517
1531
# sys.stdout.flush()
@@ -1536,15 +1550,17 @@ def search_library(self, query:str=None, entries=True, collations=True,
1536
1550
1537
1551
for entry in self .entries :
1538
1552
added = False
1539
- for f in entry .fields :
1540
- if self .get_field_attr (f , 'type' ) == 'collation' :
1541
- if (self .get_field_attr (f , 'content' ) not in collations_added ):
1542
- results .append ((ItemType .COLLATION , self .get_field_attr (f , 'content' )))
1543
- collations_added .append (self .get_field_attr (f , 'content' ))
1544
- added = True
1545
-
1546
- if not added :
1547
- results .append ((ItemType .ENTRY , entry .id ))
1553
+ allowed_ext : bool = False if os .path .splitext (entry .filename )[1 ][1 :].lower () in self .ignored_extensions else True
1554
+ if allowed_ext :
1555
+ for f in entry .fields :
1556
+ if self .get_field_attr (f , 'type' ) == 'collation' :
1557
+ if (self .get_field_attr (f , 'content' ) not in collations_added ):
1558
+ results .append ((ItemType .COLLATION , self .get_field_attr (f , 'content' )))
1559
+ collations_added .append (self .get_field_attr (f , 'content' ))
1560
+ added = True
1561
+
1562
+ if not added :
1563
+ results .append ((ItemType .ENTRY , entry .id ))
1548
1564
# for file in self._source_filenames:
1549
1565
# self.filtered_file_list.append(file)
1550
1566
results .reverse ()
0 commit comments