1

I'm coding a desktop app with Python and Qt, using PySide. I need to display a tree view in which top-level items are objects of different type than their children. Specifically, a top-level item is a Git repository, whereas its children are directories in the work tree.

For a repository, I want to show its path and currently checked-out branch. For a directory, I just want to show its name.

Right now, I do this by having my QAbstractItemModel descendant use isinstance on the underlying model object (retrieved from internalPointer() method) and decide how to format the resulting string.

I was wondering whether there was a more Pythonic (or just less clunky) way of doing this kind of double dispatch.

What I don't want to do is define a method for this purpose in my model classes for Git repo and work tree file, because I feel this would violate SRP.

Any thoughts or ideas are most welcome. Also, if anyone can think of a less clunky title for this question, let me know ;)

Vojislav Stojkovic
  • 8,043
  • 4
  • 35
  • 48

1 Answers1

0

If you were ok with each Model class having a function containing View code, then you could just call those functions. To separate the Model/View code without using isinstance, this sounds like a case for the Visitor pattern, as described in this SO answer, and as used in the ast module.

Basically, each Model class has an accept() method that takes a Visitor object. The accept() method for a repository calls the visit_repository() method of that Visitor object, passing self (which is the Model instance). Similarly, the accept() method for a directory calls the visit_directory() method of that Visitor object, passing self. The visit_repository() or visit_directory() method then has access to the Model instance and knows its type and can show the appropriate view. This separates the View code (in the Visitor object) from the Model code (in the Model class).

*Note: instead of using different function names (visit_repository() vs visit_directory()), you can use multimethods, e.g., this SO answer about multimethods in Python.

Community
  • 1
  • 1
beaslera
  • 863
  • 9
  • 19