You Got A Question? Ask    GNOME Community!


Making Fancy GNOME Apps with NodeJS, MongoDB and WebKit!

This post was made with an older stylesheet


Why

I had done a small GTK/GJS App to manage my Ruby On Rails Environments with RVM.  Today I started a new App to store my passwords and I spend 3-4h trying to fix it, without any luck. I don’t know GTK Programming and I don’t either want to learn. So I decided to try again in Clutter/GJS.

Clutter unlike GTK is exciting, it’s modern and you have unlimited freedom to create interfaces ..and in one word is just *cool*!  I have a habit to keep App data in JSON files, and later on I just push them in MongoDB. So I started to Googling around about MongoDB support in GJS/Seed but I just found support for SQLite. I can work with Relational Databases but I prefer NoSQL since are much simpler to manipulate and understand at first look.

There were more issues with GTK/Clutter/GJS/SQLite combination that were coming either from my poor knowledge (the most probable reason!) or the limitation of these libraries, but whatever the reason was, documentation didn’t help a lot. So I thought to give a try with NodeJS and GTK.


Fedora’s Apple

So I started to experiment  and I made this in about 150′, which is a good time if you think that I spend 20′ in Gimp and I don’t know GTK so I had to read some docs.

fedoras-apple

This is a GTK Window with two placeholders. On the left is just a sidebar with controlling widgets (just a button for demo). On the right is a WebKit container. What I did with WebKit, was to make a Twitter Bootstrap Page and run a NodeJS to serve it as static page with <node-static> module.

The second step was to run Linux Commands from JavaScript. That was easy with NodeJS  and Child Processes, so I managed in 5min to bind the buttons in Linux Commands. Finally I added a function that inserts every running command and output (for that specific command) in a MongoDB, which is a cool way to keep logs in this case (installing Apps).

For the people that don’t know NodeJS, is an server side framework using event-driven, asynchronous I/O. Of course you can make synchronous calls if you need to wait for a process to end before you spawn a new one.


Isn’t this nice?

I doubt that is a the perfect way to make GNOME Apps and to be honest I don’t know if there are any serious concerns with this practice. However it is cool! You have the 2 of the best Open Source technologies  (WebKit & NodeJS), you can create and run async HTML5 Apps in no time ..and you have all the tools to manage files, text, images, videos, music and databases with plenty of documentation, plus the many amazing JavaScript libraries to create rich UIs. Also you can play with WebSocket Programming and make “real time” GNOME Client / Server Apps easily.

I made this totally to experimental and to see if it is working. Since it was so easy I will try to write a regular NodeJS App and make such an App as Fedora’s Apple, which is of course a joke to Apple Inc and their close source theories ..that are collapsing day by day ;)

Oh, the other cool thing is that you don’t need any dependencies to run this! I just use GJS and I can bundle MongoDB and NodeJS executable’s inside the package, so it’s just download and run! An issue is how the GTK part (menus) can communicate with WebKit. This can be done by creating text “state” files.

fedoras-apple-web

This is obviously working also in your browser. Using the GTK you can add some options like the server port you want to run it etc, and also you save some resources, since web-browsers are getting very “hungry” lately..


The Code

This is my GJS file and how to use WebKit / GJS. The rest files are just my index.hml/CSS and NodeJS Scripts, nothing exciting there.

const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const WebKit = imports.gi.WebKit;

/***How you can set ./ Path? ***/
imports.searchPath.push("/home/alex/Projects/Playground/FedorasApple");
Properties = imports.properties;

const FedorasApple = new Lang.Class ({
    Name: 'FedorasApple',	

    _init: function () {
        this.application = new Gtk.Application ({
            application_id: 'org.example.myapp',
            flags: Gio.ApplicationFlags.FLAGS_NONE
        });

       this.application.connect('activate', Lang.bind(this, this._onActivate));
       this.application.connect('startup', Lang.bind(this, this._onStartup));
    },
	_showAbout: function() {
        print ("Dummy Print!");
    },

	_initMenus: function() {
        let menu = new Gio.Menu();        
        menu.append("Gnome 3 Rocks!", 'app.rocks');
        menu.append("Quit",'app.quit');
        this.application.set_app_menu(menu);        

        let aboutAction = new Gio.SimpleAction ({ name: 'rocks' });
        aboutAction.connect('activate', Lang.bind(this,
            function() {
                this._showAbout();
            }));
        this.application.add_action(aboutAction);

        let quitAction = new Gio.SimpleAction ({ name: 'quit' });
        quitAction.connect('activate', Lang.bind(this,
            function() {
                this._window.destroy();
            }));
         this.application.add_action(quitAction);
    },

    _buildUI: function () {
        this._window = new Gtk.ApplicationWindow  ({ application: this.application,
                                                   window_position: Gtk.WindowPosition.CENTER,
                                                   title: "Fedora's Apple" });       

		this.html5view = new WebKit.WebView();
		this.html5view.load_uri(Properties.server_url+Properties.server_port);

		this.Box = new Gtk.Box ();		
		this.hBox = new Gtk.HBox();

        this.Button = new Gtk.Button ({ label: "Gtk Widget" });
		this.hBox.add(this.Button);
		this.hBox.add(this.html5view);

		this.Box.add(this.hBox);		
		this._window.add(this.Box);

		this._window.set_size_request(1000, 600);
        this._window.set_resizable(false);       	

        this._window.show_all();
    },
    _onActivate: function () {
        this._window.present ();
    },
    _onStartup: function () {
		this._initMenus();
        this._buildUI ();
    }
});

