Cambalache 0.8.0 released!

Cambalache is a new RAD tool for Gtk 4 and 3 with a clear MVC design and data model first philosophy.

Exactly one year ago I made the first commit…

commit 51d4185cd8556f0358cc463578df5a4138ac90b5
Author: Juan Pablo Ugarte
Date: Wed Dec 9 19:14:53 2020 -0300

Initial commit

Supports type system and interface data model.
Basic history (undo/redo stack) implementation with triggers.

It consisted of just 3 files, the data model, a python script to generate history triggers automatically and a small sql script to test it.

Fast forward one year and I am starting to believe it can be on feature parity with Glade sooner than expected.

Having a pretty solid backend this release focus on adding all the big missing UX parts, like a good type selector, workspace placeholders and basic clipboard actions like copy/paste.

Type chooser bar

Borrowing the design from Glade I implemented a type chooser that categorizes object classes to make it easier to find what you need.

Workspace placeholders

Containers now have placeholders to make it easier to add children in a specific positions

It supports the following actions:

  • Double click on a placeholder to create a new widget in place
  • <Control> + Insert to add more placeholders
  • <Control> + Delete to remove placeholders
  • <Shift><Control> + Insert to add a new row
  • <Shift><Control> + Delete to remove a row

Translatable properties

Thanks to the work of Philipp Unger it is possible to mark properties as translatable and add comments for translators.

Clipboard actions

To make life easier, common clipboard actions like, Copy, Paste, Cut and Delete where added.

Better unsupported features report

Cambalache will make its best effort to notify the user about unsupported features when importing UI files and export to a different filename as a precaution to avoid loosing data.

Matrix channel

Have any question? come chat with us at #cambalache:gnome.org

Where to get it?

As always you can get the code in gitlab

git clone https://gitlab.gnome.org/jpu/cambalache.git

or download the bundle from flathub

flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install --user flathub ar.xjuan.Cambalache

UPDATE: Version 0.8.1 released!

 

Happy coding!

What’s new with Glade

It’s been a long time since my last post. After doing the last major UI rework which included a new workflow and the use of a headerbar instead of a menu bar I had little free time to work on the project.

Early this year while on quarantine and in between jobs I started working on things I been wanting to but did not had the time

Fix Glade Survey

On January the GNOME infrastructure was migrated to a new server which broke a small web service running at https://people.gnome.org/~jpu/ used to collect Glade’s survey data.

They also added surveys.gnome.org to conduct any GNOME related surveys making my custom service redundant.

So in order to properly fix the survey I made Glade act like a browser and post the data directly to surveys.gnome.org, no need to open a browser!

This means Glade has to download the survey form, parse it to extract a session token and send it as a cookie for it to work!

JavaScript support

A few years ago while working at Endless Mobile I started adding support for JavaScript widgets since we had several widgets implemented in GJS.

Unfortunately back then a really obscure bug made GJS crash so I never added support for JS in Glade. To my surprise this time around GJS did not crash, at least not on Wayland which led me to find a workaround on X11 and move on

So in order for glade to support your JavaScript widgets you will have to:

  • specify gladegjs support code as your plugin library.
  • set glade_gjs_init as you init function.
  • make sure your catalog name is the same as your JavaScript import library since
    glade_gjs_init() will use this name to import your widgets into the
    interpreter.

gjsplugin.xml

<glade-catalog name="gjsplugin" library="gladegjs"
               domain="glade" depends="gtk+">
  <init-function>glade_gjs_init</init-function>

  <glade-widget-classes>
    <glade-widget-class title="MyJSGrid" name="MyJSGrid"
                        generic-name="mygrid"/>
  </glade-widget-classes>

  <glade-widget-group name="gjs" title="Gjs">
    <glade-widget-class-ref name="MyJSGrid"/>
  </glade-widget-group>
</glade-catalog>

gjsplugin.js

const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;

