Orkestra Day 2 - MVC and Toolbar menu button

Add a couple of things since last time.

  • Create a “Default” folder and populate on start up
  • Add a toolbar button menu to add different step type

As part of updating folders, I refactored a bunch of things. There is now an AppWorld which kinda holds a number of things. It provides access to data stores and other infrastructure components.

Here is a how folders update when the application starts.

pytest-qt

Another useful thing I found is pytest-qt which is an extension to pytest to drive and test desktop applications written in PyQt. Once installed via pip, the following test checks if folders are updated

from app.views.main_window import MainWindow


def test_show_all_folders(qtbot):
    # given
    window = MainWindow()

    # when
    window.show()
    qtbot.addWidget(window)

    # then
    assert window.cmb_folders.count() == 1

And another test to make sure that any text in scratchpad will be persisted during application restart.

from app.views.main_window import MainWindow

def test_save_scratchpad(qtbot):
    # given
    window = MainWindow()
    window.show()
    qtbot.addWidget(window)

    # when
    window.txt_scratch_pad.setText("Hello World")
    window.close()

    # then
    window.show()

    # then
    assert window.txt_scratch_pad.toPlainText() == "Hello World"

Toolbar Menu

I came up with a simple method to allow user to create different step types. In the current form, it is a toolbar button with menu to expand depending on supporting types.

The code is pretty simple as well. We are looping through available step types and create a new QAction. Then a curried method is attached for each action which enables us to receive the step name when it gets triggered.

    steps_menu = QMenu()
    for step in AVAILABLE_STEPS:
        s_action = QAction(step, self.main_window)
        s_action.triggered.connect(
            partial(self.main_window.steps_controller.add_step, step)
        )
        steps_menu.addAction(s_action)

And the method which gets triggered

class StepsController:
    # ...
    
    def add_step(self, step_name):
        print("Adding step {}".format(step_name))

Then we create a new button with an icon and add it to toolbar.

    toolbar_new_step_action = QAction(
        QIcon("://images/plus-48.png"), "New Step", self.main_window
    )
    toolbar_new_step_action.setMenu(steps_menu)
    self.toolbar.addAction(toolbar_new_step_action)