Programmazione

Applicazioni multipiattaforma 100% GUI-Indipendent

|

Può capitare di dover realizzare programmi che siano utilizzabili con diverse interfacce grafiche, in Ruby ci sono diversi stratagemmi per farlo e al primo posto troviamo i blocchi, ecco un programmino d'esempio che funzione da gtk o console.

L'idea di base è che tutti i controlli dati vengono fatti dalla classe interna, mentre le interfacce si limitino solo a fare input/output; probabilmente questo approccio non va bene in tutti i casi, ma se si usano pochi semplici widget fa la sua bella figura.

Ho deciso di usare i metodi "error" e "notify", per semplicità, ma si sarebbero potute utilizzare anche le eccezioni; stesso discorso per l'alert. Gtk::Dialog sarebbe il widget giusto, ma rischierebbe di creare confusione.

Si esegue con:

ruby esempio.rb (Console) o ruby esempio.rb --gtk (Gtk)



#!/usr/bin/ruby
=begin
 == esempio.rb ==
 Una semplice implementazione di oggetti indipendenti dall'interfaccia grafica/console
 oOo. http://assente.altervista.org .oOo
=end

# Oggetto principale GUI-indipendent
class List
    def initialize()
        @a=[]
    end
    def add(value)
        # vari controlli sull'input
        if value==""
            error("Valore nullo")
        elsif value=~/[a-zA-Z]/
            error("Le lettere non sono ammesse")
        elsif value=~/[0-9]/
            @a << value
            notify("'#{value}' inserito")
        end
    end
    # yield viene sostituito con quello che passiamo a livello superiore,
    # puts oppure @display.text+=, fantastico, no?
    def show_all
        @a.each { |value| yield value}
    end
end

class ConsoleList < List
    def initialize
        super
        puts "Console mode"
        while true
            puts "1: Aggiungi 2: Visualizza 3: Esci"
            # toglie \n dall'input da terminale
            choice=gets.strip
            case (choice)
                when "1" then add
                when "2" then show_all
                when "3" then exit
            else
                error("Scelta non valida")                
            end        
        end
    end
    def add
        puts "Inserisci: "
        # manda al metodo List#add vedi su
        super(gets.strip)
    end
    # Richiamato da List
    def error(text)
        puts "!! #{text} !!"
    end
    def notify(text)
        puts ">> #{text}"    
    end
    def show_all
        super{|v| puts "|#{v}|"}
    end
end

class GtkList < List
    require 'gtk2'
    def initialize
        super
        puts "GUI mode"
        
        Gtk.init    
        
        #Inizializzo i widget
        @window=Gtk::Window.new
        @container=Gtk::VBox.new
        @entry=Gtk::Entry.new
        @display=Gtk::Label.new
        @button=Gtk::Button.new("Inserisci")
        
        #Assegno gli eventi
        @button.signal_connect("clicked"){add}
        @entry.signal_connect("activate"){add}
        @window.signal_connect("destroy"){exit}
        
        #impacchetto
        @container.add(@display).add(@entry).add(@display).add(@display).add(@button)
        @window.add(@container)
        
        @window.show_all
        
        Gtk.main
    end
    def add
        puts "Inserisci: "
        super(@entry.text)
        @entry.text=""
    end
    def error(text)
        # Con più spazio estendetevi Gtk::Alert :-)
        Gtk::Window.new.add(Gtk::Label.new("#{text}")).show_all
    end
    def notify(text)
        # Non necessario
        #Gtk::Window.new.add(Gtk::Label.new("#{text}")).show_all
        show_all
    end
    def show_all
        @display.text=""
        super{|v| @display.text+=v+" "}
    end
end

# Inizia qui
case(ARGV[0])
    when nil:     ConsoleList.new
    when "--gtk": GtkList.new
end


l'equivalente di private static in Ruby

|

Se volete contare tutti gli oggetti creati con una certa classe avete bisogno di un campo private static; in Ruby questo non esiste, ma una via molto elegante per farlo è questa:
[code]
class Counter
def initialize
@count = 0
end
def next
value = @count
@count += 1
return value
end
end

module Countable
def self.included(mod)
mod.instance_eval do
@counter = Counter.new
end

class << mod;
attr_reader :counter
end
end
end

class Counted
include Countable
def initialize
@count = self.class.counter.next
end
end

p Counted.new
p Counted.new
p Counted.new
[/code]

Ringrazio il canale #ruby-lang su irc.freenode.net per questa dritta

