Susanna Huhtanen
ihmis.suski@gmail.com 2012
Ελληνική μεταφραστική ομάδα GNOME
team@gnome.gr 2012-2015
Δημήτρης Σπίγγος
dmtrs32@gmail.com 2012, 2013
Μαρία Θουκιδίδου
marablack3@gmail.com 2014
Θάνος Τρυφωνίδης
tomtryf@gmail.com 2014, 2015

# Το κύριο αρχείο του προγράμματος

        Σε αυτό το τμήμα του οδηγού θα κατασκευάσουμε το κύριο αρχείο του προγράμματος της εφαρμογής καιρού. Για να γράψετε και να τρέξετε όλα τα παραδείγματα κώδικα οι ίδιοι, χρειαζόσαστε έναν επεξεργαστή για το γράψιμο του κώδικα, τερματικό και GNOME 3 ή μεταγενέστερο εγκατεστημένο στον υπολογιστή σας. Σε αυτό το τμήμα θα εξετάσουμε τα παρακάτω μέρη:

          Σενάριο για εκτέλεση της εφαρμογής
          Βιβλιοθήκες για εισαγωγή
          Δημιουργία του κύριου παραθύρου για την εφαρμογή
          Προσθήκη πλέγματος και όλων των απαραίτητων γραφικών στοιχείων σε αυτό
          Αίτηση των πληροφοριών καιρού ασύγχρονα
          Σύνδεση σημάτων σε κουμπί και καταχώριση.
          weatherapp.js

# Σενάριο για εκτέλεση της εφαρμογής

#!/usr/bin/gjs

Αυτή η γραμμή λέει πώς θα εκτελεστεί το σενάριο. Πρέπει να είναι η πρώτη γραμμή του κώδικα και να είναι εκτελέσιμη. Για λήψη των δικαιωμάτων εκτέλεσης πηγαίνετε στον τερματικό και εκτελέστε στον σωστό φάκελο: chmod +x όνομα σεναρίου. Ή μπορείτε να χρησιμοποιήσετε τον διαχειριστή αρχείου γραφικών. Απλά πηγαίνετε στον σωστό φάκελο όπου είναι ο κώδικας σας δεξί κλικ στο αρχείο του κώδικα σας, επιλέξτε ιδιότητες, κλικ στην καρτέλα δικαιωμάτων και σημειώστε το πλαίσιο για να επιτραπεί η εκτέλεση του αρχείου ως πρόγραμμα

# Βιβλιοθήκες για εισαγωγή

var Gtk = imports.gi.Gtk; const WeatherService = imports.geonames;

Για να έχουμε ένα αποτελεσματικό πρόγραμμα χρειαζόμαστε να εισάγουμε μια βιβλιοθήκη GObject αυτανάλυσης για χρήση. Για χρήση UI, χρειαζόμαστε Gtk. Το Gtk εισάγεται στην αρχή, έτσι το έχουμε για χρήση παντού. Εισάγουμε επίσης τη δικιά μας τοπική βιβλιοθήκη JavaScript geonames για να χρησιμοποιηθεί εδώ.

# Δημιουργία του κύριου παραθύρου για την εφαρμογή

// Initialize the gtk Gtk.init(null, 0); //create your window, name it and connect the x to quit function. Remember that window is a taken word var weatherwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL}); weatherwindow.title = "Today's weather"; //Window only accepts one widget and a title. Further structure with Gtk.boxes of similar weatherwindow.connect("destroy", function(){Gtk.main_quit()});

weatherwindow.show_all(); //and run it Gtk.main();

# Προσθήκη πλέγματος και όλων των απαραίτητων γραφικών στοιχείων σε αυτό

var grid = new Gtk.Grid(); weatherwindow.add(grid);

//We initialize the icon here, but decide the file later in geonames.js. var weatherIcon = new Gtk.Image();

//Set some labels to your window var label1 = new Gtk.Label({label: ""}); var label2 = new Gtk.Label({label: "Looking in the sky..."}); var label3 = new Gtk.Label({label: ""});

var entry = new Gtk.Entry(); entry.set_width_chars(4); entry.set_max_length(4); var label4 = new Gtk.Label({label: "Enter ICAO station for weather: "}); var button1 = new Gtk.Button({label: "search!"});

grid.attach(label4, 2, 1, 1, 1); grid.attach_next_to(label1,label4,3,1,1); grid.attach_next_to(label2,label1,3,1,1); grid.attach_next_to(label3,label2,3,1,1); grid.attach_next_to(entry,label4,1,1,1); grid.attach_next_to(button1,entry,1,1,1); grid.attach_next_to(weatherIcon,label2,1,1,1)

In this section we create the grid we are going to use for positioning the widgets. All the buttons, labels and entries are initialized and placed on the grid. As seen from the placing of the different widgets, they don't need to be related only to one widget. At this point some of the labels don't have any content. The content for those widgets is applied later. If you run the application at this stage, you have the UI ready, but the widgets are not connected to anything. For this we need to first build the weather searching local library, and then get the information we need asynchronously. When we have our local library ready we can connect it to the necessary widgets.

# Αίτηση των πληροφοριών καιρού ασύγχρονα

