import os
from send2trash import send2trash
from PyQt5.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QListWidget, QFileDialog, QMessageBox, QLineEdit
)
from PyQt5.QtGui import QFont
from PyQt5.QtCore import Qt, QTimer
class FileManagerApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("File Manager")
self.setGeometry(200, 200, 800, 500)
# 레이아웃 설정
self.main_layout = QVBoxLayout()
self.setLayout(self.main_layout)
# 버튼 및 검색어 입력 레이아웃
self.input_layout = QHBoxLayout()
self.main_layout.addLayout(self.input_layout)
# 왼쪽 폴더 선택 버튼
self.left_folder_btn = QPushButton("폴더 선택")
self.left_folder_btn.clicked.connect(self.select_left_folder)
self.input_layout.addWidget(self.left_folder_btn)
# 검색어 입력
self.search_input = QLineEdit()
self.search_input.setPlaceholderText("검색어를 입력하세요")
self.search_input.setMaximumWidth(200) # 폭을 30% 정도로 줄임
self.input_layout.addWidget(self.search_input)
# 오른쪽 파일 찾기 버튼
self.right_file_btn = QPushButton("파일 찾기")
self.right_file_btn.clicked.connect(self.start_search_files)
self.input_layout.addWidget(self.right_file_btn)
# 폴더 창 레이아웃
self.folder_layout = QHBoxLayout()
self.main_layout.addLayout(self.folder_layout)
# 왼쪽 폴더 창
self.left_list_widget = QListWidget()
self.left_list_widget.setFont(QFont("Arial", 12))
self.folder_layout.addWidget(self.left_list_widget)
# 오른쪽 폴더 창
self.right_list_widget = QListWidget()
self.right_list_widget.setFont(QFont("Arial", 12))
self.folder_layout.addWidget(self.right_list_widget)
# 현재 선택된 폴더 경로 및 오른쪽 파일 리스트
self.current_folder = None
self.right_files_list = [] # 오른쪽 폴더 창에 표시된 파일 리스트 저장
# 검색 상태
self.search_index = 0
self.search_files_list = []
def select_left_folder(self):
"""왼쪽 폴더 선택 및 파일 표시"""
# 오른쪽 폴더 창 초기화
self.right_list_widget.clear()
self.right_files_list = []
folder = QFileDialog.getExistingDirectory(self, "왼쪽 폴더 선택", "")
if folder:
self.current_folder = os.path.abspath(folder)
# 왼쪽 폴더 창 초기화
self.left_list_widget.clear()
self.populate_left_list()
def populate_left_list(self):
"""왼쪽 리스트에 폴더의 모든 파일 표시 (하위 폴더 포함)"""
if not self.current_folder:
return
# 왼쪽 폴더 창 초기화 보장
self.left_list_widget.clear()
try:
files = []
for root, _, filenames in os.walk(self.current_folder):
for file in filenames:
relative_path = os.path.relpath(os.path.join(root, file), self.current_folder)
files.append(relative_path)
if files:
self.left_list_widget.addItems(files)
else:
QMessageBox.information(self, "알림", "폴더에 파일이 없습니다.")
except Exception as e:
QMessageBox.critical(self, "오류", f"파일을 로드하는 중 오류가 발생했습니다: {e}")
def start_search_files(self):
"""파일 검색 시작"""
# 왼쪽 폴더 창 새로 고침
self.populate_left_list()
# 오른쪽 폴더 창 초기화
self.right_list_widget.clear()
self.right_files_list = []
self.search_files_list = [self.left_list_widget.item(i).text() for i in range(self.left_list_widget.count())]
search_query = self.search_input.text().strip()
if not self.search_files_list:
QMessageBox.information(self, "알림", "왼쪽 리스트에 파일이 없습니다.")
return
if not search_query:
QMessageBox.warning(self, "경고", "검색어를 입력하세요.")
return
# 진행 상태 표시를 위한 메시지 박스
self.progress_box = QMessageBox(self)
self.progress_box.setWindowTitle("파일 검색 진행 중")
self.progress_box.setStandardButtons(QMessageBox.NoButton)
self.progress_box.show()
# QTimer를 사용하여 비동기적으로 검색 작업 실행
self.timer = QTimer()
self.timer.timeout.connect(lambda: self.search_next_file(search_query))
self.timer.start(10) # 10ms 간격으로 작업 실행
def search_next_file(self, search_query):
"""다음 파일 검색"""
if self.search_index >= len(self.search_files_list):
# 검색 완료 처리
self.timer.stop()
self.progress_box.close()
self.progress_box.deleteLater() # 메시지 박스 강제 삭제
# 검색 완료 후 진행 상태 초기화
self.search_index = 0
self.update_right_list_widget()
return
file_name = self.search_files_list[self.search_index]
self.search_index += 1
# 진행 상태 업데이트
self.progress_box.setText(f"{self.search_index}/{len(self.search_files_list)}")
if search_query in file_name:
self.right_files_list.append(file_name)
def update_right_list_widget(self):
"""오른쪽 리스트 창 갱신"""
self.right_list_widget.clear()
self.right_list_widget.addItems(self.right_files_list)
def keyPressEvent(self, event):
"""DEL 키로 오른쪽 리스트에서 파일 삭제"""
if event.key() == Qt.Key_Delete:
self.delete_selected_file()
def delete_selected_file(self):
"""오른쪽 리스트에서 선택한 파일 삭제"""
selected_item = self.right_list_widget.currentItem()
if not selected_item:
return # 선택된 파일이 없으면 종료
file_name = selected_item.text()
file_path = os.path.join(self.current_folder, file_name)
file_path = os.path.normpath(file_path)
# 파일 삭제
try:
send2trash(file_path)
except Exception as e:
QMessageBox.critical(self, "오류", f"파일 삭제 중 오류가 발생했습니다: {e}")
return
# 삭제된 파일을 리스트에서 제거하고 오른쪽 창 갱신
self.right_files_list.remove(file_name)
self.update_right_list_widget()
if __name__ == "__main__":
app = QApplication([])
window = FileManagerApp()
window.show()
app.exec_()
댓글 영역
획득법
① NFT 발행
작성한 게시물을 NFT로 발행하면 일주일 동안 사용할 수 있습니다. (최초 1회)
② NFT 구매
다른 이용자의 NFT를 구매하면 한 달 동안 사용할 수 있습니다. (구매 시마다 갱신)
사용법
디시콘에서지갑연결시 바로 사용 가능합니다.