27/7/2011

Gestionar los archivos de configuración en /etc con etckeeper y mercurial

Continuando con los artículos de control de versiones distribuido con Mercurial ahora toca el respaldo y guardar las versiones de los archivos de configuración en /etc con etckeeper.

La mayoria de los artículos que se consiguen sobre etckeeper es usando git o bazaar.

Para esta guía es necesario tener conocimientos básicos de mercurial, pueden leer el artículo de control de versiones con mercurial de este blog.

Es necesario llevar un histórico de los archivos dentro del directorio /etc/, es esencial para un sistema saludable. Los beneficios rastrear cambios en los archivos dentro de /etc incluye:
  • Documentación: Los mensajes de log quedan atados a los cambios de configuración de los archivos que sirven como documentación.
  • Resolución de problemas: Permite devolver cambios en las configuraciones que han dado problemas y así mantener la estabilidad del sistema.
1.Instalación de etckeeper:
 Es necesario tener mercurial instalado.
aptitude install mercurial etckeeper

2.Configuración de etckeeper:
Se edita el archivo /etc/etckeeper/etckeeper.conf se comenta los distintos sistemas de control de versiones y se deja hg, adicionalmente se deja la opción de envío de correo a un usuario.

VCS="hg"
# Options passed to hg commit when run by etckeeper.
HG_COMMIT_OPTIONS="-u ecrespo@gmail.com"


Luego se edita el archivo /etc/mercurial/hgrc
Se agrega el correo del usuario:
[ui]
username = ecrespo@gmail.com

3. Se inicializa el control de versiones:

etckeeper init

A continuación se muestra como se ha agregado los archivos dentro de /etc en el control de versiones:
adding xdg/xfce4/Xft.xrdb
adding xdg/xfce4/helpers.rc
adding xdg/xfce4/mount.rc
adding xdg/xfce4/panel/clock-14.rc
adding xdg/xfce4/panel/launcher-10.rc
adding xdg/xfce4/panel/launcher-7.rc
adding xdg/xfce4/panel/launcher-9.rc
adding xdg/xfce4/panel/panels.xml
adding xdg/xfce4/panel/systray-4.rc
adding xdg/xfce4/panel/xfce4-menu-5.rc
adding xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-keyboard-shortcuts.xml
adding xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-session.xml
adding xdg/xfce4/xfconf/xfce-perchannel-xml/xsettings.xml
adding xdg/xfce4/xinitrc
adding xml/catalog
adding xml/docbook-xml.xml
adding xml/docbook-xsl.xml
adding xml/rarian-compat.xml
adding xml/sgml-data.xml
adding xml/xml-core.xml

4. Se hace el primer commit:
etckeeper commit "Inicializacion del control de versiones"

5. Usando etckeeper.
Al realizar la instalación de un programa se ejecutará automáticamente el agregado de los archivos de configuración en el control de versiones.
Se instalará el paquete lighttpd para mostar el proceso de agregar los archivos al control de versiones:
apt-get install lighttpd


Al final aparece una serie de archivos agregados:
adding lighttpd/conf-available/15-fastcgi-php.conf
adding lighttpd/conf-available/90-debian-doc.conf
adding lighttpd/conf-available/README
adding lighttpd/lighttpd.conf
adding logrotate.d/lighttpd
adding rc0.d/K01lighttpd
adding rc1.d/K01lighttpd
adding rc2.d/S20lighttpd
adding rc3.d/S20lighttpd
adding rc4.d/S20lighttpd
adding rc5.d/S20lighttpd
adding rc6.d/K01lighttpd

Se revisa el estatus de mercurial en el directorio /etc:
hg status /etc/
M ../etc/.etckeeper

Al revisar el log de mercurial en el directorio /etc/ muestra los cambios realizados (commit):
hg log /etc/

changeset:   1:ba22869a3179
tag:         tip
user:        ecrespo@gmail.com
date:        Wed Jul 27 22:02:27 2011 -0430
summary:     committing changes in /etc after apt run

changeset:   0:f2a3f337ecc0
user:        ecrespo@gmail.com
date:        Wed Jul 27 21:54:21 2011 -0430
summary:     Inicializacion del control de versiones

Se tiene una descripción de los cambios en el changeset 0 se muestra la inicialización del control de versiones, en el changeset 1 se muestra el cambio luego de instalar lighttpd.

Se modifica un archivo de configuración /etc/hosts :
etckeeper commit "Se elimina el dominio  del host jewel en /etc/hosts" /etc/hosts

Al volver a revisar el log de mercurial sobre el directorio /etc/ aparece el commit del cambio del archivo hosts:

hg log /etc/
changeset:   2:6efc1189bd8b
tag:         tip
user:        ecrespo@gmail.com
date:        Wed Jul 27 22:08:25 2011 -0430
summary:     Se elimina el dominio del host jewel en /etc/hosts

changeset:   1:ba22869a3179
user:        ecrespo@gmail.com
date:        Wed Jul 27 22:02:27 2011 -0430
summary:     committing changes in /etc after apt run

