dev #1

Merged
kkenny merged 8 commits from dev into main 2024-10-07 14:51:01 -04:00
4 changed files with 86 additions and 54 deletions
Showing only changes of commit aa973011c6 - Show all commits

View File

@ -1,7 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
import os import os
from os import path
from os import rename
import sys import sys
import time
from PyQt6.QtCore import QThreadPool from PyQt6.QtCore import QThreadPool
from PyQt6.QtGui import QIcon, QPixmap from PyQt6.QtGui import QIcon, QPixmap
@ -16,9 +17,7 @@ from _import_dialog import DialogImport
from _preview import MediaPreview from _preview import MediaPreview
from _thread_my_stuff import Worker from _thread_my_stuff import Worker
from _media_file import MediaFile from _media_file import MediaFile
from _file_stuff import (path_exists, from _file_stuff import path_exists,is_dir,is_file,create_folder,cmp_files
is_dir,
is_file)
from _hashing import hash_path from _hashing import hash_path
@ -173,8 +172,15 @@ class MainWindow(QMainWindow, Ui_MainWindow):
return preview return preview
def update_preview(self,preview): def update_preview(self,preview):
if preview.file_type.lower() == 'video':
thumb_ratio = 16 / 9 # 1.77
elif preview.file_type.lower() == 'image':
thumb_ratio = preview.thumbnail_ratio
else:
thumb_ratio = 1
self.set_thumbnail(preview.thumbnail, self.set_thumbnail(preview.thumbnail,
ratio=preview.thumbnail_ratio) ratio=thumb_ratio)
def update_metadata(self,preview): def update_metadata(self,preview):
self.clear_metadata() self.clear_metadata()
@ -204,7 +210,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.l_meta_content_03.setText(str(f_photo['iso'])) self.l_meta_content_03.setText(str(f_photo['iso']))
self.l_meta_content_04.setText(str(f_photo['lens_model'])) self.l_meta_content_04.setText(str(f_photo['lens_model']))
self.l_meta_content_05.setText(str(f_photo['lens_focal_length'])) self.l_meta_content_05.setText(str(f_photo['lens_focal_length']))
self.l_meta_content_06.setText(str("f_photo['camera_brand']} {f_photo['camera_model']}")) self.l_meta_content_06.setText(str(f"{f_photo['camera_brand']} {f_photo['camera_model']}"))
self.l_meta_content_07.setText(str(f_photo['aperture'])) self.l_meta_content_07.setText(str(f_photo['aperture']))
self.l_meta_content_08.setText(str(f_photo['size']['megapixels'])) self.l_meta_content_08.setText(str(f_photo['size']['megapixels']))
@ -221,13 +227,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.l_meta_08.setText('Pix Format') self.l_meta_08.setText('Pix Format')
self.l_meta_content_01.setText(str(f_video['size']['width_height'])) self.l_meta_content_01.setText(str(f_video['size']['width_height']))
self.l_meta_content_02.setText(str(f_video['r_framerate'])) self.l_meta_content_02.setText(str(f_video['r_frame_rate']))
self.l_meta_content_03.setText(str(f_video['bit_depth'])) self.l_meta_content_03.setText(str(f_video['bits_per_raw_sample']))
self.l_meta_content_04.setText(str(f_video['duration'])) self.l_meta_content_04.setText(str(f_video['duration']))
self.l_meta_content_05.setText(str(f_video['encoding'])) self.l_meta_content_05.setText(str(f_video['encoding_brand']))
self.l_meta_content_06.setText(str(f_video['codec'])) self.l_meta_content_06.setText(str(f_video['codec_long_name']))
self.l_meta_content_07.setText(str(f_video['profile'])) self.l_meta_content_07.setText(str(f_video['profile']))
self.l_meta_content_08.setText(str(f_video['pix_format'])) self.l_meta_content_08.setText(str(f_video['pix_fmt']))
def clear_metadata(self): def clear_metadata(self):
self.l_meta_01.setText('') self.l_meta_01.setText('')
@ -252,6 +258,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
if i is None: if i is None:
self.set_default_thumbnail() self.set_default_thumbnail()
else: else:
self.process_file(i.text())
print(f'index changed to: {i.text()}') print(f'index changed to: {i.text()}')
preview = self.get_preview(i.text()) preview = self.get_preview(i.text())
self.update_preview(preview) self.update_preview(preview)
@ -309,7 +316,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def worker_thread_done(self): def worker_thread_done(self):
print('scan thread complete.') print('scan thread complete.')
self.toggle_scan_button(True) self.toggle_scan_button(True)
if 0 < len(self.files): if 0 < len(self.file_list):
self.toggle_import_button(True) self.toggle_import_button(True)
else: else:
self.toggle_import_button(False) self.toggle_import_button(False)
@ -319,6 +326,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
print("THREAD COMPLETE.") print("THREAD COMPLETE.")
def add_found_file_to_list(self,f): def add_found_file_to_list(self,f):
sph = self.get_source_path_hash(f)
self.files[sph] = {}
self.file_list.addItem(f) self.file_list.addItem(f)
def gen_file_dict(self,d): def gen_file_dict(self,d):
@ -342,7 +351,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.file_total = self.get_t_files() self.file_total = self.get_t_files()
self.set_total_files(self.file_total) self.set_total_files(self.file_total)
time.sleep(3) # time.sleep(3)
file_finder = FindFiles(search_types=self.search_types, file_finder = FindFiles(search_types=self.search_types,
src_dir=self.src_dir, src_dir=self.src_dir,
@ -358,8 +367,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.find_files_dialog.set_progress_finding_files) self.find_files_dialog.set_progress_finding_files)
worker.signals.found_file.connect( worker.signals.found_file.connect(
self.add_found_file_to_list) self.add_found_file_to_list)
worker.signals.found_file.connect( # worker.signals.found_file.connect(
self.process_file) # self.process_file)
worker.signals.total_file_count.connect( worker.signals.total_file_count.connect(
self.set_total_files) self.set_total_files)
# worker.signals.result.connect( # worker.signals.result.connect(
@ -375,16 +384,18 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.threadpool.start(worker) self.threadpool.start(worker)
# From _media_import.py # From _media_import.py
def is_video(self,f): def is_video(self,sph):
if self.files[f]['type'] == 'video': print(f"Should be sph: {sph}")
print(f"Should be filetype: {self.files[sph]['file_type']}")
if self.files[sph]['file_type'] == 'video':
r = True r = True
else: else:
r = False r = False
return r return r
def is_image(self,f): def is_image(self,sph):
if self.files[f]['type'] == 'image': if self.files[sph]['file_type'] == 'image':
r = True r = True
else: else:
r = False r = False
@ -392,51 +403,70 @@ class MainWindow(QMainWindow, Ui_MainWindow):
return r return r
def t_copy_files(self, def t_copy_files(self,
import_progress_callback, progress_callback,
current_file_progress_callback, current_file_progress_callback,
imported_file_count_callback imported_file_count_callback,
found_file_callback,
total_file_count_callback
): ):
""" Copy Files. """ """ Copy Files. """
count = int(0) count = int(0)
for file in self.files: for line in range(self.file_list.count()):
self.src_dir = self.files[file]['folders']['source_path'] item = self.file_list.item(line)
self.dst_dir = self.files[file]['folders']['destination'] file = item.text()
self.path_file_source = path.join(self.src_dir, self.process_file(file)
self.files[file]['name']) sph = self.get_source_path_hash(file)
self.path_file_destination = path.join(self.dst_dir, print(sph)
self.files[file]['name']) self.src_dir = self.files[sph]['folders']['source_path']
self.destination_original_path = path.join(self.dst_dir, self.dst_dir = self.files[sph]['folders']['destination']
self.files[file]['folders']['destination_original']) self.path_file_source = path.join(self.src_dir,
self.path_file_destination_original = path.join(self.dst_dir, self.files[sph]['name'])
self.files[file]['folders']['destination_original'], self.path_file_destination = path.join(self.dst_dir,
self.files[file]['name']) self.files[sph]['name'])
self.destination_original_path = path.join(self.dst_dir,
self.files[sph]['folders']['destination_original'])
self.path_file_destination_original = path.join(self.dst_dir,
self.files[sph]['folders']['destination_original'],
self.files[sph]['name'])
self.imp_dialog.set_importing_file(self.path_file_source) self.imp_dialog.set_importing_file(self.path_file_source)
self.copy_a_file( self.copy_a_file(
file, sph,
current_file_progress_callback) progress_callback,
current_file_progress_callback,
imported_file_count_callback,
found_file_callback,
total_file_count_callback
)
if self.check_store_original(file) is True: if self.check_store_original(sph) is True:
self.copy_a_file(file, self.copy_a_file(sph,
current_file_progress_callback) progress_callback,
current_file_progress_callback,
imported_file_count_callback,
found_file_callback,
total_file_count_callback)
count += 1 count += 1
imported_file_count_callback.emit(count) imported_file_count_callback.emit(count)
import_progress_callback.emit(round((count / self.file_total) * 100, 1)) progress_callback.emit(round((count / self.file_total) * 100, 1))
self.imp_dialog.add_to_imported_list(self.path_file_source) self.imp_dialog.add_to_imported_list(self.path_file_source)
def copy_a_file(self, def copy_a_file(self,
_f, fph,
current_file_progress_callback): progress_callback,
current_file_progress_callback,
imported_file_count_callback,
found_file_callback,
total_file_count_callback):
size = path.getsize(self.path_file_source) size = path.getsize(self.path_file_source)
create_folder(self.dst_dir) create_folder(self.dst_dir)
self.check_duplicate(_f) self.check_duplicate(fph)
if self.is_video(_f): if self.is_video(fph):
self.chunk_size = (1024 * 1024) * 5 self.chunk_size = (1024 * 1024) * 5
else: else:
self.chunk_size = (16 * 1024) * 1 self.chunk_size = (16 * 1024) * 1
@ -451,9 +481,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
dst_size = path.getsize(self.path_file_destination) dst_size = path.getsize(self.path_file_destination)
current_file_progress_callback.emit(round((dst_size / size) * 100, 1)) current_file_progress_callback.emit(round((dst_size / size) * 100, 1))
def check_store_original(self,_f): def check_store_original(self,sph):
if self.config['store_originals'] is True: if self.config['store_originals'] is True:
if self.is_image(_f): if self.is_image(sph):
self.dst_dir = self.destination_original_path self.dst_dir = self.destination_original_path
self.path_file_destination = self.path_file_destination_original self.path_file_destination = self.path_file_destination_original
r = True r = True
@ -464,12 +494,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
return r return r
def check_duplicate(self,_f): def check_duplicate(self,sph):
if path_exists(self.path_file_destination): if path_exists(self.path_file_destination):
check_match = cmp_files(self.path_file_source, self.path_file_destination) check_match = cmp_files(self.path_file_source, self.path_file_destination)
if check_match is False: if check_match is False:
print(f'\nFound duplicate for {self.path_file_source}, renaming destination with hash appended.') print(f'\nFound duplicate for {self.path_file_source}, renaming destination with hash appended.')
base, extension = path.splitext(self.files[_f]['name']) base, extension = path.splitext(self.files[sph]['name'])
f_xxhash = xx_hash(self.path_file_destination) f_xxhash = xx_hash(self.path_file_destination)
file_name_hash = base + '_' + f_xxhash + extension file_name_hash = base + '_' + f_xxhash + extension
rename(self.path_file_destination, path.join(self.dst_dir, file_name_hash)) rename(self.path_file_destination, path.join(self.dst_dir, file_name_hash))
@ -491,7 +521,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.worker_thread_started) self.worker_thread_started)
worker.signals.started.connect( worker.signals.started.connect(
self.imp_dialog.open_import_dialog) self.imp_dialog.open_import_dialog)
worker.signals.import_progress.connect( worker.signals.progress.connect(
self.imp_dialog.set_progress_importing) self.imp_dialog.set_progress_importing)
worker.signals.current_file_progress.connect( worker.signals.current_file_progress.connect(
self.imp_dialog.set_progress_current_file) self.imp_dialog.set_progress_current_file)

