DEV Community

R0land013
R0land013

Posted on

Construct MVP PyQt5 application easily

Hello everybody I created a python package to easily construct a MVP PyQt5 application. I will leave here the content of the project's README.md.
You can review the source code here.
And you can find the pacakge in pypi.

Description

easy_mvp is a package that makes it easy to build desktop applications
using MVP pattern, Python and PyQt5. This is achieved by using
a set of classes and practices similar to those used in the Android framework.

The basic idea behind this package is to open a presenter from
another presenter and that the new presenter fills the window for
complete. This is similar to Android applications, which
when opening a new Activity, they replace the old one with the new one.
If the Back button is pressed, then the new Activity is removed
and the old one reappears on the screen. This gives the impression
that there is a stack of Activity.

In addition, easy_mvp offers the possibility of doing the above in more than
a window
, since desktop applications are very different to Android apps.

Installation

To install this package you need to have Python installed in your system.
Then you can run this command to install this package:

pip install easy_mvp
Enter fullscreen mode Exit fullscreen mode

Explaining the mechanism

The following explanations are reflected in demo.py program.

The application model created by easy_mvp is like this:

App Manager and windows

The ApplicationManager class is the entry point of the program. This
class is the one that knows the windows, creates them and destroys them. Each
window holds a stack of presenters. In this way it is implemented
the same behavior that Android applications have. Class
Intent is used to transition from one presenter to another,
regardless of whether the new presenter is started in a new window.

The behavior of the windows is represented as follows:

Window with its internal stack presenter

As you can see the window has a stack of presenters, the
which are attached to their views, therefore all the
presenters must possess a view
. Again we can see that the class
Intent is the one that allows to add a new pair of presenter-view
to the window stack. For this mechanism to work, the presenter
classes must inherit from the AbstractPresenter class.

AbstractPresenter has several methods to open new presenters,
close the current presenter and to handle certain flows within the
application, such as when a presenter is going to be initialized, hidden,
or closed.

The flow of events in a class that inherits from AbstractPresenter is like this:

flow_of_calls_on_presenter

The _on_initialize method is the first method called in the AbstractPresenter class.
Here the instance variables of the presenter must be initialized. Also you must
create the instance of the view that corresponds to the presenter. Once created,
the view instance must be set with the _set_view(view) method, from
this way the view is made accessible to the rest of the classes in easy_mvp environment.
The view can be obtained with the get_view method of AbstractPresenter, if it was set
by _set_view(view) first.

The on_view_shown method is called just after the presenter view
is displayed in the graphical interface. In this method the data should be loaded,
and the tables and forms filled.

If on the presenter whose view is visible, _open_other_presenter is called
then another presenter will be created, and this presenter will go to the top of the
stack of presenters, and its view will be the only one visible in the graphical interface.
The view of presenter that called _open_other_presenter will no longer be visible.
Before this last occurs, the calling presenter will receive control of the program
with the method on_view_covered.

If now the top presenter calls _close_this_presenter, then the
presenter view just below it will be visible again, and the
presenter will receive control of the main thread via on_view_discovered.
In this method the view should be updated due to some change in the model.

When the presenter at the top of the stack calls _close_this_presenter
receives the control with the on_closing_presenter method. In this method
resources should be released and observers removed. After the call to
on_closing_presenter the presenter and the view of the presenter will be
removed and it will happen what it has been explained previously.
It should be noted that if the presenter who closes is the
only one that exists in the entire application, that is, there is only one
window and it owns only a presenter then the application will close with
the status code 0. To close the program with different code, use the exit_app
method of AbstractPresenter.

Receiving data from presenters

A presenter can receive data from another presenter that it has created,
if the second one is closed using the _close_this_presenter_with_result(result_data: dict)
method. In this way, the presenter that is below in the stack receives control of the
program via on_view_discovered_with_result(action: str, data: dict) instead of
on_view_discovered. The action parameter is the action that was passed to the Intent when
it was ordered to open the new presenter. And result_data is a Python dictionary that the
presenter who was on top can pass through
_close_this_presenter_with_result(result_data: dict).

Managing global data

Data can be created to be accessible throughout the entire application. This is
accomplished with the set_global_data(key: str, data) and get_global_data(key: str)
methods of AbstractPresenter. You can also check if a global data exists with the method
has_global_data(key: str), which returns True if it exists and False otherwise.

Knowing Intent in depth

As explained Intent is what makes it possible to open new presenters. You can specify
that the new presenter must be opened on a new window using
use_new_window(use_new_window: bool = False). You can also specify that
if a new window is to be opened, then make it modal or not with the method
use_modal(self, modal: bool = False).

An intent can be specified with an action with set_action(action: str), like so
the new presenter may behave differently depending on the action received.

Intent also allows data to be passed to a new presenter via set_data(data: dict).
To see examples of how Intent is used, check out the demo.py program.

Top comments (0)