changeset:   0:f2a3f337ecc0
user:        ecrespo@gmail.com
date:        Wed Jul 27 21:54:21 2011 -0430
summary:     Inicializacion del control de versiones


Se puede ver las diferencias entre los cambios realizados en archivos dentro del directorio /etc:
hg diff /etc/
diff -r 6efc1189bd8b hosts
--- a/hosts    Wed Jul 27 22:08:25 2011 -0430
+++ b/hosts    Wed Jul 27 22:13:41 2011 -0430
@@ -1,6 +1,6 @@
 127.0.0.1    localhost
 127.0.1.1    jewel    jewel
-
+127.0.0.1    sofia   sofia
 # The following lines are desirable for IPv6 capable hosts
 ::1     ip6-localhost ip6-loopback
 fe00::0 ip6-localnet


Al realizar el commit y volver a hacer el diff está vez no muestra información por que ya los cambios se subieron al control de versiones:
etckeeper commit "Agregado el nombre sofia al host 127.0.0.1 en el archivo /etc/hosts" /etc/hosts

Al revisar los logs ahora aparece el cambio de agreado el nombre sofia al host 127.0.0.1:
hg log /etc/
changeset:   3:452065708a7e
tag:         tip
user:        ecrespo@gmail.com
date:        Wed Jul 27 22:16:13 2011 -0430
summary:     Agregado el nombre sofia al host 127.0.0.1 en el archivo /etc/hosts

changeset:   2:6efc1189bd8b
user:        ecrespo@gmail.com
date:        Wed Jul 27 22:08:25 2011 -0430
summary:     Se elimina pdvsa.com del host jewel en /etc/hosts

changeset:   1:ba22869a3179
user:        ecrespo@gmail.com
date:        Wed Jul 27 22:02:27 2011 -0430
summary:     committing changes in /etc after apt run

changeset:   0:f2a3f337ecc0
user:        ecrespo@gmail.com
date:        Wed Jul 27 21:54:21 2011 -0430
summary:     Inicializacion del control de versiones


Para ver el tip de cada repo se ejecuta hg tip dentro del repositorio:
root@jewel:/etc# hg tip
changeset:   3:452065708a7e
tag:         tip
user:        ecrespo@gmail.com
date:        Wed Jul 27 22:16:13 2011 -0430
summary:     Agregado el nombre sofia al host 127.0.0.1 en el archivo /etc/hosts


Ahora se mostrará todas las revisiones con los logs y luego se revertirá un cambio:
hg log
changeset:   3:452065708a7e
tag:         tip
user:        ecrespo@gmail.com
date:        Wed Jul 27 22:16:13 2011 -0430
summary:     Agregado el nombre sofia al host 127.0.0.1 en el archivo /etc/hosts

changeset:   2:6efc1189bd8b
user:        ecrespo@gmail.com
date:        Wed Jul 27 22:08:25 2011 -0430
summary:     Se elimina pdvsa.com del host jewel en /etc/hosts

changeset:   1:ba22869a3179
user:        ecrespo@gmail.com
date:        Wed Jul 27 22:02:27 2011 -0430
summary:     committing changes in /etc after apt run

changeset:   0:f2a3f337ecc0
user:        ecrespo@gmail.com
date:        Wed Jul 27 21:54:21 2011 -0430
summary:     Inicializacion del control de versiones


Se pueden ver los cambios con respecto a cada revisión, en el siguiente comando se revisa la revisión 1 con respecto a la 2 en /etc/hosts:
hg diff -r 1 -r 2 /etc/hostsdiff -r ba22869a3179 -r 6efc1189bd8b hosts
--- a/hosts    Wed Jul 27 22:02:27 2011 -0430
+++ b/hosts    Wed Jul 27 22:08:25 2011 -0430
@@ -1,5 +1,5 @@
 127.0.0.1    localhost
-127.0.1.1    jewel.dst.pdvsa.com    jewel
+127.0.1.1    jewel    jewel

 # The following lines are desirable for IPv6 capable hosts
 ::1     ip6-localhost ip6-loopback


Ahora se mostrará la 1 con respecto a la 3:
hg diff -r 1 -r 3 /etc/hosts
diff -r ba22869a3179 -r 452065708a7e hosts
--- a/hosts    Wed Jul 27 22:02:27 2011 -0430
+++ b/hosts    Wed Jul 27 22:16:13 2011 -0430
@@ -1,6 +1,6 @@
 127.0.0.1    localhost
-127.0.1.1    jewel.dst.pdvsa.com    jewel
-
+127.0.1.1    jewel    jewel
+127.0.0.1    sofia   sofia
 # The following lines are desirable for IPv6 capable hosts
 ::1     ip6-localhost ip6-loopback
 fe00::0 ip6-localnet

Ahora se revierte el cambio de la revisión 3 a la 2 en el archivo /etc/hosts.
hg revert -r 2 /etc/hosts

Ahora el host sofia ya no aparece en el archivo /etc/hosts:
127.0.0.1       localhost
127.0.1.1       jewel   jewel

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Si se desea respaldar los archivos en un servidor se puede usar bitbucket como ejemplo, se crea el proyecto configuracion-jewel y se sube el contenido del directorio /etc/ con el comando hg push:

hg push https://bitbucket.org/ecrespo/configuracion-jewel
http authorization required
realm: Bitbucket.org HTTP
user: ecrespo
password:
pushing to https://bitbucket.org/ecrespo/configuracion-jewel
searching for changes
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 4 changesets with 5764 changes to 5759 files
remote: bb/acl: ecrespo is allowed. accepted payload.


En la siguiente figura se muestra una captura de pantalla de los cambios del proyecto en bitbucket.


Con esta guía ya se puede llevar un control de los cambios realizados en el directorio /etc/ con un control de versiones distribuido como mercurial.

26/7/2011

Iniciar sesión de usuario autenticando vía pendrive

Cuando no se pasa uno a modo paranoico se le ocurren ideas de como validar usuarios al ingresar en una sesión de escritorio vía GDM.

En Debian/Ubuntu/Canaima existe los paquetes libpam-usb y pamusb-tools, estos permiten crear una llave, dicha llave se guarda en el pendrive. Luego se configura pam para que se pida la llave al momento de ingresar usuario y clave en el GDM del equipo; si no se conecta el pendrive el GDM colocará un mensaje que clave invalida.


Para instalar estos paquetes se ejecuta aptitude:
aptitude install libpam-usb pamusb-tools


Luego se conecta el pendrive en el equipo y se agrega el dispositivo en /etc/pamusb.conf con el comando pamusb-conf:
pamusb-conf --add-device /media/F060-785C/


Donde /media/F060-785C/ es la ruta del pendrive.

Se agrega el usuario en /etc/pamusb.conf el cual iniciará sesión en el equipo:
pamusb-conf --add-user ecrespo


Se verifica la configuración de pamusb con el usuario agregado:
pamusb-check ecrespo
* Authentication request for user "ecrespo" (pamusb-check)
* Device "/media/F060-785C/" is connected (good).
* Performing one time pad verification...
* Regenerating new pads...
* Unable to update pads.
* Access granted.

Al devolver el programa acceso garantizado ya se tiene todo listo para usar el pendrive en el momento de inicio de sesión, sólo falta modificar pam para que permita la autenticación con el pendrive.
Se edita el archivo /etc/pam.d/common-aut y se agrega la siguiente línea:
auth sufficient pam_usb.so
Con esta línea el GDM verifica el token de la llave, si se quiere que pida tanto la contraseña como el token se cambia sufficient a required.
auth required pam_usb.so
A partir de ahora al iniciar sesión se necesita la contraseña y el token.
A continuación se muestra el mensaje que envía la consola al ejecutar sudo -s :
[sudo] password for ecrespo: 
* pam_usb v0.4.2
* Authentication request for user "ecrespo" (sudo)
* Device "/media/F060-785C/" is connected (good).
* Performing one time pad verification...
* Regenerating new pads...
* Unable to update pads.
* Access granted.

23/7/2011

Tutorial de PyQt. checkbutton, pixmap, QFileDialog y Código QR. Parte 8.

Este post trata de un formulario en PyQt que se ingresa los datos, una foto, los días que desea por ejemplo apoyar en un evento y genera un código QR con dicha información.

Los widgets nuevos que se utilizarán son:
  • QCheckButton: Permite crear botones check, se pueden seleccionar varios opciones.
  • QPixmap: Permite agregar una imagen a una etiqueta.
  • QFileDialog: Abre una ventana de dialogo para abrir o salvar  un archivo.


El código del programa es el siguiente:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#modulo qrencode
from qrencode import encode

#Se importa el modulo sys
import sys 
#De PyQt4 importar QtGui y QtCore
from PyQt4 import QtGui, QtCore

#Import os
import os 