var MyJSGrid = GObject.registerClass({
  GTypeName: 'MyJSGrid',
  Properties: {
    'string-property': GObject.ParamSpec.string('string-property',
      'String Prop',
      'Longer description',
      GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
      'Foobar'),
    'int-property': GObject.ParamSpec.int('int-property',
      'Integer Prop',
      'Longer description',
      GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
      0, 10, 5)
    },
  Signals: {'mysignal': {param_types: [GObject.TYPE_INT]}},
}, class MyJSGrid extends Gtk.Grid {
  _init(props) {
    super._init(props);
    this.label = new Gtk.Label ({ visible: true });
    this.add (this.label);
    this.connect('notify::string-property',
                 this._update.bind(this));
    this.connect('notify::int-property',
                 this._update.bind(this));
    this._update();
  }
  _update (obj, pspec) {
    this.label.set_text ('JS Properties\nInteger = ' + 
                         this.int_property + '\nString = \'' +
                         this.string_property + '\'');
  }
});

Save these files in a directory added as extra catalog path in the preferences dialog, restart and you should have the new JS classes ready to use.

Composite templates improvements

So far the only way to add custom widgets to glade is by writing a catalog which can be tedious so probably not a feature used by most people.

So to make things easier I made Glade load any template file saved in any extra catalog path automatically.

This means all you have to do to is:

  1. Create your composite template as usual
  2. Save it on a directory
  3. Add the directory to the “Extra Catalog & Templates paths” in preferences
  4. And use your new composite type!

This features will be included in the next stable release, and are already available in nightly flatpak (wiki instructions)

Better deprecations checks

Glade started before GObject introspection so it keeps version and deprecation information in its catalog files which makes it hard to keep it in sync with Gtk. There was also no way to specify in which Gtk version a property or signal was deprecated.

Unfortunately even tough all this metadata is extracted and stored in Gir files it is not available in typelib which makes using libgirepository not an option for Glade instead I decided to make a small script that will take all this information from Gir files and update Glade’s catalog directly making maintaining versioning information way easier!

This means that Glade should catch almost all deprecations and version mismatches even if you are not targeting the latest Gtk version.

Enjoy!

Juan Pablo

Glade in Libre Application Summit

First of all ISponsored by GNOME Foundation would like to thanks the GNOME foundation for sponsoring my trip to Denver to attend Libre Application Summit

As usual, it was a great opportunity to catch up with old friends and make new ones specially outside the GNOME community.

This opportunity I talked about the plans I have to integrate Glade with Gnome Builder and other IDEs

You can find the slides of my talk as PDF here, and the sources here!

Sources you say?

Yes sources, since my talk about custom UI interfaces in 2013 I been making all my slides with Glade and using glade-previewer to present them live

glade-previewer is a tiny application shipped with Glade used mainly to preview UI

It’s relevant options are:

-f, --filename=FILENAME  Name of the file to preview
--screenshot             File name to save a screenshot
--css                    CSS file to use
--slideshow              Make a slideshow of every toplevel widget
                         by adding them in a GtkStack

Normally to preview a glade file with a custom css file you would use a command like

$ glade-previewer -f talk.glade --css talk.css

Now if you instead want to make a presentation with it all you need to do is add –slideshow option and glade-previewer will pack every toplevel widget in a GtkStack and switch between pages with PageUp/PageDown buttons

As a bonus I extended –screenshot option so that when used in conjunction with –slideshow it will take a screenshot of every toplevel and save them as multiple pages if the format supports it!

It’s always fun to be at GUADEC

Sponsored by GNOME FoundationAs usual I would like to thanks the GNOME foundation for sponsoring my trip to Manchester to enjoy such a wonderful conference and give me the opportunity to present to the community the work I been doing on Glade’s UI for the past few months.

You can find the slides at https://people.gnome.org/~jpu/docs/2017-GUADEC/

Obviously they are made with Glade, something which might seems odd, but is it really?

modern-ui branch

 

So besides a PDF you will find a tarball with all the source files. BTW You can use glade-previewer and PgUp and PgDown to switch pages

$ glade-previewer -f talk.glade --css talk.css --slideshow

https://www.youtube.com/watch?v=0krTtJCJ0Pg

 

And some random pictures from GUADEC…

Developer Experience Hackfest 2016

