Four backends now for GUIDeFATE...but the struggle continues

Just as you are thinking you got the hang of something, believing you know how to work the system, imagining you have a problem licked, then you wake up to find out it was just a dream. That has been my experience in developing GUIDeFATE (A contrived acronym for the project - Graphical User Interface Design From A Text Editor).

GUIDeFATE is a tool that simplifies GUI design by choosing only a few useful elements that make a usable graphical application and making those elements accessible to the beginner developer. Handy too if you want a quick and dirty desktop application in Perl. A tool that converts a string into a GUI, using one of the many backends that exist. So I have been making this over the past month or so, using the often woefully outdated resources found on the internet. I had a rudimentary Wx Backend after about a week, by another week I had Tk, and was persuaded to put the project up on Github. Soon Gtk was also covered easy as pie in 3 days. Even started working on Win32...(I only have Linux machines at home, fortunately also have more skilled help in this matter in the form of mpersico)...then CRUNCH...

A fellow redditor daxim suggested Qt. Great idea, I thought. Qt well supported on Linux and other platforms. And Gtk was a breeze to handle. Significantly Qt and Perl have had a close relationship. This would be a walk in the park I figured. I figured wrong. Just to get Qt development setup on my system was a struggle. Installs from CPAN failed, installs from repositories are no longer updated. ppas claiming to offer this also fail. Switched to Kubuntu, wrecking some of my settings, no joy. Near defeat, daxim once again gently guided me to a reasonable install of Qt4. Problems over? No. Just beginning.

Qt

Qt is sophisticated, powerful, all-encompassing. Getting control of this sophistication and power needs huge brains which I lack and a dextrous use of Qt Designer, which defeats the object of GUIDeFATE. Secondly, Qt internal design appears to have evolved in a parallel universe, isolated from other paradigms of GUI design, even though on the surface looking similar. Sort of like Convergent evolution that gave flies and birds wings and legs. To crowbar this interface into GUIDeFATE was not easy (for me).

Key to this is how GUIDeFATE allocates actions (eg on button click, menu select etc) to widgets...it merely takes a reference to subroutine in main:: that has not been yet created. An example from a button widget generator from the front end sends a reference to a list of parameters for each widget like this: -

