I have been learing about the MVVM pattern and i decided to use it in one of my PyQt5 applications, but i realised i still have a lot to learn regarding this concept. One thing i have failed to understand is where in my software structure i should put the logic that opens a custom dialog.
Let me give an example: Below is a simple MVVM pattern in python that increments a counter.
For example, i want to add a dialog that saves the counter to a file. To accomplish this, a "save" button is added. And when the data is saved, a message in the main window shows: "Data saved to file_name.txt"
Now my question is as follows: Where should the logic be added to open the dialog? should it be opened in the view, as it is an UI element? Or should it be handled by the model? And should the dialog be using a seperate MVVM pattern as well, or should that be part of the mainwindow MVVM?
main
import sys
from PyQt5.QtWidgets import QApplication
from mainwindow.MainWindowModel import MainWindowModel
from mainwindow.MainWindowViewModel import MainWindowViewModel
from mainwindow.MainWindowView import MainWindowView
if __name__ == "__main__":
app = QApplication(sys.argv)
model = MainWindowModel()
view_model = MainWindowViewModel(model)
view = MainWindowView(view_model)
view.show()
sys.exit(app.exec())
view
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QPushButton
class MainWindowView(QWidget):
def __init__(self, _view_model):
super().__init__()
self._view_model = _view_model # The ViewModel instance
self._view_model.count_changed.connect(self.update_label) # Connect signal to the slot
self.init_UI() # Initialize the UI
def init_UI(self):
self.setWindowTitle('Counter') # Window title
self.layout = QVBoxLayout() # Vertical layout
self.label = QLabel('0') # Label to show the count
self.layout.addWidget(self.label)
self.button = QPushButton('Increment') # Button to increment the count
self.button.clicked.connect(self._view_model.increment) # Connect button click to ViewModel
self.layout.addWidget(self.button)
self.setLayout(self.layout) # Set the layout of the widget
def update_label(self, count):
self.label.setText(str(count)) # Update the label with the current count
viewmodel
from PyQt5.QtCore import QObject, pyqtSignal
class MainWindowViewModel(QObject):
count_changed = pyqtSignal(int) # Signal to update the count in the view
def __init__(self, model):
super().__init__()
self._model = model # Reference to the model
def increment(self):
self._model.increment() # Call increment of the model
self.count_changed.emit(self._model.counter) # Emit the updated count
model
class MainWindowModel:
def __init__(self):
self.counter = 0 # Initialize the counter to 0
def increment(self):
self.counter += 1 # Increment the counter
Source for example code here
I was considering opening the dialog in the MainWindowView when the save button is pressed, and then connecting events of the dialog MVVM pattern to the main window, but i doubt that is correct