Sponsored by GNOME FoundationFirst of all I would like to thanks the GNOME Foundation for sponsoring once again my trip to Brussels for the GNOME Developer Experience Hackfest.
Besides hacking on Glade and attending FOSDEM I had a great time meeting with old friends and making new ones, not to mention the amount and variety of beers consumed!

beerBut beer was not the only thing we had!

wafles

Back on the hacking, together with Tristan we managed to fix several bugs and add the much needed support for id-less objects! This way Glade is one step closer to support every Gtk+ template file.
I will not go into much details since it was already covered by him in his blog post

Pretty workspace

Besides doing some CSS cleanups in the workspace and user survey window to improve theme compatibility I added the modernized original Glade logo to the workspace background as a tribute to Glade roots!
Glade workspace logo

I also got the chance to work on the Glade User Survey results, the final results will be posted soon on Glade’s website once I finish automating the results from the Data Base.

Glade User Survey Preliminary Results

3114 people took the time to fill the survey since 11-11-2013.
54 % of them use it for commercial purposes and 42 % for personal use.
Most users are from the US and Brazil with Germany, China and France as a close third.

USA 10.98 % Italy 3.44 %
Brazil 10.18 % Spain 3.37 %
Germany 6.29 % UK 3.11 %
China 5.59 % Canada 2.37 %
France 4.65 % Poland 2.21 %
Mexico 4.07 % Argentina 1.70 %
Russia 3.85 % Australia 1.47 %
India 3.76 % Turkey 1.44 %

How long have you been programming? (years)

< 1 5.17 % 11 – 20 15.83 %
1 – 2 30.72 % 21 – 30 6.26 %
3 – 5 18.49 % 31 – 40 2.95 %
6 – 10 18.33 % > 40 2.21 %

Not Programmer 16.66 %

Preferred programming languages do you prefer?

Python 50.32 % JavaScript 21.80 %
C 47.01 % C Sharp 15.25 %
CPP 38.59 % Vala 9.24 %
Java 24.85 % Perl 6.96 %
Other 25.49 %

When did you start using Glade? (years ago)

1 58.38 % 4 – 5 5.94 %
2 4.94 % 6 – 10 6.48 %
3 2.79 % > 11 2.98 %

Which version do you normally use?

What is available in my OS 82.72 % Master 1.47 %
Latest stable from sources 9.44 % Other 0.83 %
3.8 for Gtk+ 2 3.94 %

On what operating system?

Linux 58.83 % OSX 1.02 %
Windows 2.69 % BSD 0.96 %
Other 1.25 % Solaris 0.44 %

How often do you use it?

Every day 43.89 % Few days a week 10.82 %
A few times a year 20 % Every week 5.84 %
A few times a month 13.96 % Once a month 3.94 %

What level of Glade user would you say you are?

Beginner 78.29 %
Intermediate 16.44 %
Advanced 3.78 %

Under what kind of license(s) do you release the software you used Glade to create?

Free Software 42.19 % None 25.72 %
Open Source 34.32 % Commercial 9.5 %

In which field(s) is the software you used Glade to create generally used?

Desktop applications 42.77 % Industrial applications 8.95 %
Academic 18.68 % Embedded applications 7.35 %
Educational 13.48 % Accounting 4.56 %
Scientific 12.13 % Medical 2.92 %

In your opinion what is the biggest problem with Glade?

Lack of documentation 66.89 %
Other 11.23 %
Lack of publicity/exposure 9.79 %
Lack of official binary releases for other OS (Win32, OSX) 5.78 %
Lack of professional training 2.63 %
Lack of professional support 1.5 %

18 % of users found a bug, 6.9 % reported it and 21.96 % contributed to the project.

Porting widgets to the new template API… the LAZY way!

First of all I want to thanks everyone involved in GUADEC organization specially to the GNOME foundation for sponsoring me once again.

It is been great meeting with old friends and making new ones!

So after Tristan’s talk UI developer experience with Glade/GtkBuilder where he talked about the new template API some good friend of us, lets see if you can guess who, came and ask:

friend: How do I port my widgets to the new templates stuff?
friend: I do not want to redo all of them in glade
me: What kind of widgets?
friend: “A grid with some s#it in it!”
me: hmmm…
 

So we talked about it and told him if that he was that lazy not to redo all widgets in glade manually he could do some function that iterate over containers and spit some xml to get at least the hierarchy right.

As we all know the lazier a programmer is the better, since it will end up writing a program to do its chores!

Anyways I did!

I made a function you can paste in your program and use it together with libgladeui api to dump a runtime GtkWidget to an xml definition.

#include <gladeui/glade.h>

/* Create a Glade project */
GladeProject *project = glade_project_new ();

/* add as many widgets as you want in the project */
glade_project_add_widget_from_object (project, widget, NULL);

/* And then save it to a file */
glade_project_save (project, "myclass.ui", NULL);

And that is all you have to do if the widget is simple enough.
You will have to mark internal children manually since there is no easy way to introspect them, say for example you want to dump a GtkDialog derived widget…

#include <gladeui/glade.h>

/* Create a Glade project */
GladeProject *project = glade_project_new ();

/* We need to mark every internal children manually */
INTERNAL_CHILD (gtk_dialog_get_action_area (GTK_DIALOG (widget)),
                "action_area");
INTERNAL_CHILD (gtk_dialog_get_content_area (GTK_DIALOG (widget)),
                "vbox");

/* add as many widgets as you want in the project */
glade_project_add_widget_from_object (project, widget, NULL);

/* And then save it to a file */
glade_project_save (project, "myclass.ui", NULL);

Here is the cut&paste code glade_dump.c

This is obviously hacky code, it was not heavily tested and will probably make gladeui and gtk API complain a lot but it works pretty well for what is intended.

BTW you have to link with gladeui-2.0 library for this code to work!

I think that is all, happy porting!

Sponsored by GNOME Foundation

Glade Drag & Drop support

New Drag & Drop support in 3.15 development series:Sponsored by GNOME Foundation

First of all I would like to thanks once again to the foundation for sponsoring my trip to Brussels to attend the Developer Experience Hackhest and Alberto for inviting me in the first place!

After the hackfest we all agreed that Glade needs some love to make it more newbie friendly, nothing we did not already knew, but please do not move along Glade needs your help!

On of the thing that new people find the most difficult to understand about creating GUI with Gtk+/Glade is the container packing paradigm which is very powerful once you get used to it but not as intuitive as one would like.

A way to improve this situation would be to create a new free form layout container similar to Java’s GroupLayout as suggested by Alex in this mail which of course is a lot of work specially in Glade so… help and/or sponsorship is welcome!!

But for now being able to drag & drop widgets around should make thinks easier, right?

[vimeo width=”640″ height=”400″]https://vimeo.com/60841071[/vimeo]

The next thing we want to address is the property editor. Not only does not look good (In its defense the whole thing is autogenerated) but thanks to wide screen displays being ubiquitous nowadays it is wasting some precious vertical space :S

This is how it currently looks like

glade_property_editor_old

So… to save some vertical space and make it look more modern this are the changes I made

glade_property_editor_new

  • New ATK icon
  • Replaced toggle buttons with switches
  • Fields do not expand by default
  • Replaced text field edit button with an entry edit icon
  • Removed class field title
  • Moved clear and help buttons to the top of the notebook

The last item is definitely not definitive since it might make more sense to move it inside the scrolled window or simply to the toolbar.

As you can see there is lot of room for improvement so if you come up with a good idea help us!

Cross compiling Glade for win32

It was a long time since I did not give cross compiling a try and it turns out to be easier than expected if you use precompiled binaries from windows:mingw[1] project on the OpenSUSE Build Service. (OBS)

First of all we need to install the cross compiler, in Debian and Debian based distros do

$ sudo apt-get install mingw-w64

Then we need to download a python script [2] that makes downloading mingw packages from OBS easy.

wget https://github.com/mkbosmans/download-mingw-rpm/raw/master/download-mingw-rpm.py

Now we can download the dependencies (hicolor-icon-theme is only needed at runtime)