class App(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        #Se define el tamagno y posicion de la ventana
        self.setGeometry(0, 50, 600, 400)
        
        #Se le coloca un titulo a la ventana y se asocia un icono.
        self.setWindowTitle('Generacion de codigo QR')
        self.setWindowIcon(QtGui.QIcon('./openlogo-50.png'))
        
        #Se crea la etiqueta para la foto
        foto = QtGui.QLabel("Foto: ")
        self.imagen = QtGui.QLabel("")
        
        #Se crea el boton para cargar la foton
        cargar = QtGui.QPushButton("Cargar Foto",self)
        
        #Etiqueta nombre
        self.nombre = QtGui.QLabel('Nombre: ')
        #Entrada de datos del nombre
        self.nombreEdit = QtGui.QLineEdit()
        
        #Se crea la etiqueta y etrada de datos de la cedula        
        self.etiquetaCedula = QtGui.QLabel("Cedula")
        self.cedula = QtGui.QLineEdit()
        
        #Se crea la etiqueta y el widget para la fecha
        #de nacimiento        
        fechaEtiqueta = QtGui.QLabel("Fecha de Nacimiento")
        self.fecha = QtGui.QDateEdit(self)
        #Se define el formato dia/mes/agno
        self.fecha.setDisplayFormat("dd/MM/yyyy")
        #Se fija la fecha inicial a la fecha actual
        self.fecha.setDate(QtCore.QDate.currentDate())
        
        #Se define la etiqueta que pregunta por el sexo
        etiquetaSexo = QtGui.QLabel("Sexo:")
        #Se definen los botones de radio para masculino y femenino
        self.botonradio1 = QtGui.QRadioButton("&Masculino",self)
        self.botonradio2 = QtGui.QRadioButton("&Femenino",self)
        
        #Etiqueta ciudad.
        self.ciudadEtiqueta = QtGui.QLabel("Ciudad de Nacimiento:")
        #Se define el comboBox con las ciudades
        self.combo = QtGui.QComboBox(self)
        ciudades = ["Maracaibo",
        "Valencia","Maracay","Barquisimeto","Merida","Caracas",
        "San Cristobal","Barinas","El vigia","Ciudad Bolivar",
        "Puerto Ordaz","Coro","Puerto Cabello","Margarita"]
        for ciudad in ciudades:
            self.combo.addItem(ciudad)
        
        #Se crea la etiqueta de dia de la semana
        diasemana = QtGui.QLabel("Dia semana")
        #Se define los botones de check para los dias de la semana
        self.lunes = QtGui.QCheckBox("Lunes",self)
        self.martes = QtGui.QCheckBox("Martes",self)
        self.miercoles = QtGui.QCheckBox("Miercoles",self)
        self.jueves = QtGui.QCheckBox("Jueves",self)
        self.viernes = QtGui.QCheckBox("Viernes",self)
        
        #Se define el boton salir
        quit = QtGui.QPushButton('Salir', self)

        #Se define el boton procesar la informacion
        okButton = QtGui.QPushButton("Procesar",self)
        
        #Se crea la etiqueta que mostrara el codigo QR
        self.label = QtGui.QLabel(self) 
        
        #Se define un timer
        self.timer = QtCore.QBasicTimer()
        self.step = 0
        
        #Se empaquetan los widgets en la ventana.
        grid = QtGui.QGridLayout()
        grid.setSpacing(10)
        grid.addWidget(foto,1,0)
        grid.addWidget(self.imagen,1,1)
        grid.addWidget(cargar,1,2)
        grid.addWidget(self.nombre, 2, 0)
        grid.addWidget(self.nombreEdit, 2, 1)
        grid.addWidget(etiquetaSexo,3,0)
        grid.addWidget(self.botonradio1,3,1)
        grid.addWidget(self.botonradio2,3,2)
        grid.addWidget(self.etiquetaCedula,4,0)
        grid.addWidget(self.cedula,4,1)
        grid.addWidget(fechaEtiqueta,5,0)
        grid.addWidget(self.fecha,5,1)
        grid.addWidget(self.ciudadEtiqueta,6,0)
        grid.addWidget(self.combo,6,1)
        grid.addWidget(diasemana,7,0)
        grid.addWidget(self.lunes,7,1)
        grid.addWidget(self.martes,7,2)
        grid.addWidget(self.miercoles,7,3)
        grid.addWidget(self.jueves,7,4)
        grid.addWidget(self.viernes,7,5)
        grid.addWidget(okButton, 8, 0)
        grid.addWidget(self.label,9,1)
        grid.addWidget(quit, 10, 1)
        self.setLayout(grid)
        
        #Se definen las segnales de los widgets.
        #boton salir, procesar y cargar foto
        self.connect(quit, QtCore.SIGNAL('clicked()'),QtGui.qApp, QtCore.SLOT('quit()'))
        self.connect(okButton,QtCore.SIGNAL('clicked()'),self.Procesar)
        self.connect(cargar, QtCore.SIGNAL('clicked()'), self.showDialog)
        
    
    def showDialog(self):
        #Muestra una ventana de dialogo para abrir un archivo
        #guarda la ruta del archivo.
        self.filename = QtGui.QFileDialog.getOpenFileName(self, 'Open file',
                    '/home')
        
        #Se define la imagen en la etiqueta
        pixmap = QtGui.QPixmap("%s" %self.filename)
        self.imagen.setPixmap(pixmap)
    
    
    
    def Procesar(self):
        #Captura la informacion y genera el codigo QR
        
        #Define el resultado de los botones de radio
        if self.botonradio1.isChecked() == True:
            sexo = "Masculino"
        elif self.botonradio2.isChecked() == True:
            sexo = "Femenino"
        
        #Se procesa la informacion de los botones de check
        lista = {}
        dias = ("Lunes","Martes","Miercoles","Jueves","Viernes")
        lista["Lunes"] = self.lunes.isChecked()
        lista["Martes"] = self.martes.isChecked()
        lista["Miercoles"] = self.miercoles.isChecked()
        lista["Jueves"] = self.jueves.isChecked()
        lista["Viernes"] = self.viernes.isChecked()
        resultado = ""
        flag = 0
        for dia in lista.keys():
            for i in dias:
                if dia == i:
                    if lista[dia] == True:
                        if flag == 0:
                            resultado = dia
                            flag = 1
                        elif flag == 1:
                            resultado = resultado + ",%s" %dia
        
        #Se le da formato a la informacion recabada para generar el codigo QR
        texto = """
        Nombre:%s\n
        Cedula: %s\n
        Fecha Nacimiento: %s\n
        Sexo: %s\n
        Foto: %s\n
        Dia de participacion: %s\n
        
        """ %(self.nombreEdit.text(),
            self.cedula.text(),
            self.fecha.textFromDateTime(self.fecha.dateTime()),
            sexo,
            self.filename,
            resultado)
            
        #Se verifica si el archivo del codigo qr no existe, si no se borra
        if os.path.isfile("./archivosalida.png"):
            remove("./archivosalida.png")
        
        #Se crea la imagen del codigo qr
        imagen = encode(texto)[2]
        #Se salva la imagen en un archivo.
        imagen.save("./archivosalida.png")
        
        #Se muestra la imagen en la etiqueta
        pixmap = QtGui.QPixmap("./archivosalida.png")
        self.label.setPixmap(pixmap)

if __name__ == "__main__":    
   #Se instancia la clase QApplication    
   app = QtGui.QApplication(sys.argv)    
   #Se instancia el objeto QuitButton    
   qb = App()    
   #Se muestra la aplicacion    
   qb.show()    
   #Se sale de la aplicacion    
   sys.exit(app.exec_())
La siguiente figura muestra la aplicación al iniciarse:






La siguiente imagen muestra la ventana de dialogo para subir la foto:

La siguiente imagen muestra el formulario con los datos sin generar el código QR:

La siguiente imagen muestra la ventana con la información ya procesada y con el código QR generado:

Por último se muestra la imagen de un celular con Android donde se proceso el código QR y muestra la información del mismo:

20/7/2011

Creación de Código QR desde Python

En los artículos que he escrito sobre script en python para Android siempre he dejado una imagen que contiene una especie de código de barras pero en 2 dimensiones, este código se llama Código QR (Quick Response Barcode), más información sobre esté código lo pueden leer en wikipedia.

En el artículo de como compartir script en Android hay un enlace de una página que permite generar el código QR a partir de una información dada.

La idea es crear el código desde Linux y el programa que permite hacerlo se llama qrencode.

Para instalarlo en Debian simplemente se ejecuta aptitude:
aptitude install qrencode

El comando para generar un archivo con la imagen del código QR se muestra a continuación:
qrencode -o output.png 'Hola mundo!'

Este ejemplo genera un archivo png llamado output con el código QR de "Hola Mundo!"

El código se muestra en la siguiente figura:



También existe un módulo para python que permite generar código directamente, este paquete en Debian se llama python-qrencode, para instalarlo se ejecuta aptitude:
aptitude install python-qrencode

La página del proyecto python-qrencode se encuentra en github en este enlace.

De este módulo se usará la función encode, se le pasa un string como dato y devuelve una tupla con 3 valores, la versión, tamaño de la imagen y la imagen.

Está imagen es un objeto de Imagen, se puede salvar dicha imagen en un archivo.

El código de ejemplo del uso de python-qrencode se muestra a continuación:
#!/usr/bin/env python


#modulo qrencode
from qrencode import encode

#El texto a convertir en codigo QR
texto = """Esta es uan prueba de generacion de codigo QR\n
desde python usando el modulo qrencode."""

#Se crea el codigo QR del texto,la funcion encode 
#genera una tupla donde el ultimo elemento es un
#objeto Imagen.

imagen = encode(texto)[2]

#Se salva la imagen en el archivo
#archivoprueba.png
imagen.save("/home/ernesto/archivoprueba.png")

La imagen del código QR se muestra a continuación:

13/7/2011

Tutorial de PyQt. RadioButton. Parte 7.

Este post explicará como usar los botones de radio en PyQt.

La idea es que el usuario seleccione uno de las opciones presentadas en este caso se le pregunta el sexo; al darle clip con el ratón o presionar alt+f para femenino o alt+m para masculino el resultado se muestre en una etiqueta automáticamente. Se tiene un botón para salir del programa.

El widget nuevo en la continuación de estos tutoriales de PyQt es:
  • QRadioButton : Crea la instancia de un widget RadioButton.
 Como esté widget hereda del widget Button se puede usar la señal clicked para capturar el momento de seleccionar una de las opciones.


El código que muestra el programa se muestra a continuación:
#!/usr/bin/env python # -*- coding: utf-8 -*- #Se importa el modulo sys import sys #De PyQt4 importar QtGui y QtCore. from PyQt4 import QtGui from PyQt4 import QtCore class App(QtGui.QWidget):     def __init__(self,parent=None):         QtGui.QWidget.__init__(self, parent)         #Se define el tamano de la ventana         self.setGeometry(0, 50, 350, 250)         #Se le coloca un titulo a la ventana y se asocia un icono.         self.setWindowTitle('Prueba')         self.setWindowIcon(QtGui.QIcon('./openlogo-50.png'))                 #Se define la etiqueta donde se pregunta por el sexo.         etiqueta = QtGui.QLabel("Sexo:")         #Se define la etiqueta que muestra la palabra resultado.         resultado = QtGui.QLabel("Resultado:")         #Se define la etiqueta donde se mostrara la informacion         #seleccionada del boton de radio         self.texto = QtGui.QLabel("")                 #Se crea los botones de radio para seleccionar masculino o femenino.         #Se define ahi el uso del alt+m y alt+f para seleccionar         #un boton.         self.botonradio1 = QtGui.QRadioButton("&Masculino",self)         self.botonradio2 = QtGui.QRadioButton("&Femenino",self)                 #Se crea el boton para salir del programa         quit = QtGui.QPushButton('Salir', self)                 #Empaquetamiento de los widgets en una cuadricula.         grid = QtGui.QGridLayout()         grid.setSpacing(10)         #Se agrega los widgets de etiquetas,radiobuttons y         #el boton salir         grid.addWidget(etiqueta, 0, 0)         grid.addWidget(self.botonradio1,0,1)         grid.addWidget(self.botonradio2,0,3)         grid.addWidget(resultado,2,0)         grid.addWidget(self.texto,2,1)         grid.addWidget(quit,3,0)         self.setLayout(grid)                 #Se conecta la segnal con los 2 botones de radio y el boton para         #salir del programa, se asocian a los metodos respectivos.         self.connect(quit, QtCore.SIGNAL('clicked()'),QtGui.qApp, QtCore.SLOT('quit()'))         self.connect(self.botonradio1,QtCore.SIGNAL('clicked()'),self.Mostrar1)         self.connect(self.botonradio2,QtCore.SIGNAL('clicked()'),self.Mostrar2)             def Mostrar1(self):         #Se muestra el resultado seleccionado         self.texto.setText("Masculino")             def Mostrar2(self):         #Se muestra el resultado seleccionado         self.texto.setText("Femenino")                 #Se ejecuta el programa principal if __name__ == "__main__":       #Se instancia la clase QApplication       app = QtGui.QApplication(sys.argv)       #Se instancia el objeto QuitButton       qb = App()       #Se muestra la aplicacion       qb.show()       #Se sale de la aplicacion       sys.exit(app.exec_())
A continuación se muestra la figura del programa iniciando:



La siguiente figura muestra el resultado de darle clip al botón de radio Masculino:


La siguiente figura muestra el resultado de presionar alt+f para seleccionar el botón de radio para Femenino:



Noten que la información a mostrar cambia al seleccionar uno de los botones de radio.

9/7/2011

Tutorial de PyQt, crear un navegador web. Parte 6

Continuando con los tutoriales de PyQt, ahora toca explicar como crear un navegador web.

La idea es tener una ventana de entrada de datos donde se escribe el url a navegar, a su lado se tiene un botón que ejecuta la navegación al url dado, luego abajo se tiene el widget de navegación y por último abajo se tiene un botón de salir. Se puede navegar también dando enter en el campo del url.

El widget nuevo que se está usando es:
  • QWebView: Permite crear una vista de navegación web.

El código del programa se muestra a continuación:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Se importa el modulo sys
import sys
#De PyQt4 importar QtGui,QtCore y QtWebkit.
from PyQt4 import QtGui
from PyQt4 import QtCore
from PyQt4 import QtWebKit
class App(QtGui.QWidget):
    def __init__(self,parent=None):
        QtGui.QWidget.__init__(self, parent)
        #Se define el tamano de la ventana
        # posicion en x,y, ancho y alto
        self.setGeometry(0, 50, 1024, 550)
        #Se le coloca un titulo a la ventana y se asocia un icono.
        self.setWindowTitle('Navegador')
        self.setWindowIcon(QtGui.QIcon('./openlogo-50.png'))
        
        #Se crea una entrada de datos donde se pasa el url a navegar
        self.entradaUrl = QtGui.QLineEdit("http://www.debian.org.ve")
        #Se crea el boton para ir a una pagina web
        navegar = QtGui.QPushButton("Ir",self)
        #Se crea el boton salir
        quit = QtGui.QPushButton("Salir",self)
        #Se crea el widget donde se mostrara la pagina web
        self.web = QtWebKit.QWebView()
        #Se habilita el atributo de plugins
        self.web.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled,True)
        #Se carga la pagina de debian venezuela al inicio
        self.web.load(QtCore.QUrl("http://www.debian.org.ve"))
        
        
        #Empaquetamiento de los widgets en una cuadricula.
        grid = QtGui.QGridLayout()
        grid.setSpacing(10)
        #Se agrega la entrada de datos
        grid.addWidget(self.entradaUrl, 1, 0)
        #Se agrega el boton navegar al lado de la
        #entrada de datos
        grid.addWidget(navegar,1,1)
        #Se agrega el widget web
        grid.addWidget(self.web,2,0)
        #Se agrega el boton salir
        grid.addWidget(quit,3,0)
        
        #Se define el layout pasando la grilla
        self.setLayout(grid)
        
        #Se define la asociacion de segnales:
        #Se define la segnal del boton quit, salir del programa
        self.connect(quit, QtCore.SIGNAL('clicked()'),QtGui.qApp, QtCore.SLOT('quit()'))
        #Se define la segnal del boton navegar, al darle clip se ejecuta el metodo navegar
        self.connect(navegar,QtCore.SIGNAL('clicked()'),self.navegar)
        #Se define la segnal de la entrada de datos
        #Al darle enter se ejecuta el metodo navegar
        self.connect(self.entradaUrl,QtCore.SIGNAL('returnPressed()'),self.navegar)
        
        
    def navegar(self):
        #Navegar captura el texto de la entrada de datos
        #Y se carga la nueva pagina.
        url = self.entradaUrl.text()
        self.web.load(QtCore.QUrl("%s" %url))
        
    
