Bastante se ha hablado acerca de la Ley de Infogobierno y su tortuosa historia en las redes sociales. Desde carismáticos y políticos discursos, hasta técnicos y conservadores argumentos, la mayoría ha expresado su opinión. Este artículo pretende hacer un resumen de los acontecimientos, y una prospectiva de los escenarios actuales. El episodio Tascón (2006) La Ley de Infogobierno es un Proyecto de Ley que tuvo su motivación en la creación de un marco jurídico que regulará el acceso a la información de los ciudadanos a través de los medios electrónicos del estado. Era de esperarse, que la ley fundamentara sus aspectos operativos en los preceptos del Software Libre y los estándares abiertos. Sin embargo, la discusión tuvo varios matices agrios e inesperados. El entonces Presidente de la Subcomisión de Ciencia y Tecnología, Diputado Luis Tascón (PSUV), dirigió en 2006 una serie de debates públicos y privados, en donde partidarios del Software Libre y Software Privativo pudieron exponer sus puntos de vista. En esa época, podíamos escuchar a José Parella, Ernesto Hernández-Novich, Felipe Pérez, entre otros, apoyando y defendiendo las visiones del Software Libre, como se muestra en la siguiente intervención de Ernesto Hernández-Novich en el Foro “Software Libre vs. Software Privativo” llevado a cabo en la Asamblea Nacional. Estas reuniones llegaron a pocos consensos, principalmente por la insistencia de los argumentos pro-Microsoft, y el Diputado Tascón terminó por adoptar una posición en favor del Software Privativo, como se le puede escuchar en la entrevista que le realizara Ernesto Villegas en 2006 para el programa “En Confianza”. La Ley salió de la subcomisión con un contenido a favor del Software Privativo y la neutralidad tecnológica, cosa que molestó mucho a la Comunidad de Software Libre. Afortunadamente, en la discusión de la plenaria de diputados, la aprobación de la ley se estancó, lográndose sancionar tan solo 6 artículos. La Ley no sería tomada en cuenta de nuevo hasta dentro de 6 años. El episodio Leomagno (2012) 6 años después, las cosas han cambiado radicalmente: para empezar, el Diputado Luis Tascón falleció luego de luchar contra una terrible enfermedad; la presidencia de la Comisión de Ciencia y Tecnología está en manos del Diputado Leomagno Flores (AD); por otro lado, el Software Libre ha venido recibiendo un sostenido apoyo del estado, generando experiencias prácticas y casos de éxito en la Administración Pública; además, existe una distribución nacional llamada “Canaima”, apoyada en estrategias de masificación de las TIL a través de proyectos como “Canaima Educativo” y el “Plan Internet Equipado”. En ese contexto, por iniciativa del vicepresidente de la Comisión de Ciencia y Tecnología, se introdujo a la plenaria una petición de levantamiento de la sanción a los 6 artículos aprobados en 2006, permitiendo discutir la ley desde cero. En una infame intervención de réplica, el Diputado Flores aseveró que el Software Libre “era la dictadura de un sistema informático”, lo que generó el inmediato rechazo de las Comunidades de Software Libre. ¿Afortunadamente?, en el inicio del nuevo período legislativo del año 2013 ocurrió una rotación en la presidencia de la comisión, siendo nombrado el Diputado William Dávila (AD), quién mostró tener un mayor grado de conocimiento y aceptación del Software Libre durante una entrevista realizada por Carlos Croes en el programa “Regiones”. Situación actual (2013) Luego de estos antecedentes, estamos en la víspera del inicio de una nueva discusión pública de la ley, con un contenido diferente y actores diferentes. En ese sentido, se ha conocido el contenido del nuevo borrador de manera extraoficial, el cual se puede descargar a través del siguiente enlace. El texto del borrador es magnífico. Se rescatan las luchas de la Comunidad del Software Libre, además de proveer un marco operativo que no tiene lugar para dudas. Los artículos 35, 36 y 37 establecen claramente la exclusividad del Software Libre y Estándares Abiertos en la prestación de servicios, garantizan el cumplimiento de las 4 libertades, e impulsan la apropiación social del conocimiento libre. Una maravilla. Por si fuera poco, se establece un régimen sancionatorio (art. 66 al 68). Todo aquel funcionario o institución que incumpla con los términos de la ley, puede recibir una sanción valorada entre las 50 y 250 unidades tributarias (entre unos 5000BsF y 25000BsF para la fecha). Por otro lado, se reestructura al Centro Nacional de Tecnologías de Información (CNTI) para que asuma funciones de Normalizador y Fiscalizador en materia de Tecnologías de Información dentro del estado, según se establece en los artículos 45 y 46. Además, se crea la Industria Nacional de Tecnologías de Información Libres (art. 57), con el objetivo de impulsar el desarrollo de las Tecnologías Libres. Finalmente, la ley deroga el controversial decreto presidencial N° 3390, en donde se establecía el uso “prioritario” de Software Libre en la Administración Pública Nacional. Esperamos que el llamado público a discusión cuente una historia diferente a la de 2006, permitiendo la participación protagonista de las Comunidades de Software Libre, y manteniendo el espíritu del borrador actual.
Un mantenedor de paquetes Debian es aquella persona que se encarga de transformar una determinada pieza de software (como por ejemplo una aplicación, un conjunto de scripts, archivos de imágenes, etc.) en otra pieza de software (un paquete) capaz de instalarse a través de un esquema común de instalación. El mantenedor Debian conoce muy bien el sistema operativo, y por tanto, sabe cuáles son los cambios que debe aplicar para hacer que la pieza de software funcione correctamente y de acuerdo a las normas y estándares de la distribución. Una de las normas de calidad de Debian establece que no se debe tocar directamente el código de la pieza de software proveniente del desarrollador original. Si se debe hacer una modificación, debe hacerse a través de un parche durante el proceso de construcción del paquete. Esto permite aislar los cambios, asegurando que: El conjunto de cambios reflejados en el parche pueden ser enviados a los desarrolladores originales para corregir errores o mejorar procesos. Los cambios pueden ser aplicados a las sucesivas versiones del software, siempre y cuando las líneas afectadas no hayan sido modificadas por los desarrolladores originales. Para mayor información puedes consultar la Guía para la creación de parches. En líneas generales, quilt es una herramienta que asiste a un mantenedor de paquetes Debian, ayudando en la gestión de cambios y diferencias con respecto a los desarrolladores originales del software que contiene el paquete en mantenimiento. Permite crear y modificar parches, así como también aplicarlos o desaplicarlos. Cada paquete Debian que contiene parches posee un archivo series (debian/patches/series), el cual almacena el nombre de cada uno de los parches que deben ser aplicados en el momento de construcción del paquete. Si se desea deshabilitar un parche en específico sin borrarlo (para uso posterior), simplemente se borra su nombre del archivo series. Quilt interpreta este archivo como una pila de nombres que pueden ser agregados y/o removidos según su orden de entrada y/o salida. Para instalarlo, debemos introducir el siguiente comando desde una Terminal de Root (Menú > Aplicaciones > Accesorios > Terminal de Root): aptitude install quilt Antes de comenzar a usar quilt, debemos configurarlo para que utilice siempre la carpeta debian/patches que se encuentra dentro de cada paquete. Para hacer esto, desde una Terminal de Usuario (Menú > Aplicaciones > Accesorios > Terminal) ejecuta el siguiente comando: echo "QUILT_PATCHES=debian/patches" > ~/.quiltrc Operaciones manuales con quilt Quilt trabaja dinámicamente dentro del código fuente del paquete. No es necesario hacer copias previas del código, ni mantener el código duplicado, ni mucho menos ejecutar comandos diff, svn o git. El proceso de creación de un parche con quilt es relativamente sencillo y puede ser resumido de la siguiente manera: Notificar a quilt que se va a trabajar con un parche en específico. Trabajar en el parche. Pedirle a quilt que actualice el contenido del parche en cuestión. Para empezar a trabajar en un parche ejecutamos el siguiente comando en una Terminal de Usuario desde el directorio raíz del proyecto: quilt new [NOMBRE] Una buena práctica es anteponer una numeración al [NOMBRE] del parche y colocar la extensión .patch. Este comando creará una nueva entrada en debian/patches y se convertirá en el último parche aplicado en la pila. Para comenzar las modificaciones que formarán parte del parche, ubicamos la ruta del primer archivo a editar y hacemos: quilt edit [RUTA] Este comando lanzará nuestro editor de texto predeterminado para que realicemos las modificaciones. Luego de guardar el archivo, es posible editar tantos archivos como de deban editar para completar el cambio deseado. El parche contendrá todas las modificaciones; sin embargo, se recomienda separar los parches por módulo o por funcionalidad agregada/modificada, para mantener un orden. Siempre es preferible modularizar a hacer un parche gigante. Cuando se termine la edición de archivos, escribiremos los cambios al parche con el siguiente comando: quilt refresh Con este comando hemos terminado la creación del parche, sin embargo es bueno saber que el parche ha quedado aplicado. Si hacemos quilt applied podremos ver cuáles son los parches que están aplicados al código fuente. Para desaplicar el último parche de la pila, hacemos quilt pop. Esto hará que el próximo parche se ponga en el tope de la pila. Para desaplicar todos los parches que se encuentran el la pila, hacemos quilt pop -a. De forma similar, para aplicar parches uno a uno se hace quilt push, y para aplicar todos los parches en la pila, se hace quilt push -a. Para modificar un parche, dicho parche debe estar en el tope de la pila y aplicado. La forma más fácil de hacer esto es desaplicar todos los parches e ir aplicando uno por uno hasta llegar al parche que se desea modificar. También se puede hace quilt push [NOMBRE], si se conoce el nombre exacto del parche. Una vez hecho esto, se hace quilt edit [RUTA] para realizar la (o las) modificación(es) necesaria(s) y finalmente, quilt refresh. Integrando con paquetes Antes de la aparición de quilt, era necesario gestionar, aplicar y desaplicar parches manualmente durante la construcción de un paquete. Varias rutinas eran necesarias para completar esta tarea completamente, y aunque la lógica era sencilla, muchas veces representaba un dolor de cabeza para quienes se iniciaban en el mantenimiento de paquetes. Si eres (o piensas ser) mantenedor para Debian, Canaima o Ubuntu, y quieres utilizar quilt para gestionar tus parches, es necesario que realices los siguientes cambios en tus paquetes: Coloca el formato de construcción para el paquete fuente en 3.0 (quilt). Añade la dependencia de construcción (Build-Depends) a quilt en el archivo debian/control. Construye los parches manualmente como se explicó en este artículo. Recuerda desaplicar todos tus parches antes de construir el paquete. Cualquier duda, haz la pregunta en los comentarios.
Este artículo contiene información avanzada relacionada con el desarrollo bajo versionamiento git. Si deseas ampliar tus conocimientos antes de continuar, puedes leer los siguientes artículos: Guía de desarrollo básico con git. Guía de desarrollo avanzado con git. El oráculo git del desarrollador. Los submódulos en git permiten insertar uno o más repositorios externos dentro de otro repositorio. Es decir, permiten manejar uno o varios subproyectos dentro de un gran proyecto versionado con git. Esta característica puede ser útil, por ejemplo, para referenciar archivos que estén en proyectos complementarios, pero administrados por diferentes grupos o personas. Por ejemplo, supongamos que tres personas se ponen de acuerdo para desarrollar una aplicación. La aplicación tiene una interfaz gráfica, un esquema de documentación y un esquema de generación de imágenes, por lo que se reparten el trabajo en partes iguales. El que escoja la interfaz principal, podría insertar los repositorios de desarrollo de sus otros dos compañeros en la ruta del proyecto correspondiente para realizar una integración de código. De esta forma, los tres proyectos siguen siendo independientes y pueden ser integrados y desintegrados en cualquier momento. Para esta práctica, necesitaremos instalar git, lo cual podemos hacer introduciendo el siguiente comando desde una Terminal de Root (Menú > Aplicaciones > Accesorios > Terminal de Root): aptitude install git Luego, clonaremos el repositorio de Aguilas (sistema de autenticación del Proyecto Canaima) y entraremos en la carpeta con los siguientes comandos: git clone git://github.com/HuntingBears/aguilas.git cd aguilas Aguilas contiene dos submódulos: el wiki para github y el wiki para google code. Estas características nos permitirán ilustrar mas adelante algunas funcionalidades de los submódulos. Agregar un submódulo Agregar un submódulo dentro de un proyecto git es relativamente sencillo. Por ejemplo, supongamos que queremos añadir documentación adicional para Aguilas dentro de la carpeta documentation/extradocs, desde un repositorio git externo ubicado en git://github.com/HuntingBears/fudcon-presentation.git. Lo hacemos así: git submodule add git://github.com/HuntingBears/fudcon-presentation.git documentation/extradocs Podemos diferenciar tres partes principales en este comando: git submodule add: Esto simplemente le dice a git que se está agregando un submódulo. [REPOSITORIO]: Este es el repositorio externo que debe ser agregado como un submódulo. La sintaxis exacta de la dirección variará de acuerdo a la permisología que se posee sobre el repositorio. Siempre se debe verificar que se tienen permisos de lectura sobre el repositorio. [CARPETA]: Esta es la carpeta donde se insertará el repositorio dentro del repositorio principal o “anfitrión”. Si hacemos git status, se podrá evidenciar que la carpeta suministrada fué creada, y que también se ha creado un archivo .gitmodules. Este nuevo archivo contiene los datos relacionados con el nuevo submódulo y puede contener lo siguiente: [submodule "documentation/extradocs"] path = documentation/extradocs url = git://github.com/HuntingBears/fudcon-presentation.git Si nos fijamos dentro de la carpeta documentation/extradocs, veremos que está vacía. A fin de completar la operación, es necesario inicializar y actualizar los submódulos. Desde la carpeta raíz de Aguilas, introduciremos los siguientes comandos: git submodule init git submodule update Al revisar la carpeta documentation/extradocs, encontraremos los archivos correspondientes al proyecto de documentación. Actualización de submódulos Para actualizar el contenido de un submódulo, es decir, hacer un git pull del subproyecto más no del proyecto que lo alberga, debemos inicializar y actualizar los submódulos así: git submodule init git submodule update Luego accedemos a la carpeta que contiene el submódulo: cd documentation/extradocs Cambiamos a la rama del subproyecto donde se encuentra la información: git checkout master Y hacemos la actualización del contenido: git pull Quitar un submódulo ¿Qué pasa si tenemos que quitar un submódulo? Tal vez cometimos un error. También podría ser que el diseño del proyecto haya cambiado, y la ruta del submódulo ya no es la misma. Por desgracia, git no posee una forma automática para remover submódulos. Se debe hacer manualmente. Siguiendo con el ejemplo, vamos a quitar el submódulo que agregamos en documentation/extradocs. Para ello debemos realizar los siguientes pasos: Eliminar la entrada del submódulo en el archivo .gitmodules. Lo abrimos con gedit, vim, o tu editor de texto favorito, y eliminamos las tres líneas pertenecientes al submódulo. Para este caso, removemos las siguientes líneas: [submodule "documentation/extradocs"] path = documentation/extradocs url = git://github.com/HuntingBears/fudcon-presentation.git Eliminar la entrada del submódulo en el archivo .git/config: Lo abrimos con gedit, vim, o tu editor de texto favorito, y eliminamos las dos líneas pertenecientes al submódulo. Para este caso, removemos las siguientes líneas: [submodule "documentation/extradocs"] url = git://github.com/HuntingBears/fudcon-presentation.git Eliminar del versionamiento la carpeta creada para el submódulo: rm -rf documentation/extradocs git rm --cached documentation/extradocs Eso es todo lo que se debe saber para trabajar con submódulos en git. Espero que sea de utilidad.
Este artículo asume que ya conoces el propósito y las funciones fundamentales de git y que estás preparado para entender tareas más complejas. Si lo deseas, puedes leer la Guía básica de desarrollo con git antes de continuar. Comenzar a trabajar en un proyecto de programación es relativamente fácil: simplemente comienza por donde más te guste y será suficiente. Ahora, comenzar a versionar código depende realmente de cómo empezaste a programar. Si estás empezando desde cero, puedes hacer lo siguiente: mkdir miproyecto cd miproyecto git init git add . git commit -a git init inicializa el repositorio, git add . añade todos los archivos en el directorio actual al registro y git commit -a crea la importación inicial de los archivos. Si por el contrario vas a descargar un proyecto git público ([URL]), debes hacer lo siguiente: git clone [URL] Por ejemplo: git clone http://git.gitorious.org/canaima-gnu-linux/canaima-desarrollador.git Cualquiera que sea el caso, ahora el árbol del proyecto está oficialmente versionado con git. Hay que notar que no importa cuántos subdirectorios tenga el proyecto, todo el sistema de versionamiento está guardado en una carpeta .git en el directorio raíz del proyecto (a diferencia de subversion, por ejemplo). ¡Ahora es tiempo de que hagamos algunas modificaciones! Edita algunos archivos dentro del proyecto canaima-desarrollador que acabas de clonar. Cuando hayas terminado, lo siguiente que debes hacer es agregarlos al control de versiones con git add .. Pero antes, podemos obtener información interesante: git diff git diff te mostrará en formato de parche (diff) las modificaciones que acabas de hacer. Incluso, pudieras ver las diferencias entre el estado actual y un [COMMIT] anterior: git diff [COMMIT] O las diferencias entre un rango de commits: git diff [COMMIT-A] [COMMIT-B] También, puedes obtener una representación más concisa de los cambios: git status Esto te mostrará una lista de todos los archivos modificados, agregados, borrados o que no han sido agregados al sistema de versionamiento. Además mostrará la rama actual de trabajo. Para los archivos sin versionar, debemos agregarlos así: git add . O eliminarlos (en el caso de que se trate de archivos no deseados de un proceso de compilación, por ejemplo): ADVERTENCIA: esto eliminará todos los archivos sin seguimiento para siempre. git clean -fd También puedes especificar todos los archivos que deseas ignorar para siempre. Estos archivos nunca serán añadidos al control de versiones. Lo que hay que hacer es crear un archivo llamado .gitignore en el directorio raíz del proyecto, que contenga una lista de los archivos, línea por línea, especificando rutas relativas al directorio raíz. Si realizaste un cambio en un archivo y todavía no has hecho commit, puedes restaurarlo desde el estado del último commit disponible con el siguiente comando: git checkout [RUTA] Finalmente es hora de guardar nuestros cambios: git commit -a -m "[MENSAJE DESCRIPTIVO]" Hay tres consideraciones a tener en cuenta: En primer lugar, se debe especificar -a si se quiere hacer commit de todos los cambios versionados. En caso contrario, se debe usar git commit [RUTA] para hacer commit archivo por archivo. En segundo lugar, los commits de git son privados por defecto, es decir, no son enviados a un servidor central a menos que se le especifique. Y en tercer lugar, se acostumbra a colocar un [MENSAJE DESCRIPTIVO] que resuma en pocas palabras la modificación que se realizó en el código, así otros desarrolladores podrán entender fácilmente sin necesidad de revisar línea por línea los cambios realizados. Explorando el proyecto Ahora que hemos hecho commit de algunas cosas, es posible que queramos ver un registro de lo hecho hasta ahora: git log git blame [RUTA] git log es un comando muy potente. Muestra el registro completo de todos los commits hechos en el historial, además de información adicional como autor y fecha. git blame también es muy útil ya que identifica el autor de cada línea de cada archivo registrado por git. Por otro lado, se puede ver el contenido de un archivo en estado en que estaba para un determinado [COMMIT] con git show: git show [COMMIT]:[RUTA] git show [COMMIT]:[RUTA] git show -s [COMMIT] git show [COMMIT] Ramas y Etiquetas Las ramas y etiquetas en git son tratadas como marcas asociadas a commits dentro del historial de trabajo. Se puede crear una rama con los siguientes comandos: git branch [NUEVA] [COMMIT] git checkout [NUEVA] El primer comando crea una nueva rama basada en la rama donde nos encontramos en el momento. El segundo comando cambia el árbol de archivos a la rama recién creada. Es posible pasar un argumento adicional en el primer comando para basar la rama en un commit específico. Ejecutar git branch sin argumentos mostrará la lista de ramas existentes. Para mover el árbol de archivos hasta cierto commit anterior, hacemos así: git checkout [COMMIT] Las etiquetas en git son muy similares a las ramas, pero con algunas características adicionales. Una etiqueta puede tener una fecha, un autor y un mensaje tal como los commits. Pueden ser firmadas por una llave PGP, lo que es útil a la hora de garantizar que el código original no ha sido modificado por nadie más. Para hacerlo, solo basta con hacer lo siguiente: git tag [ETIQUETA] Para una lista de las etiquetas existentes y mostrar el mensaje de la etiqueta: git tag -l git show [ETIQUETA] Fusionando ramas Supongamos que hemos estado trabajando en una nueva versión de nuestro software en una rama llamada “desarrollo” y que ya ha alcanzado un nivel de estabilidad tal que hemos decidido hacer un lanzamiento. Para ello, fusionaremos la rama “desarrollo” con la rama “estable” de la siguiente forma: git checkout estable git merge desarrollo Si los cambios se hicieron sólo en la rama “desarrollo” desde la última fusión, simplemente se copia su contenido en la rama “estable” (llamado fast-forward merge). Si se hicieron cambios en ambas ramas, se combinan de forma inteligente (llamado three-way merge). Si la fusión three-way no tiene conflictos de combinación, se genera un commit con un mensaje descriptivo (la opción --no-commit desactiva este comportamiento). Si hay conflictos de combinación (cuando las líneas de uno o más archivos que se fusionarán tienen valores diferentes en el estado anterior), git merge notificará acerca de todos los archivos en conflicto. Para resolver un conflicto, debemos abrir cada archivo en conflicto y buscar el siguiente patrón: <<<<<<< Los cambios realizados en mi rama ======= Los cambios realizados en la rama que estoy fusionando >>>>>>> Debemos editar el archivo manualmente para dejar las líneas que consideremos apropiadas. Después de resolver todos los conflictos, se debe hacer commit: git commit -a Trabajando con servidores remotos Si hemos descargado el proyecto a través de git clone, git ha configurado automáticamente un repositorio remoto llamado origin. Si hemos creado el proyecto a partir de cero, tendremos que configurarlo. Para mostrar los servidores remotos configurados actualmente, se puede ejecutar el comando git remote. En él se enumerarán los nombres cortos de cada servidor remoto configurado. git remote -v Para añadir un nuevo servidor remoto como un nombre corto al que se puede hacer referencia fácilmente, ejecuta: git remote add [NOMBRE] [URL] Si se ha clonado el repositorio, todas las ramas y etiquetas han sido descargadas. Sin embargo, las ramas no aparecerán en la lista a menos que antes se comiencen a utilizar con git checkout [RAMA]. Ahora, ¿Cómo se descargan nuevos cambios desde un repositorio remoto? Se puede utilizar git fetch para descargar los cambios. Si lo que deseamos es descargar y combinar los cambios con nuestra rama, hacemos git pull [NOMBRE] [RAMA]. Para subir cambios a un repositorio remoto, se utiliza el comando git push [NOMBRE] [RAMA]. Este comando sólo funciona si se ha clonado a partir de un servidor al que se tiene acceso de escritura y si nadie ha enviado cambios nuevos desde el momento en que se clonó. Si dos personas clonan el repositorio al mismo tiempo, uno sube cambios y luego el otro sube otros, el envío del último será rechazado. Se debe descargar los cambios del otro antes de subir los propios para que pueda funcionar.
La Conferencia Internacional de Desarrolladores de Debian (DebConf) se realiza todos los años en diferentes ciudades alrededor del mundo. Su objetivo principal es reunir a la mayoría de los desarrolladores, mantenedores, colaboradores y usuarios de Debian, una comunidad experimentada que está dedicada a generar Sistemas Operativos Libres, además de otros proyectos tecnológicos derivados. Dentro de la planificación del evento, se realizan charlas, talleres, discusiones y otras actividades que permiten mejorar los diferentes aspectos de los proyectos de la comunidad. Se incluyen además, actividades recreativas que permiten pasar un momento agradable con miembros del proyecto que provienen de culturas y latitudes tan variadas y remotas. Puerto La Cruz (Venezuela) ha sido propuesta como sede para la 14va Conferencia Internacional de Desarrolladores de Debian (DebConf14). A través de este artículo, espero poder reseñar todas los aspectos que se han adelantado en la organización de la propuesta e invitar a todos los interesados a participar en la organización del evento en sus diferentes niveles. Puerto La Cruz: Ciudad Costera Estamos proponiendo la ciudad costera de Puerto La Cruz, que es una ciudad turística por excelencia. Existe un gran grupo de hoteles de la ciudad con vistas al mar, clubes náuticos, campos de golf, campos de tenis, y muchas otras actividades interesantes por descubrir. Existen alrededor de 400.000 personas en esta ciudad. Cuenta con un aeropuerto local y está a 160 kilometros del principal Aeropuerto Internacional de Venezuela. Los hoteles Venetur Maremares y Puerto La Cruz poseen amplias salas de conferencias, por lo que el mismo hotel puede ser utilizado como lugar de estadía y trabajo. Por ser cadenas turísticas del estado, se pueden conseguir buenos patrocinios. Sin embargo, existen otros hoteles más pequeños que también pueden ser utilizados. Otro de los atractivos magníficos de este lugar es el Parque Nacional Mochima. El parque se extiende sobre una superficie de 94.935 hectáreas y su región occidental está rodeada por algunas playas realmente sorprendentes. Otros lugares como la Playa Conoma, Isla de Plata, Playa Arapito e Isla Arapo son también conocidos por su belleza inmaculada. La Isla de Margarita, Isla de Coche, y otras islas menores se encuentran relativamente cerca, fácilmente accesibles a través de barco, lo cual las convierten en excelentes opciones para el Day Trip. Puerto La Cruz es también una ciudad académica. Tiene varias universidades que dictan carreras técnicas, de ingeniería, informática y tecnologías de la información que pueden albergar las actividades relacionadas con el DebCamp y el Debian Day, o incluso albergar algunas de las actividades del DebConf. Las siguientes universidades se encuentran cerca del lugar: UDO - Universidad de Oriente. UGMA - Universidad Gran Mariscal de Ayacucho. USM - Universidad Santa María. IUPSM - Instituto Politécnico “Santiago Mariño”. La propuesta La propuesta fue presentada en Managua (Nicaragua) durante nuestra asistencia al DebConf12. Dadas las condiciones, a algunos de nosotros nos pareció que Venezuela podía volver a ser candidata para ser sede de tan selecto evento. En ese sentido, armamos la propuesta que recibió muy buena crítica en la Comunidad de Software Libre. A continuación se muestra el video completo para la presentación de las propuestas (inglés). Hasta ahora, estamos compitiendo con Martinica (Francia) y Montreal (Canadá). Un equipo con experiencia Venezuela posee una gran comunidad de Software Libre que organiza más de 15 grandes eventos al año en todo el país. La comunidad de Software Libre tiene muy buenas relaciones con el Gobierno Venezolano, y recibe amplio apoyo logístico y económico. Es también una comunidad diversa y cooperativa con miembros de diferentes colectivos, entre los que podemos nombrar: Comunidad Debian Venezuela. Comunidad Ubuntu Venezuela. Comunidad Canaima. Comunidad Fedora Venezuela. Comunidad Mozilla Venezuela. Hasta ahora, se han anotado 34 personas como colaboradores en la organización de la propuesta. La elección de la sede definitiva del DebConf14 será en Diciembre de 2012. Antes de la elección existen algunos aspectos que ya se han cubierto, después de la elección comienzan las actividades logísticas y es cuando se necesita el mayor grado de colaboración. La coordinación de los trabajos a realizar la está liderizando la Comunidad Debian Venezuela a través de la lista de correo debian-ve@lists.riseup.net. Por ahora, las nuevas noticias al respecto se manejarán por esa vía. La página oficial de la propuesta de Puerto La Cruz se puede conseguir en este enlace. ¿Y tu, ayudarías a organizar el DebConf en Puerto La Cruz?
Una Autoridad Certificadora Raíz (ACR) es una entidad de confianza, responsable de emitir y revocar los certificados digitales utilizados en la firma electrónica, para lo cual se emplea la criptografía de clave pública. Todas las versiones de Firefox, Iceweasel o Cunaguaro vienen con un número determinado de ACR precargadas que pueden ser consultadas en sus preferencias (Menú > Editar > Preferencias > Avanzado > Cifrado > Ver certificados > Autoridades). Cada ACR pasa por un proceso de verificación riguroso de la Fundación Mozilla que permite comprobar la veracidad y confiabilidad de los datos proporcionados. Las ACR verificadas son recopiladas en una base de datos llamada NSS (Netscape Security) que se incluye dentro del código fuente de los navegadores. NSS no puede ser modificada luego de que ha sido compilada e incluida dentro del navegador y por esto resulta muy difícil alterar la lista predeterminada de ACR. Sin embargo, agregar una ACR a un navegador derivado de Firefox deja de ser una tarea difícil una vez que se entienden todos los aspectos y términos involucrados. En este artículo pretendemos explicar como agregar un ACR de forma predeterminada para que cualquier navegador web basado en Firefox pueda reconocer las aplicaciones web cuyos certificados sean derivados de una ACR en partícular. Sin embargo, el procedimiento también puede ser replicado para agregar certificados individuales, provenientes de aplicaciones particulares (no es necesario que pertenezca a una ACR). El procedimiento se realiza principalmente dentro del código fuente de NSS. Si utilizamos los paquetes que distribuye Debian, Canaima o Ubuntu para Iceweasel, Cunaguaro o Firefox, no es necesario compilar todo el navegador desde cero debido a que en las mencionadas distribuciones, NSS es una librería que viene en un paquete por separado. En pocas palabras, lo que haremos será modificar NSS a través de parches para reempaquetarlo. Preparando herramientas Necesitaremos hacer algunos procedimientos previos antes de hacer la modificación como tal. Necesitarás el Certificado Raíz de la ACR en formato x509 PEM (ASCII), el cual puedes obtener directamente de la Autoridad Certificadora. Para este ejemplo utilizaremos el certificado de PROCERT, quien hace los certificados de SUSCERTE, una institución que se encarga de dictar las políticas en materia de seguridad informática para el estado venezolano. Para obtener el certificado de PROCERT, lo podemos descargar usando un Terminal de Usuario (Menú > Aplicaciones > Accesorios > Terminal) con el siguiente comando (o simplemente copia el enlace y pégalo en el navegador): wget http://acraiz.suscerte.gob.ve/sites/default/files/certificados/CERTIFICADO-RAIZ-SHA384.crt Tip: Recuerda en cual carpeta descargaste el certificado con el comando pwd. Necesitamos instalar git para generar el parche de modificación, git-buildpackage para empaquetar, build-essential para hacer las compilaciones y quilt para gestionar los parches. En una Terminal de Root (Menú > Aplicaciones > Accesorios > Terminal de Root) ejecuta el siguiente comando: aptitude install git git-buildpackage build-essential quilt Descargando el código fuente de NSS Seguidamente necesitarás el código fuente de NSS con algunos componentes de NSPR. Para ello insertarás una línea de repositorio fuente en tu archivo /etc/apt/sources.list utilizando tu editor de texto favorito (desde una Terminal de Root). Dependiendo de la distribución, la línea será: Para Canaima, podemos utilizar nss de la versión 3.1 (auyantepui): deb-src http://paquetes.canaima.softwarelibre.gob.ve/ auyantepui main aportes no-libres Para Debian, podemos utilizar nss de la versión 6.0 (squeeze): deb-src http://ftp.us.debian.org/debian squeeze main contrib non-free Para Ubuntu, podemos utilizar nss de la versión 3.1 (auyantepui): deb-src http://paquetes.canaima.softwarelibre.gob.ve/ auyantepui main aportes no-libres Para la fecha de escritura de este artículo, las versiones indicadas para Canaima, Debian y Ubuntu correspondían a las versiones estables. Puede que no sean las versiones ni las distribuciones que utilizas, así que revisa bien antes. Lo importante es que tengas una línea de repositorio fuente correspondiente a la versión y distribución que utilizas. Si tienes otras líneas de repositorios externos, coméntalas poniéndoles un # al principio de la línea para evitar descargar versiones inapropiadas. Si no estás seguro, coméntalas todas y deja sólo la linea que te indicamos mas arriba. Luego actualizamos los repositorios desde un Terminal de Root con el siguiente comando: aptitude update Y descargamos el código con el siguiente comando desde una Terminal de Usuario: apt-get source nss nspr Se descargará automáticamente la versión apropiada de NSS y NSPR según tu distribución. Por ejemplo, para Canaima Popular 3.1, el resultado es el siguiente: ls nspr-4.8.8 nss-3.12.11 Accederemos a la carpeta del código fuente de NSS para desaplicar los parches que fueron aplicados automáticamente al final de la descarga: cd nss-3.12.11 export QUILT_PATCHES=debian/patches quilt pop -a Compilando la herramienta addbuiltin Antes de compilar addbuiltin, versionaremos el código con git para facilitarnos un poco el proceso en los pasos posteriores. Accederemos a la carpeta de NSS recién creada y ejecutamos los siguientes comandos (en una Terminal de Usuario): git init git add . git commit -a -m "Versión original del código fuente." Esto nos permitirá devolvernos al estado inicial luego de que hayamos hecho las modificaciones correspondientes. Si deseas aprender más de git, puedes ampliar la información acá. Bien, necesitaremos hacer un enlace simbólico al código fuente de NSPR dentro de la carpeta mozilla para que NSS pueda acceder a ciertos componentes durante la compilación. Lo hacemos así: cd mozilla ln -s ../../nspr-4.8.8/mozilla/nsprpub/ . Luego accedemos a la carpeta que contiene el código de NSS y compilamos. Si nuestra arquitectura es i386, los comandos para compilar son los siguientes: cd security/nss/ make nss_build_all BUILD_OPT=1 cd cmd/addbuiltin/ make BUILD_OPT=1 Si nuestra arquitectura es amd64, los comandos son los siguientes: cd security/nss/ make nss_build_all BUILD_OPT=1 USE_64=1 cd cmd/addbuiltin/ make BUILD_OPT=1 USE_64=1 Esto generará el binario addbuiltin dentro de la carpeta Linux3.2_x86_glibc_PTH_OPT.OBJ, la cual tendrá un nombre diferente dependiendo de la arquitectura y el Kernel que estés ejecutando en ese momento. Para el ejemplo se muestra un Kernel 3.2 i386, pero si estás corriendo un Kernel 2.6 amd64, entonces el nombre será Linux2.6_x86_64_glibc_PTH_64_OPT.OBJ y así con el resto de los casos. Finalmente, en un Terminal de Root procedemos a copiar el binario de addbuiltin a la carpeta /usr/bin/ para hacerlo disponible como comando de consola. cp Linux3.2_x86_glibc_PTH_OPT.OBJ/addbuiltin /usr/bin/ Convirtiendo el certificado con addbuiltin Desde una Terminal de Usuario, accede a la carpeta donde descargaste el certificado de la ACR. Seguidamente convertiremos el certificado de formato PEM a formato DER con el siguiente comando: cd /ruta/al/certificado/ openssl x509 -inform PEM -outform DER -in CERTIFICADO-RAIZ-SHA384.crt -out CERTIFICADO-RAIZ-SHA384.der Luego obtendremos el nombre oficial de la ACR con el siguiente comando: openssl x509 -inform PEM -text -in CERTIFICADO-RAIZ-SHA384.crt | grep "Subject" Lo que arroja: Subject: emailAddress=contacto@procert.net.ve, L=Chacao, ST=Miranda, OU=Proveedor de Certificados PROCERT, O=Sistema Nacional de Certificacion Electronica, C=VE, CN=PSCProcert Siendo el nombre el valor del campo “O” (Organization) o el “CN” (Common Name). En este caso, “Proveedor de Certificados PROCERT”. Finalmente podemos procesar el certificado para que NSS lo entienda con addbuiltin, indicando el nombre de la ACR de la siguiente manera: cat CERTIFICADO-RAIZ-SHA384.der | addbuiltin -n "Proveedor de Certificados PROCERT" -t "C,C,C" > CERTIFICADO-RAIZ-SHA384.nss Parcheando y reempaquetando NSS Ahora que finalmente tenemos los datos del certificado de la ACR en el archivo CERTIFICADO-RAIZ-SHA384.nss, entonces vamos a hacer el paquete con las modificaciones. Necesitamos limpiar todos los residuos de compilación y volver al estado original del código. Asegúrate de respaldar el archivo CERTIFICADO-RAIZ-SHA384.nss en un lugar seguro (fuera de la carpeta del código fuente de nss), porque lo que haremos a continuación borrará todo lo que hemos hecho hasta ahora. Ejecutamos los siguientes comandos desde la carpeta de NSS (desde una Terminal de Usuario): git reset --hard git clean -fd Seguidamente debemos decirle a git-buildpackage el número de la última versión-revisión del paquete que aparece en el archivo debian/changelog mediante un tag (etiqueta). Para ello debemos ejecutar el siguiente comando: dpkg-parsechangelog | grep "Version:" | awk '{print $2}' Lo que en nuestro caso arroja: 3.12.11-4 Luego hacemos el tag así: git tag debian/3.12.11-4 Bien, ahora debemos agregar el contenido del archivo CERTIFICADO-RAIZ-SHA384.nss al final del archivo mozilla/security/nss/lib/ckfw/builtins/certdata.txt, lo cual podemos hacer manualmente (CTRL-C + CTRL-V) o automáticamente con el siguiente comando: cat /ruta/al/archivo/CERTIFICADO-RAIZ-SHA384.nss >> mozilla/security/nss/lib/ckfw/builtins/certdata.txt Luego accedemos al directorio donde se encuentra el archivo certdata.txt y lo procesamos así: cd mozilla/security/nss/lib/ckfw/builtins/ make generate ¡Listo! Las modificaciones necesarias están hechas para que al reempaquetar NSS, esté incluído el certificado de tu ACR. El próximo paso es realizar un parche de estas modificaciones para evitar ser intrusivos en el código original. Para ello ejecutaremos los siguientes comandos: cd ../../../../../.. mkdir -p debian/patches git diff > ../99_ACR-certificates.patch git reset --hard git clean -fd mv ../99_ACR-certificates.patch debian/patches/ echo "99_ACR-certificates.patch" >> debian/patches/series Luego, aplicamos y desaplicamos los parches para comprobar que no hay ningún problema: export QUILT_PATCHES=debian/patches quilt push -af quilt refresh rm -rf mozilla/security/nss/lib/ckfw/builtins/certdata.c.rej quilt pop -a Y reempaquetamos: git add . git commit -a -m "Agregando parche para el certificado ACR de SUSCERTE" git-buildpackage -us -uc Lo cual generará nuestros paquetes .deb que contienen los nuevos certificados. Es posible que en Canaima necesites instalar debhelper desde el repositorio de backports, ya que es una dependencia de construcción. Puedes descargarte el paquete desde aquí y luego instalarlo con el siguiente comando (desde una Terminal de Root): dpkg -i /ruta/al/paquete/.deb Espero les sea de utilidad.
Este Miércoles 14 de Noviembre se realizará el lanzamiento oficial de Canaima Popular 3.1 en la ciudad de Mérida, con participación de todo el equipo de desarrollo, la prensa y altas personalidades del Ministerio de Ciencia, Tecnología e Innovación. Luego de 1 año de desarrollo, integración y maduración, la versión 3.1 está lista para ser publicada como versión estable. Canaima Popular 3.1 fue pensada para corregir los errores de la versión 3.0, incorporar nuevas aplicaciones y actualizar algunas otras. El diseño, desarrollo e implementación estuvo a cargo del equipo de desarrollo del CNTI, conformado por Sasha Solano, Francisco Vásquez, Erick Birbe, Carlos Espinoza y Luis Martínez. Dentro de las novedades podemos mencionar: Un nuevo instalador hecho en python, más robusto, eficiente y amigable. Permite instalar usando todo el disco, redimensionando particiones existentes, en espacio libre disponible o utilizando el particionador manual (usuarios avanzados). Este instalador tiene un modo OEM, que permite configurar la cuenta de usuario después de la instalación, ideal para fabricantes de hardware nacionales como VIT y Síragon. Ucumari, una nueva aplicación que tiene como objetivo condensar un gran número de aspectos relacionados con configuraciones del sistema, permitiendo a los usuarios adaptar el comportamiento de Canaima sin la necesidad de editar archivos ni escribir comandos en una consola. Nuevo estilo visual que incluye nuevos fondos de pantalla, nuevo tema del gestor de arranque (burg), nuevo tema para el indicador de carga (plymouth) y una disposición de paneles de escritorio adaptada al espacio reducido de las pantallas de las netbooks. La aplicación de bienvenida fue reescrita en python-webkit para mejorar la estética y agregar mayores funcionalidades. Inclusión por defecto de herramientas de accesibilidad básica para personas con discapacidad visual. Actualización de LibreOffice (suite ofimática), Cunaguaro (navegador web), Guácharo (cliente de correo), Turpial (cliente de twitter), Amigu (asistente de migración) Mejora de las técnicas de construcción de las piezas (paquetes) que conforman la estructura informática de la distribución. Se implementaron las mejores prácticas y estándares de la distribución padre (Debian). Adaptación del Centro de Software de Ubuntu para Canaima. Eliminación de componentes duplicados dentro de la imagen ISO de Canaima: íconos de gnome, punteros del mouse de gnome, temas GTK de gnome, cliente de correo Evolution, navegador web Epiphany, entre otros. Por otro lado, se incluyó Pitivi, un compositor de videos básico, y un analizador de uso en disco. Implementación de un nuevo esquema de repositorios unificados aprobado por la Comunidad en la 6ta Cayapa Barinas. Además, como resultado del proceso de depuración, se lanzaron 4 Versiones Candidatas que permitieron corregir 169 errores del proceso de desarrollo.
Otra de las investigaciones que realicé en el marco de las mejoras al instalador de Canaima Popular 3.1, estuvo relacionada con la elaboración de animaciones y gráficos dentro de ventanas GTK utilizando python-cairo. Cairo es una librería de renderizado de vectores que permite la creación de gráficos a través de objetos python que luego pueden ser renderizados en ventanas, botones, tablas o casi cualquier otro widget GTK. Incluso, es posible renderizar los gráficos en archivos de imagen PNG. En esta oportunidad explicaré como realizar una barra de desplazamiento animada que permita obtener la posición del cursor dentro de un rango de valores. Opcionalmente, la barra de desplazamiento puede estar dividida en varios sectores o partes. La explicación de la creación de este widget se hará por partes, comenzando desde los elementos básicos, hasta armar el script python completo al final del artículo. Es decir, si quieres ahorrarte la explicación, puedes adelantarte hasta el final. Instalación de herramientas Para esta práctica necesitaremos python-gtk2 y python-cairo, los cuales instalaremos desde una Terminal de Root (Menú > Aplicaciones > Accesorios > Terminal de Root) con el siguiente comando: aptitude install python-gtk2 python-cairo Lienzo de trabajo Lo primero que haremos será construir nuestro lienzo de trabajo. El lienzo no es más que una ventana GTK que nos permitirá visualizar los dibujos que vamos realizando. Los comentarios dentro del código irán describiendo cada una de las líneas. # Declaramos una clase que hereda gtk.Window # En otras palabras, la clase ahora se comporta como gtk.Window class Ventana(gtk.Window): ancho = 500 alto = 200 presionado = False pos = [] def __init__(self): # Inicializamos gtk.Window encima de las demás ventanas gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) # Colocamos la ventana en el centro gtk.Window.set_position(self, gtk.WIN_POS_CENTER_ALWAYS) # Establecemos un título para la ventana self.set_title('Ventana') # Definimos el tamaño en pixeles de la ventana self.set_size_request(self.ancho, self.alto) # Deshabilitamos la redimensión de la ventana self.set_resizable(False) # Establecemos el margen interno a 5 pixeles self.set_border_width(5) # Conectamos los eventos de cerrado de la ventana a # la salida del loop principal de gtk self.connect("destroy", gtk.main_quit) self.connect("delete-event", gtk.main_quit) # Declaramos una Caja Vertical que nos permitirá incrustar objetos # dentro de la ventana secuencialmente self.contenedor = gtk.VBox() # Incrustamos la caja vertical en la ventana self.add(self.contenedor) # Declaramos un Área de Dibujo self.barra = gtk.DrawingArea() # Definimos el tamaño en pixeles del área # en donde se dibujará la barra de desplazamiento self.barra.set_size_request(self.ancho - 10, self.alto - 100) # Obtenemos el tamaño de la barra para utilizarlo después self.bancho = self.barra.get_size_request()[0] self.balto = self.barra.get_size_request()[1] # Definimos los eventos a los cuales reaccionará el área self.barra.set_events( gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK ) # Lo agregamos a la caja vertical self.contenedor.add(self.barra) # Declaramos una etiqueta de texto para mostrar información self.texto = gtk.Label('100%') # Definimos el tamaño self.texto.set_size_request(self.ancho - 10, self.alto - 110) # Lo agregamos a la caja vertical self.contenedor.add(self.texto) # Mostramos todo self.show_all() Bloque N°1: Ventana de pruebas. Creando gradientes de colores Comenzaremos haciendo un gradiente cairo que nos permitirá rellenar un rectángulo. Los colores en cairo se definen en un formato RGB particular que está compuesto de números decimales entre 0 y 1 en vez del modelo tradicional. Para evitar cálculos engorrosos, haremos una función que permita hacer gradientes basados en colores HTML (notación hexadecimal) porque son más fáciles de especificar. La siguiente función acepta un valor hexadecimal como #000000 (negro) o #FFFFFF (blanco) y retorna una tupla con los tres componentes RGB estándar (números enteros del 0 al 255). def hex_to_rgb(hx): # Preparamos una lista vacía r = [] # Removemos el caracter '#' de la notación HTML h = hx.lstrip('#') # Iteramos de dos en dos hasta la longitud de caracteres del color (6) for i in range(0, 6, 2): # Añadimos a la lista la conversión de cada par hexadecimal r.append(int(h[i:i + 2], 16)) # Retornamos la tupla (R,G,B) (notación estándar) return tuple(r) Bloque N°2: Conversión hexadecimal a RGB estándar. La siguiente función permitirá generar un objeto de gradiente lineal en cairo. Un objeto de gradiente lineal necesita la longitud del gradiente (alto en pixeles), un color de inicio y un color de final (en formato RGB de cairo). Se utilizará la función hex_to_rgb (Bloque N°2) para convertir los colores de inicio y fin de notación HTML a formato RGB estándar. def gradiente(alto, start, end): # Declaramos el objeto de gradiente lineal grad = cairo.LinearGradient(0.0, 0.0, 0.0, alto) # Generamos la tupla de color de inicio (inicio, R, G, B) s = (0.0,) + hex_to_rgb(start) # Generamos la tupla de color final (fin, R, G, B) e = (1.0,) + hex_to_rgb(end) # Iteramos por el inicio y fin for i in s, e: # Convertimos RGB estándar a RGB de cairo rgb = float(i[0]), float(i[1] / 255.0), float(i[2] / 255.0), float(i[3] / 255.0) # Agregamos el punto de color al objeto de gradiente lineal grad.add_color_stop_rgb(*rgb) # Retornamos el objeto de gradiente return grad Bloque N°3: Creación del gradiente. Ahora, para hacernos la vida un poco más fácil, he creado la siguiente función que condensa una serie de colores conocidos. Permite crear un gradiente utilizando la función gradiente (Bloque N°3) y un conjunto de colores preseleccionados que generan un sutil gradiente para cada uno. def crear_color(clr, alto): if clr == 'naranja': grad = gradiente(alto, '#ff5d2e', '#ff912e') elif clr == 'azul-claro': grad = gradiente(alto, '#2460c8', '#2e7bff') elif clr == 'azul': grad = gradiente(alto, '#1b4794', '#2460c8') elif clr == 'azul-oscuro': grad = gradiente(alto, '#102b58', '#1b4794') elif clr == 'verde-claro': grad = gradiente(alto, '#00b900', '#00ff00') elif clr == 'verde': grad = gradiente(alto, '#008100', '#00b900') elif clr == 'verde-oscuro': grad = gradiente(alto, '#003800', '#008100') elif clr == 'marron-oscuro': grad = gradiente(alto, '#382720', '#895f4d') elif clr == 'marron': grad = gradiente(alto, '#895f4d', '#e49e80') elif clr == 'marron-claro': grad = gradiente(alto, '#e49e80', '#ffcfbb') elif clr == 'rojo': grad = gradiente(alto, '#650000', '#cc0000') elif clr == 'morado': grad = gradiente(alto, '#45374f', '#806794') elif clr == 'morado-claro': grad = gradiente(alto, '#806794', '#b994d5') elif clr == 'amarillo': grad = gradiente(alto, '#e89900', '#e8d000') elif clr == 'blanco': grad = gradiente(alto, '#ffffff', '#ffffff') elif clr == 'aguamarina': grad = gradiente(alto, '#7dfcfe', '#7dfcfe') elif clr == 'negro': grad = gradiente(alto, '#000000', '#000000') elif clr == 'gris': grad = gradiente(alto, '#b8b598', '#b8b598') return grad Bloque N°4: Asignación del gradiente según nombre del color. Dibujando rectángulos de bordes redondeados Los rectángulos de bordes redondeados nos ayudarán a dibujar nuestra barra de desplazamiento. rectangulo_red es una función que construye un rectángulo redondeado con un fondo en gradiente. Acepta los siguientes parámetros: cr corresponde a una sesión cairo abierta (lo explicaremos maś adelante), area son las coordenadas de las dimensiones del rectángulo, r es el radio de los arcos redondeados del rectángulo y clr es el nombre del color de fondo con el que colorearemos el rectángulo. Mayor explicación en los comentarios del código. def rectangulo_red(cr, area, r, clr): # area debe ser una lista de cuatro items: # x1, y1: coordenada en pixeles de la esquina superior izquierda del rectángulo # x2, y2: coordenada en pixeles de la esquina inferior derecha del rectángulo x1, y1, x2, y2 = area # clr es el nombre del color, por ejemplo, 'azul' # y2 - y1 es el cálculo del alto que se utilizará para el gradiente color = crear_color(clr, y2 - y1) # Las próximas cuatro líneas corresponden al dibujo de los cuatro arcos # de las esquinas del rectángulo. Los cuatro parámetros se explican así: # cr.arc(A, B, C, D) # A: Coordenada horizontal del centro del arco # B: Coordenada vertical del centro del arco # C: Coordenada cartesiana del ángulo de apertura del arco # D: Coordenada cartesiana del ángulo donde termina el arco. cr.arc(x1 + r, y1 + r, r, 2 * (math.pi / 2), 3 * (math.pi / 2)) cr.arc(x2 - r, y1 + r, r, 3 * (math.pi / 2), 4 * (math.pi / 2)) cr.arc(x2 - r, y2 - r, r, 0 * (math.pi / 2), 1 * (math.pi / 2)) cr.arc(x1 + r, y2 - r, r, 1 * (math.pi / 2), 2 * (math.pi / 2)) # Establecemos el color cr.set_source(color) # Cerramos los trazos de los arcos cr.close_path() # Rellenamos el rectángulo con el gradiente cr.fill() Bloque N°5: Creación del rectángulo. Al utilizar la función rectángulo_red, habremos creado un rectángulo dentro de una sesión cairo (cr). Interactividad y movimiento La interactividad se obtiene a través del uso apropiado de los eventos dentro del área de dibujo. Es decir, si asociamos determinadas funciones con los eventos, lograremos que el usuario pueda interactuar con nuestra ventana GTK. La asociación de eventos con funciones introduce un inmenso panorama de posibilidades, pero por ahora basta saber que las funciones necesitan recibir un parámetro widget (el que lo referencia) y un parámetro evento (que contiene información acerca del evento que la invocó). La función dibujar es una función de asistencia que nos permitirá dibujar el estado inicial de nuestro dibujo, y además refrescar el lienzo cada vez que se invoque. La idea es conectar el evento de exposición (expose-event) con esta función para que el dibujo se mantenga refrescado. Dibujaremos varios cuadros que se describirán en una lista y al final dibujaremos un rectángulo vertical que podrá moverse de lado a lado, simulando un selector. Adicionalmente, le pasaremos información a la función acerca de la ventana donde se encuentra y los cuadros que debe dibujar. def dibujar(widget, evento, ventana): lista = [] # La posición del selector se calcula restando el espacio libre después # del sector al espacio total selector = ventana.total - ventana.libre # Este factor es el factor de redimensión de cada uno de los cuadros segun # la posición del selector factor = selector / ventana.total # Refrescamos el lienzo del dibujo ventana.lienzo = ventana.barra.window.cairo_create() # Iteramos a través de cada uno de los cuadros # Cada cuadro debe venir en la forma [inicio, fin, color] for j in ventana.cuadros: # Recalculamos el tamaño de cada cuadro según el factor lista.append([j[0] * factor, j[1] * factor, j[2]]) # Agregamos un cuadro gris que estará después del selector lista.append([selector, ventana.total, 'gris']) # Iteramos por cada uno de los cuadros for c in lista: # Radio de los cuadros r = 5 # Los cuadros inician en el tope superior y1 = 0 # Y terminan en el tope inferior y2 = ventana.balto # En c tenemos el punto inicial del cuadro, el punto final y el color a1, a2, clr = c # Recalculamos la posición de x1 y x2 según el factor de ancho de la # ventana con respecto al ancho "bancho" que es el ancho máximo de los cuadros x1 = a1 * ventana.bancho / ventana.total + 1 x2 = a2 * ventana.bancho / ventana.total - 1 # Si el ancho de un cuadro llega a ser menor a 12px, cambiamos el # espaciado y el radio para conservar estética if x2 - x1 < 12: x1 = x1 - 1 x2 = x2 + 1 r = 0 # Componemos el área del cuadro area = [x1, y1, x2, y2] # Dibujamos el cuadro rectangulo_red(ventana.lienzo, area, r, clr) # Armamos el cuadro correspondiente al selector y1_sel = 10 y2_sel = ventana.balto - 10 x1_sel = (selector * ventana.bancho / ventana.total) - 5 x2_sel = (selector * ventana.bancho / ventana.total) + 5 # Dibujamos el selector ventana.sel = [x1_sel, y1_sel, x2_sel, y2_sel] rectangulo_red(ventana.lienzo, ventana.sel, 3, 'negro') Bloque N°6: Creación del dibujo en el lienzo. Necesitamos saber en qué momento se presiona y en qué momento se suelta el selector. Para ello utilizaremos una variable asociada a la ventana (ventana.presionado), la cuál se establecerá True o False convenientemente. La función presionar estará asociada al evento button-press-event, el cual se acciona cada vez que se hace click dentro del lienzo. Para este evento, la variable evento.x y evento.y van a contener el valor de las coordenadas del cursor dentro del lienzo de dibujo; esto nos permitirá saber el momento en que se haga click dentro del área asociada al selector (establecida en ventana.sel). Por otro lado, la función soltar estará asociada al evento button-release-event, que establecerá ventana.presionado a False cuando se suelte el click del ratón. def presionar(widget, evento, ventana): if evento.x >= ventana.sel[0] and \ evento.x <= ventana.sel[2] and \ evento.y >= ventana.sel[1] and \ evento.y <= ventana.sel[3]: ventana.presionado = True def soltar(widget, evento, ventana): ventana.presionado = False Bloque N°7: Funciones para presionar y soltar. Luego haremos una función que nos permita redibujar los cuadros de acuerdo al movimiento del selector, para ello la conectaremos al evento motion-notify-event. Para este evento, la variable evento.x y evento.y van a tener el valor de la posición del cursor dentro del lienzo de dibujo; esto nos permitirá saber el momento en que el cursor pase por encima del selector, en donde podremos cambiar el tipo de cursor que se muestra. Por otro lado, la variable ventana.presionado nos permitirá saber si el cursor se encuentra presionado, momento en el cuál procederemos a actualizar la posición y tamaño de los cuadros mediante la función queue_draw(), la cual invoca el evento expose-event, que ejecuta la función dibujar(). def redibujar(widget, evento, ventana): # Si el cursor está dentro del área del selector if evento.x >= ventana.sel[0] and \ evento.x <= ventana.sel[2] and \ evento.y >= ventana.sel[1] and \ evento.y <= ventana.sel[3]: # Establecemos el cursor tipo mano cursor = gtk.gdk.Cursor(gtk.gdk.HAND2) ventana.barra.window.set_cursor(cursor) else: # De loc ontrario, establecemos el cursor tipo normal cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR) ventana.barra.window.set_cursor(cursor) # Si se ha presionado el selector ... if ventana.presionado == True: # ... y el cursor se encuentra dentro de los límites del lienzo if evento.x <= ventana.bancho and evento.x >= 0: # Calculamos la posición del selector de acuerdo a la proporción x = float(evento.x * ventana.total / ventana.bancho) # Calculamos el espacio a la derecha del selector ventana.libre = ventana.total - x # Establecemos el porcentaje ventana.texto.set_label(str(int(x))+'%') # Mandamos a redibujar ventana.barra.queue_draw() Bloque N°8: Redibujar de acuerdo a la posición del selector. Por último, declararemos nuestras variables, ventana y conectaremos cada evento con sus funciones. if __name__ == "__main__": # Instanciamos la ventana ventana = Ventana() # Esta variable define cuánto es la unidad máxima posible para los cuadros. # A partir de este valor se calculará el factor de tamaño de los cuadros. # Puede entenderse mejor si se interpreta como porcentaje (100%). ventana.total = 100.0 # Esta variable define cuanto espacio libre habrá a la derecha del selector ventana.libre = 0.0 # Construímos el arreglo de cuadros, tomando en cuenta el valor máximo ventana.cuadros = [ [0.0, 20.0, 'verde'], [20.0, 60.0, 'rojo'], [60.0, 100.0, 'amarillo'] ] # Conectamos las funciones a los eventos ventana.barra.connect("expose-event", dibujar, ventana) ventana.barra.connect("button-press-event", presionar, ventana) ventana.barra.connect("button-release-event", soltar, ventana) ventana.barra.connect("motion-notify-event", redibujar, ventana) # Iniciamos el loop principal de gtk gtk.main() # Salimos apropiadamente sys.exit() Bloque N°7: Llamado de la ventana y conexión de eventos con funciones. Resultados Bueno, finalmente toca juntar todos los bloques en un sólo archivo de texto. Lo guardamos como “barra.py” y lo ejecutamos en una Terminal de Usuario (Menú > Aplicaciones > Accesorios > Terminal de Usuario) de la siguiente manera: cd /ruta/a/la/carpeta/ python barra.py Y a continuación se muestra el script completo. Espero que les sea de utilidad. #!/usr/bin/env python # -*- coding: utf-8 -*- # Importamos las librerías import gtk, sys, cairo, math # Declaramos una clase que hereda gtk.Window # En otras palabras, la clase ahora se comporta como gtk.Window class Ventana(gtk.Window): ancho = 500 alto = 200 presionado = False pos = [] def __init__(self): # Inicializamos gtk.Window encima de las demás ventanas gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) # Colocamos la ventana en el centro gtk.Window.set_position(self, gtk.WIN_POS_CENTER_ALWAYS) # Establecemos un título para la ventana self.set_title('Ventana') # Definimos el tamaño en pixeles de la ventana self.set_size_request(self.ancho, self.alto) # Deshabilitamos la redimensión de la ventana self.set_resizable(False) # Establecemos el margen interno a 5 pixeles self.set_border_width(5) # Conectamos los eventos de cerrado de la ventana a # la salida del loop principal de gtk self.connect("destroy", gtk.main_quit) self.connect("delete-event", gtk.main_quit) # Declaramos una Caja Vertical que nos permitirá incrustar objetos # dentro de la ventana secuencialmente self.contenedor = gtk.VBox() # Incrustamos la caja vertical en la ventana self.add(self.contenedor) # Declaramos un Área de Dibujo self.barra = gtk.DrawingArea() # Definimos el tamaño en pixeles del área # en donde se dibujará la barra de desplazamiento self.barra.set_size_request(self.ancho - 10, self.alto - 100) # Obtenemos el tamaño de la barra para utilizarlo después self.bancho = self.barra.get_size_request()[0] self.balto = self.barra.get_size_request()[1] # Definimos los eventos a los cuales reaccionará el área self.barra.set_events( gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK ) # Lo agregamos a la caja vertical self.contenedor.add(self.barra) # Declaramos una etiqueta de texto para mostrar información self.texto = gtk.Label('100%') # Definimos el tamaño self.texto.set_size_request(self.ancho - 10, self.alto - 110) # Lo agregamos a la caja vertical self.contenedor.add(self.texto) # Mostramos todo self.show_all() def hex_to_rgb(hx): # Preparamos una lista vacía r = [] # Removemos el caracter '#' de la notación HTML h = hx.lstrip('#') # Iteramos de dos en dos hasta la longitud de caracteres del color (6) for i in range(0, 6, 2): # Añadimos a la lista la conversión de cada par hexadecimal r.append(int(h[i:i + 2], 16)) # Retornamos la lista [R,G,B] (notación estándar) return tuple(r) def gradiente(alto, start, end): # Declaramos el objeto de gradiente lineal grad = cairo.LinearGradient(0.0, 0.0, 0.0, alto) # Generamos la tupla de color de inicio (inicio, R, G, B) s = (0.0,) + hex_to_rgb(start) # Generamos la tupla de color final (fin, R, G, B) e = (1.0,) + hex_to_rgb(end) # Iteramos por el inicio y fin for i in s, e: # Convertimos RGB estándar a RGB de cairo rgb = float(i[0]), float(i[1] / 255.0), float(i[2] / 255.0), float(i[3] / 255.0) # Agregamos el punto de color al objeto de gradiente lineal grad.add_color_stop_rgb(*rgb) # Retornamos el objeto de gradiente return grad def crear_color(clr, alto): if clr == 'naranja': grad = gradiente(alto, '#ff5d2e', '#ff912e') elif clr == 'azul-claro': grad = gradiente(alto, '#2460c8', '#2e7bff') elif clr == 'azul': grad = gradiente(alto, '#1b4794', '#2460c8') elif clr == 'azul-oscuro': grad = gradiente(alto, '#102b58', '#1b4794') elif clr == 'verde-claro': grad = gradiente(alto, '#00b900', '#00ff00') elif clr == 'verde': grad = gradiente(alto, '#008100', '#00b900') elif clr == 'verde-oscuro': grad = gradiente(alto, '#003800', '#008100') elif clr == 'marron-oscuro': grad = gradiente(alto, '#382720', '#895f4d') elif clr == 'marron': grad = gradiente(alto, '#895f4d', '#e49e80') elif clr == 'marron-claro': grad = gradiente(alto, '#e49e80', '#ffcfbb') elif clr == 'rojo': grad = gradiente(alto, '#650000', '#cc0000') elif clr == 'morado': grad = gradiente(alto, '#45374f', '#806794') elif clr == 'morado-claro': grad = gradiente(alto, '#806794', '#b994d5') elif clr == 'amarillo': grad = gradiente(alto, '#e89900', '#e8d000') elif clr == 'blanco': grad = gradiente(alto, '#ffffff', '#ffffff') elif clr == 'aguamarina': grad = gradiente(alto, '#7dfcfe', '#7dfcfe') elif clr == 'negro': grad = gradiente(alto, '#000000', '#000000') elif clr == 'gris': grad = gradiente(alto, '#b8b598', '#b8b598') return grad def rectangulo_red(cr, area, r, clr): # area debe ser una lista de cuatro items: # x1, y1: coordenada en pixeles de la esquina superior izquierda del rectángulo # x2, y2: coordenada en pixeles de la esquina inferior derecha del rectángulo x1, y1, x2, y2 = area # clr es el nombre del color, por ejemplo, 'azul' # y2 - y1 es el cálculo del alto que se utilizará para el gradiente color = crear_color(clr, y2 - y1) # Las próximas cuatro líneas corresponden al dibujo de los cuatro arcos # de las esquinas del rectángulo. Los cuatro parámetros se explican así: # cr.arc(A, B, C, D) # A: Coordenada horizontal del centro del arco # B: Coordenada vertical del centro del arco # C: Coordenada cartesiana del ángulo de apertura del arco # D: Coordenada cartesiana del ángulo donde termina el arco. cr.arc(x1 + r, y1 + r, r, 2 * (math.pi / 2), 3 * (math.pi / 2)) cr.arc(x2 - r, y1 + r, r, 3 * (math.pi / 2), 4 * (math.pi / 2)) cr.arc(x2 - r, y2 - r, r, 0 * (math.pi / 2), 1 * (math.pi / 2)) cr.arc(x1 + r, y2 - r, r, 1 * (math.pi / 2), 2 * (math.pi / 2)) # Establecemos el color cr.set_source(color) # Cerramos los trazos de los arcos cr.close_path() # Rellenamos el rectángulo con el gradiente cr.fill() def dibujar(widget, evento, ventana): lista = [] # La posición del selector se calcula restando el espacio libre después # del sector al espacio total selector = ventana.total - ventana.libre # Este factor es el factor de redimensión de cada uno de los cuadros segun # la posición del selector factor = selector / ventana.total # Refrescamos el lienzo del dibujo ventana.lienzo = ventana.barra.window.cairo_create() # Iteramos a través de cada uno de los cuadros # Cada cuadro debe venir en la forma [inicio, fin, color] for j in ventana.cuadros: # Recalculamos el tamaño de cada cuadro según el factor lista.append([j[0] * factor, j[1] * factor, j[2]]) # Agregamos un cuadro gris que estará después del selector lista.append([selector, ventana.total, 'gris']) # Iteramos por cada uno de los cuadros for c in lista: # Radio de los cuadros r = 5 # Los cuadros inician en el tope superior y1 = 0 # Y terminan en el tope inferior y2 = ventana.balto # En c tenemos el punto inicial del cuadro, el punto final y el color a1, a2, clr = c # Recalculamos la posición de x1 y x2 según el factor de ancho de la # ventana con respecto al ancho "bancho" que es el ancho máximo de los cuadros x1 = a1 * ventana.bancho / ventana.total + 1 x2 = a2 * ventana.bancho / ventana.total - 1 # Si el ancho de un cuadro llega a ser menor a 12px, cambiamos el # espaciado y el radio para conservar estética if x2 - x1 < 12: x1 = x1 - 1 x2 = x2 + 1 r = 0 # Componemos el área del cuadro area = [x1, y1, x2, y2] # Dibujamos el cuadro rectangulo_red(ventana.lienzo, area, r, clr) # Armamos el cuadro correspondiente al selector y1_sel = 10 y2_sel = ventana.balto - 10 x1_sel = (selector * ventana.bancho / ventana.total) - 5 x2_sel = (selector * ventana.bancho / ventana.total) + 5 # Dibujamos el selector ventana.sel = [x1_sel, y1_sel, x2_sel, y2_sel] rectangulo_red(ventana.lienzo, ventana.sel, 3, 'negro') def presionar(widget, evento, ventana): if evento.x >= ventana.sel[0] and \ evento.x <= ventana.sel[2] and \ evento.y >= ventana.sel[1] and \ evento.y <= ventana.sel[3]: ventana.presionado = True def soltar(widget, evento, ventana): ventana.presionado = False def redibujar(widget, evento, ventana): # Si el cursor está dentro del área del selector if evento.x >= ventana.sel[0] and \ evento.x <= ventana.sel[2] and \ evento.y >= ventana.sel[1] and \ evento.y <= ventana.sel[3]: # Establecemos el cursor tipo mano cursor = gtk.gdk.Cursor(gtk.gdk.HAND2) ventana.barra.window.set_cursor(cursor) else: # De loc ontrario, establecemos el cursor tipo normal cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR) ventana.barra.window.set_cursor(cursor) # Si se ha presionado el selector ... if ventana.presionado == True: # ... y el cursor se encuentra dentro de los límites del lienzo if evento.x <= ventana.bancho and evento.x >= 0: # Calculamos la posición del selector de acuerdo a la proporción x = float(evento.x * ventana.total / ventana.bancho) # Calculamos el espacio a la derecha del selector ventana.libre = ventana.total - x # Establecemos el porcentaje ventana.texto.set_label(str(int(x))+'%') # Mandamos a redibujar ventana.barra.queue_draw() if __name__ == "__main__": # Instanciamos la ventana ventana = Ventana() # Esta variable define cuánto es la unidad máxima posible para los cuadros. # A partir de este valor se calculará el factor de tamaño de los cuadros. # Puede entenderse mejor si se interpreta como porcentaje (100%). ventana.total = 100.0 # Esta variable define cuanto espacio libre habrá a la derecha del selector ventana.libre = 0.0 # Construímos el arreglo de cuadros, tomando en cuenta el valor máximo ventana.cuadros = [ [0.0, 20.0, 'verde'], [20.0, 60.0, 'rojo'], [60.0, 100.0, 'amarillo'] ] # Conectamos las funciones a los eventos ventana.barra.connect("expose-event", dibujar, ventana) ventana.barra.connect("button-press-event", presionar, ventana) ventana.barra.connect("button-release-event", soltar, ventana) ventana.barra.connect("motion-notify-event", redibujar, ventana) # Iniciamos el loop principal de gtk gtk.main() # Salimos apropiadamente sys.exit()
El pasado día viernes 02/11/12 estuve conversando con Luigino Bracci en su programa “Cópiate esta Radio”, que se transmite por la emisora Alba Ciudad 96.3FM todos los viernes a las 02:00pm. Durante la entrevista, conversamos acerca del nuevo instalador de Canaima, las nuevas características de la versión 3.1, y un poco de mi experiencia en el DebConf12. Más abajo se puede escuchar el fragmento de la entrevista. Archivo editado con Audacity (Editor de audio Software Libre). Descarga: Copiate ésta Radio - Viernes 02/11/12 Peso: 40,3MB Duración: 17min
El instalador es una de las nuevas aplicaciones que se incluyen en Canaima Popular 3.1 y es quizás una de las más importantes. La incorporación de nuevas aplicaciones dentro del CD de Canaima, hizo necesario que se explorara la eliminación de otras aplicaciones menos relevantes. Se tomó la decisión de hacer un instalador desde cero, en un lenguaje popular y ampliamente documentado (python), más completo, robusto y amigable, pero sobre todo: liviano. Esta decisión nos permitió prescindir de los antiguos instaladores de Canaima 3.0 (debian-installer, canaima-instalador-vivo), que en total ocupaban alrededor de 100MB de los 700MB disponibles en un CD. El nuevo instalador integra varias tecnologías, entre las que podemos mencionar: python-gtk2, python-cairo, python-parted, python-webkit, jquery, multihilos, entre otros. La creación estuvo a cargo de William Cabrera, Erick Birbe y este servidor, Luis Martínez. ¿Cómo ayudo con las pruebas? La mejor forma de ayudarnos es instalando Canaima tantas veces y a tantas personas como puedas. Es importante que tu computadora esté conectada a internet. Las instrucciones son sencillas: Descarga la última imagen ISO de Canaima según la arquitectura de tu computador, desde los enlaces que aparecen abajo (si no conoces la arquitectura, descarga la i386). Descargar imagen ISO para arquitectura amd64 Descargar imagen ISO para arquitectura i386 Una vez descargada la imagen ISO, utiliza un programa quemador de CD/DVD como Brasero, K3b o Nero (Windows) para grabar la imagen ISO en un CD o DVD. También puedes utilizar un procedimiento similar para grabarlo en un pen-drive, que puedes consultar en este enlace. Después de tener tu CD o DVD con la imagen grabada, insertalo en la bandeja de la unidad CD/DVD y reinicia tu computadora. Tu computador iniciará el sistema operativo que se encuentra en el CD o DVD en vez del sistema operativo que se encuentra en tu disco duro. No hay de que alarmarse, una vez que extraigas el CD o DVD y reinicies tu PC, todo volverá a como estaba antes. Aparecerá la pantalla de inicio de la imagen, en donde deberás esperar algunos minutos mientras se carga Canaima desde el CD o DVD. Al terminar la carga, aparecerá el escritorio, en donde deberás ejecutar el Terminal de Root (haz click en el menú, luego en Accesorios y luego Terminal de Root) y ejecutar los siguientes comandos: aptitude update aptitude upgrade canaima-instalador Normalmente estos comandos no hay que ejecutarlos en una instalación normal de Canaima, pero para este período de pruebas, nos ayudarán a corregir algunos errores. Seguidamente, ejecutamos el instalador con el siguiente comando dentro de la misma Terminal de Root. canaima-instalador Las instrucciones en pantalla son bastante intuitivas. Síguelas con atención y observa todos los detalles que puedas. Si detectas un comportamiento inesperado, necesitamos que nos avises para que podamos corregirlo. La mejor manera de avisarnos es a través de nuestro sistema de reporte de tickets. Para poder reportar un ticket, necesitas tener una cuenta en la plataforma colaborativa del proyecto Canaima. Si no posees una, puedes crear una rápidamente a través del siguiente enlace. Si ya tienes una cuenta, autentícate en el sistema de tickets a través de este enlace para que puedas reportar el error. Dentro del reporte de error, cuéntanos que estabas haciendo cuando ocurrió el error, qué te salió y cuál es el error en sí. Es muy importante que copies de la terminal la mayoría de las líneas de error y las pegues al final del reporte de ticket, nos ayudará mucho a resolver el problema. Descripción general El nuevo instalador posee una pantalla de selección para la distribución del teclado con una ilustración que refleja la selección actual. Seguidamente, encontraremos la pantalla de selección del disco y método de instalación; en esta pantalla se puede elegir dentro de una serie de opciones disponibles según las condiciones del disco seleccionado, a saber: Instalar usando todo el disco: estará disponible en la mayoría de los casos, a excepción de cuando el disco tenga una capacidad inferior al espacio mínimo necesario (6GB). Esta opción borrará todas las particiones existentes en el disco (junto con los datos) e instalará Canaima en todo el disco. Instalar redimensionando /dev/sdXY para liberar espacio: esta opción estará disponible cuando exista una partición que esté habilitada para cambiar de tamaño y que además tenga 6GB o más de espacio sin ocupar. En este caso, Canaima se instalará en el espacio liberado. Instalar en el espacio libre de XGB: estará disponible cuando exista un espacio libre mayor o igual a 6GB. El espacio libre se utilizará para instalar Canaima. Instalar particionando manualmente: estará disponible cuando el tamaño del disco sea mayor o igual a 6GB. Esta opción permitirá crear, borrar, redimensionar, formatear (entre otras operaciones) tantas particiones como el usuario desee, sin necesidad de utilizar un programa externo. Si se selecciona “Instalar usando todo el disco” o “Instalar usando espacio libre de XGB”, la siguiente pantalla será una barra de desplazamiento que permitirá decidir cuanto espacio libre se dejará contiguo a la instalación de Canaima (o en su defecto usar todo el espacio). La misma pantalla también permite elegir cómo se particionará el disco (separando /home, /boot, /var, /usr, entre otros). Si se selecciona “Instalar redimensionando /dev/sdXY para liberar espacio”, la siguiente pantalla también presentará una barra de desplazamiento que permitirá decidir cuanto se reducirá la partición para hacer espacio para la instalación de Canaima. También permite elegir cómo se particionará el disco. Si se selecciona “Instalar particionando manualmente”, la siguiente pantalla presentará un cuadro con las particiones existentes y el espacio libre (de existir) junto con un conjunto de botones que permitiran editar las particiones según las necesidades del usuario. La pantalla siguiente es la de la información de usuario. Se le preguntará por sus contraseñas, su nombre real, su nombre de usuario y algunas configuraciones adicionales. Seguidamente, la pantalla de resúmen y luego la instalación como tal. La instalación tarda entre 10 y 15min en un equipo de prestaciones medias. Al terminar la instalación, revisa que todo esté en orden y échanos el cuento!