new stuff

This commit is contained in:
Kameron Kenny 2024-09-18 18:12:27 -04:00
parent 2a7262a273
commit 75d6105f89
No known key found for this signature in database
GPG Key ID: E5006629839D2276
13 changed files with 739 additions and 177 deletions

3
.gitignore vendored
View File

@ -1,5 +1,8 @@
*.swp *.swp
*.orig *.orig
*.spec
build/
dist/
config.yaml config.yaml
.DS_Store .DS_Store
.idea .idea

View File

@ -20,15 +20,12 @@
<x>20</x> <x>20</x>
<y>10</y> <y>10</y>
<width>871</width> <width>871</width>
<height>121</height> <height>71</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="grid_dir_selector"> <layout class="QGridLayout" name="grid_dir_selector">
<item row="1" column="0"> <item row="2" column="1">
<widget class="QLabel" name="label_1_src_dir"> <widget class="QLineEdit" name="lineEdit_dst_dir">
<property name="text">
<string>Source Directory</string>
</property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
@ -41,23 +38,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEdit_dst_dir">
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2_dst_dir">
<property name="text">
<string>Destination Directory</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QLineEdit" name="lineEdit_src_dir"> <widget class="QLineEdit" name="lineEdit_src_dir">
<property name="alignment"> <property name="alignment">
@ -72,31 +52,23 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="1" column="0">
<widget class="QPushButton" name="pushButton_3_scan_dir"> <widget class="QLabel" name="label_1_src_dir">
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>Scan Directory</string> <string>Source Directory</string>
</property> </property>
<property name="icon"> <property name="alignment">
<iconset theme="edit-find"> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="checkable"> </widget>
<bool>false</bool> </item>
<item row="2" column="0">
<widget class="QLabel" name="label_2_dst_dir">
<property name="text">
<string>Destination Directory</string>
</property> </property>
<property name="flat"> <property name="alignment">
<bool>false</bool> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
</widget> </widget>
</item> </item>
@ -106,7 +78,7 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>20</x> <x>20</x>
<y>150</y> <y>160</y>
<width>871</width> <width>871</width>
<height>701</height> <height>701</height>
</rect> </rect>
@ -116,9 +88,9 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>910</x> <x>910</x>
<y>580</y> <y>650</y>
<width>551</width> <width>311</width>
<height>251</height> <height>211</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="grid_metadata" columnstretch="0,1"> <layout class="QGridLayout" name="grid_metadata" columnstretch="0,1">
@ -136,6 +108,12 @@
</property> </property>
<item row="6" column="0"> <item row="6" column="0">
<widget class="QLabel" name="l_camera"> <widget class="QLabel" name="l_camera">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text"> <property name="text">
<string>Camera</string> <string>Camera</string>
</property> </property>
@ -143,6 +121,12 @@
</item> </item>
<item row="4" column="0"> <item row="4" column="0">
<widget class="QLabel" name="l_iso"> <widget class="QLabel" name="l_iso">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text"> <property name="text">
<string>ISO</string> <string>ISO</string>
</property> </property>
@ -157,6 +141,12 @@
</item> </item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="l_date_time_created"> <widget class="QLabel" name="l_date_time_created">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text"> <property name="text">
<string>Date / Time Created</string> <string>Date / Time Created</string>
</property> </property>
@ -164,6 +154,12 @@
</item> </item>
<item row="7" column="0"> <item row="7" column="0">
<widget class="QLabel" name="l_lens"> <widget class="QLabel" name="l_lens">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text"> <property name="text">
<string>Lens</string> <string>Lens</string>
</property> </property>
@ -171,6 +167,12 @@
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="l_dpi"> <widget class="QLabel" name="l_dpi">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text"> <property name="text">
<string>Resolution (DPI)</string> <string>Resolution (DPI)</string>
</property> </property>
@ -178,6 +180,12 @@
</item> </item>
<item row="5" column="0"> <item row="5" column="0">
<widget class="QLabel" name="l_aperture"> <widget class="QLabel" name="l_aperture">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text"> <property name="text">
<string>Aperture</string> <string>Aperture</string>
</property> </property>
@ -206,6 +214,12 @@
</item> </item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="l_megapixels"> <widget class="QLabel" name="l_megapixels">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text"> <property name="text">
<string>Megapixels</string> <string>Megapixels</string>
</property> </property>
@ -220,6 +234,12 @@
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="l_width_height"> <widget class="QLabel" name="l_width_height">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text"> <property name="text">
<string>Width / Height</string> <string>Width / Height</string>
</property> </property>
@ -241,8 +261,14 @@
</item> </item>
<item row="8" column="0"> <item row="8" column="0">
<widget class="QLabel" name="l_zoom"> <widget class="QLabel" name="l_zoom">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text"> <property name="text">
<string>Zoom</string> <string>Focal Length</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -266,7 +292,7 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>910</x> <x>910</x>
<y>550</y> <y>630</y>
<width>371</width> <width>371</width>
<height>16</height> <height>16</height>
</rect> </rect>
@ -341,28 +367,28 @@
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="1"> <item row="0" column="1">
<widget class="QProgressBar" name="progressBar_overall"> <widget class="QProgressBar" name="progressBar_processing">
<property name="value"> <property name="value">
<number>24</number> <number>24</number>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="l_import_progress">
<property name="text"> <property name="text">
<string>Current Progress</string> <string>Import Progress</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="l_proecessing_progress">
<property name="text"> <property name="text">
<string>Overall Progress</string> <string>Processing Progress</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QProgressBar" name="progressBar_current"> <widget class="QProgressBar" name="progressBar_importing">
<property name="value"> <property name="value">
<number>24</number> <number>24</number>
</property> </property>
@ -389,6 +415,265 @@
<string/> <string/>
</property> </property>
</widget> </widget>
<widget class="QWidget" name="gridLayoutWidget_6">
<property name="geometry">
<rect>
<x>910</x>
<y>530</y>
<width>541</width>
<height>91</height>
</rect>
</property>
<layout class="QGridLayout" name="grid_metadata_2" rowstretch="0,1,0,1" columnstretch="0">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="horizontalSpacing">
<number>20</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="l_data_file_source_path">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="l_file_source_path">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Source Path</string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="l_file_dest_path">
<property name="font">
<font>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Destination Path</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="l_data_file_dest_path">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget_2">
<property name="geometry">
<rect>
<x>20</x>
<y>119</y>
<width>871</width>
<height>35</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkBox_verify_checksum">
<property name="toolTip">
<string>After copying, verify that the hash of the original file equals the hash of the copied file.</string>
</property>
<property name="text">
<string>Validate Checksum</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_cleanup_files">
<property name="toolTip">
<string>After copy, delete the copied files in the source directory. This automatically enables checksum validation and will not delete the source file if the file hashes do not match.</string>
</property>
<property name="text">
<string>Cleanup Files</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_store_originals">
<property name="toolTip">
<string>For images only, create a folder called &quot;Originals&quot; at the destination and place an additional copy of the image in it. This is useful for those who use editors that still do destructive editing.</string>
</property>
<property name="text">
<string>Store Originals</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_import">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Import Media</string>
</property>
<property name="icon">
<iconset theme="drive-harddisk"/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget_3">
<property name="geometry">
<rect>
<x>20</x>
<y>80</y>
<width>871</width>
<height>35</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Search For</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkBox_search_for_images">
<property name="text">
<string>Images</string>
</property>
<property name="icon">
<iconset theme="camera-photo"/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_search_for_video">
<property name="text">
<string>Video</string>
</property>
<property name="icon">
<iconset theme="camera-video"/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_search_for_audio">
<property name="text">
<string>Audio</string>
</property>
<property name="icon">
<iconset theme="multimedia-player"/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_3_scan_dir">
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="text">
<string>Scan Directory</string>
</property>
<property name="icon">
<iconset theme="edit-find">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
<widget class="QMenuBar" name="menubar"> <widget class="QMenuBar" name="menubar">
<property name="geometry"> <property name="geometry">

