6
6
import logging
7
7
import typing
8
8
9
- from PySide6 .QtCore import Qt , QThreadPool
9
+ from PySide6 .QtCore import QThread , Qt , QThreadPool
10
10
from PySide6 .QtWidgets import QWidget , QVBoxLayout , QHBoxLayout , QLabel , QPushButton
11
11
12
12
from src .core .library import Library
13
13
from src .qt .helpers .function_iterator import FunctionIterator
14
14
from src .qt .helpers .custom_runnable import CustomRunnable
15
15
from src .qt .modals .delete_unlinked import DeleteUnlinkedEntriesModal
16
16
from src .qt .modals .relink_unlinked import RelinkUnlinkedEntries
17
- from src .qt .modals .merge_dupe_entries import MergeDuplicateEntries
18
17
from src .qt .widgets .progress import ProgressWidget
19
18
20
19
# Only import for type checking/autocompletion, will not be imported at runtime.
21
20
if typing .TYPE_CHECKING :
22
21
from src .qt .ts_qt import QtDriver
23
22
24
23
25
- ERROR = "[ERROR]"
26
- WARNING = "[WARNING]"
27
- INFO = "[INFO]"
24
+ ERROR = f "[ERROR]"
25
+ WARNING = f "[WARNING]"
26
+ INFO = f "[INFO]"
28
27
29
28
logging .basicConfig (format = "%(message)s" , level = logging .INFO )
30
29
31
30
32
31
class FixUnlinkedEntriesModal (QWidget ):
32
+ # done = Signal(int)
33
33
def __init__ (self , library : "Library" , driver : "QtDriver" ):
34
34
super ().__init__ ()
35
35
self .lib = library
36
36
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" )
40
39
self .setWindowModality (Qt .WindowModality .ApplicationModal )
41
40
self .setMinimumSize (400 , 300 )
42
41
self .root_layout = QVBoxLayout (self )
43
42
self .root_layout .setContentsMargins (6 , 6 , 6 , 6 )
44
43
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
+ ""
51
54
)
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
+ ""
75
68
)
69
+ self .missing_count .setAlignment (Qt .AlignmentFlag .AlignCenter )
70
+ # self.missing_count.setText('Missing Files: N/A')
76
71
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 ())
79
75
80
76
self .search_button = QPushButton ()
81
77
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 () )
85
81
self .search_button .clicked .connect (lambda : self .relink_class .repair_entries ())
86
82
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
-
98
83
self .manual_button = QPushButton ()
99
84
self .manual_button .setText ("&Manual Relink" )
100
85
@@ -107,46 +92,65 @@ def __init__(self, library: "Library", driver: "QtDriver"):
107
92
self .delete_button .setText ("De&lete Unlinked Entries" )
108
93
self .delete_button .clicked .connect (lambda : self .delete_modal .show ())
109
94
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
+
110
103
self .button_container = QWidget ()
111
104
self .button_layout = QHBoxLayout (self .button_container )
112
105
self .button_layout .setContentsMargins (6 , 6 , 6 , 6 )
113
106
self .button_layout .addStretch (1 )
114
107
115
108
self .done_button = QPushButton ()
116
109
self .done_button .setText ("&Done" )
110
+ # self.save_button.setAutoDefault(True)
117
111
self .done_button .setDefault (True )
118
112
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()))
119
115
self .button_layout .addWidget (self .done_button )
120
116
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 )
124
124
self .root_layout .addWidget (self .search_button )
125
125
self .manual_button .setHidden (True )
126
126
self .root_layout .addWidget (self .manual_button )
127
127
self .root_layout .addWidget (self .delete_button )
128
+ # self.root_layout.setStretch(1,2)
128
129
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 )
134
130
self .root_layout .addWidget (self .button_container )
135
131
136
- self .set_missing_count (self .missing_count )
137
- self .set_dupe_count (self .dupe_count )
132
+ self .set_missing_count (self .count )
138
133
139
134
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
+
140
143
iterator = FunctionIterator (self .lib .refresh_missing_files )
141
144
pw = ProgressWidget (
142
145
window_title = "Scanning Library" ,
143
- label_text = "Scanning Library for Unlinked Entries..." ,
146
+ label_text = f "Scanning Library for Unlinked Entries..." ,
144
147
cancel_button_text = None ,
145
148
minimum = 0 ,
146
149
maximum = len (self .lib .entries ),
147
150
)
148
151
pw .show ()
149
152
iterator .value .connect (lambda v : pw .update_progress (v + 1 ))
153
+ # rmf.value.connect(lambda v: pw.update_label(f'Progress: {v}'))
150
154
r = CustomRunnable (lambda : iterator .run ())
151
155
QThreadPool .globalInstance ().start (r )
152
156
r .done .connect (
@@ -155,76 +159,30 @@ def refresh_missing_files(self):
155
159
pw .deleteLater (),
156
160
self .set_missing_count (len (self .lib .missing_files )),
157
161
self .delete_modal .refresh_list (),
158
- self .refresh_dupe_entries (),
159
162
)
160
163
)
161
164
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
182
170
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)
204
174
205
175
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 :
208
178
self .search_button .setDisabled (True )
209
179
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 :
212
182
self .search_button .setDisabled (True )
213
183
self .delete_button .setDisabled (True )
214
- self .missing_count_label .setText (f"Unlinked Entries: { count } " )
184
+ self .missing_count .setText (f"Unlinked Entries: { count } " )
215
185
else :
216
186
self .search_button .setDisabled (False )
217
187
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