增加python 界面。
This commit is contained in:
parent
5b11af6c13
commit
914761fb78
|
|
@ -2,4 +2,10 @@ bin
|
|||
Packages
|
||||
Windows API Code Pack 1.1
|
||||
obj
|
||||
Windows API Code Pack 1.1.zip
|
||||
Windows API Code Pack 1.1.zip
|
||||
.venv
|
||||
.vscode
|
||||
__pycache__
|
||||
*.whl
|
||||
pyvenv.cfg
|
||||
*suo
|
||||
BIN
ImgGPS2KML.suo
BIN
ImgGPS2KML.suo
Binary file not shown.
|
|
@ -0,0 +1,118 @@
|
|||
import os
|
||||
import glob
|
||||
from typing import List
|
||||
from exif import Image
|
||||
from datetime import datetime
|
||||
import os
|
||||
from PySide6.QtCore import QThread, Signal # 导入 QThread 和 Signal 类
|
||||
|
||||
|
||||
# import shutil
|
||||
def get_jpg_files(file_path: str):
|
||||
"""获取当前目录下所有.jpg文件的完整路径"""
|
||||
current_dir = os.path.abspath(file_path)
|
||||
return glob.glob(os.path.join(current_dir, "*.jpg"))
|
||||
|
||||
|
||||
def get_datetime_from_image_exif(image_path: str):
|
||||
with open(image_path, "rb") as image_f:
|
||||
my_image = Image(image_f)
|
||||
if hasattr(my_image, "datetime_original"):
|
||||
return my_image.datetime_original
|
||||
else:
|
||||
print(my_image.list_all())
|
||||
raise Exception(f"{image_path}该图片没有时间信息")
|
||||
|
||||
|
||||
def convert_to_unix_timestamp(date_time_str):
|
||||
# 将字符串解析为 datetime 对象
|
||||
date_time_obj = datetime.strptime(date_time_str, "%Y:%m:%d %H:%M:%S")
|
||||
|
||||
# 将 datetime 对象转换为 Unix 时间戳
|
||||
unix_timestamp = date_time_obj.timestamp()
|
||||
|
||||
return unix_timestamp
|
||||
|
||||
|
||||
# 把时间戳相差在2分钟以内的分为一组
|
||||
def group_datetime(image_with_datetime: list):
|
||||
"""把时间戳相差在2分钟以内的分为一组"""
|
||||
image_with_datetime.sort(key=lambda x: x[1])
|
||||
grouped_images = []
|
||||
current_group = []
|
||||
|
||||
for i in range(len(image_with_datetime)):
|
||||
if i == 0:
|
||||
current_group.append(image_with_datetime[i])
|
||||
else:
|
||||
# 计算当前图像与前一个图像的时间差
|
||||
time_diff = image_with_datetime[i][1] - image_with_datetime[i - 1][1]
|
||||
if time_diff <= 120: # 2分钟 = 120秒
|
||||
current_group.append(image_with_datetime[i])
|
||||
else:
|
||||
grouped_images.append(current_group)
|
||||
current_group = [image_with_datetime[i]]
|
||||
|
||||
# 添加最后一组
|
||||
grouped_images.append(current_group)
|
||||
return grouped_images
|
||||
|
||||
|
||||
def get_file_name_before_bracket(file_path):
|
||||
# 获取文件名
|
||||
file_name = os.path.basename(file_path)
|
||||
|
||||
# 查找括号的位置
|
||||
bracket_index = file_name.find("(")
|
||||
|
||||
# 如果找到了括号,返回括号前的部分
|
||||
if bracket_index != -1:
|
||||
return file_name[:bracket_index]
|
||||
else:
|
||||
# 如果没有找到括号,返回整个文件名
|
||||
return file_name
|
||||
|
||||
|
||||
class Worker(QThread):
|
||||
progress = Signal(int) # 定义一个信号,用于传递进度
|
||||
|
||||
def __init__(self, images_path: List[str], start_index: int = 0):
|
||||
super().__init__()
|
||||
self.images_path = images_path
|
||||
self.start_index = start_index
|
||||
|
||||
def run(self):
|
||||
if len(self.images_path) == 0:
|
||||
return
|
||||
# 以下是接需要设置的参数
|
||||
# image_path = r"D:/现场查看/"
|
||||
# 提取目录路径
|
||||
new_dir_location = os.path.join(os.path.dirname(self.images_path[0]), "整理后")
|
||||
# start_index = 156 # 目录编号
|
||||
# 以下是实际代码
|
||||
# all_images = get_jpg_files(image_path)
|
||||
all_images = self.images_path
|
||||
image_with_datetime = []
|
||||
for image_path in all_images:
|
||||
image_datetime = get_datetime_from_image_exif(image_path)
|
||||
image_with_datetime.append(
|
||||
(image_path, convert_to_unix_timestamp(image_datetime))
|
||||
) # 第一个是图片路径,第二个是时间戳
|
||||
grouped_image = group_datetime(image_with_datetime)
|
||||
# total_files = sum(len(group) for group in grouped_image)
|
||||
processed_files = 0
|
||||
for group in grouped_image:
|
||||
dir_name = get_file_name_before_bracket(group[0][0])
|
||||
new_dir_name = f"{new_dir_location}/{self.start_index}.{dir_name}"
|
||||
os.makedirs(new_dir_name, exist_ok=True)
|
||||
for image in group:
|
||||
processed_files += 1
|
||||
self.progress.emit(processed_files) # 发射进度信号
|
||||
new_file_path_name = new_dir_name.replace("/", "//")
|
||||
os.system(
|
||||
f'copy "{os.path.normpath(image[0])}" "{os.path.normpath(new_file_path_name)}" /Y'
|
||||
)
|
||||
# shutil.copy(image[0], destination_path)
|
||||
print(f"copy {image[0]} {new_file_path_name}")
|
||||
# print(group)
|
||||
self.start_index += 1
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
from ui import FolderSelectorApp
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication,
|
||||
)
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
window = FolderSelectorApp()
|
||||
window.show()
|
||||
app.exec()
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
from PySide6.QtWidgets import (
|
||||
QApplication,
|
||||
QFileDialog,
|
||||
QMainWindow,
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
QListView,
|
||||
QAbstractItemView,
|
||||
QTreeView,
|
||||
QTableView,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QHBoxLayout,
|
||||
QMessageBox,
|
||||
QProgressBar, # 导入 QProgressBar 类
|
||||
)
|
||||
from PySide6.QtWidgets import QHeaderView
|
||||
from PySide6.QtGui import QStandardItemModel, QStandardItem
|
||||
from PySide6.QtCore import Slot # 导入 Slot 装饰器
|
||||
import core
|
||||
|
||||
|
||||
class FolderSelectorApp(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("照片整理")
|
||||
self.setGeometry(100, 100, 600, 400)
|
||||
|
||||
# 创建按钮
|
||||
# TODO: 暂时不用选择文件夹按钮
|
||||
self.select_folders_button = QPushButton("选择多个文件夹", None)
|
||||
self.select_folders_button.clicked.connect(self.select_folders)
|
||||
|
||||
self.select_files_button = QPushButton("选择多个文件", self)
|
||||
self.select_files_button.clicked.connect(self.select_files)
|
||||
|
||||
# 整理照片按钮
|
||||
self.arrage_button = QPushButton("开始整理", self)
|
||||
self.arrage_button.clicked.connect(self.arrage_pic)
|
||||
|
||||
# 创建文件开始计数
|
||||
self.start_index_label = QLabel("目录开始基数:", self)
|
||||
self.start_index_text = QLineEdit(self)
|
||||
self.start_index_text.setText("0")
|
||||
|
||||
# 创建QTableView
|
||||
self.table_view = QTableView(self)
|
||||
self.model = QStandardItemModel(0, 2, self)
|
||||
self.model.setHorizontalHeaderLabels(["文件夹名称", "路径"])
|
||||
self.table_view.setModel(self.model)
|
||||
self.table_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Fixed)
|
||||
self.table_view.setColumnWidth(0, int(self.width() * 0.3))
|
||||
self.table_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
|
||||
|
||||
# 创建进度条
|
||||
self.progress_bar = QProgressBar(self)
|
||||
self.progress_bar.setValue(0)
|
||||
|
||||
# 布局
|
||||
# 设置计数的布局
|
||||
start_index_layout = QHBoxLayout()
|
||||
start_index_layout.addWidget(self.start_index_label)
|
||||
start_index_layout.addWidget(self.start_index_text)
|
||||
start_index_layout.addStretch(2)
|
||||
# 选择文件的布局
|
||||
layout = QVBoxLayout()
|
||||
# layout.addWidget(self.select_folders_button)
|
||||
layout.addLayout(start_index_layout)
|
||||
layout.addWidget(self.select_files_button)
|
||||
layout.addWidget(self.arrage_button)
|
||||
layout.addWidget(self.table_view)
|
||||
layout.addWidget(self.progress_bar) # 添加进度条到布局
|
||||
|
||||
container = QWidget(self)
|
||||
# container.setLayout(start_index_layout)
|
||||
container.setLayout(layout)
|
||||
|
||||
# container.layout.addLayout(start_index_layout)
|
||||
self.setCentralWidget(container)
|
||||
|
||||
self.worker = None # 初始化 worker 为 None
|
||||
|
||||
def select_folders(self):
|
||||
# 打开文件夹选择对话框,允许多选
|
||||
dialog = QFileDialog(self)
|
||||
dialog.setWindowTitle("请选择多个文件夹")
|
||||
dialog.setFileMode(QFileDialog.Directory) # 设置为目录选择模式
|
||||
dialog.setOption(
|
||||
QFileDialog.DontUseNativeDialog, True
|
||||
) # 使用Qt对话框以支持多选
|
||||
dialog.setOption(QFileDialog.ShowDirsOnly, True) # 只显示文件夹
|
||||
dialog.setOption(QFileDialog.DontResolveSymlinks, True) # 不解析符号链接
|
||||
|
||||
# 设置列表视图和树视图为多选模式
|
||||
for view in dialog.findChildren(QListView) + dialog.findChildren(QTreeView):
|
||||
view.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
||||
# 设置样式表,使选中项的背景色为蓝色
|
||||
view.setStyleSheet(
|
||||
"""QAbstractItemView::item:selected {
|
||||
background-color: #0078D7;
|
||||
color: white;
|
||||
}
|
||||
QAbstractItemView::item:selected:!active {
|
||||
background-color: #CCE8FF;
|
||||
color: black;
|
||||
}"""
|
||||
)
|
||||
|
||||
if dialog.exec():
|
||||
folder_paths = dialog.selectedFiles() # 获取选择的文件夹路径
|
||||
print("选择的文件夹路径:", folder_paths)
|
||||
|
||||
# 清空当前模型
|
||||
self.model.removeRows(0, self.model.rowCount())
|
||||
|
||||
# 添加新的文件夹路径到模型
|
||||
for path in folder_paths:
|
||||
folder_name = (
|
||||
path.split("/")[-1] if "/" in path else path.split("\\")[-1]
|
||||
)
|
||||
name_item = QStandardItem(folder_name)
|
||||
path_item = QStandardItem(path)
|
||||
self.model.appendRow([name_item, path_item])
|
||||
|
||||
@Slot(int) # 使用 Slot 装饰器
|
||||
def update_progress(self, value):
|
||||
"""更新进度条的值"""
|
||||
self.progress_bar.setValue(value)
|
||||
|
||||
def arrage_pic(self):
|
||||
# 获取table_view中第一列的数据
|
||||
name_list = []
|
||||
for row in range(self.model.rowCount()):
|
||||
item = self.model.item(row, 1)
|
||||
if item is not None:
|
||||
name_list.append(item.text())
|
||||
if len(name_list) == 0:
|
||||
QMessageBox.warning(self, "警告", "请选择文件!")
|
||||
return
|
||||
|
||||
# 设置进度条的最大值
|
||||
self.progress_bar.setMaximum(len(name_list))
|
||||
self.progress_bar.setValue(0)
|
||||
|
||||
# 创建 Worker 实例
|
||||
self.worker = core.Worker(
|
||||
name_list, start_index=int(self.start_index_text.text())
|
||||
)
|
||||
self.worker.progress.connect(self.update_progress) # 连接信号到槽函数
|
||||
self.worker.finished.connect(self.worker.deleteLater) # 任务完成后删除 worker
|
||||
self.worker.start() # 启动线程
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super().resizeEvent(event)
|
||||
self.table_view.setColumnWidth(0, int(self.width() * 0.3))
|
||||
|
||||
def select_files(self):
|
||||
# 打开文件选择对话框,允许多选
|
||||
dialog = QFileDialog(self)
|
||||
dialog.setWindowTitle("请选择多个文件")
|
||||
dialog.setFileMode(QFileDialog.ExistingFiles) # 设置为文件选择模式
|
||||
dialog.setOption(
|
||||
QFileDialog.DontUseNativeDialog, False
|
||||
) # 使用Qt对话框以支持多选
|
||||
|
||||
# 设置列表视图和树视图为多选模式
|
||||
for view in dialog.findChildren(QListView) + dialog.findChildren(QTreeView):
|
||||
view.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
||||
# 设置样式表,使选中项的背景色为蓝色
|
||||
view.setStyleSheet(
|
||||
"""QAbstractItemView::item:selected {
|
||||
background-color: #0078D7;
|
||||
color: white;
|
||||
}
|
||||
QAbstractItemView::item:selected:!active {
|
||||
background-color: #CCE8FF;
|
||||
color: black;
|
||||
}"""
|
||||
)
|
||||
|
||||
if dialog.exec():
|
||||
file_paths = dialog.selectedFiles() # 获取选择的文件路径
|
||||
print("选择的文件路径:", file_paths)
|
||||
|
||||
# 清空当前模型
|
||||
self.model.removeRows(0, self.model.rowCount())
|
||||
|
||||
# 添加新的文件路径到模型
|
||||
for path in file_paths:
|
||||
file_name = path.split("/")[-1] if "/" in path else path.split("\\")[-1]
|
||||
name_item = QStandardItem(file_name)
|
||||
path_item = QStandardItem(path)
|
||||
self.model.appendRow([name_item, path_item])
|
||||
Loading…
Reference in New Issue