python3 download-mingw-rpm.py --deps gtk3-devel libxml2-devel \
        hicolor-icon-theme

This will unpack everything under usr/i686-w64-mingw32/sys-root/mingw

Next we need to setup some variables for the cross compilation

export CC=i686-w64-mingw32-gcc
export MINGW_ROOT=`readlink -f usr/i686-w64-mingw32/sys-root/mingw`
export PKG_CONFIG_LIBDIR=$MINGW_ROOT/lib/pkgconfig
export PKG_CONFIG_PATH=$MINGW_ROOT/share/pkgconfig
export PKG_CONFIG="pkg-config --define-variable=prefix=$MINGW_ROOT"

CC: the cross compiler
MINGW_ROOT: is an absolute path we are going to use as a prefix for our build
PKG_CONFIG_LIBDIR: this way we tell pkg-config to use mingw libs
PKG_CONFIG_PATH: just to make sure we are not pointing some where else
PKG_CONFIG: ask pkg-config to replace .pc files prefix variable with the real path

And this is pretty much it, now we can proceed to run autogen.sh with –host and –target flags and glade should compile

git clone git://git.gnome.org/glade
cd glade
./autogen.sh --prefix=$MINGW_ROOT --host i686-w64-mingw32 \
--target i686-w64-mingw32 --enable-shared=yes --enable-static=no
make
make install

Before you can run it you need to update glib schemas bin file

glib-compile-schemas $MINGW_ROOT/share/glib-2.0/schemas

BTW there is a scrip file that automates this process and creates a windows installer using nsis
in glade sources under build/mingw-w64 directory.

1) https://build.opensuse.org/project/show?project=windows%3Amingw%3Awin32
2) https://github.com/mkbosmans/download-mingw-rpm

Hacking Glade in Glade: A recursion exercise

Last week, inspired by Tristan’s GtkComposite branch idea of embedding builder xml into widget classes together with the old eagerness  of implementing Glade UI with Glade itself I started hacking Glade in glade!

The first step was to recreate GladeWindow widget hierarchy in Glade, that was quick and easy. Then I started replacing the hard coded widgets with it but since I wanted to use the very same executable I was hacking on to edit its own UI definition file I had to make sure I got the palette, design view, inspector and property editor properly working before removing the old code.

Later on I proceeded to remove the old menu that was implemented using GtkUIManager… big mistake! How was I supposed to edit the file if I was not able to save the file, so I revert it and moved it to the end of the window and keep it until the new menu had a working save menu item!

After this, Glade was functional and only had one regression. For some reason GtkAccelLabel does not show up the accelerator when used with a related action.  But that seems to be a Gtk+ bug (see bugzilla report)

The only problem left to solve was the dependency GladeWindow had on the UI file. I really did not like the idea of a class depending on a file so I decided it was a good time to give GResource a try! GResource allows you to easily embed resources into your code. All you have to do is define all your resources in GResource xml format, in this case only one file glade.glade.

glade-resources.gresource.xml:

<?xml version="1.0" encoding="UTF-8"?>
<gresources>
 <gresource prefix="/org/gnome/glade">
  <file compressed="true">glade.glade</file>
 </gresource>
</gresources>

And compile it into source using glib-compile-resourses tool, which can be done automatically with a couple of Makefile rules.

# Rules to compile resources
%.h: %.gresource.xml
  $(GLIB_COMPILE_RESOURCES) --generate $< --target=$@
%.c: %.gresource.xml
  $(GLIB_COMPILE_RESOURCES) --generate $< --target=$@
 
# Dependencies rule, and do not forget to do a make after
# editing the UI with glade!
glade-resources.c glade-resources.h: \
       glade-resources.gresource.xml \
       $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies \
         glade-resources.gresource.xml)

Once you have the build system setup it is as simply as using the resource uri instead of a file path.

GtkBuilder *builder = gtk_builder_new ();
GError *error = NULL;
gtk_builder_add_from_resource (builder,
                               "/org/gnome/glade/glade.glade",
                               error);

As usual you can find this in git master
git clone git://git.gnome.org/glade