Skip to content

Instantly share code, notes, and snippets.

@heLomaN
Last active April 18, 2021 11:05
Show Gist options
  • Save heLomaN/139d698ac8c87702bf6fb907c73e3992 to your computer and use it in GitHub Desktop.
Save heLomaN/139d698ac8c87702bf6fb907c73e3992 to your computer and use it in GitHub Desktop.
A simple tool to view fusion folder content on windows with pyqt

本地文件索引器

  • 首次运行会生成一个json文件,保存磁盘中的文件信息
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QListWidget
from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QTextEdit, QPushButton, QLineEdit, QCheckBox, QComboBox, QLabel
from PyQt5 import QtGui, QtCore
from collections import OrderedDict
# list all folder with depth 2 then save
# gen app command : pyinstaller --noconsole -F PTBrowserSimple.py
import os, sys
import json, re
def is_target_folder(sub_path):
return "col_" in sub_path or "fstore" in sub_path
def get_folder_scan_depth(sub_path):
return 6 if "col_book" in sub_path else 3
global_valid_entries = []
def collect_path(sub_path, depth):
res = []
if depth <= 0:
res.append(sub_path)
else:
for entry in os.scandir(sub_path):
if os.access(entry, os.R_OK) and os.path.isdir(entry):
res += collect_path(entry.path, depth - 1)
res.append(entry.path)
return res
def glob_folders(top_path):
if not os.access(top_path, os.R_OK):
return
for entry in os.scandir(top_path):
if os.access(entry, os.R_OK) and is_target_folder(entry.path):
scan_depth = get_folder_scan_depth(entry.path)
global global_valid_entries
global_valid_entries += collect_path(entry.path, scan_depth)
# only match first matched
category_mapping = OrderedDict (
[
("col_book", "Book"),
("col_atv", "Atv"),
("fstore", "Atv"),
("col_course", "Course"),
("col_movie", "Movie"),
("col_music", "Music"),
("col_game", "Game"),
("col_tv", "TV"),
("col_soft", "Software"),
("col_pic", "Picture"),
("col_", "Other")
])
def split_categories(all_paths):
seperated_lists = {}
for kvp in category_mapping.values():
seperated_lists[kvp] = []
for sp in all_paths:
for kvp in category_mapping.items():
if kvp[0] in sp:
seperated_lists[kvp[1]].append(sp)
break
return seperated_lists
class MainWindow(QMainWindow):
def __init__(self, data, parent=None):
super(MainWindow, self).__init__(parent)
self.data = data
self.category_data = split_categories(data)
self.setWindowTitle('PTBrowser')
toolbar = QHBoxLayout()
self.category_select = QComboBox()
self.category_select.addItems(self.category_data.keys())
self.category_select.currentTextChanged.connect(self.on_switch_category)
search_text = QLineEdit("")
search_text.setPlaceholderText("pattern")
search_text.setMaximumSize(400, 30)
self.search_text = search_text
search_btn = QPushButton("Refresh Search")
search_btn.pressed.connect(self.on_search)
search_text.editingFinished.connect(self.on_search)
self.normal_or_re = QCheckBox("Regex")
self.search_info = QLabel(" ")
toolbar.addWidget(self.category_select)
toolbar.addWidget(self.normal_or_re)
toolbar.addWidget(search_text)
toolbar.addWidget(search_btn)
toolbar.addWidget(self.search_info)
toolbar.setAlignment(QtCore.Qt.AlignLeft)
path_list = QListWidget()
path_list.doubleClicked.connect(self.item_double_click)
path_list.setUniformItemSizes(True)
self.path_list = path_list
top_layout = QVBoxLayout()
top_layout.addLayout(toolbar, 0)
top_layout.addWidget(path_list, 10)
widget = QWidget()
widget.setLayout(top_layout)
self.setCentralWidget(widget)
self.category_select.setCurrentText("Book")
self.on_switch_category("Book")
def on_switch_category(self, text):
self.path_list.clear()
self.path_list.addItems(self.category_data[text])
self.search_info.setText("Valid: {}".format(self.path_list.count()))
def on_search(self):
text = self.search_text.text().lower()
try:
re_obj = re.compile(".*" + text + ".*", re.UNICODE)
except Exception as e:
print(e)
return
valid_items_count = 0
for idx in range(self.path_list.count()):
item = self.path_list.item(idx)
current = item.text().lower()
if self.normal_or_re.isChecked():
not_visible = not re_obj.search(current)
else:
not_visible = not text in current
item.setHidden(not_visible)
if not not_visible:
valid_items_count += 1
self.search_info.setText("Valid: {}".format(valid_items_count))
def item_double_click(self, index):
item = self.path_list.itemFromIndex(index)
QtGui.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(item.text()))
def prepare_data():
global global_valid_entries
try:
with open("data-cache.json", encoding="utf-8") as f:
data = f.read()
global_valid_entries = json.loads(data)
except Exception as e:
pass
if not global_valid_entries:
valid_disk_sections = 'FGHIJKLMNOPQRSTUVWXYZ'
for letter in valid_disk_sections:
glob_folders("{}:\\".format(letter))
with open("PTBrowserSimple-data-cache.json", "w", encoding='utf-8') as jsonfile:
json.dump(global_valid_entries, jsonfile, ensure_ascii=False)
global_valid_entries.sort(key = lambda x : x[2:] if len(x) > 2 else "0")
if __name__ == "__main__":
prepare_data()
app = QApplication(sys.argv)
w = MainWindow(global_valid_entries)
w.showMaximized()
sys.exit(app.exec_())
@heLomaN
Copy link
Author

heLomaN commented May 21, 2020

A tool for which have a lot of disks, especially PT. With which we can view files without care of partitions.

For example:

image

Desc:

'GHIJKLMNOPQRSTUVWXYZ' : means disk partitions to fusion

"col_" in sub_path or "fstore" in sub_path: here I only want fusion top folders with name "col_". Modify it as your wish.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment