how can I find an sbs file outputting certain texture name on win10?
I asume it could be done by reading with "find text" option in something like total commander ? is there any easy quick method?
I asume it could be done by reading with "find text" option in something like total commander ? is there any easy quick method?
Hey Kirill,
I have now a folder in my scripts directory named "for_kirill", because you have so many great ideas and I hope to make them all happen.
For this one, here is a working prototype, not the nicest UI and not really tested, but it should serve the purpose.
Just copy this code and run it in the SD Python Editor (see the attached video, for a quick demo)
import xml.etree.ElementTree as ET
import os
import sd # type: ignore
from PySide6 import QtWidgets
from PySide6 import QtGui
class ListItem(QtWidgets.QWidget):
def __init__(
self,
filepath: str,
):
super().__init__()
self.filepath = filepath
# LAYOUT
self.header_layout = QtWidgets.QVBoxLayout(self)
self.filename_label = QtWidgets.QLabel(filepath)
self.filename_label.setSizePolicy(
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Expanding,
)
self.header_layout.addWidget(self.filename_label)
def mouseDoubleClickEvent(self, event):
ctx = sd.getContext()
app = ctx.getSDApplication()
app.getPackageMgr().loadUserPackage(self.filepath)
return super().mouseDoubleClickEvent(event)
def enterEvent(self, event):
self.filename_label.setText(f"<html><body><u>{self.filepath}</u></body></html>")
self.filename_label.setCursor(QtGui.Qt.CursorShape.PointingHandCursor)
super().enterEvent(event)
self.update()
def leaveEvent(self, event):
self.filename_label.setText(self.filepath)
self.filename_label.setCursor(QtGui.Qt.CursorShape.ArrowCursor)
super().leaveEvent(event)
self.update()
class ScrollableListWidget(QtWidgets.QScrollArea):
def __init__(self, parent=None):
super().__init__(parent)
self.list_items = []
self.list_widget = QtWidgets.QWidget()
self.list_layout = QtWidgets.QVBoxLayout(self.list_widget)
self.setStyleSheet(f"background-color:#262626;")
self.setWidget(self.list_widget)
self.setWidgetResizable(True)
def add_list_item(self, item):
item.setParent(self)
self.list_items.append(item)
self.list_layout.insertWidget(self.list_layout.count() - 1, item)
def clear_list_items(self):
for list_item in self.list_items:
self.list_layout.removeWidget(list_item)
list_item.setParent(None)
self.list_items.clear()
class SBSFileSearchDialog(QtWidgets.QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Search SBS Files")
self.setMinimumSize(640, 256)
self.search_path = os.getcwd()
# FILE PATH
self.search_path_layout = QtWidgets.QHBoxLayout()
self.lbl_search_path = QtWidgets.QLabel(self.search_path)
self.btn_search_path = QtWidgets.QPushButton("Choose Path")
self.btn_search_path.setFixedWidth(96)
self.btn_search_path.clicked.connect(self.choose_search_file_path)
self.search_path_layout.addWidget(self.lbl_search_path)
self.search_path_layout.addWidget(self.btn_search_path)
# SEARCH KEYWORD
self.search_string_layout = QtWidgets.QHBoxLayout()
self.txt_search_string = QtWidgets.QLineEdit("")
self.txt_search_string.setPlaceholderText("Keyword...")
self.btn_search_string = QtWidgets.QPushButton("Search")
self.btn_search_string.setFixedWidth(96)
self.btn_search_string.clicked.connect(self.search_string_in_files)
self.search_string_layout.addWidget(self.txt_search_string)
self.search_string_layout.addWidget(self.btn_search_string)
# SEARCH OPTIONS
self.search_options_layout = QtWidgets.QGridLayout()
# MATCHING
self.lbl_search_options = QtWidgets.QLabel("Search Options")
self.opt_match_case = QtWidgets.QCheckBox("Match Case")
self.opt_match_whole_word = QtWidgets.QCheckBox("Match Whole Word")
self.search_options_layout.addWidget(self.lbl_search_options, 0, 1)
self.search_options_layout.addWidget(self.opt_match_case, 1, 1)
self.search_options_layout.addWidget(self.opt_match_whole_word, 2, 1)
# INCLUDE / EXCLUDE
self.lbl_include_options = QtWidgets.QLabel("Include Options")
self.opt_include_graph_identifier = QtWidgets.QCheckBox("Graph Identifier")
self.opt_include_graph_identifier.setChecked(True)
self.opt_include_output_identifier = QtWidgets.QCheckBox("Outputs Identifier")
self.opt_include_input_parameters = QtWidgets.QCheckBox("Graph Parameters")
self.opt_include_dependencies = QtWidgets.QCheckBox("Graph Dependencies")
self.search_options_layout.addWidget(self.lbl_include_options, 0, 0)
self.search_options_layout.addWidget(self.opt_include_graph_identifier, 1, 0)
self.search_options_layout.addWidget(self.opt_include_output_identifier, 2, 0)
self.search_options_layout.addWidget(self.opt_include_input_parameters, 3, 0)
self.search_options_layout.addWidget(self.opt_include_dependencies, 4, 0)
# RESULTS
self.lbl_search_results = QtWidgets.QLabel(
"Search Results (Double Click to open the package in SD)"
)
self.list_search_results = ScrollableListWidget()
# MAIN LAYOUT
self.main_layout = QtWidgets.QVBoxLayout(self)
self.main_layout.addLayout(self.search_path_layout)
self.main_layout.addLayout(self.search_string_layout)
self.main_layout.addLayout(self.search_options_layout)
self.main_layout.addSpacerItem(QtWidgets.QSpacerItem(0, 8))
self.main_layout.addWidget(self.lbl_search_results)
self.main_layout.addWidget(self.list_search_results)
def choose_search_file_path(self):
directory = QtWidgets.QFileDialog.getExistingDirectory(
None, "Select Directory", "."
)
if directory:
self.lbl_search_path.setText(directory)
self.search_path = directory
def search_string_in_files(self):
self.list_search_results.clear_list_items()
keyword = self.txt_search_string.text()
sbs_files = self.list_sbs_files(self.search_path)
for current_file_index, sbs_file in enumerate(sbs_files):
print(
f"SEARCHING FILE {current_file_index + 1}/{len(sbs_files)}:\n{sbs_file}"
)
keyword_found = False
filepath = sbs_file
tree = ET.parse(filepath)
root = tree.getroot()
dependencies = None
content = None
graphs = None
dependencies = root.find("dependencies")
content = root.find("content")
if content is not None:
graphs = content.findall("graph")
if self.opt_include_graph_identifier.isChecked():
for graph in graphs:
if graph is not None:
identifier = graph.find("identifier")
if identifier is not None:
value = identifier.attrib.get("v")
if self.match_keyword(value, keyword):
keyword_found = True
if self.opt_include_dependencies.isChecked():
if dependencies is not None:
for dependency in dependencies:
if dependency is not None:
filename = dependency.find("filename")
if filename is not None:
value = filename.attrib.get("v")
if self.match_keyword(value, keyword):
keyword_found = True
if self.opt_include_input_parameters.isChecked():
if graph is not None:
for graph in graphs:
paraminputs = graph.find("paraminputs")
if paraminputs is not None:
for paraminput in paraminputs:
if paraminput is not None:
identifier = paraminput.find("identifier")
if identifier is not None:
value = identifier.attrib.get("v")
if self.match_keyword(value, keyword):
keyword_found = True
if self.opt_include_output_identifier.isChecked():
for graph in graphs:
if graph is not None:
graphoutputs = graph.find("graphOutputs")
if graphoutputs is not None:
for graphoutput in graphoutputs:
if graphoutput is not None:
identifier = graphoutput.find("identifier")
if identifier is not None:
value = identifier.attrib.get("v")
if self.match_keyword(value, keyword):
keyword_found = True
if keyword_found:
list_item = ListItem(filepath)
self.list_search_results.add_list_item(list_item)
def match_keyword(self, search_value: str, keyword: str):
if self.opt_match_case.isChecked():
if self.opt_match_whole_word.isChecked():
if keyword == search_value:
return True
else:
if keyword in search_value:
return True
else:
if self.opt_match_whole_word.isChecked():
if keyword.lower() == search_value.lower():
return True
else:
if keyword.lower() in search_value.lower():
return True
return False
def list_sbs_files(self, directory):
sbs_files = []
for root, _, files in os.walk(directory):
for file in files:
if file.endswith(".sbs"):
sbs_files.append(os.path.join(root, file))
return sbs_files
dialog = SBSFileSearchDialog()
dialog.show()
Stay healthy and creative
Marco
Already have an account? Login
Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.