Esportare i contatti di Evolution su GMail con vcf2csv

|

Finalmente uno script che mi funziona per esportare un file vcf di Evolution in uno csv pe GMail; ne avevo provati degli altri ma non mi funzionavano.. forse perchè Evolution cambia in ogni versione il modo in cui registra il campo email; attualmente sto utilizzando la 2.0.0 e ho quindi usato [b]EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:[/b], ma se usate versioni precedenti può darsi che sia [b]EMAIL:[/b] o altro, vi conviene fare prima un bel sostituisci :)

Lo script è in Ruby, sicuramente poteva essere più flessibile, compatto, ecc.. Ma per adesso dovete accontentarvi di questo visto che devo ancora imparalo ad usare bene.

Se avete idee migliori su come ottimizzarlo o per qualsiasi altra cosa, lasciatemi un commento.

Non vedo l'ora di poter sincronizzare i contatti/appuntamenti tra GMail-evolution-cellulare (Dai che per Natale arriva il [url=http://www.newsmobile.it/schedapalm/qteks100]qtek s100[/url], non vedo l'ora), speriamo che in futuro si possano gestire anche gli appuntamenti con [url=http://www.gmail.com]GMail[/url].
[code]
#! /usr/bin/ruby
=begin
vcf2csf - Export vcffile to csvfile
$Author: Assente $
Copyright (C) 2004 assente.altervista.org
This program is free software.
You can distribute/modify this program under
the terms of the GPL License.
=end
# CONFIG ME
vcfwords=["FN:","EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:","TEL;TYPE=CELL;X-EVOLUTION-UI-SLOT=3:"]
csvwords=["Full Name","Email Address","Mobile"]
#
if (ARGV[0]=="--help" || ARGV[0]==nil || ARGV[1]==nil)
puts "Usage: ./vcf2csf.rb [input-vcf] [output-csv]
Function: Convert a vcffile to csvfile, usefull to export contacts from Evolution to GMail"
else
vcffile=ARGV[0]
csvfile=ARGV[1]
csv=""
rows=open(vcffile).readlines
for i in 0..rows.length-1
if rows[i].slice(0,5)=='BEGIN'
csv << "\n"
end
for j in 0..vcfwords.length-1

if rows[i].slice(0,vcfwords[j].length)==vcfwords[j]
csv << rows[i].slice(vcfwords[j].length,30).chomp
csv << ","
end
end
end
c=open(csvfile,'w+');
c.write(csvwords.join(",")+csv)
c.close
end
[/code]

Confronto prestazioni tra linguaggi

Confronto prestazioni tra linguaggi

[code]
def fib(n)
if n>2
n
else
fib(n-2)+fib(n-1)
end
end
print(fib(30), "\n");
[/code]

Il codice sopra è stato "tradotto" in vari linguaggi di programmazione moderni; [b]Java[/b] e [b]C#[/b] sono linguaggi ibridi semicompilati, mentre i restanti [b]Ruby[/b], [b]Python[/b] e [b]Perl[/b] sono interpretati.
Il comando [u]time[/u] misura il tempo impiegato a generare l'output, con questo difficilmente si deduce che un linguaggio è più veloce di un'altro, comunque sia, ci si può fare una vaga idea delle loro prestazioni in piccoli programmi.
Concludendo, ogni linguaggio ha la sua peculiarit? e i propri vantaggi/svantaggi, personalmente mi affascinano molto Ruby e C#, ma se cercate delle soluzioni più mature forse Java, Python e Perl sono le più collaudate...

Come sempre a voi la scelta ;-)

[code]
pc01:~$ dmesg | grep CPU
CPU0: AMD Athlon(TM) XP1700+ stepping 02
pc01:~$
pc01:~$ uname -a
Linux pc01 2.4.22.tutto #1 SMP gio ott 16 17:35:03 CEST 2003 i686 GNU/Linux
pc01:~$
pc01:~$ time java fib
832040

real 0m1.892s
user 0m0.100s
sys 0m0.210s
pc01:~$ time mono fib.exe
832040

real 0m0.928s
user 0m0.100s
sys 0m0.060s
pc01:~$ time ruby fib.rb
832040

real 0m3.829s
user 0m3.650s
sys 0m0.040s
pc01:~$ time python fib.py
832040

real 0m2.484s
user 0m1.880s
sys 0m0.040s
pc01:~$ time perl fib.pl
832040

real 0m4.160s
user 0m3.670s
sys 0m0.010s
pc01:~$
[/code]

Syndicate content