Skip to content

Commit

Permalink
refactor: add function for common ProgressWidget use
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
seakrueger committed Nov 10, 2024
1 parent 8fbbe18 commit 5d36abc
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 159 deletions.
27 changes: 5 additions & 22 deletions tagstudio/src/qt/modals/delete_unlinked.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import typing

from PySide6.QtCore import Qt, QThreadPool, Signal
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QStandardItem, QStandardItemModel
from PySide6.QtWidgets import (
QHBoxLayout,
Expand All @@ -15,8 +15,6 @@
QWidget,
)
from src.core.utils.missing_files import MissingRegistry
from src.qt.helpers.custom_runnable import CustomRunnable
from src.qt.helpers.function_iterator import FunctionIterator
from src.qt.widgets.progress import ProgressWidget

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

def delete_entries(self):
def displayed_text(x):
return f"Deleting {x}/{self.tracker.missing_files_count} Unlinked Entries"

pw = ProgressWidget(
window_title="Deleting Entries",
label_text="",
cancel_button_text=None,
minimum=0,
maximum=self.tracker.missing_files_count,
)
pw.show()

iterator = FunctionIterator(self.tracker.execute_deletion)
files_count = self.tracker.missing_files_count
iterator.value.connect(
lambda idx: (
pw.update_progress(idx),
pw.update_label(f"Deleting {idx}/{files_count} Unlinked Entries"),
)
)

r = CustomRunnable(iterator.run)
QThreadPool.globalInstance().start(r)
r.done.connect(
lambda: (
pw.hide(),
pw.deleteLater(),
self.done.emit(),
)
)
pw.from_iterable_function(self.tracker.execute_deletion, displayed_text, self.done.emit)
49 changes: 11 additions & 38 deletions tagstudio/src/qt/modals/drop_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import shutil
from enum import Enum
from pathlib import Path
from typing import TYPE_CHECKING, Callable
from typing import TYPE_CHECKING

import structlog
from PySide6.QtCore import Qt, QThreadPool, QUrl
from PySide6.QtCore import Qt, QUrl
from PySide6.QtGui import QStandardItem, QStandardItemModel
from PySide6.QtWidgets import (
QHBoxLayout,
Expand All @@ -17,8 +17,6 @@
QVBoxLayout,
QWidget,
)
from src.qt.helpers.custom_runnable import CustomRunnable
from src.qt.helpers.function_iterator import FunctionIterator
from src.qt.widgets.progress import ProgressWidget

if TYPE_CHECKING:
Expand Down Expand Up @@ -164,12 +162,16 @@ def displayed_text(x):

return text