View File

@ -8,6 +8,7 @@
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object): class Ui_MainWindow(object):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow") MainWindow.setObjectName("MainWindow")
@ -15,26 +16,18 @@ class Ui_MainWindow(object):
self.centralwidget = QtWidgets.QWidget(parent=MainWindow) self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
self.centralwidget.setObjectName("centralwidget") self.centralwidget.setObjectName("centralwidget")
self.gridLayoutWidget = QtWidgets.QWidget(parent=self.centralwidget) self.gridLayoutWidget = QtWidgets.QWidget(parent=self.centralwidget)
self.gridLayoutWidget.setGeometry(QtCore.QRect(20, 10, 871, 121)) self.gridLayoutWidget.setGeometry(QtCore.QRect(20, 10, 871, 71))
self.gridLayoutWidget.setObjectName("gridLayoutWidget") self.gridLayoutWidget.setObjectName("gridLayoutWidget")
self.grid_dir_selector = QtWidgets.QGridLayout(self.gridLayoutWidget) self.grid_dir_selector = QtWidgets.QGridLayout(self.gridLayoutWidget)
self.grid_dir_selector.setContentsMargins(0, 0, 0, 0) self.grid_dir_selector.setContentsMargins(0, 0, 0, 0)
self.grid_dir_selector.setObjectName("grid_dir_selector") self.grid_dir_selector.setObjectName("grid_dir_selector")
self.label_1_src_dir = QtWidgets.QLabel(parent=self.gridLayoutWidget)
self.label_1_src_dir.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop)
self.label_1_src_dir.setObjectName("label_1_src_dir")
self.grid_dir_selector.addWidget(self.label_1_src_dir, 1, 0, 1, 1)
self.pushButton_src_browse = QtWidgets.QPushButton(parent=self.gridLayoutWidget)
self.pushButton_src_browse.setObjectName("pushButton_src_browse")
self.grid_dir_selector.addWidget(self.pushButton_src_browse, 1, 2, 1, 1)
self.lineEdit_dst_dir = QtWidgets.QLineEdit(parent=self.gridLayoutWidget) self.lineEdit_dst_dir = QtWidgets.QLineEdit(parent=self.gridLayoutWidget)
self.lineEdit_dst_dir.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop) self.lineEdit_dst_dir.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop)
self.lineEdit_dst_dir.setObjectName("lineEdit_dst_dir") self.lineEdit_dst_dir.setObjectName("lineEdit_dst_dir")
self.grid_dir_selector.addWidget(self.lineEdit_dst_dir, 2, 1, 1, 1) self.grid_dir_selector.addWidget(self.lineEdit_dst_dir, 2, 1, 1, 1)
self.label_2_dst_dir = QtWidgets.QLabel(parent=self.gridLayoutWidget) self.pushButton_src_browse = QtWidgets.QPushButton(parent=self.gridLayoutWidget)
self.label_2_dst_dir.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop) self.pushButton_src_browse.setObjectName("pushButton_src_browse")
self.label_2_dst_dir.setObjectName("label_2_dst_dir") self.grid_dir_selector.addWidget(self.pushButton_src_browse, 1, 2, 1, 1)
self.grid_dir_selector.addWidget(self.label_2_dst_dir, 2, 0, 1, 1)
self.lineEdit_src_dir = QtWidgets.QLineEdit(parent=self.gridLayoutWidget) self.lineEdit_src_dir = QtWidgets.QLineEdit(parent=self.gridLayoutWidget)
self.lineEdit_src_dir.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop) self.lineEdit_src_dir.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop)
self.lineEdit_src_dir.setObjectName("lineEdit_src_dir") self.lineEdit_src_dir.setObjectName("lineEdit_src_dir")
@ -42,31 +35,36 @@ class Ui_MainWindow(object):
self.pushButton_dst_browse = QtWidgets.QPushButton(parent=self.gridLayoutWidget) self.pushButton_dst_browse = QtWidgets.QPushButton(parent=self.gridLayoutWidget)
self.pushButton_dst_browse.setObjectName("pushButton_dst_browse") self.pushButton_dst_browse.setObjectName("pushButton_dst_browse")
self.grid_dir_selector.addWidget(self.pushButton_dst_browse, 2, 2, 1, 1) self.grid_dir_selector.addWidget(self.pushButton_dst_browse, 2, 2, 1, 1)
self.pushButton_3_scan_dir = QtWidgets.QPushButton(parent=self.gridLayoutWidget) self.label_1_src_dir = QtWidgets.QLabel(parent=self.gridLayoutWidget)
self.pushButton_3_scan_dir.setBaseSize(QtCore.QSize(0, 0)) self.label_1_src_dir.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop)
font = QtGui.QFont() self.label_1_src_dir.setObjectName("label_1_src_dir")
font.setPointSize(16) self.grid_dir_selector.addWidget(self.label_1_src_dir, 1, 0, 1, 1)
self.pushButton_3_scan_dir.setFont(font) self.label_2_dst_dir = QtWidgets.QLabel(parent=self.gridLayoutWidget)
icon = QtGui.QIcon.fromTheme("edit-find") self.label_2_dst_dir.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop)
self.pushButton_3_scan_dir.setIcon(icon) self.label_2_dst_dir.setObjectName("label_2_dst_dir")
self.pushButton_3_scan_dir.setCheckable(False) self.grid_dir_selector.addWidget(self.label_2_dst_dir, 2, 0, 1, 1)
self.pushButton_3_scan_dir.setFlat(False)
self.pushButton_3_scan_dir.setObjectName("pushButton_3_scan_dir")
self.grid_dir_selector.addWidget(self.pushButton_3_scan_dir, 3, 0, 1, 1)
self.file_list = QtWidgets.QListWidget(parent=self.centralwidget) self.file_list = QtWidgets.QListWidget(parent=self.centralwidget)
self.file_list.setGeometry(QtCore.QRect(20, 150, 871, 701)) self.file_list.setGeometry(QtCore.QRect(20, 160, 871, 701))
self.file_list.setObjectName("file_list") self.file_list.setObjectName("file_list")
self.gridLayoutWidget_2 = QtWidgets.QWidget(parent=self.centralwidget) self.gridLayoutWidget_2 = QtWidgets.QWidget(parent=self.centralwidget)
self.gridLayoutWidget_2.setGeometry(QtCore.QRect(910, 580, 551, 251)) self.gridLayoutWidget_2.setGeometry(QtCore.QRect(910, 650, 311, 211))
self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2") self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2")
self.grid_metadata = QtWidgets.QGridLayout(self.gridLayoutWidget_2) self.grid_metadata = QtWidgets.QGridLayout(self.gridLayoutWidget_2)
self.grid_metadata.setContentsMargins(0, 0, 0, 0) self.grid_metadata.setContentsMargins(0, 0, 0, 0)
self.grid_metadata.setHorizontalSpacing(20) self.grid_metadata.setHorizontalSpacing(20)
self.grid_metadata.setObjectName("grid_metadata") self.grid_metadata.setObjectName("grid_metadata")
self.l_camera = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.l_camera = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_camera.setFont(font)
self.l_camera.setObjectName("l_camera") self.l_camera.setObjectName("l_camera")
self.grid_metadata.addWidget(self.l_camera, 6, 0, 1, 1) self.grid_metadata.addWidget(self.l_camera, 6, 0, 1, 1)
self.l_iso = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.l_iso = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_iso.setFont(font)
self.l_iso.setObjectName("l_iso") self.l_iso.setObjectName("l_iso")
self.grid_metadata.addWidget(self.l_iso, 4, 0, 1, 1) self.grid_metadata.addWidget(self.l_iso, 4, 0, 1, 1)
self.label_data_width_height = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.label_data_width_height = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
@ -74,15 +72,31 @@ class Ui_MainWindow(object):
self.label_data_width_height.setObjectName("label_data_width_height") self.label_data_width_height.setObjectName("label_data_width_height")
self.grid_metadata.addWidget(self.label_data_width_height, 1, 1, 1, 1) self.grid_metadata.addWidget(self.label_data_width_height, 1, 1, 1, 1)
self.l_date_time_created = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.l_date_time_created = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_date_time_created.setFont(font)
self.l_date_time_created.setObjectName("l_date_time_created") self.l_date_time_created.setObjectName("l_date_time_created")
self.grid_metadata.addWidget(self.l_date_time_created, 0, 0, 1, 1) self.grid_metadata.addWidget(self.l_date_time_created, 0, 0, 1, 1)
self.l_lens = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.l_lens = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_lens.setFont(font)
self.l_lens.setObjectName("l_lens") self.l_lens.setObjectName("l_lens")
self.grid_metadata.addWidget(self.l_lens, 7, 0, 1, 1) self.grid_metadata.addWidget(self.l_lens, 7, 0, 1, 1)
self.l_dpi = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.l_dpi = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_dpi.setFont(font)
self.l_dpi.setObjectName("l_dpi") self.l_dpi.setObjectName("l_dpi")
self.grid_metadata.addWidget(self.l_dpi, 2, 0, 1, 1) self.grid_metadata.addWidget(self.l_dpi, 2, 0, 1, 1)
self.l_aperture = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.l_aperture = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_aperture.setFont(font)
self.l_aperture.setObjectName("l_aperture") self.l_aperture.setObjectName("l_aperture")
self.grid_metadata.addWidget(self.l_aperture, 5, 0, 1, 1) self.grid_metadata.addWidget(self.l_aperture, 5, 0, 1, 1)
self.label_data_iso = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.label_data_iso = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
@ -98,6 +112,10 @@ class Ui_MainWindow(object):
self.label_data_lens.setObjectName("label_data_lens") self.label_data_lens.setObjectName("label_data_lens")
self.grid_metadata.addWidget(self.label_data_lens, 7, 1, 1, 1) self.grid_metadata.addWidget(self.label_data_lens, 7, 1, 1, 1)
self.l_megapixels = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.l_megapixels = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_megapixels.setFont(font)
self.l_megapixels.setObjectName("l_megapixels") self.l_megapixels.setObjectName("l_megapixels")
self.grid_metadata.addWidget(self.l_megapixels, 3, 0, 1, 1) self.grid_metadata.addWidget(self.l_megapixels, 3, 0, 1, 1)
self.label_data_megapixels = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.label_data_megapixels = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
@ -105,6 +123,10 @@ class Ui_MainWindow(object):
self.label_data_megapixels.setObjectName("label_data_megapixels") self.label_data_megapixels.setObjectName("label_data_megapixels")
self.grid_metadata.addWidget(self.label_data_megapixels, 3, 1, 1, 1) self.grid_metadata.addWidget(self.label_data_megapixels, 3, 1, 1, 1)
self.l_width_height = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.l_width_height = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_width_height.setFont(font)
self.l_width_height.setObjectName("l_width_height") self.l_width_height.setObjectName("l_width_height")
self.grid_metadata.addWidget(self.l_width_height, 1, 0, 1, 1) self.grid_metadata.addWidget(self.l_width_height, 1, 0, 1, 1)
self.label_data_date_time_created = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.label_data_date_time_created = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
@ -116,6 +138,10 @@ class Ui_MainWindow(object):
self.label_data_camera.setObjectName("label_data_camera") self.label_data_camera.setObjectName("label_data_camera")
self.grid_metadata.addWidget(self.label_data_camera, 6, 1, 1, 1) self.grid_metadata.addWidget(self.label_data_camera, 6, 1, 1, 1)
self.l_zoom = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.l_zoom = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_zoom.setFont(font)
self.l_zoom.setObjectName("l_zoom") self.l_zoom.setObjectName("l_zoom")
self.grid_metadata.addWidget(self.l_zoom, 8, 0, 1, 1) self.grid_metadata.addWidget(self.l_zoom, 8, 0, 1, 1)
self.label_data_zoom = QtWidgets.QLabel(parent=self.gridLayoutWidget_2) self.label_data_zoom = QtWidgets.QLabel(parent=self.gridLayoutWidget_2)
@ -128,7 +154,7 @@ class Ui_MainWindow(object):
self.grid_metadata.addWidget(self.label_data_dpi, 2, 1, 1, 1) self.grid_metadata.addWidget(self.label_data_dpi, 2, 1, 1, 1)
self.grid_metadata.setColumnStretch(1, 1) self.grid_metadata.setColumnStretch(1, 1)
self.l_exif_ffprobe_title = QtWidgets.QLabel(parent=self.centralwidget) self.l_exif_ffprobe_title = QtWidgets.QLabel(parent=self.centralwidget)
self.l_exif_ffprobe_title.setGeometry(QtCore.QRect(910, 550, 371, 16)) self.l_exif_ffprobe_title.setGeometry(QtCore.QRect(910, 630, 371, 16))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(18) font.setPointSize(18)
font.setBold(True) font.setBold(True)
@ -168,26 +194,132 @@ class Ui_MainWindow(object):
self.gridLayout_3 = QtWidgets.QGridLayout(self.gridLayoutWidget_5) self.gridLayout_3 = QtWidgets.QGridLayout(self.gridLayoutWidget_5)
self.gridLayout_3.setContentsMargins(0, 0, 0, 0) self.gridLayout_3.setContentsMargins(0, 0, 0, 0)
self.gridLayout_3.setObjectName("gridLayout_3") self.gridLayout_3.setObjectName("gridLayout_3")
self.progressBar_overall = QtWidgets.QProgressBar(parent=self.gridLayoutWidget_5) self.progressBar_processing = QtWidgets.QProgressBar(parent=self.gridLayoutWidget_5)
self.progressBar_overall.setProperty("value", 0) self.progressBar_processing.setProperty("value", 24)
self.progressBar_overall.setObjectName("progressBar_overall") self.progressBar_processing.setObjectName("progressBar_processing")
self.gridLayout_3.addWidget(self.progressBar_overall, 0, 1, 1, 1) self.gridLayout_3.addWidget(self.progressBar_processing, 0, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(parent=self.gridLayoutWidget_5) self.l_import_progress = QtWidgets.QLabel(parent=self.gridLayoutWidget_5)
self.label_2.setObjectName("label_2") self.l_import_progress.setObjectName("l_import_progress")
self.gridLayout_3.addWidget(self.label_2, 1, 0, 1, 1) self.gridLayout_3.addWidget(self.l_import_progress, 1, 0, 1, 1)
self.label = QtWidgets.QLabel(parent=self.gridLayoutWidget_5) self.l_proecessing_progress = QtWidgets.QLabel(parent=self.gridLayoutWidget_5)
self.label.setObjectName("label") self.l_proecessing_progress.setObjectName("l_proecessing_progress")
self.gridLayout_3.addWidget(self.label, 0, 0, 1, 1) self.gridLayout_3.addWidget(self.l_proecessing_progress, 0, 0, 1, 1)
self.progressBar_current = QtWidgets.QProgressBar(parent=self.gridLayoutWidget_5) self.progressBar_importing = QtWidgets.QProgressBar(parent=self.gridLayoutWidget_5)
self.progressBar_current.setProperty("value", 0) self.progressBar_importing.setProperty("value", 24)
self.progressBar_current.setObjectName("progressBar_current") self.progressBar_importing.setObjectName("progressBar_importing")
self.gridLayout_3.addWidget(self.progressBar_current, 1, 1, 1, 1) self.gridLayout_3.addWidget(self.progressBar_importing, 1, 1, 1, 1)
self.img_preview = QtWidgets.QLabel(parent=self.centralwidget) self.img_preview = QtWidgets.QLabel(parent=self.centralwidget)
self.img_preview.setGeometry(QtCore.QRect(910, 150, 541, 371)) self.img_preview.setGeometry(QtCore.QRect(910, 150, 541, 371))
self.img_preview.setAutoFillBackground(True) self.img_preview.setAutoFillBackground(True)
self.img_preview.setFrameShape(QtWidgets.QFrame.Shape.StyledPanel) self.img_preview.setFrameShape(QtWidgets.QFrame.Shape.StyledPanel)
self.img_preview.setText("") self.img_preview.setText("")
self.img_preview.setObjectName("img_preview") self.img_preview.setObjectName("img_preview")
self.gridLayoutWidget_6 = QtWidgets.QWidget(parent=self.centralwidget)
self.gridLayoutWidget_6.setGeometry(QtCore.QRect(910, 530, 541, 91))
self.gridLayoutWidget_6.setObjectName("gridLayoutWidget_6")
self.grid_metadata_2 = QtWidgets.QGridLayout(self.gridLayoutWidget_6)
self.grid_metadata_2.setContentsMargins(0, 0, 0, 0)
self.grid_metadata_2.setHorizontalSpacing(20)
self.grid_metadata_2.setObjectName("grid_metadata_2")
self.l_data_file_source_path = QtWidgets.QLabel(parent=self.gridLayoutWidget_6)
font = QtGui.QFont()
font.setPointSize(11)
self.l_data_file_source_path.setFont(font)
self.l_data_file_source_path.setText("")
self.l_data_file_source_path.setObjectName("l_data_file_source_path")
self.grid_metadata_2.addWidget(self.l_data_file_source_path, 1, 0, 1, 1)
self.l_file_source_path = QtWidgets.QLabel(parent=self.gridLayoutWidget_6)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_file_source_path.setFont(font)
self.l_file_source_path.setScaledContents(False)
self.l_file_source_path.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop)
self.l_file_source_path.setObjectName("l_file_source_path")
self.grid_metadata_2.addWidget(self.l_file_source_path, 0, 0, 1, 1)
self.l_file_dest_path = QtWidgets.QLabel(parent=self.gridLayoutWidget_6)
font = QtGui.QFont()
font.setBold(True)
font.setItalic(True)
self.l_file_dest_path.setFont(font)
self.l_file_dest_path.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop)
self.l_file_dest_path.setObjectName("l_file_dest_path")
self.grid_metadata_2.addWidget(self.l_file_dest_path, 2, 0, 1, 1)
self.l_data_file_dest_path = QtWidgets.QLabel(parent=self.gridLayoutWidget_6)
font = QtGui.QFont()
font.setPointSize(11)
self.l_data_file_dest_path.setFont(font)
self.l_data_file_dest_path.setText("")
self.l_data_file_dest_path.setObjectName("l_data_file_dest_path")
self.grid_metadata_2.addWidget(self.l_data_file_dest_path, 3, 0, 1, 1)
self.grid_metadata_2.setRowStretch(1, 1)
self.grid_metadata_2.setRowStretch(3, 1)
self.horizontalLayoutWidget_2 = QtWidgets.QWidget(parent=self.centralwidget)
self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(20, 119, 871, 35))
self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_2.addItem(spacerItem)
self.checkBox_verify_checksum = QtWidgets.QCheckBox(parent=self.horizontalLayoutWidget_2)
self.checkBox_verify_checksum.setChecked(True)
self.checkBox_verify_checksum.setObjectName("checkBox_verify_checksum")
self.horizontalLayout_2.addWidget(self.checkBox_verify_checksum)
self.checkBox_cleanup_files = QtWidgets.QCheckBox(parent=self.horizontalLayoutWidget_2)
self.checkBox_cleanup_files.setChecked(False)
self.checkBox_cleanup_files.setObjectName("checkBox_cleanup_files")
self.horizontalLayout_2.addWidget(self.checkBox_cleanup_files)
self.checkBox_store_originals = QtWidgets.QCheckBox(parent=self.horizontalLayoutWidget_2)
self.checkBox_store_originals.setChecked(False)
self.checkBox_store_originals.setObjectName("checkBox_store_originals")
self.horizontalLayout_2.addWidget(self.checkBox_store_originals)
self.pushButton_import = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget_2)
self.pushButton_import.setEnabled(False)
icon = QtGui.QIcon.fromTheme("drive-harddisk")
self.pushButton_import.setIcon(icon)
self.pushButton_import.setObjectName("pushButton_import")
self.horizontalLayout_2.addWidget(self.pushButton_import)
self.horizontalLayoutWidget_3 = QtWidgets.QWidget(parent=self.centralwidget)
self.horizontalLayoutWidget_3.setGeometry(QtCore.QRect(20, 80, 871, 35))
self.horizontalLayoutWidget_3.setObjectName("horizontalLayoutWidget_3")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_3)
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.label = QtWidgets.QLabel(parent=self.horizontalLayoutWidget_3)
self.label.setObjectName("label")
self.horizontalLayout_3.addWidget(self.label)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_3.addItem(spacerItem1)
self.checkBox_search_for_images = QtWidgets.QCheckBox(parent=self.horizontalLayoutWidget_3)
icon = QtGui.QIcon.fromTheme("camera-photo")
self.checkBox_search_for_images.setIcon(icon)
self.checkBox_search_for_images.setChecked(True)
self.checkBox_search_for_images.setObjectName("checkBox_search_for_images")
self.horizontalLayout_3.addWidget(self.checkBox_search_for_images)
self.checkBox_search_for_video = QtWidgets.QCheckBox(parent=self.horizontalLayoutWidget_3)
icon = QtGui.QIcon.fromTheme("camera-video")
self.checkBox_search_for_video.setIcon(icon)
self.checkBox_search_for_video.setChecked(True)
self.checkBox_search_for_video.setObjectName("checkBox_search_for_video")
self.horizontalLayout_3.addWidget(self.checkBox_search_for_video)
self.checkBox_search_for_audio = QtWidgets.QCheckBox(parent=self.horizontalLayoutWidget_3)
icon = QtGui.QIcon.fromTheme("multimedia-player")
self.checkBox_search_for_audio.setIcon(icon)
self.checkBox_search_for_audio.setChecked(True)
self.checkBox_search_for_audio.setObjectName("checkBox_search_for_audio")
self.horizontalLayout_3.addWidget(self.checkBox_search_for_audio)
self.pushButton_3_scan_dir = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget_3)
self.pushButton_3_scan_dir.setBaseSize(QtCore.QSize(0, 0))
font = QtGui.QFont()
font.setPointSize(16)
self.pushButton_3_scan_dir.setFont(font)
icon = QtGui.QIcon.fromTheme("edit-find")
self.pushButton_3_scan_dir.setIcon(icon)
self.pushButton_3_scan_dir.setCheckable(False)
self.pushButton_3_scan_dir.setFlat(False)
self.pushButton_3_scan_dir.setObjectName("pushButton_3_scan_dir")
self.horizontalLayout_3.addWidget(self.pushButton_3_scan_dir)
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(parent=MainWindow) self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1473, 24)) self.menubar.setGeometry(QtCore.QRect(0, 0, 1473, 24))
@ -208,11 +340,10 @@ class Ui_MainWindow(object):
def retranslateUi(self, MainWindow): def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label_1_src_dir.setText(_translate("MainWindow", "Source Directory"))
self.pushButton_src_browse.setText(_translate("MainWindow", "Browse")) self.pushButton_src_browse.setText(_translate("MainWindow", "Browse"))
self.label_2_dst_dir.setText(_translate("MainWindow", "Destination Directory"))
self.pushButton_dst_browse.setText(_translate("MainWindow", "Browse")) self.pushButton_dst_browse.setText(_translate("MainWindow", "Browse"))
self.pushButton_3_scan_dir.setText(_translate("MainWindow", "Scan Directory")) self.label_1_src_dir.setText(_translate("MainWindow", "Source Directory"))
self.label_2_dst_dir.setText(_translate("MainWindow", "Destination Directory"))
self.l_camera.setText(_translate("MainWindow", "Camera")) self.l_camera.setText(_translate("MainWindow", "Camera"))
self.l_iso.setText(_translate("MainWindow", "ISO")) self.l_iso.setText(_translate("MainWindow", "ISO"))
self.l_date_time_created.setText(_translate("MainWindow", "Date / Time Created")) self.l_date_time_created.setText(_translate("MainWindow", "Date / Time Created"))
@ -221,11 +352,25 @@ class Ui_MainWindow(object):
self.l_aperture.setText(_translate("MainWindow", "Aperture")) self.l_aperture.setText(_translate("MainWindow", "Aperture"))
self.l_megapixels.setText(_translate("MainWindow", "Megapixels")) self.l_megapixels.setText(_translate("MainWindow", "Megapixels"))
self.l_width_height.setText(_translate("MainWindow", "Width / Height")) self.l_width_height.setText(_translate("MainWindow", "Width / Height"))
self.l_zoom.setText(_translate("MainWindow", "Zoom")) self.l_zoom.setText(_translate("MainWindow", "Focal Length"))
self.l_exif_ffprobe_title.setText(_translate("MainWindow", "Exif / ffprobe Data")) self.l_exif_ffprobe_title.setText(_translate("MainWindow", "Exif / ffprobe Data"))
self.labelEvent.setText(_translate("MainWindow", "Event Label")) self.labelEvent.setText(_translate("MainWindow", "Event Label"))
self.label_3.setText(_translate("MainWindow", "Files Found")) self.label_3.setText(_translate("MainWindow", "Files Found"))
self.label_2.setText(_translate("MainWindow", "Current Progress")) self.l_import_progress.setText(_translate("MainWindow", "Import Progress"))
self.label.setText(_translate("MainWindow", "Overall Progress")) self.l_proecessing_progress.setText(_translate("MainWindow", "Processing Progress"))
self.l_file_source_path.setText(_translate("MainWindow", "Source Path"))
self.l_file_dest_path.setText(_translate("MainWindow", "Destination Path"))
self.checkBox_verify_checksum.setToolTip(_translate("MainWindow", "After copying, verify that the hash of the original file equals the hash of the copied file."))
self.checkBox_verify_checksum.setText(_translate("MainWindow", "Validate Checksum"))
self.checkBox_cleanup_files.setToolTip(_translate("MainWindow", "After copy, delete the copied files in the source directory. This automatically enables checksum validation and will not delete the source file if the file hashes do not match."))
self.checkBox_cleanup_files.setText(_translate("MainWindow", "Cleanup Files"))
self.checkBox_store_originals.setToolTip(_translate("MainWindow", "For images only, create a folder called \"Originals\" at the destination and place an additional copy of the image in it. This is useful for those who use editors that still do destructive editing."))
self.checkBox_store_originals.setText(_translate("MainWindow", "Store Originals"))
self.pushButton_import.setText(_translate("MainWindow", "Import Media"))
self.label.setText(_translate("MainWindow", "Search For"))
self.checkBox_search_for_images.setText(_translate("MainWindow", "Images"))
self.checkBox_search_for_video.setText(_translate("MainWindow", "Video"))
self.checkBox_search_for_audio.setText(_translate("MainWindow", "Audio"))
self.pushButton_3_scan_dir.setText(_translate("MainWindow", "Scan Directory"))
self.menuBit_Mover.setTitle(_translate("MainWindow", "Bit Mover")) self.menuBit_Mover.setTitle(_translate("MainWindow", "Bit Mover"))
self.actionScan_Directory.setText(_translate("MainWindow", "Scan Directory")) self.actionScan_Directory.setText(_translate("MainWindow", "Scan Directory"))