function getWeatherForStation() { var station = entry.get_text();

var GeoNames = new WeatherService.GeoNames(station); //"EFHF";

GeoNames.getWeather(function(error, weather) { //Αυτό εδώ δουλεύει λίγο σαν σήματα. Αυτός ο κώδικας θα εκτελεστεί όταν έχουμε καιρό. if (error) { label2.set_text("Suggested ICAO station does not exist Try EFHF"); return; } weatherIcon.file = GeoNames.getIcon(weather);

label1.set_text("Temperature is " + weather.weatherObservation.temperature + " degrees."); if (weather.weatherObservation.weatherCondition !== "n/a"){ label2.set_text("Looks like there is " + weather.weatherObservation.weatherCondition + " in the sky."); } else { label2.set_text("Looks like there is " + weather.weatherObservation.clouds + " in the sky."); } label3.set_text("Windspeed is " + weather.weatherObservation.windSpeed + " m/s") // ... }); }

Αυτή η λειτουργία αφιερώνεται στην κλήση για τις πληροφορίες καιρού και ενημέρωση ετικετών και εικονιδίων ανάλογα. Στην αρχή της λειτουργίας παίρνουμε την είσοδο χρήστη για αναζήτηση. Έτσι εδώ για την πρώτη φορά χρησιμοποιούμε τη δική μας βιβλιοθήκη και τις αποδίδουμε τη μεταβλητή GeoNames. Ενώ εκχωρούμε την WeatherService της δίνουμε τον σταθμό. Το πρώτο πράγμα που κάνουμε με τα GeoNames είναι η αίτηση καιρού. Οτιδήποτε μετά τα GeoNamesgetWeather.getWeather (συνάρτηση (σφάλμα, καιρός) συμβαίνει μόνο εάν είτε πάρουμε ένα μήνυμα σφάλματος ή πληροφορίες καιρού. Εάν δεν έρθει κανένα, το υπόλοιπο του προγράμματος δουλεύει τόσο κανονικά, όσο το main_Quit δουλεύει.

# Σύνδεση σημάτων σε κουμπί και καταχώριση.

entry.connect("key_press_event", function(widget, event) { if (entry.get_text().length === 4) { // Enough is enough getWeatherForStation(); } return false; });

button1.connect("clicked", function(){ getWeatherForStation(); });

Και τελικά έχουμε τις συνδέσεις που κάνουν όλη την εφαρμογή να τρέχει όπως θα έπρεπε. Συνδέουμε και την καταχώριση και το κουμπί για να κάνουν το ίδιο πράγμα, παίρνοντας τον καιρό. Έτσι δεν πειράζει, εάν πατήσετε εάν πατήσετε εισαγωγή ή κλικ στο κουμπί αναζήτησης.

# Weatherapp.js

Το αρχείο Weatherapp.js μοιάζει με αυτό:

#!/usr/bin/gjs //The previous line is a hash bang tells how to run the script. // Note that the script has to be executable (run in terminal in the right folder: chmod +x scriptname)

var Gtk = imports.gi.Gtk;

const WeatherService = imports.geonames; //Bring your own library from same folder (as set in GJS_PATH). If using autotools .desktop will take care of this

// Initialize the gtk Gtk.init(null, 0); //create your window, name it and connect the x to quit function. Remember that window is a taken word var weatherwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL}); weatherwindow.title = "Today's weather"; //Window only accepts one widget and a title. Further structure with Gtk.boxes of similar weatherwindow.connect("destroy", function(){Gtk.main_quit()}); //We initialize the icon here, but decide the file later in geonames.js.

var weatherIcon = new Gtk.Image();

//Set some labels to your window var label1 = new Gtk.Label({label: ""}); var label2 = new Gtk.Label({label: "Looking in the sky..."}); var label3 = new Gtk.Label({label: ""});

var grid = new Gtk.Grid(); weatherwindow.add(grid);

var entry = new Gtk.Entry(); entry.set_width_chars(4); entry.set_max_length(4); var label4 = new Gtk.Label({label: "Enter ICAO station for weather: "}); var button1 = new Gtk.Button({label: "search!"});

//some weather

entry.connect("key_press_event", function(widget, event) { // FIXME: Get weather on enter (key 13) if (entry.get_text().length === 4) { // Enough is enough getWeatherForStation(); } return false; });

button1.connect("clicked", function(){ getWeatherForStation(); });

function getWeatherForStation() { var station = entry.get_text();

var GeoNames = new WeatherService.GeoNames(station); //"EFHF";

GeoNames.getWeather(function(error, weather) { //this here works bit like signals. This code will be run when we have weather. if (error) { label2.set_text("Suggested ICAO station does not exist Try EFHF"); return; } weatherIcon.file = GeoNames.getIcon(weather);

label1.set_text("Temperature is " + weather.weatherObservation.temperature + " degrees."); if (weather.weatherObservation.weatherCondition !== "n/a"){ label2.set_text("Looks like there is " + weather.weatherObservation.weatherCondition + " in the sky."); } else { label2.set_text("Looks like there is " + weather.weatherObservation.clouds + " in the sky."); } label3.set_text("Windspeed is " + weather.weatherObservation.windSpeed + " m/s") // ... }); }

grid.attach(label4, 2, 1, 1, 1); grid.attach_next_to(label1,label4,3,1,1); grid.attach_next_to(label2,label1,3,1,1); grid.attach_next_to(label3,label2,3,1,1); grid.attach_next_to(entry,label4,1,1,1); grid.attach_next_to(button1,entry,1,1,1); grid.attach_next_to(weatherIcon,label2,1,1,1) weatherwindow.show_all(); //and run it Gtk.main();

Εκτέλεση μέχρι να έχετε όλα τα αρχεία autotools έτοιμα. :

     $  GJS_PATH=`pwd` gjs weatherapp.js

Χρησιμοποιήστε αυτήν την εντολή στο τερματικό ενώ αναπτύσσετε τα αρθρώματά σας. Όταν καλείτε το πρόγραμμά σας με αυτόν τον τρόπο, ξέρει πού θα βρει τις προσαρμοσμένες JSlibraries, σε αυτήν την περίπτωση το geonames.js.