self.create_progress_bar(
pw = ProgressWidget(
window_title="Import Files",
label_text="Importing New Files...",
cancel_button_text=None,
minimum=0,
maximum=len(self.files),
)

pw.from_iterable_function(
self.copy_files,
"Import Files",
"Importing New Files...",
None,
len(self.files),
displayed_text,
self.driver.add_new_files_callback,
self.deleteLater,
Expand Down Expand Up @@ -222,32 +224,3 @@ def _get_renamed_duplicate_filename(self, filepath: Path) -> str:
)
index += 1
return filepath.name

def create_progress_bar(
self,
function: Callable,
title: str,
text: str,
cancel_button_text: str | None,
max_value: int,
update_label_callback: Callable,
*done_callback,
):
"""Displays a progress widget from an iterable function."""
iterator = FunctionIterator(function)

pw = ProgressWidget(
window_title=title,
label_text=text,
cancel_button_text=cancel_button_text,
minimum=0,
maximum=max_value,
)
pw.show()

iterator.value.connect(lambda x: pw.update_progress(x[0] + 1))
iterator.value.connect(lambda x: pw.update_label(update_label_callback(x)))

r = CustomRunnable(lambda: iterator.run())
r.done.connect(lambda: (pw.hide(), [callback() for callback in done_callback])) # type: ignore
QThreadPool.globalInstance().start(r)
32 changes: 13 additions & 19 deletions tagstudio/src/qt/modals/fix_unlinked.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@

import typing

from PySide6.QtCore import Qt, QThreadPool
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget
from src.core.library import Library
from src.core.utils.missing_files import MissingRegistry
from src.qt.helpers.custom_runnable import CustomRunnable
from src.qt.helpers.function_iterator import FunctionIterator
from src.qt.modals.delete_unlinked import DeleteUnlinkedEntriesModal
from src.qt.modals.merge_dupe_entries import MergeDuplicateEntries
from src.qt.modals.relink_unlinked import RelinkUnlinkedEntries
Expand Down Expand Up @@ -85,7 +83,7 @@ def __init__(self, library: "Library", driver: "QtDriver"):
self.delete_modal = DeleteUnlinkedEntriesModal(self.driver, self.tracker)
self.delete_modal.done.connect(
lambda: (
self.set_missing_count(self.tracker.missing_files_count),
self.set_missing_count(),
# refresh the grid
self.driver.filter_items(),
)
Expand Down Expand Up @@ -125,23 +123,19 @@ def refresh_missing_files(self):
maximum=self.lib.entries_count,
)

pw.show()

iterator = FunctionIterator(self.tracker.refresh_missing_files)
iterator.value.connect(lambda v: pw.update_progress(v + 1))
r = CustomRunnable(iterator.run)
QThreadPool.globalInstance().start(r)
r.done.connect(
lambda: (
pw.hide(),
pw.deleteLater(),
self.set_missing_count(self.tracker.missing_files_count),
self.delete_modal.refresh_list(),
)
pw.from_iterable_function(
self.tracker.refresh_missing_files,
None,
self.set_missing_count,
self.delete_modal.refresh_list,
)

def set_missing_count(self, count: int):
self.missing_count = count
def set_missing_count(self, count: int | None = None):
if count:
self.missing_count = count
else:
self.missing_count = self.tracker.missing_files_count

if self.missing_count < 0:
self.search_button.setDisabled(True)
self.delete_button.setDisabled(True)
Expand Down
16 changes: 3 additions & 13 deletions tagstudio/src/qt/modals/merge_dupe_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@

import typing

from PySide6.QtCore import QObject, QThreadPool, Signal
from PySide6.QtCore import QObject, Signal
from src.core.library import Library
from src.core.utils.dupe_files import DupeRegistry
from src.qt.helpers.custom_runnable import CustomRunnable
from src.qt.helpers.function_iterator import FunctionIterator
from src.qt.widgets.progress import ProgressWidget

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

def merge_entries(self):
iterator = FunctionIterator(self.tracker.merge_dupe_entries)

pw = ProgressWidget(
window_title="Merging Duplicate Entries",
label_text="",
label_text="Merging Duplicate Entries...",
cancel_button_text=None,
minimum=0,
maximum=self.tracker.groups_count,
)
pw.show()

iterator.value.connect(lambda x: pw.update_progress(x))
iterator.value.connect(lambda: (pw.update_label("Merging Duplicate Entries...")))

r = CustomRunnable(iterator.run)
r.done.connect(lambda: (pw.hide(), pw.deleteLater(), self.done.emit()))
QThreadPool.globalInstance().start(r)
pw.from_iterable_function(self.tracker.merge_dupe_entries, None, self.done.emit)
30 changes: 11 additions & 19 deletions tagstudio/src/qt/modals/mirror_entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import typing
from time import sleep

from PySide6.QtCore import Qt, QThreadPool, Signal
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QStandardItem, QStandardItemModel
from PySide6.QtWidgets import (
QHBoxLayout,
Expand All @@ -17,8 +17,6 @@
QWidget,
)
from src.core.utils.dupe_files import DupeRegistry
from src.qt.helpers.custom_runnable import CustomRunnable
from src.qt.helpers.function_iterator import FunctionIterator
from src.qt.widgets.progress import ProgressWidget

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

def mirror_entries(self):
iterator = FunctionIterator(self.mirror_entries_runnable)
def displayed_text(x):
return f"Mirroring {x + 1}/{self.tracker.groups_count} Entries..."

pw = ProgressWidget(
window_title="Mirroring Entries",
label_text=f"Mirroring 1/{self.tracker.groups_count} Entries...",
label_text="",
cancel_button_text=None,
minimum=0,
maximum=self.tracker.groups_count,
)
pw.show()
iterator.value.connect(lambda x: pw.update_progress(x + 1))
iterator.value.connect(
lambda x: pw.update_label(f"Mirroring {x + 1}/{self.tracker.groups_count} Entries...")
)
r = CustomRunnable(iterator.run)
QThreadPool.globalInstance().start(r)
r.done.connect(
lambda: (
pw.hide(),
pw.deleteLater(),
self.driver.preview_panel.update_widgets(),
self.done.emit(),
)

pw.from_iterable_function(
self.mirror_entries_runnable,
displayed_text,
self.driver.preview_panel.update_widgets,
self.done.emit,
)

def mirror_entries_runnable(self):
Expand Down
31 changes: 6 additions & 25 deletions tagstudio/src/qt/modals/relink_unlinked.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio


from PySide6.QtCore import QObject, QThreadPool, Signal
from PySide6.QtCore import QObject, Signal
from src.core.utils.missing_files import MissingRegistry
from src.qt.helpers.custom_runnable import CustomRunnable
from src.qt.helpers.function_iterator import FunctionIterator
from src.qt.widgets.progress import ProgressWidget


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

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

pw = ProgressWidget(
window_title="Relinking Entries",
Expand All @@ -28,24 +29,4 @@ def repair_entries(self):
maximum=self.tracker.missing_files_count,
)

pw.show()

iterator.value.connect(
lambda idx: (
pw.update_progress(idx),
pw.update_label(
f"Attempting to Relink {idx}/{self.tracker.missing_files_count} Entries. "
f"{self.tracker.files_fixed_count} Successfully Relinked."
),
)
)

r = CustomRunnable(iterator.run)
r.done.connect(
lambda: (
pw.hide(),
pw.deleteLater(),
self.done.emit(),
)
)
QThreadPool.globalInstance().start(r)
pw.from_iterable_function(self.tracker.fix_missing_files, displayed_text, self.done.emit)
21 changes: 1 addition & 20 deletions tagstudio/src/qt/ts_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,26 +702,6 @@ def add_new_files_runnable(self, tracker: RefreshDirTracker):
Threaded method.
"""
# pb = QProgressDialog(
# f"Running Configured Macros on 1/{len(new_ids)} New Entries", None, 0, len(new_ids)
# )
# pb.setFixedSize(432, 112)
# pb.setWindowFlags(pb.windowFlags() & ~Qt.WindowType.WindowCloseButtonHint)
# pb.setWindowTitle('Running Macros')
# pb.setWindowModality(Qt.WindowModality.ApplicationModal)
# pb.show()

# r = CustomRunnable(lambda: self.new_file_macros_runnable(pb, new_ids))
# r.done.connect(lambda: (pb.hide(), pb.deleteLater(), self.filter_items('')))
# r.run()
# # QThreadPool.globalInstance().start(r)

# # self.main_window.statusbar.showMessage(
# # f"Running configured Macros on {len(new_ids)} new Entries...", 3
# # )

# # pb.hide()

files_count = tracker.files_count

iterator = FunctionIterator(tracker.save_new_files)
Expand All @@ -733,6 +713,7 @@ def add_new_files_runnable(self, tracker: RefreshDirTracker):
maximum=files_count,
)
pw.show()

iterator.value.connect(
lambda x: (
pw.update_progress(x + 1),
Expand Down
Loading

0 comments on commit 5d36abc

Please sign in to comment.