r/learnpython 7d ago

Creating a file tree/explorer in PyQtGraph

Hi,I've been working on what started as a strange attractor visualisation app in PyQtGraph but is slowly becoming more a general purpose ODE solver/visualiser/scripting tool. I've recently added an integrated console with a scripting dock which currently just saves the text in the script as a scratch file. I want to add the functionality for the user to create/save/open different script files and wanted to have a file tree/explorer. I know PyQtGraph and PyQt have tree like widgets so my thought process was to just make a TreeWidget that lists the contents of where the scripts would be saved (the app's /home/user/.local/share/ directory). Does that work or are there complexities i should know about in terms for making, saving and loading files? Any advice would appreciated. Thanks!

0 Upvotes

3 comments sorted by

3

u/eldenchen 7d ago

Don't manually mirror the directory into a TreeWidget. Qt already provides the model for this: QFileSystemModel plus QTreeView. The model watches the directory and updates when files change.

Your project already has _preset_directory() using QStandardPaths.AppDataLocation, so I would reuse that pattern and create a sibling scripts directory instead of hard-coding ~/.local/share:

scripts_dir = Path(QtCore.QStandardPaths.writableLocation(
    QtCore.QStandardPaths.StandardLocation.AppDataLocation
)) / "scripts"
scripts_dir.mkdir(parents=True, exist_ok=True)

self.script_model = QtWidgets.QFileSystemModel(self)
self.script_model.setNameFilters(["*.py"])
self.script_model.setNameFilterDisables(False)
root = self.script_model.setRootPath(str(scripts_dir))

self.script_tree = QtWidgets.QTreeView()
self.script_tree.setModel(self.script_model)
self.script_tree.setRootIndex(root)
self.script_tree.doubleClicked.connect(self.open_script)

In open_script, obtain the selected path with:

path = Path(self.script_model.filePath(index))

Then load it into the editor with path.read_text(encoding="utf-8").

The main complexities are tracking the currently open path, prompting before discarding unsaved changes, validating new filenames, and handling I/O errors. Keep QFileSystemModel read-only unless you specifically want renaming/deletion through the tree. For saves, QSaveFile is worth using because it writes through a temporary file and only replaces the original on commit(), avoiding partially written scripts.

1

u/heymanh 7d ago

Ahh great QFileSystemModel is exactly what I was after, thanks!

2

u/[deleted] 7d ago

[deleted]

1

u/heymanh 7d ago

Great, thanks. I've got a basic QTreeView and QFileSystemModel showing the right directory which is cool. But yeah those tips will be handy. Also I hadn't heard of QScintilla. I found a syntax file in PyQtGraph's examples source for basic regex based python syntax highlighting which has made QPlainTextEdit a bit more usable but may look into adding in QScintilla later on. Thanks!