Skip to content

Commit 803f430

Browse files
committed
refactor: add function for common ProgressWidget use
Extracts the create_progress_bar function from drop_import to the ProgressWidget class. Instead of creating a ProgressWidget, FunctionIterator, and CustomRunnable every time a thread-safe progress widget is needed, the from_iterable function in ProgressWidget now handles all of that.
1 parent 2f9ae0d commit 803f430

File tree

8 files changed

+77
-159
lines changed

8 files changed

+77
-159
lines changed

tagstudio/src/qt/modals/delete_unlinked.py

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import typing
66

7-
from PySide6.QtCore import Qt, QThreadPool, Signal
7+
from PySide6.QtCore import Qt, Signal
88
from PySide6.QtGui import QStandardItem, QStandardItemModel
99
from PySide6.QtWidgets import (
1010
QHBoxLayout,
@@ -15,8 +15,6 @@
1515
QWidget,
1616
)
1717
from src.core.utils.missing_files import MissingRegistry
18-
from src.qt.helpers.custom_runnable import CustomRunnable
19-
from src.qt.helpers.function_iterator import FunctionIterator
2018
from src.qt.widgets.progress import ProgressWidget
2119

2220
# Only import for type checking/autocompletion, will not be imported at runtime.
@@ -82,30 +80,15 @@ def refresh_list(self):
8280
self.model.appendRow(item)
8381

8482
def delete_entries(self):
83+
def displayed_text(x):
84+
return f"Deleting {x}/{self.tracker.missing_files_count} Unlinked Entries"
85+
8586
pw = ProgressWidget(
8687
window_title="Deleting Entries",
8788
label_text="",
8889
cancel_button_text=None,
8990
minimum=0,
9091
maximum=self.tracker.missing_files_count,
9192
)
92-
pw.show()
93-
94-
iterator = FunctionIterator(self.tracker.execute_deletion)
95-
files_count = self.tracker.missing_files_count
96-
iterator.value.connect(
97-
lambda idx: (
98-
pw.update_progress(idx),
99-
pw.update_label(f"Deleting {idx}/{files_count} Unlinked Entries"),
100-
)
101-
)
10293

103-
r = CustomRunnable(iterator.run)
104-
QThreadPool.globalInstance().start(r)
105-
r.done.connect(
106-
lambda: (
107-
pw.hide(),
108-
pw.deleteLater(),
109-
self.done.emit(),
110-
)
111-
)
94+
pw.from_iterable_function(self.tracker.execute_deletion, displayed_text, self.done.emit)

tagstudio/src/qt/modals/drop_import.py

Lines changed: 11 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
import enum
55
import shutil
66
from pathlib import Path
7-
from typing import TYPE_CHECKING, Callable
7+
from typing import TYPE_CHECKING
88

99
import structlog
10-
from PySide6.QtCore import Qt, QThreadPool, QUrl
10+
from PySide6.QtCore import Qt, QUrl
1111
from PySide6.QtGui import QStandardItem, QStandardItemModel
1212
from PySide6.QtWidgets import (
1313
QHBoxLayout,
@@ -17,8 +17,6 @@
1717
QVBoxLayout,
1818
QWidget,
1919
)
20-
from src.qt.helpers.custom_runnable import CustomRunnable
21-
from src.qt.helpers.function_iterator import FunctionIterator
2220
from src.qt.widgets.progress import ProgressWidget
2321

2422
if TYPE_CHECKING:
@@ -168,12 +166,16 @@ def displayed_text(x):
168166

169167
return text
170168

