First off, Happy New Year to *Everyone*! Since this is the first post of the new year, I thought to put a fancy title ;)
I don’t know if this is the best way to make things, but what I did was to use the best and most established technologies that are available today and making a simple GNOME App. So I used WebKit, NodeJS, MongoDB and a bit of GTK/GJS, so I can call it a GNOME App ;)
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.
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.
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:
- http://git.gnome.org/browse/gjs/tree/
- http://developer.gnome.org/gnome-devel-demos/unstable/beginner.js.html.en#tutorials
- http://www.roojs.com/seed/gir-1.2-gtk-3.0/gjs/
- http://www.roojs.com/seed/gir-1.2-gtk-3.0/seed/
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



Pingback: Run GNOME + HTML5 Applications over Network | woGue