addWidget(["btn",$bid, $label,[$locationX,$locationY,[$width,$height], \&{"main::btn".$bid}]);

GUIDeFATE's middleware for each backend stores this referenced list in a list of widgets before it sets up content in new(). This means that the developer can create his own functions easily as long as he knows the id of the widgets, the autogenerator can generate the skeleton for these functions and Bob's your uncle. All the other backends quite easily accepted a dereferenced function as parameter in their widget.

Not so Qt. Qt uses SLOTs and SIGNALss. A powerful system, SLOTS are attached to the Qt::MainWindow, which is a Parent of the Qt::Widget container (in my case) containing all the widgets. So the SLOTS are in a different place to the generator of the SIGNAL. There is no way to add slots dynamically (as far as I can see), and you have to declare them at the beginning...difficult if you dont know what the functions are going to be. Then you have select a SIGNAL to be associated with a widget and connect the two. A simple Perl example is here.

Fortunately there is SignalMapper. This allows SIGNALs to be mapped to a single SLOT in signal mapper. Then comes the complexity of extracting signals from different events by a dispatcher which distributes that signal to the correct function.

Setting up the SignalMapper in new(): -

$self->{SigMan} = Qt::SignalMapper($self);
$self->connect($self->{SigMan}, SIGNAL 'mapped(QString)', $self, SLOT 'mapAction(QString)');

Adding a Signal to the widget, and giving the signal mapper clues about the source for the dispatcher to work on:-

$self->connect($canvas->{"btn".$id}, SIGNAL 'clicked()', $self->{SigMan}, SLOT 'map()');
$self->{SigMan}->setMapping($canvas->{"btn".$id}, "btn".$id);

And creating a dispatcher: -

sub mapAction{
   my $widgetIndex=getItem(shift);                   #find the widget parameters
   my @widget=@{$widgets[$widgetIndex]};             #using the clue (the Id)
                                                     #provided by SignalMapper
   my $wType=shift @widget;                          #remove the type,
                                                     #which allows you locate
   if ($widgetIndex !=-1){                           
      if     ($wType eq "mb")   { &{$widget[3]};}    # the function referenced
      elsif  ($wType eq "btn")  { &{$widget[4]};}    # and call that function
      elsif  ($wType eq "combo")  { &{$widget[4]};}
   }

}

So learnt a new paradigm, and finally GUIDeFATE 0.08 has another backend.

Four backends supported.png

One thing I am struggling with is understanding packages and the differences between "use ", "use parent " and "use base ", and other ways of absorbing other modules into the code. It takes a lot of guesswork and fiddling and trying different combinations for me to get these backends to work. It may be the way their Perl interfaces and the C libraries work. More likely it is something to do with my lack of understanding, but it sure leads to messy code, and scrambled brains.

9 Comments

Hi

I'm impressed that you've tried a range of packages to experiment with ... but ...

Your statement 'Then comes the complexity of extracting signals from different events by a dispatcher which distributes that signal to the correct function' is proof that you should - at that point - forever give up this course of action and do something else.

Vast amounts of code have been written to handle this, and the best make it effortless.

If you think in terms of urls (aka 'routes') submitted, then you can search MetaCPAN.org for a wide range of modules handles the magic word 'routes'. There are I venture to add too many of them just in Perl.

But, the plan was of course doomed from the start. I hope you now see it as an intriguing learning exercise, but ultimately futile in terms of producing meaningful code.

Why? Because the world in complex, programming is hard, and (gasp) requirements change over both short and long time periods.

Basically you're trying to work within a string as your constraint, whereas you're infinitely better off using Perl (hint) to do the work. IOW your efforts are politely called reinventing the wheel.

If you went with https://metacpan.org/release/Mojolicious you can let it generate a whole, simple, app, as a Mojolicious::Lite thingy.

Anyway, thanx for blogging about it.

Cheers
Ron

Ron,

I am confused; I don't see anywhere in this project where a web server is relevant.

As I understand it, this project is about GUIs - local, on machine, no-network programs. From the post:

"GUIDeFATE is a tool that simplifies GUI design by choosing only a few useful elements that make a usable graphical application and making those elements accessible to the beginner developer."

If I have a Perl script that takes a number of options, why not text up a description of a one-screen set of fields with dropboxes and add that to the script?

Why do I need a web environment for that?

I'm not sure what problem space you are thinking of, but I see this as the Perl equivalent/integration of https://linux.die.net/man/1/xdialog

Hi

I should apologise for mentioning web servers without explaining why I brought them into the discussion. I clearly confused a number of people. The idea which went thru my head was that the problem of laying out stuff on the screen has been attacked and solved many times, and using web browsers is one way of handling that. My view is that there is no point in reinventing that particular wheel. The most pathological way I know of, of building such a new wheel, is of course MS's Visual Basic, but I personally take the view that Qt, etc, are just variations on that theme. I much prefer, and strongly encourage, programmers to simply see web browsers as a per-existing, reliable tool, to be used rather than re-invented.

Hi Saif

Sounds good. The other point I should make is re complexity in the real world. I'm sure your technique would be adequate for little setups, but as complexity grows, I feel the time you spend addressing more and more requirements would be much better spent diving into Mojo.

I have a small number of Mojo-based apps for personal use (Local::*) so they won't be on CPAN, but if you're interested email me and I send you the source for one of them.

For a very complex app using Mojo see WWW::Garden::Design.

Hi Saif

Damn, forgot. For an article on the garden design app see Flowers.

Leave a comment

About Saif

user-pic An Orthopaedic Surgeon, A Tissue Engineering Scientist, Lecturer, (and Hobbyist Programmer, Electronics Engineer and Roboticist)