171-
self.create_progress_bar(
169+
pw = ProgressWidget(
170+
window_title="Import Files",
171+
label_text="Importing New Files...",
172+
cancel_button_text=None,
173+
minimum=0,
174+
maximum=len(self.files),
175+
)
176+
177+
pw.from_iterable_function(
172178
self.copy_files,
173-
"Import Files",
174-
"Importing New Files...",
175-
None,
176-
len(self.files),
177179
displayed_text,
178180
self.driver.add_new_files_callback,
179181
self.deleteLater,
@@ -225,32 +227,3 @@ def _get_renamed_duplicate_filename(self, filepath: Path) -> str:
225227
)
226228
index += 1
227229
return filepath.name
228-
229-
def create_progress_bar(
230-
self,
231-
function: Callable,
232-
title: str,
233-
text: str,
234-
cancel_button_text: str | None,
235-
max_value: int,
236-
update_label_callback: Callable,
237-
*done_callback,
238-
):
239-
"""Displays a progress widget from an iterable function."""
240-
iterator = FunctionIterator(function)
241-
242-
pw = ProgressWidget(
243-
window_title=title,
244-
label_text=text,
245-
cancel_button_text=cancel_button_text,
246-
minimum=0,
247-
maximum=max_value,
248-
)
249-
pw.show()
250-
251-
iterator.value.connect(lambda x: pw.update_progress(x[0] + 1))
252-
iterator.value.connect(lambda x: pw.update_label(update_label_callback(x)))
253-
254-
r = CustomRunnable(lambda: iterator.run())
255-
r.done.connect(lambda: (pw.hide(), [callback() for callback in done_callback])) # type: ignore
256-
QThreadPool.globalInstance().start(r)

tagstudio/src/qt/modals/fix_unlinked.py

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@
55

66
import typing
77

8-
from PySide6.QtCore import Qt, QThreadPool
8+
from PySide6.QtCore import Qt
99
from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget
1010
from src.core.library import Library
1111
from src.core.utils.missing_files import MissingRegistry
12-
from src.qt.helpers.custom_runnable import CustomRunnable
13-
from src.qt.helpers.function_iterator import FunctionIterator
1412
from src.qt.modals.delete_unlinked import DeleteUnlinkedEntriesModal
1513
from src.qt.modals.merge_dupe_entries import MergeDuplicateEntries
1614
from src.qt.modals.relink_unlinked import RelinkUnlinkedEntries
@@ -85,7 +83,7 @@ def __init__(self, library: "Library", driver: "QtDriver"):
8583
self.delete_modal = DeleteUnlinkedEntriesModal(self.driver, self.tracker)
8684
self.delete_modal.done.connect(
8785
lambda: (
88-
self.set_missing_count(self.tracker.missing_files_count),
86+
self.set_missing_count(),
8987
# refresh the grid
9088
self.driver.filter_items(),
9189
)
@@ -125,23 +123,19 @@ def refresh_missing_files(self):
125123
maximum=self.lib.entries_count,
126124
)
127125

128-
pw.show()
129-
130-
iterator = FunctionIterator(self.tracker.refresh_missing_files)
131-
iterator.value.connect(lambda v: pw.update_progress(v + 1))
132-
r = CustomRunnable(iterator.run)
133-
QThreadPool.globalInstance().start(r)
134-
r.done.connect(
135-
lambda: (
136-
pw.hide(),
137-
pw.deleteLater(),
138-
self.set_missing_count(self.tracker.missing_files_count),
139-
self.delete_modal.refresh_list(),
140-
)
126+
pw.from_iterable_function(
127+
self.tracker.refresh_missing_files,
128+
None,
129+
self.set_missing_count,
130+
self.delete_modal.refresh_list,
141131
)
142132

143-
def set_missing_count(self, count: int):
144-
self.missing_count = count
133+
def set_missing_count(self, count: int | None = None):
134+
if count is not None:
135+
self.missing_count = count
136+
else:
137+
self.missing_count = self.tracker.missing_files_count
138+
145139
if self.missing_count < 0:
146140
self.search_button.setDisabled(True)
147141
self.delete_button.setDisabled(True)

tagstudio/src/qt/modals/merge_dupe_entries.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@
44

55
import typing
66

7-
from PySide6.QtCore import QObject, QThreadPool, Signal
7+
from PySide6.QtCore import QObject, Signal
88
from src.core.library import Library
99
from src.core.utils.dupe_files import DupeRegistry
10-
from src.qt.helpers.custom_runnable import CustomRunnable
11-
from src.qt.helpers.function_iterator import FunctionIterator
1210
from src.qt.widgets.progress import ProgressWidget
1311

1412
# Only import for type checking/autocompletion, will not be imported at runtime.
@@ -26,20 +24,12 @@ def __init__(self, library: "Library", driver: "QtDriver"):
2624
self.tracker = DupeRegistry(library=self.lib)
2725

2826
def merge_entries(self):
29-
iterator = FunctionIterator(self.tracker.merge_dupe_entries)
30-
3127
pw = ProgressWidget(
3228
window_title="Merging Duplicate Entries",
33-
label_text="",
29+
label_text="Merging Duplicate Entries...",
3430
cancel_button_text=None,
3531
minimum=0,
3632
maximum=self.tracker.groups_count,
3733
)
38-
pw.show()
39-
40-
iterator.value.connect(lambda x: pw.update_progress(x))
41-
iterator.value.connect(lambda: (pw.update_label("Merging Duplicate Entries...")))
4234

43-
r = CustomRunnable(iterator.run)
44-
r.done.connect(lambda: (pw.hide(), pw.deleteLater(), self.done.emit()))
45-
QThreadPool.globalInstance().start(r)
35+
pw.from_iterable_function(self.tracker.merge_dupe_entries, None, self.done.emit)

tagstudio/src/qt/modals/mirror_entities.py

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import typing
77
from time import sleep
88

9-
from PySide6.QtCore import Qt, QThreadPool, Signal
9+
from PySide6.QtCore import Qt, Signal
1010
from PySide6.QtGui import QStandardItem, QStandardItemModel
1111
from PySide6.QtWidgets import (
1212
QHBoxLayout,
@@ -17,8 +17,6 @@
1717
QWidget,
1818
)
1919
from src.core.utils.dupe_files import DupeRegistry
20-
from src.qt.helpers.custom_runnable import CustomRunnable
21-
from src.qt.helpers.function_iterator import FunctionIterator
2220
from src.qt.widgets.progress import ProgressWidget
2321

2422
# Only import for type checking/autocompletion, will not be imported at runtime.
@@ -83,28 +81,22 @@ def refresh_list(self):
8381
self.model.appendRow(QStandardItem(str(i)))
8482

8583
def mirror_entries(self):
86-
iterator = FunctionIterator(self.mirror_entries_runnable)
84+
def displayed_text(x):
85+
return f"Mirroring {x + 1}/{self.tracker.groups_count} Entries..."
86+
8787
pw = ProgressWidget(
8888
window_title="Mirroring Entries",
89-
label_text=f"Mirroring 1/{self.tracker.groups_count} Entries...",
89+
label_text="",
9090
cancel_button_text=None,
9191
minimum=0,
9292
maximum=self.tracker.groups_count,
9393
)
94-
pw.show()
95-
iterator.value.connect(lambda x: pw.update_progress(x + 1))
96-
iterator.value.connect(
97-
lambda x: pw.update_label(f"Mirroring {x + 1}/{self.tracker.groups_count} Entries...")
98-
)
99-
r = CustomRunnable(iterator.run)
100-
QThreadPool.globalInstance().start(r)
101-
r.done.connect(
102-
lambda: (
103-
pw.hide(),
104-
pw.deleteLater(),
105-
self.driver.preview_panel.update_widgets(),
106-
self.done.emit(),
107-
)
94+
95+
pw.from_iterable_function(
96+
self.mirror_entries_runnable,
97+
displayed_text,
98+
self.driver.preview_panel.update_widgets,
99+
self.done.emit,
108100
)
109101

110102
def mirror_entries_runnable(self):

tagstudio/src/qt/modals/relink_unlinked.py

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
44

55

6-
from PySide6.QtCore import QObject, QThreadPool, Signal
6+
from PySide6.QtCore import QObject, Signal
77
from src.core.utils.missing_files import MissingRegistry
8-
from src.qt.helpers.custom_runnable import CustomRunnable
9-
from src.qt.helpers.function_iterator import FunctionIterator
108
from src.qt.widgets.progress import ProgressWidget
119

1210

@@ -18,7 +16,10 @@ def __init__(self, tracker: MissingRegistry):
1816
self.tracker = tracker
1917

2018
def repair_entries(self):
21-
iterator = FunctionIterator(self.tracker.fix_missing_files)
19+
def displayed_text(x):
20+
text = f"Attempting to Relink {x}/{self.tracker.missing_files_count} Entries. \n"
21+
text += f"{self.tracker.files_fixed_count} Successfully Relinked."
22+
return text
2223

2324
pw = ProgressWidget(
2425
window_title="Relinking Entries",
@@ -28,24 +29,4 @@ def repair_entries(self):
2829
maximum=self.tracker.missing_files_count,
2930
)
3031

31-
pw.show()
32-
33-
iterator.value.connect(
34-
lambda idx: (
35-
pw.update_progress(idx),
36-
pw.update_label(
37-
f"Attempting to Relink {idx}/{self.tracker.missing_files_count} Entries. "
38-
f"{self.tracker.files_fixed_count} Successfully Relinked."
39-
),
40-
)
41-
)
42-
43-
r = CustomRunnable(iterator.run)
44-
r.done.connect(
45-
lambda: (
46-
pw.hide(),
47-
pw.deleteLater(),
48-
self.done.emit(),
49-
)
50-
)
51-
QThreadPool.globalInstance().start(r)
32+
pw.from_iterable_function(self.tracker.fix_missing_files, displayed_text, self.done.emit)

tagstudio/src/qt/ts_qt.py

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -702,26 +702,6 @@ def add_new_files_runnable(self, tracker: RefreshDirTracker):
702702

703703
Threaded method.
704704
"""
705-
# pb = QProgressDialog(
706-
# f"Running Configured Macros on 1/{len(new_ids)} New Entries", None, 0, len(new_ids)
707-
# )
708-
# pb.setFixedSize(432, 112)
709-
# pb.setWindowFlags(pb.windowFlags() & ~Qt.WindowType.WindowCloseButtonHint)
710-
# pb.setWindowTitle('Running Macros')
711-
# pb.setWindowModality(Qt.WindowModality.ApplicationModal)
712-
# pb.show()
713-
714-
# r = CustomRunnable(lambda: self.new_file_macros_runnable(pb, new_ids))
715-
# r.done.connect(lambda: (pb.hide(), pb.deleteLater(), self.filter_items('')))
716-
# r.run()
717-
# # QThreadPool.globalInstance().start(r)
718-
719-
# # self.main_window.statusbar.showMessage(
720-
# # f"Running configured Macros on {len(new_ids)} new Entries...", 3
721-
# # )
722-
723-
# # pb.hide()
724-
725705
files_count = tracker.files_count
726706

727707
iterator = FunctionIterator(tracker.save_new_files)
@@ -733,6 +713,7 @@ def add_new_files_runnable(self, tracker: RefreshDirTracker):
733713
maximum=files_count,
734714
)
735715
pw.show()
716+
736717
iterator.value.connect(
737718
lambda x: (
738719
pw.update_progress(x + 1),

0 commit comments

Comments
 (0)