#Se ejecuta el programa principal
if __name__ == "__main__":    
   #Se instancia la clase QApplication    
   app = QtGui.QApplication(sys.argv)    
   #Se instancia el objeto QuitButton    
   qb = App()    
   #Se muestra la aplicacion    
   qb.show()    
   #Se sale de la aplicacion    
   sys.exit(app.exec_())
A continuación se muestra la ventana del navegador al ejecutar el programa:



La siguiente figura muestra que se escribe un url nuevo y se puede darle clip al botón ir o darle enter a la entrada de datos:


7/7/2011

Manejo de Fecha y Hora con PyQt. Parte 5

En este artículo se creará una ventana con 2 pestañas, 2 botones, y una etiqueta; el primer botón capturará le fecha o fecha y hora según la pestaña seleccionada y lo presentará en la etiqueta, el otro botón es para salir de la aplicación; en la primera pestaña se muestra el widget de fecha y en la segunda se muestra el widget de fecha y hora.

Se utilizarán los siguientes widgets:

  • QtGui.QTabWidget: Permite crear pestañas.
  • QtGui.QDateEdit: Permite crear el widget incremental o decremental de la fecha.
  • QtGui.QDateTimeEdit: Permite crear el widget incremental o decremental de la fecha y hora.


Como se tiene un solo botón para capturar la fecha para ambas pestañas es necesario capturar el identificador de cada pestaña para así dependiendo del caso generar el resultado de la fecha u fecha y hora.