let app = new FedorasApple ();
app.application.run (ARGV);

This is where you have to use your html page. It could be a link, eg http://google.com

Properties.server_url+Properties.server_port

I didn’t make anything crazy here, I just mostly copied code from these sources:

I picked GJS (GNOME JavaScript/Spidermonkey bindings) and not Seed (GNOME WebKit Javascript bindings) only because is what GNOME uses.


This is a dummy Application that it just makes sure that basic functionality can work in a real one!

Other Sources


 
  We can't watch comments unless G+ provides an API or if you send a notification, e.g +World Of Gnome
     Sometimes is better to place your questions on GNOME Community
  • Philip Witte

    Nice tutorial. Happy New Year!

    • alex285

      Happy new year! I just finished my passwords App.. Goodbye gEdit :)

      • Rajesh KSV

        Wow that’s nice … Looking crazy as well ;) Can you please share the github link for the app ?

        Happy New Year btw !

        • alex285

          Hello, what app?

      • http://varemenos.com/ Adonis K. (Varemenos)

        lol, gEdit for storing passwords

  • http://funsurf-blog.blogspot.com/ Satyajit Sahoo

    I have only two problems with HTML5 apps, they don’t look native, and generally more resource hungry than native code.

    • http://0rAX0.deviantart.com Reda Lazri

      Sometimes, not looking like a GTK app is an advantage. ;)

      • Eduard Gotwig

        So whats the point of that, if I just can use apt://SOFTWAREPACKAGE :/?

        • alex285

          Well, the difference is that you are not limited to apt:// ..You can do whatever a native GNOME can do, plus you can create awesome interfaces and plus you have some better functionality for handling files and databases that GNOME gives you.

          But the bottom line is that you can create advanced apps easily and fast, and everything is in javascript, that is the most popular language. NodeJS is javascript, mongodb is javascript, GJS is javascript. It is not suitable for every kind of App, but for handling databases it rocks!

          • alex285

            Also you can run it online from distance, if you put some protection.

  • http://twitter.com/paugnu Pau Iranzo

    Alex! Could you please share the whole code and explain how to execute it?

    • alex285

      Hello!
      Okay, I will make the day after tomorrow a step by step tutorial for the people that haven’t been to nodejs yet, with the basic things like execute system commands from your web interface, read and write log files etc!

  • http://profiles.google.com/fabianofranz Fabiano Franz

    Nice tutorial!

    This is very similar to the node-webkit project:

    https://github.com/rogerwang/node-webkit

    Which is used for example by the Stormcloud app:

    https://github.com/consindo/stormcloud

    Cheers!

    • alex285

      Hey, thanks for sharing this!

  • http://varemenos.com/ Adonis K. (Varemenos)

    happy new year!

    inb4, apple sues you for the name :D

  • sramkrishna

    Well done, Alex. :-) Somebody’s lightbulb just went off! :-)

  • http://jewelfox.dreamwidth.org/ Taryn Fox

    Oh hey, I wrote some of that tutorial code. ^.^ Very nice to see someone putting it to good use!

    • alex285

      Yeap, I remember you from that weird blog of yours! Thanks for the samples!

  • Craig

    JavaScript is a truly awful language. I tolerate it for client-side web work but actually *opting* to use it when you don’t have to is insane.

    • alex285

      I guess you mean the syntax of JS, but you can use CoffeeScript. There are all these options like Jade, Stylus, Sass, CoffeeScript, etc, is up to you what you want to use. In my case in this WP I used css and javascript because these are the defaults. In rails I use coffee and sass. In NodeJS I do Jade, Stylus and Ejs.. In the end of the day all feel the same, is just css/javascript/html.

  • Pingback: Run GNOME + HTML5 Applications over Network | woGue