Project

General

Profile

Code layout to enable graphical GUI design

Added by Petric Frank almost 10 years ago

Hello,

i am developing in Qt for several years now. From there i liked the QtDesigner very much. It allows to design a Window/Dialog on a grahical way.

This results in a XML-file generated. This file will be compiled to a header file (using the qic tool of Qt) containing the code to set up the presenation.

Due i am a beginner in Wt development this might be completely nonsense.

This poposal is to adapt the qic tool (and maybe also QtDesigner) to ease development of the Web UI.

As first step it may be enough to generate Wt flavors of the Qt classes (QLabel -> WText, QRadioButton -> WRadioButton, ...) to the resulting header file.

An example. Thie original design could look like this:

Page.h:

#ifndef PAGE_H
#define PAGE_H

#include <Wt/WContainerWidget>
#include <Wt/WText>
#include <Wt/WString>
#include <Wt/WNavigationBar>
#include <Wt/WMenu>
#include <Wt/WMenuItem>
#include <Wt/WStackedWidget>


class Page : public Wt::WContainerWidget
{
  public:
    Page (WContainerWidget * parent = 0);

  private:
    Wt::WStackedWidget *contentsStack;
    Wt::WNavigationBar *navBar;
    Wt::WMenu *mainMenu;
    Wt::WMenuItem *fileMenu;
    Wt::WMenuItem *editMenu;
};

#endif // PAGE_H

Page.cpp:

#include "Page.h"

using namespace Wt;


Page::Page (WContainerWidget * parent)
: WContainerWidget(parent)
{
      container->setStyleClass ("container");
      contentsStack = new Wt::WStackedWidget;
      contentsStack->setStyleClass ("container");
      contentsStack->setPadding (48, Wt::Top);

      navBar = new Wt::WNavigationBar (container);
      navBar->setTitle ("MyApp", "http://localhost:8080");
      navBar->setResponsive (true);
      navBar->addStyleClass ("container");
      navBar->setPositionScheme (Wt::Fixed);

      mainMenu = new Wt::WMenu (contentsStack, container);
      navBar->addMenu (mainMenu);

      fileMenu = new Wt::WMenuItem (Wt::WString::fromUTF8("Edit"), new WText (WString::fromUTF8 ("File Options")));
      mainMenu->addItem (Wt::WString::fromUTF8("File"), fileMenu);
      editMenu = new Wt::WMenuItem (Wt::WString::fromUTF8("Edit"), new WText (WString::fromUTF8 ("Edit Options")));
      mainMenu->addItem (Wt::WString::fromUTF8("Edit"), editMenu);

      container->addWidget (contentsStack);
}

This coding makes it impossible to have generated code embedded.

I suggest (inspired by the Qt behaviour) the following:

Page,h:

#ifndef PAGE_H
#define PAGE_H

#include <Wt/WContainerWidget>
#include <Wt/WText>
#include <Wt/WString>
#include <Wt/WNavigationBar>
#include <Wt/WMenu>
#include <Wt/WStackedWidget>


namespace Ui
{
  class Page;
}


class Page : public Wt::WContainerWidget
{
  public:
    Page (WContainerWidget * parent = 0);
    virtual ~Page ();

  private:
    Ui::Page * ui;
};

#endif // PAGE_H

Page.cpp:

#include "Page.h"
#include "Ui_Page.h"

using namespace Wt;


Page::Page (WContainerWidget * parent)
: WContainerWidget(parent),
  ui (new Ui::Page)
{
  ui->setupUi (this);

  dynamic_cast<WContainerWidget *> (ui->fileMenu->contents ())->addWidget (new WText (WString::fromUTF8 ("File Options")));
  dynamic_cast<WContainerWidget *> (ui->editMenu->contents ())->addWidget (new WText (WString::fromUTF8 ("Edit Options")));
}


Page::~Page ()
{
  delete ui;
}

An a new Ui_Page.h:

#ifndef UI_PAGE_H
#define UI_PAGE_H

#include <Wt/WContainerWidget>
#include <Wt/WString>
#include <Wt/WMenu>
#include <Wt/WMenuItem>
#include <Wt/WNavigationBar>


class Ui_Page
{
  public:
    Wt::WStackedWidget * contentsStack;
    Wt::WNavigationBar * navBar;
    Wt::WMenu * mainMenu;
    Wt::WMenuItem * fileMenu;
    Wt::WMenuItem * editMenu;

    void setupUi (Wt::WContainerWidget * container)
    {
      container->setStyleClass ("container");
      contentsStack = new Wt::WStackedWidget;
      contentsStack->setStyleClass ("container");
      contentsStack->setPadding (48, Wt::Top);

      navBar = new Wt::WNavigationBar (container);
      navBar->setTitle ("MyApp", "http://localhost:8080");
      navBar->setResponsive (true);
      navBar->addStyleClass ("container");
      navBar->setPositionScheme (Wt::Fixed);

      mainMenu = new Wt::WMenu (contentsStack, container);
      navBar->addMenu (mainMenu);

      fileMenu = new Wt::WMenuItem (Wt::WString::fromUTF8("File"), new Wt::WContainerWidget);
      mainMenu->addItem (fileMenu);
      editMenu = new Wt::WMenuItem (Wt::WString::fromUTF8("Edit"), new Wt::WContainerWidget);
      mainMenu->addItem (editMenu);

      container->addWidget (contentsStack);
    }
};


namespace Ui
{
  class Page : public Ui_Page {};
}

#endif // UI_PAGE_H

As you can see all elements of Ui_Page.h could be generated by a tool. The processing code is still located in Page.cpp.

With an adapted qic tool from Qt it could be make easier for the designer to develop web UIs. For sure there may be some work

WMenuItem does not allow to set the contents after construction. So i need a workaround giving WContainerWidget at instanciation time of WMenuItem.

This also results in a downcast in Page.cpp.

Pro (incomplete):

  • UI design by using QtDesigner
  • Makes use of QtCreator easier (new project types, generator for new projects)
  • Decouples UI from control logic

What do you think on this proposal ?


Replies (1)

RE: Code layout to enable graphical GUI design - Added by Wim Dumon almost 10 years ago

Hi Frank,

A graphical editor for Wt Widgets would be nice, and what you suggest has been suggested before (and probably even tried). Until now, I don't know of efforts that lead to a solution. Using qic is probably difficult, since HTML and CSS are quite different from how Qt's layouting works.

In Wt we recommend to use WTemplate and HTML fragments to separate UI organisation from control structures. Granted, a visual entry tool would be great, but in our experience this leads to a manageable solution.

Best regards,

Wim.

    (1-1/1)