El código del programa se muestra a continuación:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
     
#Se importa el modulo sys
import sys


#De PyQt4 importar QtGui y QtCore
from PyQt4 import QtGui
from PyQt4 import QtCore


class App(QtGui.QWidget):
    def __init__(self,parent=None):
        QtGui.QWidget.__init__(self, parent)
        #Se define el tamano de la ventana
        self.setGeometry(500, 500, 350, 250)
        #Se le coloca un titulo a la ventana y se asocia un icono.
        self.setWindowTitle('Fecha y Hora')
        self.setWindowIcon(QtGui.QIcon('./openlogo-50.png'))
        
        #Se crea la instancia del widget de la fecha
        #Se define el formato de la fecha
        #Se le asigna al widget la fecha actual.
        self.fecha = QtGui.QDateEdit(self)
        self.fecha.setDisplayFormat("dd/MM/yyyy")
        self.fecha.setDate(QtCore.QDate.currentDate())
        
        
        
        #Se crea la instancia del widget de la fecha y hora.
        #Se le da formato a la fecha y hora.
        #Se le asigna la fecha y hora actual al widget.
        self.fechayhora = QtGui.QDateTimeEdit(self)
        self.fechayhora.setDisplayFormat("dd/MM/yyyy HH:mm:ss")
        self.fechayhora.setDateTime(QtCore.QDateTime.currentDateTime())
        
        #Se crea el boton que captura la fecha u hora
        captura1 = QtGui.QPushButton("Captura",self)
        #Se crea el boton para salir de la aplicacion
        quit = QtGui.QPushButton('Salir', self)
        
        #Se crea la etiqueta donde se muestra la fecha u hora
        self.etiqueta = QtGui.QLabel("Fecha:")
         
        #Se crea la instancia del widget pestagna
        #Se define que no se puede cerrar las pestagnas
        self.tab = QtGui.QTabWidget(self)
        self.tab.setTabsClosable(False)
        
        #Se agrega a la 1era pestagna el widget de la fecha
        self.tab.addTab(self.fecha,"Fecha")
        #Se agrega a la 2da pestagna el widget de la fecha y hora
        self.tab.addTab(self.fechayhora,"Fecha y Hora")


        #Empaquetamiento de los widgets en una cuadricula.
        grid = QtGui.QGridLayout()
        grid.setSpacing(10)
        #Se agrega el widget pestagna, boton de captura,
        #etiqueta y boton de salida.
        grid.addWidget(self.tab, 1, 0)
        grid.addWidget(captura1,2,0)
        grid.addWidget(self.etiqueta, 3, 0)
        grid.addWidget(quit,4,0)
        self.setLayout(grid)
        
        #Se conecta la segnal del boton captura con el evento clicked al
        #metodo mostrarIndice.
        self.connect(captura1,QtCore.SIGNAL('clicked()'),self.mostrarFechayHora)
        #Se asocia ala segnal del boton quit al evento clicked y se ejecuta la
        #salida del programa.
        self.connect(quit, QtCore.SIGNAL('clicked()'),QtGui.qApp, QtCore.SLOT('quit()'))
    
        
    def mostrarFechayHora(self):
        #Captura el indice de la pestagna para mostrar
        #la informacion de la fecha u fecha y hora.
        if self.tab.currentIndex() == 0:
            #Se presenta en la etiqueta la fecha con el
            #formato dia/mes/agno.
            #se toma la informacion de la funcion date del widget
            #este devuelve una fecha y se captura el dia, mes y agno.
            self.etiqueta.setText("Fecha: %s/%s/%s"
                                  %(self.fecha.date().day(),
                                    self.fecha.date().month(),
                                    self.fecha.date().year()) )
            
        else:
            #Se presenta en la etiqueta la informacion de la fecha y hora.
            #con el formato dia/mes/agno hora:minutos:segundos.
            #Se utiliza el metodo textFromDateTime que devuelve un string
            #pasandole una fecha y hora 
            self.etiqueta.setText("Fecha y Hora: %s"
                                  %self.fechayhora.textFromDateTime(self.fechayhora.dateTime()))
        
    
        


