66import logging
77import typing
88
9- from PySide6 .QtCore import Qt , QThreadPool
9+ from PySide6 .QtCore import QThread , Qt , QThreadPool
1010from PySide6 .QtWidgets import QWidget , QVBoxLayout , QHBoxLayout , QLabel , QPushButton
1111
1212from src .core .library import Library
1313from src .qt .helpers .function_iterator import FunctionIterator
1414from src .qt .helpers .custom_runnable import CustomRunnable
1515from src .qt .modals .delete_unlinked import DeleteUnlinkedEntriesModal
1616from src .qt .modals .relink_unlinked import RelinkUnlinkedEntries
17- from src .qt .modals .merge_dupe_entries import MergeDuplicateEntries
1817from src .qt .widgets .progress import ProgressWidget
1918
2019# Only import for type checking/autocompletion, will not be imported at runtime.
2120if typing .TYPE_CHECKING :
2221 from src .qt .ts_qt import QtDriver
2322
2423
25- ERROR = "[ERROR]"
26- WARNING = "[WARNING]"
27- INFO = "[INFO]"
24+ ERROR = f "[ERROR]"
25+ WARNING = f "[WARNING]"
26+ INFO = f "[INFO]"
2827
2928logging .basicConfig (format = "%(message)s" , level = logging .INFO )
3029
3130
3231class FixUnlinkedEntriesModal (QWidget ):
32+ # done = Signal(int)
3333 def __init__ (self , library : "Library" , driver : "QtDriver" ):
3434 super ().__init__ ()
3535 self .lib = library
3636 self .driver = driver
37- self .missing_count = - 1
38- self .dupe_count = - 1
39- self .setWindowTitle ("Fix Unlinked Entries" )
37+ self .count = - 1
38+ self .setWindowTitle (f"Fix Unlinked Entries" )
4039 self .setWindowModality (Qt .WindowModality .ApplicationModal )
4140 self .setMinimumSize (400 , 300 )
4241 self .root_layout = QVBoxLayout (self )
4342 self .root_layout .setContentsMargins (6 , 6 , 6 , 6 )
4443
45- self .unlinked_desc_widget = QLabel ()
46- self .unlinked_desc_widget .setObjectName ("unlinkedDescriptionLabel" )
47- self .unlinked_desc_widget .setWordWrap (True )
48- self .unlinked_desc_widget .setStyleSheet ("text-align:left;" )
49- self .unlinked_desc_widget .setText (
50- """Each library entry is linked to a file in one of your directories. If a file linked to an entry is moved or deleted outside of TagStudio, it is then considered unlinked. Unlinked entries may be automatically relinked via searching your directories, manually relinked by the user, or deleted if desired."""
44+ self .desc_widget = QLabel ()
45+ self .desc_widget .setObjectName ("descriptionLabel" )
46+ self .desc_widget .setWordWrap (True )
47+ self .desc_widget .setStyleSheet (
48+ # 'background:blue;'
49+ "text-align:left;"
50+ # 'font-weight:bold;'
51+ # 'font-size:14px;'
52+ # 'padding-top: 6px'
53+ ""
5154 )
52-
53- self .dupe_desc_widget = QLabel ()
54- self .dupe_desc_widget .setObjectName ("dupeDescriptionLabel" )
55- self .dupe_desc_widget .setWordWrap (True )
56- self .dupe_desc_widget .setStyleSheet ("text-align:left;" )
57- self .dupe_desc_widget .setText (
58- """Duplicate entries are defined as multiple entries which point to the same file on disk. Merging these will combine the tags and metadata from all duplicates into a single consolidated entry. These are not to be confused with "duplicate files", which are duplicates of your files themselves outside of TagStudio."""
59- )
60-
61- self .missing_count_label = QLabel ()
62- self .missing_count_label .setObjectName ("missingCountLabel" )
63- self .missing_count_label .setStyleSheet ("font-weight:bold;" "font-size:14px;" )
64- self .missing_count_label .setAlignment (Qt .AlignmentFlag .AlignCenter )
65-
66- self .dupe_count_label = QLabel ()
67- self .dupe_count_label .setObjectName ("dupeCountLabel" )
68- self .dupe_count_label .setStyleSheet ("font-weight:bold;" "font-size:14px;" )
69- self .dupe_count_label .setAlignment (Qt .AlignmentFlag .AlignCenter )
70-
71- self .refresh_unlinked_button = QPushButton ()
72- self .refresh_unlinked_button .setText ("&Refresh All" )
73- self .refresh_unlinked_button .clicked .connect (
74- lambda : self .refresh_missing_files ()
55+ self .desc_widget .setText ("""Each library entry is linked to a file in one of your directories. If a file linked to an entry is moved or deleted outside of TagStudio, it is then considered unlinked.
56+ Unlinked entries may be automatically relinked via searching your directories, manually relinked by the user, or deleted if desired.""" )
57+ self .desc_widget .setAlignment (Qt .AlignmentFlag .AlignCenter )
58+
59+ self .missing_count = QLabel ()
60+ self .missing_count .setObjectName ("missingCountLabel" )
61+ self .missing_count .setStyleSheet (
62+ # 'background:blue;'
63+ # 'text-align:center;'
64+ "font-weight:bold;"
65+ "font-size:14px;"
66+ # 'padding-top: 6px'
67+ ""
7568 )
69+ self .missing_count .setAlignment (Qt .AlignmentFlag .AlignCenter )
70+ # self.missing_count.setText('Missing Files: N/A')
7671
77- self .merge_class = MergeDuplicateEntries (self .lib , self .driver )
78- self .relink_class = RelinkUnlinkedEntries (self .lib , self .driver )
72+ self .refresh_button = QPushButton ()
73+ self .refresh_button .setText ("&Refresh" )
74+ self .refresh_button .clicked .connect (lambda : self .refresh_missing_files ())
7975
8076 self .search_button = QPushButton ()
8177 self .search_button .setText ("&Search && Relink" )
82- self .relink_class . done . connect (
83- lambda : self .refresh_and_repair_dupe_entries ( self . merge_class )
84- )
78+ self .relink_class = RelinkUnlinkedEntries ( self . lib , self . driver )
79+ self . relink_class . done . connect ( lambda : self .refresh_missing_files () )
80+ self . relink_class . done . connect ( lambda : self . driver . update_thumbs () )
8581 self .search_button .clicked .connect (lambda : self .relink_class .repair_entries ())
8682
87- self .refresh_dupe_button = QPushButton ()
88- self .refresh_dupe_button .setText ("Refresh Duplicate Entries" )
89- self .refresh_dupe_button .clicked .connect (lambda : self .refresh_dupe_entries ())
90-
91- self .merge_dupe_button = QPushButton ()
92- self .merge_dupe_button .setText ("&Merge Duplicate Entries" )
93- self .merge_class .done .connect (lambda : self .set_dupe_count (- 1 ))
94- self .merge_class .done .connect (lambda : self .set_missing_count (- 1 ))
95- self .merge_class .done .connect (lambda : self .driver .filter_items ())
96- self .merge_dupe_button .clicked .connect (lambda : self .merge_class .merge_entries ())
97-
9883 self .manual_button = QPushButton ()
9984 self .manual_button .setText ("&Manual Relink" )
10085
@@ -107,46 +92,65 @@ def __init__(self, library: "Library", driver: "QtDriver"):
10792 self .delete_button .setText ("De&lete Unlinked Entries" )
10893 self .delete_button .clicked .connect (lambda : self .delete_modal .show ())
10994
95+ # self.combo_box = QComboBox()
96+ # self.combo_box.setEditable(False)
97+ # # self.combo_box.setMaxVisibleItems(5)
98+ # self.combo_box.setStyleSheet('combobox-popup:0;')
99+ # self.combo_box.view().setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
100+ # for df in self.lib.default_fields:
101+ # self.combo_box.addItem(f'{df["name"]} ({df["type"].replace("_", " ").title()})')
102+
110103 self .button_container = QWidget ()
111104 self .button_layout = QHBoxLayout (self .button_container )
112105 self .button_layout .setContentsMargins (6 , 6 , 6 , 6 )
113106 self .button_layout .addStretch (1 )
114107
115108 self .done_button = QPushButton ()
116109 self .done_button .setText ("&Done" )
110+ # self.save_button.setAutoDefault(True)
117111 self .done_button .setDefault (True )
118112 self .done_button .clicked .connect (self .hide )
113+ # self.done_button.clicked.connect(lambda: self.done.emit(self.combo_box.currentIndex()))
114+ # self.save_button.clicked.connect(lambda: save_callback(widget.get_content()))
119115 self .button_layout .addWidget (self .done_button )
120116
121- self .root_layout .addWidget (self .missing_count_label )
122- self .root_layout .addWidget (self .unlinked_desc_widget )
123- self .root_layout .addWidget (self .refresh_unlinked_button )
117+ # self.returnPressed.connect(lambda: self.done.emit(self.combo_box.currentIndex()))
118+
119+ # self.done.connect(lambda x: callback(x))
120+
121+ self .root_layout .addWidget (self .desc_widget )
122+ self .root_layout .addWidget (self .missing_count )
123+ self .root_layout .addWidget (self .refresh_button )
124124 self .root_layout .addWidget (self .search_button )
125125 self .manual_button .setHidden (True )
126126 self .root_layout .addWidget (self .manual_button )
127127 self .root_layout .addWidget (self .delete_button )
128+ # self.root_layout.setStretch(1,2)
128129 self .root_layout .addStretch (1 )
129- self .root_layout .addWidget (self .dupe_count_label )
130- self .root_layout .addWidget (self .dupe_desc_widget )
131- self .root_layout .addWidget (self .refresh_dupe_button )
132- self .root_layout .addWidget (self .merge_dupe_button )
133- self .root_layout .addStretch (2 )
134130 self .root_layout .addWidget (self .button_container )
135131
136- self .set_missing_count (self .missing_count )
137- self .set_dupe_count (self .dupe_count )
132+ self .set_missing_count (self .count )
138133
139134 def refresh_missing_files (self ):
135+ logging .info (f"Start RMF: { QThread .currentThread ()} " )
136+ # pb = QProgressDialog(f'Scanning Library for Unlinked Entries...', None, 0,len(self.lib.entries))
137+ # pb.setFixedSize(432, 112)
138+ # pb.setWindowFlags(pb.windowFlags() & ~Qt.WindowType.WindowCloseButtonHint)
139+ # pb.setWindowTitle('Scanning Library')
140+ # pb.setWindowModality(Qt.WindowModality.ApplicationModal)
141+ # pb.show()
142+
140143 iterator = FunctionIterator (self .lib .refresh_missing_files )
141144 pw = ProgressWidget (
142145 window_title = "Scanning Library" ,
143- label_text = "Scanning Library for Unlinked Entries..." ,
146+ label_text = f "Scanning Library for Unlinked Entries..." ,
144147 cancel_button_text = None ,
145148 minimum = 0 ,
146149 maximum = len (self .lib .entries ),
147150 )
148151 pw .show ()
149152 iterator .value .connect (lambda v : pw .update_progress (v + 1 ))
153+ # rmf.value.connect(lambda v: pw.update_label(f'Progress: {v}'))
150154 r = CustomRunnable (lambda : iterator .run ())
151155 QThreadPool .globalInstance ().start (r )
152156 r .done .connect (
@@ -155,76 +159,30 @@ def refresh_missing_files(self):
155159 pw .deleteLater (),
156160 self .set_missing_count (len (self .lib .missing_files )),
157161 self .delete_modal .refresh_list (),
158- self .refresh_dupe_entries (),
159162 )
160163 )
161164
162- def refresh_dupe_entries (self ):
163- iterator = FunctionIterator (self .lib .refresh_dupe_entries )
164- pw = ProgressWidget (
165- window_title = "Scanning Library" ,
166- label_text = "Scanning Library for Duplicate Entries..." ,
167- cancel_button_text = None ,
168- minimum = 0 ,
169- maximum = len (self .lib .entries ),
170- )
171- pw .show ()
172- iterator .value .connect (lambda v : pw .update_progress (v + 1 ))
173- r = CustomRunnable (lambda : iterator .run ())
174- QThreadPool .globalInstance ().start (r )
175- r .done .connect (
176- lambda : (
177- pw .hide (),
178- pw .deleteLater (),
179- self .set_dupe_count (len (self .lib .dupe_entries )),
180- )
181- )
165+ # r = CustomRunnable(lambda: self.lib.refresh_missing_files(lambda v: self.update_scan_value(pb, v)))
166+ # r.done.connect(lambda: (pb.hide(), pb.deleteLater(), self.set_missing_count(len(self.lib.missing_files)), self.delete_modal.refresh_list()))
167+ # QThreadPool.globalInstance().start(r)
168+ # # r.run()
169+ # pass
182170
183- def refresh_and_repair_dupe_entries (self , merge_class : MergeDuplicateEntries ):
184- iterator = FunctionIterator (self .lib .refresh_dupe_entries )
185- pw = ProgressWidget (
186- window_title = "Scanning Library" ,
187- label_text = "Scanning Library for Duplicate Entries..." ,
188- cancel_button_text = None ,
189- minimum = 0 ,
190- maximum = len (self .lib .entries ),
191- )
192- pw .show ()
193- iterator .value .connect (lambda v : pw .update_progress (v + 1 ))
194- r = CustomRunnable (lambda : iterator .run ())
195- QThreadPool .globalInstance ().start (r )
196- r .done .connect (
197- lambda : (
198- pw .hide (),
199- pw .deleteLater (),
200- self .set_dupe_count (len (self .lib .dupe_entries )),
201- merge_class .merge_entries (),
202- )
203- )
171+ # def update_scan_value(self, pb:QProgressDialog, value=int):
172+ # # pb.setLabelText(f'Scanning Library for Unlinked Entries ({value}/{len(self.lib.entries)})...')
173+ # pb.setValue(value)
204174
205175 def set_missing_count (self , count : int ):
206- self .missing_count = count
207- if self .missing_count < 0 :
176+ self .count = count
177+ if self .count < 0 :
208178 self .search_button .setDisabled (True )
209179 self .delete_button .setDisabled (True )
210- self .missing_count_label .setText ("Unlinked Entries: N/A" )
211- elif self .missing_count == 0 :
180+ self .missing_count .setText (f "Unlinked Entries: N/A" )
181+ elif self .count == 0 :
212182 self .search_button .setDisabled (True )
213183 self .delete_button .setDisabled (True )
214- self .missing_count_label .setText (f"Unlinked Entries: { count } " )
184+ self .missing_count .setText (f"Unlinked Entries: { count } " )
215185 else :
216186 self .search_button .setDisabled (False )
217187 self .delete_button .setDisabled (False )
218- self .missing_count_label .setText (f"Unlinked Entries: { count } " )
219-
220- def set_dupe_count (self , count : int ):
221- self .dupe_count = count
222- if self .dupe_count < 0 :
223- self .dupe_count_label .setText ("Duplicate Entries: N/A" )
224- self .merge_dupe_button .setDisabled (True )
225- elif self .dupe_count == 0 :
226- self .dupe_count_label .setText (f"Duplicate Entries: { count } " )
227- self .merge_dupe_button .setDisabled (True )
228- else :
229- self .dupe_count_label .setText (f"Duplicate Entries: { count } " )
230- self .merge_dupe_button .setDisabled (False )
188+ self .missing_count .setText (f"Unlinked Entries: { count } " )
0 commit comments