It works.

This commit is contained in:
Kameron Kenny 2024-09-17 14:47:20 -04:00
parent fc32855c86
commit e8861abbdc
No known key found for this signature in database
GPG Key ID: E5006629839D2276
5 changed files with 108 additions and 97 deletions

View File

@ -1,36 +1,32 @@
#!/usr/bin/env python
import os
import sys
# import time
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
import traceback
from PyQt6.QtCore import pyqtSignal, pyqtSlot, QRunnable, QObject, QThreadPool
from PyQt6.QtWidgets import QMainWindow, QApplication
from PyQt6.QtGui import QIcon,QPixmap
from PIL import Image
from configure import CONFIG_FILE, Configure
from file_stuff import is_file, get_t_files
from file_stuff import is_file
from BitMover_MainWindow import Ui_MainWindow
from get_image_tag import get_exif_tag
from media import Media
from lumberjack import timber
from raw_photo import extract_jpg_thumb
from raw_photo import extract_jpg_thumb, get_raw_image_dimensions
log = timber(__name__)
class WorkerSignals(QObject):
"""
Defines the signals available from a running worker thread.
Defines the signals avail from a running worker thread.
Supported signals are:
finished
No data
No Data
error
tuple (exctype, value, traceback.format_exc() )
@ -40,17 +36,16 @@ class WorkerSignals(QObject):
progress
int indicating % progress
"""
started = pyqtSignal()
finished = pyqtSignal()
error = pyqtSignal(tuple)
result = pyqtSignal(object)
progress = pyqtSignal(int)
class Worker(QRunnable):
"""
Worker thread
Worker Thread
Inherits from QRunnable to handler worker thread setup, signals and wrap-up.
@ -61,10 +56,10 @@ class Worker(QRunnable):
:param kwargs: Keywords to pass to the callback function
"""
def __init__(self, fn, *args, **kwargs):
super(Worker, self).__init__()
def __init__(self,fn,*args,**kwargs):
super(Worker,self).__init__()
# Store constructor arguments (re-used for processing)
# Store constructor args (re-used for processing)
self.fn = fn
self.args = args
self.kwargs = kwargs
@ -78,18 +73,18 @@ class Worker(QRunnable):
"""
Initialise the runner function with passed args, kwargs.
"""
# Retrieve args/kwargs here; and fire processing using them
try:
self.signals.started.emit()
result = self.fn(*self.args, **self.kwargs)
except:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
self.signals.error.emit((exctype,value,traceback.format_exc()))
else:
self.signals.result.emit(result) # Return the result of the processing
self.signals.result.emit(result)
finally:
self.signals.finished.emit() # Done
self.signals.finished.emit()
# Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow, Ui_MainWindow):
@ -100,12 +95,17 @@ class MainWindow(QMainWindow, Ui_MainWindow):
c = Configure(CONFIG_FILE)
self.config = c.load_config()
self.total_files = 0
# self.t_find_files = threading.Thread(target=self.find_files)
self.file_total = 0
self.threads = {}
self.lcd_files_found.display(int(0))
self.set_progress(0, 0)
self.setWindowTitle("BitMover")
self.setWindowIcon(QIcon('assets/forklift.png'))
self.threadpool = QThreadPool()
print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())
self.src_dir = self.config['folders']['source']['base']
self.dst_dir = self.config['folders']['destination']['base']
@ -117,20 +117,24 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.pushButton_src_browse.clicked.connect(self.select_src_directory)
self.pushButton_dst_browse.clicked.connect(self.select_dst_directory)
self.pushButton_3_scan_dir.clicked.connect(self.find_files)
self.toggle_scan_button(True)
# self.pushButton_3_scan_dir.clicked.connect(self.t_find_files.start)
self.lcd_files_found.display(int(0))
self.set_progress(0,0)
self.img_preview.setPixmap(QPixmap('assets/preview_placeholder.jpg'))
self.img_preview.setScaledContents(True)
# self.img_preview.setFixedWidth(preview_width)
# self.img_preview.setFixedHeight(preview_height)
self.file_list.currentItemChanged.connect(self.index_changed)
self.threadpool = QThreadPool()
self.files = {}
def toggle_scan_button(self,enable=True):
if enable:
self.pushButton_3_scan_dir.setEnabled(True)
else:
self.pushButton_3_scan_dir.setDisabled(True)
def index_changed(self,i):
f = i.text()
@ -143,19 +147,17 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.label_data_date_time_created.setText(dtc)
if m.file_type == 'image':
# img = Image.open(f)
dpi = get_exif_tag(f,"xresolution")
width = get_exif_tag(f,"image width")
height = get_exif_tag(f,"image height")
if width is None:
get_exif_tag(f,"exifimagewidth")
if height is None:
get_exif_tag(f,"exifimagelength")
# width = img.width
# height = img.height
if f.lower().endswith("jpg") or f.lower().endswith("jpeg"):
img = Image.open(f)
width = img.width
height = img.height
else:
width = get_raw_image_dimensions(f)[1]
height = get_raw_image_dimensions(f)[0]
size = f'{width}x{height}'
if width is not None and height is not None:
mpixels = (width * height) / 1000000
mpixels = round((width * height) / 1000000, 1)
else:
mpixels = ''
iso = get_exif_tag(f,"iso")
@ -191,7 +193,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
jpg = extract_jpg_thumb(f)
self.img_preview.setPixmap(QPixmap(jpg))
def select_src_directory(self):
directory = QFileDialog.getExistingDirectory(self,
"Select Directory",
@ -212,74 +213,99 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.dst_dir = directory
self.lineEdit_dst_dir.setText(self.dst_dir)
def set_total_files(self,t):
self.total_files = t
self.lcd_files_found.display(self.total_files)
def progress_fn(self,n):
# print("%d%% done" % n)
self.progressBar_overall.setValue(int(n))
def set_progress(self,p,t):
"""
set progress for bar,
p = progress counter
t = target total
o = progress bar object
"""
if int(t) == 0:
t += 1
#
# while QPainter.isActive(Ui_MainWindow.QPainter()):
# print('painter active')
# time.sleep(0.02)
percent_complete = (int(p) / int(t)) * 100
self.progressBar_overall.setValue(int(percent_complete))
def print_output(self, s):
print(s)
def thread_complete(self):
print("THREAD COMPLETE!")
def thread_find_files(self):
print('in thread_find_files')
print(self.src_dir)
worker = Worker(self.find_files())
worker.signals.result.connect(self.print_output)
worker.signals.finished.connect(self.thread_complete)
worker.signals.progress.connect(self.progress_fn)
self.threadpool.start(worker)
def find_files(self):
""" find files to build a dictionary out of """
log.info('In find_files')
print(self.src_dir)
def get_t_files(self):
for folder, subfolders, filename in os.walk(self.src_dir):
for f_type in self.file_types:
for ext in self.file_types[f_type]:
for file in filename:
if file.lower().endswith(ext):
current_file = os.path.join(folder, file)
if is_file(current_file):
self.file_total += int(1)
else:
print(f"Skipping {current_file} as it does not look like a real file.")
def t_find_files(self,progress_callback):
file_count = int(0)
file_total = get_t_files(self.src_dir,self.file_types)
self.get_t_files()
self.set_total_files(self.file_total)
for folder, subfolders, filename in os.walk(self.src_dir):
for f_type in self.file_types:
for ext in self.file_types[f_type]:
# for file in tqdm(filename,
# desc='Finding ' + ext + ' Files in ' + folder):
for file in filename:
if file.lower().endswith(ext):
current_file = os.path.join(folder, file)
if is_file(current_file):
file_count += int(1)
self.process_file(folder, file)
self.set_progress(file_count,file_total)
self.process_file(current_file)
# self.set_progress(file_count,file_total)
# time.sleep(.02)
else:
print(f"Skipping {current_file} as it does not look like a real file.")
progress_callback.emit((file_count / file_total) * 100)
progress_callback.emit((file_count / self.file_total) * 100)
return "Done."
def print_output(self,s):
print(s)
def scan_thread_started(self):
print('scan thread started')
self.toggle_scan_button(False)
def scan_thread_done(self):
print('scan thread complete.')
self.toggle_scan_button(True)
def thread_complete(self):
print("THREAD COMPLETE.")
def find_files(self):
""" find files to build a dictionary out of """
worker = Worker(self.t_find_files)
# worker.signals.started.connect(self.toggle_scan_button(enable=False))
worker.signals.started.connect(self.scan_thread_started)
worker.signals.result.connect(self.print_output)
worker.signals.finished.connect(self.thread_complete)
worker.signals.finished.connect(self.scan_thread_done)
# worker.signals.finished.connect(self.toggle_scan_button(enable=True))
worker.signals.progress.connect(self.progress_fn)
# Execute.
self.threadpool.start(worker)
def get_event(self):
event_name = self.eventName.text()
return event_name
def process_file(self,path_name, f_name):
def process_file(self,p):
""" gather information and add to dictionary """
path_name = os.path.dirname(p)
f_name = os.path.basename(p)
event = self.get_event()
c = self.config

View File

@ -19,7 +19,7 @@ args = parser.parse_args()
if args.folder:
FOLDER = args.folder
else:
print("you need to specify a folder.")
print("you need to specify a folder. Dedup")
sys.exit()
if args.dryrun:
dry_run = True

View File

@ -126,18 +126,3 @@ def validate_config_dir_access(config):
accessible = True
return accessible
def get_t_files(p,t):
total = int(0)
for folder, subfolders, filename in os.walk(p):
for f_type in t:
for ext in t[f_type]:
# for file in tqdm(filename,
# desc='Finding ' + ext + ' Files in ' + folder):
for file in filename:
if file.lower().endswith(ext):
current_file = os.path.join(folder, file)
if is_file(current_file):
total += int(1)
else:
print(f"Skipping {current_file} as it does not look like a real file.")
return total

View File

@ -21,8 +21,8 @@ def extract_jpg_thumb(raw_file_path):
return 'thumbnail.jpg'
# thumbnail_path = extract_jpg_thumb('your_raw_image.nef')
# if thumbnail_path:
# print("Thumbnail extracted to:", thumbnail_path)
# else:
# print("No thumbnail found or unsupported format.")
def get_raw_image_dimensions(raw_file_path):
i = imread(raw_file_path)
height, width = i.raw_image.shape[:2]
return height,width

View File

@ -19,7 +19,7 @@ args = parser.parse_args()
if args.folder:
FOLDER = args.folder
else:
print("you need to specify a folder.")
print("you need to specify a folder. Duh.")
sys.exit()
if args.dryrun:
dry_run = True