#Se ejecuta el programa principal
if __name__ == "__main__":    
   #Se instancia la clase QApplication    
   app = QtGui.QApplication(sys.argv)    
   #Se instancia el objeto QuitButton    
   qb = App()    
   #Se muestra la aplicacion    
   qb.show()    
   #Se sale de la aplicacion    
   sys.exit(app.exec_())

La figura muestra el programa al iniciarse:



La siguiente figura muestra que se modifico la fecha con los botones de incrementar o decrementar y luego se presionó al botón captura:



La siguiente figura muestra cuando se selecciona la segunda pestaña:



La última figura muestra que se modifico la fecha y la hora con los botones incrementales o decrementales y luego se presionó al botón captura:

5/7/2011

Feliz Bicentenario Venezuela!!!

Hoy celebramos 200 años de la Independencia de Venezuela.

Google coloca por ese motivo un Doodle alegórico a nuestra Fecha de Independencia:


Cenditel como Homenaje a nuestro Bicentenario ha publicado un protector de pantalla  con fondos alegórico de nuestra Independencia:

http://www.cenditel.gob.ve/node/1173

Estos fondos de pantalla se podrán instalar en Debian, Ubuntu y Canaima.

4/7/2011

Tutorial de PyQt (calendario). Parte 4

Continuando con los artículos sobre PyQt, ahora explicare como usar un calendario y capturar la selección de una fecha dada, la fecha seleccionada se muestra en una etiqueta de forma dinámica y al final se agrega un botón de salir.