View File

@ -11,11 +11,11 @@ from file_stuff import is_file
from BitMover_MainWindow import Ui_MainWindow from BitMover_MainWindow import Ui_MainWindow
from media import Media from media import Media
from lumberjack import timber from lumberjack import timber
from raw_photo import extract_jpg_thumb
from thread_my_stuff import Worker from thread_my_stuff import Worker
from img_preview import ImgPreview from img_preview import ImgPreview
log = timber(__name__) log = timber(__name__)
basedir = os.path.dirname(__file__)
# Subclass QMainWindow to customize your application's main window # Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow, Ui_MainWindow): class MainWindow(QMainWindow, Ui_MainWindow):
@ -24,7 +24,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.setupUi(self) self.setupUi(self)
self.setWindowTitle("BitMover") self.setWindowTitle("BitMover")
self.setWindowIcon(QIcon('assets/forklift.png')) self.setWindowIcon(QIcon(os.path.join(basedir,'assets', 'forklift.ico')))
c = Configure(CONFIG_FILE) c = Configure(CONFIG_FILE)
self.config = c.load_config() self.config = c.load_config()
@ -42,8 +42,11 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# Initialize widgets # Initialize widgets
self.lcd_files_found.display(int(0)) self.lcd_files_found.display(int(0))
self.set_progress(0, 0) self.set_progress_processing(0)
self.img_preview.setPixmap(QPixmap('assets/preview_placeholder.jpg')) self.set_progress_importing(0)
self.img_preview.setPixmap(QPixmap(os.path.join(basedir,
'assets',
'preview_placeholder.jpg')))
self.img_preview.setScaledContents(True) self.img_preview.setScaledContents(True)
self.file_list.currentItemChanged.connect(self.index_changed) self.file_list.currentItemChanged.connect(self.index_changed)
@ -59,10 +62,19 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def toggle_scan_button(self,enable=True): def toggle_scan_button(self,enable=True):
self.pushButton_3_scan_dir.setEnabled(enable) self.pushButton_3_scan_dir.setEnabled(enable)
def index_changed(self,i): def update_preview(self,i):
preview = ImgPreview(file=i.text(),event=self.get_event(),config=self.config) preview = ImgPreview(file=i.text(), event=self.get_event(), config=self.config)
self.label_data_date_time_created.setText(preview.dtc) self.label_data_date_time_created.setText(preview.dtc)
path_hash = preview.path_hash
self.l_data_file_source_path.setText(
self.files[path_hash]['folders']['source_path'])
self.l_data_file_dest_path.setText(
self.files[path_hash]['folders']['destination'])
self.img_preview.setPixmap(QPixmap(preview.thumbnail))
self.img_preview.setFixedHeight(self.img_preview.width() / preview.thumbnail_ratio)
if preview.file_type == 'image': if preview.file_type == 'image':
self.label_data_width_height.setText(str(preview.size)) self.label_data_width_height.setText(str(preview.size))
@ -73,15 +85,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.label_data_camera.setText(str(preview.camera)) self.label_data_camera.setText(str(preview.camera))
self.label_data_aperture.setText(str(preview.aperture)) self.label_data_aperture.setText(str(preview.aperture))
self.label_data_megapixels.setText(str(preview.mpixels)) self.label_data_megapixels.setText(str(preview.mpixels))
#
# h = self.img_preview.width * (preview.height / preview.width)
# self.img_preview.setFixedHeight(h)
if preview.is_jpg: def index_changed(self,i):
self.img_preview.setPixmap(QPixmap(preview.file)) if i is None:
else: self.img_preview.setPixmap(QPixmap(os.path.join(basedir,
jpg = extract_jpg_thumb(preview.file) 'assets',
self.img_preview.setPixmap(QPixmap(jpg)) 'preview_placeholder.jpg')))
else:
self.update_preview(i)
def select_src_directory(self): def select_src_directory(self):
directory = QFileDialog.getExistingDirectory(self, directory = QFileDialog.getExistingDirectory(self,
@ -107,25 +118,17 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.total_files = t self.total_files = t
self.lcd_files_found.display(self.total_files) self.lcd_files_found.display(self.total_files)
def progress_fn(self,n): def set_progress_processing(self, n):
# print("%d%% done" % n) # print("%d%% done" % n)
self.progressBar_overall.setValue(int(n)) self.progressBar_processing.setValue(int(n))
def set_progress(self,p,t): def set_progress_importing(self, n):
""" # print("%d%% done" % n)
set progress for bar, self.progressBar_importing.setValue(int(n))
p = progress counter
t = target total
"""
if int(t) == 0:
t += 1
percent_complete = (int(p) / int(t)) * 100 def get_t_files(self,search_types):
self.progressBar_overall.setValue(int(percent_complete))
def get_t_files(self):
for folder, subfolders, filename in os.walk(self.src_dir): for folder, subfolders, filename in os.walk(self.src_dir):
for f_type in self.file_types: for f_type in search_types:
for ext in self.file_types[f_type]: for ext in self.file_types[f_type]:
for file in filename: for file in filename:
if file.lower().endswith(ext): if file.lower().endswith(ext):
@ -137,25 +140,39 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def t_find_files(self,progress_callback): def t_find_files(self,progress_callback):
file_count = int(0) file_count = int(0)
self.get_t_files()
search_types = []
if self.checkBox_search_for_images.isChecked():
search_types.append('image')
if self.checkBox_search_for_video.isChecked():
search_types.append('video')
if self.checkBox_search_for_audio.isChecked():
search_types.append('audio')
self.get_t_files(search_types)
self.set_total_files(self.file_total) self.set_total_files(self.file_total)
for folder, subfolders, filename in os.walk(self.src_dir): if len(search_types) > 0:
for f_type in self.file_types: for folder, subfolders, filename in os.walk(self.src_dir):
for ext in self.file_types[f_type]: for f_type in search_types:
for file in filename: for ext in self.file_types[f_type]:
if file.lower().endswith(ext): for file in filename:
current_file = os.path.join(folder, file) if file.lower().endswith(ext):
if is_file(current_file): current_file = os.path.join(folder, file)
file_count += int(1) if is_file(current_file):
self.process_file(current_file) file_count += int(1)
# self.set_progress(file_count,file_total) self.process_file(current_file)
# time.sleep(.02)
else:
print(f"Skipping {current_file} as it does not look like a real file.")
progress_callback.emit((file_count / self.file_total) * 100) else:
print(f"Skipping {current_file} as it does not look like a real file.")
progress_callback.emit(round((file_count / self.file_total) * 100, 0))
else:
print("Nothing to search for.")
return "Done." return "Done."
@staticmethod @staticmethod
@ -176,12 +193,27 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def find_files(self): def find_files(self):
""" find files to build a dictionary out of """ """ find files to build a dictionary out of """
# Initialize widgets
self.lcd_files_found.display(int(0))
self.set_progress_processing(0)
self.set_progress_importing(0)
self.img_preview.setPixmap(QPixmap(os.path.join(basedir,
'assets',
'preview_placeholder.jpg')))
self.file_list.clear()
# File Stuff
self.total_files = 0
self.file_total = 0
self.files = {}
worker = Worker(self.t_find_files) worker = Worker(self.t_find_files)
worker.signals.started.connect(self.scan_thread_started) worker.signals.started.connect(self.scan_thread_started)
worker.signals.result.connect(self.print_output) worker.signals.result.connect(self.print_output)
worker.signals.finished.connect(self.thread_complete) worker.signals.finished.connect(self.thread_complete)
worker.signals.finished.connect(self.scan_thread_done) worker.signals.finished.connect(self.scan_thread_done)
worker.signals.progress.connect(self.progress_fn) worker.signals.progress.connect(self.set_progress_processing)
# Execute. # Execute.
self.threadpool.start(worker) self.threadpool.start(worker)
@ -203,9 +235,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
m = Media(os.path.join(path_name,f_name),event, c) m = Media(os.path.join(path_name,f_name),event, c)
i = m.source_path_hash i = m.source_path_hash
log.debug(f'Source Path Hash: {i}') # log.debug(f'Source Path Hash: {i}')
self.files[i] = { 'folders': {}, 'date': {} } self.files[i] = {
'folders': {},
'date': {},
'event': {}
}
self.files[i]['folders']['source_path'] = m.source_path_dir self.files[i]['folders']['source_path'] = m.source_path_dir
self.files[i]['type'] = m.file_type self.files[i]['type'] = m.file_type
@ -217,6 +253,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.files[i]['date']['capture_date']['d'] = m.capture_date[2] self.files[i]['date']['capture_date']['d'] = m.capture_date[2]
self.files[i]['folders']['destination'] = m.destination_path self.files[i]['folders']['destination'] = m.destination_path
self.files[i]['folders']['destination_original'] = m.destination_originals_path self.files[i]['folders']['destination_original'] = m.destination_originals_path
self.files[i]['event']['name'] = m.event_name
self.file_list.addItem(f"{self.files[i]['folders']['source_path']}/{self.files[i]['name']}") self.file_list.addItem(f"{self.files[i]['folders']['source_path']}/{self.files[i]['name']}")
app = QApplication(sys.argv) app = QApplication(sys.argv)

44
_video.py Normal file
View File

@ -0,0 +1,44 @@
#!/usr/bin/env python
import sys
import ffmpeg
class Video:
def __init__(self,max_width=1024,*args,**kwargs):
super(Video,self).__init__()
self.args = args
self.kwargs = kwargs
self.file = kwargs['file']
self.out = 'thumbnail.jpg'
self.max_width = max_width
def gen_video_thumbnail(self):
"""
Generate a thumbnail from a video
"""
probe = ffmpeg.probe(self.file)
time = float(probe['streams'][0]['duration']) // 5
v_width = probe['streams'][0]['width']
width = self.set_width(v_width)
try:
(
ffmpeg.input(self.file, ss=time)
.filter('scale', width, -1)
.output(self.out, vframes=1)
.overwrite_output()
.run(capture_stdout=True, capture_stderr=True)
)
except ffmpeg.Error as e:
print(e.stderr.decode(), file=sys.stderr)
return self.out
def set_width(self,v_width):
if v_width > self.max_width:
width = self.max_width
else:
width = v_width
return width

BIN
assets/forklift.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -4,11 +4,13 @@
Load the config file from yaml file Load the config file from yaml file
""" """
import sys import sys
import os
import yaml import yaml
from lumberjack import timber from lumberjack import timber
basedir = os.path.dirname(__file__)
files = {} files = {}
CONFIG_FILE = 'config.yaml' CONFIG_FILE = os.path.join(basedir, 'config.yaml')
log = timber(__name__) log = timber(__name__)
class Configure: class Configure:

View File

@ -3,7 +3,8 @@
from media import Media from media import Media
from get_image_tag import get_exif_tag from get_image_tag import get_exif_tag
from PIL import Image from PIL import Image
from raw_photo import get_raw_image_dimensions from raw_photo import get_raw_image_dimensions, extract_jpg_thumb
from _video import Video
class ImgPreview: class ImgPreview:
def __init__(self,*args,**kwargs): def __init__(self,*args,**kwargs):
@ -19,6 +20,13 @@ class ImgPreview:
self.file_type = self.m.file_type self.file_type = self.m.file_type
self.is_jpg = False self.is_jpg = False
self.is_raw = False self.is_raw = False
self.path_hash = self.m.source_path_hash
self.dtc = f'{self.m.capture_date[0]}/{self.m.capture_date[1]}/{self.m.capture_date[2]}'
self.thumbnail = 'thumbnail.jpg'
self.ratio = None
self.thumbnail_width = None
self.thumbnail_height = None
self.thumbnail_ratio = None
if self.file_type == 'image': if self.file_type == 'image':
self._img_preview() self._img_preview()
@ -31,8 +39,12 @@ class ImgPreview:
print(f'aperture: {self.aperture}') print(f'aperture: {self.aperture}')
print(f'mpixels: {self.mpixels}') print(f'mpixels: {self.mpixels}')
if self.file_type == 'video':
self._video_preview()
self.thumb_ratio()
def _img_preview(self): def _img_preview(self):
self.dtc = f'{self.m.capture_date[0]}/{self.m.capture_date[1]}/{self.m.capture_date[2]}'
self.dpi = get_exif_tag(self.file, "xresolution") self.dpi = get_exif_tag(self.file, "xresolution")
self.iso = get_exif_tag(self.file, 'iso') self.iso = get_exif_tag(self.file, 'iso')
self.aperture = get_exif_tag(self.file, 'fnumber') self.aperture = get_exif_tag(self.file, 'fnumber')
@ -55,13 +67,41 @@ class ImgPreview:
else: else:
self.mpixels = 'Unknown :(' self.mpixels = 'Unknown :('
def _jpg_preview(self): def _jpg_preview(self):
self.is_jpg = True self.is_jpg = True
img = Image.open(self.file) img = Image.open(self.file)
self.width = img.width self.width = img.width
self.height = img.height self.height = img.height
self.gen_thumb_from_jpg()
def gen_thumb_from_jpg(self):
"""Generates a thumbnail image from the given input image."""
thumb_width = 500
thumb_size = (thumb_width, int(thumb_width // 1.5))
try:
with Image.open(self.file) as img:
img.thumbnail(thumb_size)
img.save(self.thumbnail, "JPEG")
except IOError:
print(f"Error: Cannot create thumbnail for '{self.file}'")
def _raw_preview(self): def _raw_preview(self):
self.is_raw = True self.is_raw = True
self.width = get_raw_image_dimensions(self.file)[1] self.width = get_raw_image_dimensions(self.file)[1]
self.height = get_raw_image_dimensions(self.file)[0] self.height = get_raw_image_dimensions(self.file)[0]
self.thumbnail = extract_jpg_thumb(self.file)
def _video_preview(self):
vid = Video(file=self.file)
self.thumbnail = vid.gen_video_thumbnail()
def thumb_ratio(self):
img = Image.open(self.thumbnail)
self.thumbnail_width = img.width
self.thumbnail_height = img.height
self.thumbnail_ratio = float(self.thumbnail_width / self.thumbnail_height)
print(self.thumbnail_width)
print(self.thumbnail_height)
print(self.thumbnail_ratio)

View File

@ -4,8 +4,11 @@
A class for logging... no, not timber A class for logging... no, not timber
""" """
import logging
import logging
import os
basedir = os.path.dirname(__file__)
# class Logger(object): # class Logger(object):
# level_relations = { # level_relations = {
# 'debug': logging.DEBUG, # 'debug': logging.DEBUG,
@ -29,7 +32,7 @@ import logging
def timber(name): def timber(name):
file_formatter = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s') file_formatter = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')
file_handler = logging.FileHandler("log/all.log") file_handler = logging.FileHandler(os.path.join(basedir, "log", "all.log"))
file_handler.setLevel(logging.DEBUG) file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(file_formatter) file_handler.setFormatter(file_formatter)

View File

@ -147,24 +147,3 @@ def get_capture_date(path, f_type):
month = stamp.strftime("%m") month = stamp.strftime("%m")
day = stamp.strftime("%d") day = stamp.strftime("%d")
return year, month, day return year, month, day
# def process_file(path_name, f_name, event, c):
# """ gather information and add to dictionary """
# log.debug(f'process_file({path_name}, {f_name}, {event}, {c})')
#
# m = Media(os.path.join(path_name,f_name),event, c)
# i = m.source_path_hash
# log.debug(f'Source Path Hash: {i}')
#
# files[i] = { 'folders': {}, 'date': {} }
#
# files[i]['folders']['source_path'] = m.source_path_dir
# files[i]['type'] = m.file_type
# files[i]['name'] = m.file_name
# files[i]['extension'] = m.file_ext
# files[i]['date']['capture_date'] = {}
# files[i]['date']['capture_date']['y'] = m.capture_date[0]
# files[i]['date']['capture_date']['m'] = m.capture_date[1]
# files[i]['date']['capture_date']['d'] = m.capture_date[2]
# files[i]['folders']['destination'] = m.destination_path
# files[i]['folders']['destination_original'] = m.destination_originals_path

View File

@ -14,6 +14,7 @@ def extract_jpg_thumb(raw_file_path):
if thumb.format == ThumbFormat.JPEG: if thumb.format == ThumbFormat.JPEG:
with open('thumbnail.jpg', 'wb') as f: with open('thumbnail.jpg', 'wb') as f:
f.write(thumb.data) f.write(thumb.data)
f.close()
elif thumb.format == ThumbFormat.BITMAP: elif thumb.format == ThumbFormat.BITMAP:
imageio.imsave('thumbnail.jpg', thumb.data) imageio.imsave('thumbnail.jpg', thumb.data)
else: else:

11
requirements.txt Normal file
View File

@ -0,0 +1,11 @@
ffmpeg-python~=0.2.0
setuptools~=56.0.0
xxhash~=3.5.0
tqdm~=4.66.5
PyYAML~=6.0.2
imageio~=2.35.1
rawpy~=0.21.0
PyQt6~=6.7.1
PyQt6-sip~=13.8.0
pillow~=10.4.0
ExifRead~=3.0.0

12
setup.py Normal file
View File

@ -0,0 +1,12 @@
from setuptools import setup
setup(
name='Media Utils',
version='0.0.1',
packages=[''],
url='thelinux.pro',
license='',
author='Kameron Kenny',
author_email='kkenny379@gmail.com',
description='A utility to manage multimedia files'
)