View File

@ -21,7 +21,7 @@ class MediaFile:
self.config = config self.config = config
self.event_name = str(event_name) self.event_name = str(event_name)
self.store_originals = self.config['store_originals'] self.store_originals = self.config['store_originals']
self.src_dir = self.config['folders']['source']['base'] self.src_dir = os.path.dirname(self.path_file_name)
self.base_dst_dir = self.config['folders']['destination']['base'] self.base_dst_dir = self.config['folders']['destination']['base']
self.source_path_hash = hash_path(self.path_file_name) self.source_path_hash = hash_path(self.path_file_name)
self.file_name = get_file_name(self.path_file_name) self.file_name = get_file_name(self.path_file_name)
@ -61,7 +61,7 @@ class MediaFile:
p = f'{p1}/{p2}/{p3}' # <--- Dumb. p = f'{p1}/{p2}/{p3}' # <--- Dumb.
if self.event_name: if self.event_name:
p4 = '-' + self.event_name p4 = '-' + self.event_name
p = os.path.join(p,p4) p = p + p4
if self.file_type == 'image': if self.file_type == 'image':
p = os.path.join(p,'PHOTO') p = os.path.join(p,'PHOTO')

View File

@ -15,15 +15,15 @@ class MediaPreview:
self.source_path_hash = hash_path(self.path_file_name) self.source_path_hash = hash_path(self.path_file_name)
# print(f'_preview.py,MediaPreview:\n\tpath_file_name: {self.path_file_name}\n\thash: {self.source_path_hash}\n\tmedia_files_list: {self.media_files_list}\n') # print(f'_preview.py,MediaPreview:\n\tpath_file_name: {self.path_file_name}\n\thash: {self.source_path_hash}\n\tmedia_files_list: {self.media_files_list}\n')
self.thumbnail = 'thumbnail.jpg' self.thumbnail = 'thumbnail.jpg'
self.thumbnail_ratio = self.media_files_list[self.source_path_hash]['image_meta']['photo']['size']['ratio']
self.file_type = self.media_files_list[self.source_path_hash]['file_type'] self.file_type = self.media_files_list[self.source_path_hash]['file_type']
if self.media_files_list[self.source_path_hash]['file_type'] == 'image': if self.media_files_list[self.source_path_hash]['file_type'] == 'image':
self.thumbnail_ratio = self.media_files_list[self.source_path_hash]['image_meta']['photo']['size']['ratio']
self.mpixels = self.media_files_list[self.source_path_hash]['image_meta']['photo']['size']['megapixels']
self._img_preview() self._img_preview()
elif self.media_files_list[self.source_path_hash]['file_type'] == 'video': elif self.media_files_list[self.source_path_hash]['file_type'] == 'video':
self._video_preview() self._video_preview()
self.mpixels = self.media_files_list[self.source_path_hash]['image_meta']['photo']['size']['megapixels']
def _img_preview(self): def _img_preview(self):
if self.media_files_list[self.source_path_hash]['image_meta']['photo']['is_jpg'] is True: if self.media_files_list[self.source_path_hash]['image_meta']['photo']['is_jpg'] is True:
@ -52,7 +52,7 @@ class MediaPreview:
self.thumbnail = extract_jpg_thumb(self.path_file_name) self.thumbnail = extract_jpg_thumb(self.path_file_name)
def _video_preview(self): def _video_preview(self):
vid = VideoFile(file=self.path_file_name) vid = VideoFile(path_file_name=self.path_file_name)
self.thumbnail = vid.gen_video_thumbnail() self.thumbnail = vid.gen_video_thumbnail()
self.width = self.media_files_list[self.source_path_hash]['video_meta']['video']['size']['width'] self.width = self.media_files_list[self.source_path_hash]['video_meta']['video']['size']['width']

View File

@ -39,6 +39,7 @@ class VideoFile:
""" """
Generate a thumbnail from a video Generate a thumbnail from a video
""" """
self.video_meta()
time_seconds = self.stream['video']['seconds'] // 5 time_seconds = self.stream['video']['seconds'] // 5
v_width = int(self.stream['video']['size']['width']) v_width = int(self.stream['video']['size']['width'])
width = self.set_thumb_width(v_width) width = self.set_thumb_width(v_width)
@ -117,6 +118,7 @@ class VideoFile:
'video': { 'video': {
'bits_per_raw_sample': self.video_stream['bits_per_raw_sample'], 'bits_per_raw_sample': self.video_stream['bits_per_raw_sample'],
'codec_long_name': self.video_stream['codec_long_name'], 'codec_long_name': self.video_stream['codec_long_name'],
'seconds': float(self.video_stream['duration']),
'duration': self.convert_from_seconds(float(self.video_stream['duration'])), 'duration': self.convert_from_seconds(float(self.video_stream['duration'])),
'encoding_brand': self.format_stream['tags']['major_brand'], 'encoding_brand': self.format_stream['tags']['major_brand'],
'pix_fmt': self.video_stream['pix_fmt'], 'pix_fmt': self.video_stream['pix_fmt'],