Basicamente se usará QtGui.QCalendarWidget usando con una cuadricula con el método setGridVisible que tiene dos opciones True o False.

A continuación el código del programa:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
     
#Se importa el modulo sys
import sys


#De PyQt4 importar QtGui y QtCore
from PyQt4 import QtGui
from PyQt4 import QtCore




class App(QtGui.QWidget):
    
    
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        #Se define el tamano de la ventana
        self.setGeometry(400, 400, 250, 150)
        #Se le coloca un titulo a la ventana y se asocia un icono.
        self.setWindowTitle('Calendario')
        self.setWindowIcon(QtGui.QIcon('./openlogo-50.png'))
        
        #Define el calendario en una ventana
        self.cal = QtGui.QCalendarWidget(self)
        #Se define una cuadricula al calendario
        self.cal.setGridVisible(True)
        #Se define una etiqueta donde se mostrara
        #La fecha seleccionada
        self.etiqueta = QtGui.QLabel(self)
        
        #Se captura la fecha y se muestra en la etiqueta
        self.fecha = self.cal.selectedDate()
        self.etiqueta.setText(str(self.fecha.toPyDate()))
        
        #Se define el boton para salir
        
        quit = QtGui.QPushButton('Salir', self)
        #Se define como empaquetar los widgets.
        #En este caso se usa grilla.
        #Se crea la instancia
        grid = QtGui.QGridLayout()
        grid.setSpacing(10)
        
        grid.addWidget(self.cal, 1, 0)
        grid.addWidget(self.etiqueta, 2, 0)
        
        grid.addWidget(quit,3,0)
        #Se define el layout pasando la grilla
        self.setLayout(grid)
        
        self.connect(quit, QtCore.SIGNAL('clicked()'),QtGui.qApp, QtCore.SLOT('quit()'))
        self.connect(self.cal, QtCore.SIGNAL('selectionChanged()'), 
            self.mostrarFecha)
        
    def mostrarFecha(self):
        self.fecha = self.cal.selectedDate()
        self.etiqueta.setText(str(self.fecha.toPyDate()))
        
    


#Se ejecuta el programa principal
if __name__ == "__main__":    
   #Se instancia la clase QApplication    
   app = QtGui.QApplication(sys.argv)    
   #Se instancia el objeto QuitButton    
   qb = App()    
   #Se muestra la aplicacion    
   qb.show()    
   #Se sale de la aplicacion    
   sys.exit(app.exec_())

La figura muestra el programa en funcionamiento:


AddThis