Accéder au contenu principal

Extracting Boxes' wizard's pages

A few days ago, Zeeshan suggested me to extract Boxes' wizard's pages out of the Wizard class and to make them full fledged widgets/classes. This idea is very welcome as it would move a lot of complexity out of the Wizard class (as it is currently implementing most of the pages) and, in the long run, make its port to GtkAssistant easier.

I spent the last few days playing with the pages, discovering how they are implemented and extracting some of them.

Boxes' wizard's page graph
Extracting pages, kind of

The current state of Boxes' installation wizard

Here is the wizard's page flow as presented to the user:

Boxes' wizard's page graph
The current page flow

The wizard is currently implemented with such a widget hierarchy:

  • the WizardWindow class
    • the WizardToolbar class
    • the Wizard class, a stack of pages
      • the WizardSource class
        • the source selection page
        • the URL entry page
      • the preparation page
      • the setup page
      • the review page
    • the file chooser page
    • the customization page

The wizard has three layers of pages, most of them behaving slightly differently: the WizardSource class is composed of the source selection page and of the URL entry page; the preparation, setup and review pages are directly implemented by the Wizard class; and the file chooser and customization pages are implemented by the WizardWindow class. Also, the URL entry page have its own back button and doesn't use the common one in the headerbar to go back to the source selection page, which is inconsistent with every other page's behaviour.

Most pages are directly implemented by the Wizard class, making of it a mishmash of intertwined behaviours and responsibilities, especially as every page is directly modifying the wizard's state. Some other are handled by the WizardWindow and WizardSource classes, but in the end, no page exist as a single class. All of this lead to a great complexity which should be corrected in order to make the wizard more maintainable and to port it to GtkAssistant.

Where to go

I want to keep the page flow the same while changing the implementation drastically: the Wizard should inherit GtkAssistant, each page should be a widget with its own class and no page should be nested. Here is what I want to achieve:

  • Wizard
    • WizardSourceSelectionPage
    • WizardFileChooserPage
    • WizardUrlEntryPage
    • WizardPreparationPage
    • WizardSetupPage
    • WizardCustomizationPage
    • WizardReviewPage

This refactoring has to be done properly: what's the point of moving from known code to something not inherently better and known only by the person who wrote it?

In order to untangle the pages from the wizard without changing their code too much, I want to use more event-driven programming so that the pages don't change the wizard's state directly but notify it of changes, letting it react accordingly. It will help to uncouple the wizard's behaviour from the implementations of the pages, hence making its code simpler and its porting to GtkAssistant easier.

Going there

What have been done:

  • spliting the model of the WizardSource class from the widget: patch submitted
  • renaming WizardSource as WizardSourcePage to keep the page names consistent
  • extracting the preparation page from the Wizard class: patch submitted
  • extracting the setup page from the Wizard class: patch submitted
  • extracting the review page from the Wizard class: patch submitted

What has to be done:

  • editing the Wizard class' API to mimick GtkAssistant's one: in progress
  • extracting the source selection page from the WizardSourcePage class
  • extracting the URL entry page from the WizardSourcePage class
  • removing the WizardSourcePage class
  • extracting the file chooser page from the WizardWindow
  • extracting the customization page from the WizardWindow
  • merging the Wizard, WizardToolbar and WizardWindow classes
  • making the Wizard class inherit from GtkAssistant

As pointed out in my last article, GtkAssistant forced a padding to its pages which was problematic as some of Boxes' wizard's pages need to take all the available space to display complex widgets or infobars. This bug have been solved pretty quickly by Matthias Classen who added a way to disable the padding for specific pages. Thanks Matthias, it will be useful. =)

Other stuff

I started working on other stuff too.

I tried to add support for the application/x-cd-image MIME type to Boxes but without success. Starting Boxes with a path or an URI pointing to an ISO file works perfectly, but trying to open one with Boxes via Nautilus or xdg-open didn't work. I need to investigate this.

Last march I started adding a list view to Boxes' collection view. It worked well except for a warning that I didn't understand and didn't have time to investigate. The warning was still present and I tracked it as coming from libgd, I then opened a ticket and submitted a patch, which so far are still waiting for reviews.

I have no time to get bored when working on Boxes! =D

Commentaires

Posts les plus consultés de ce blog

GTK+ Apps on Phones

As some of you may already know, I recently joined Purism to help developing GTK+ apps for the upcoming Librem 5 phone . Purism and GNOME share a lot of ideas and values, so the GNOME HIG and GNOME apps are what we will focus on primarily: we will do all we can to not fork nor to reinvent the wheel but to help allowing existing GTK+ applications to work on phones. How Fit are Existing GTK+ Apps? Phones are very different from laptops and even tablets: their screen is very small and their main input method is a single thumb on a touchscreen. Luckily, many GNOME applications are touch-friendly and are fit for small screens. Many applications present you a tree of information you can browse and I see two main layouts used by for GNOME applications to let you navigate it. A first kind of layout is found in applications like Documents, I'll call it stack UI : it uses all the available space to display the collection of information sources (in that case, documents), clicking a...

libhandy 0.0.10

libhandy 0.0.10 just got released, and it comes with a few new adaptive widgets for your GTK app. You can get this new version here . The View Switcher GNOME applications typically use a GtkStackSwitcher to switch between their views. This design works fine on a desktop, but not so well on really narrow devices like mobile phones, so Tobias Bernard designed a more modern and adaptive replacement — now available in libhandy as the HdyViewSwitcher . In many ways, the HdyViewSwitcher functions very similarly to a GtkStackSwitcher : you assign it a GtkStack containing your application's pages, and it will display a row of side-by-side, homogeneously-sized buttons, each representing a page. It differs in that it can display both the title and the icon of your pages, and that the layout of the buttons automatically adapts to a narrower version, depending on the available width. We have also added a view switcher bar, designed to be used at he bottom of the window: HdyView...

My Name is Handy, Lib Handy

Libhandy 0.0.7 just got released! I didn't blog about this mobile and adaptive oriented GTK widget library since the release of its 0.0.4 version three months ago , so let's catch up on what has been added since. List Rows A common pattern in GNOME applications is lists , which are typically implemented via GtkListBox . More specific patterns arose, where rows have a title at the start, an optional subtitle below it, actions at the end and an icon or some other widget like a radio button as a prefix. These rows can also be expanded to reveal nested rows or anything else that fits the need. So far every application using these patterns implemented the rows by hand for each and every row. It made using these a bit cumbersome and it led to inconsistencies in sizing, even inside a single application. To make these patterns easier to use, we implemented HdyActionRow , HdyComboRow and HdyExpanderRow . HdyActionRow The action row is a simple and flexible row, it lets...