Tu calendario de Google en Ubuntu 11.10

Esta entrada la estoy escribiendo porque en las versiones anteriores a Ubuntu 11.10 teníamos como cliente predeterminado de correo a Evolution el cual tenía como parte de sus componentes la gestión de contactos, calendario de actividades y notas.

Como ya te habrás dado cuenta, en la versión 11.10 de Ubuntu el cliente de correo predeterminado ya es Mozilla Thunderbird y resulta que por mas que le busqué no encontré por ningún lado que contenga la gestión del calendario y actividades :( así que buscando un poco encontré que se puede instalar un plugin para que se pueda tener la opción de manejar tu calendario de Google desde Thunderbird.

Primero que nada debemos instalar el plugin y eso lo podemos hacer desde el centro de software de Ubuntu buscando la palabra Thunderbird y luego seleccionando la opción más información como se muestra en la siguiente imagen:


Para que en la pantalla que nos muestra posteriormente seleccionemos de la parte de Añadidos la opción que dice: Extensión de calendario para Thunderbird - soporte para Google Calendar como se muestra en la siguiente imagen:


Con lo anterior, al abrir Thunderbird podrás ver que ya aparece la opción Calendar (desgraciadamente el plugin no está en español) se ve en la siguiente imagen:


Para finalizar, tienes que crear un nuevo calendario y eso lo puedes hacer dando doble click con el botón izquierdo de tu ratón en el área blanca debajo de la palabra Calendar de la barra del lado izquierdo y te aparecerá la siguiente pantalla:


Tienes que seleccionar que tu calendario estará almacenado remotamente dando click en la opción: On the Network y después click sobre Siguiente, con lo que aparecerá la siguiente pantalla en la que deberás seleccionar la opción Google Calendar:



En la parte de Location deberás poner el Link que sacarás de tu configuración de tu calendario desde la página de Google, entras a Calendario -> Configuración y después seleccionas el calendario que quieres sincronizar:


En la pantalla de tu calendario deberás seleccionar uno de los Links XML que dicen ahí y la información que te mostrará en una ventana la copias y la pegas en tu pantalla de Thunderbird.



Con esto podrás tener tu calendario de Google sincronizado en Ubuntu 11.10 :)

En Ubuntu 11.10 instalando impresora compartida desde Windows

Resulta que en las versiones anteriores de Ubuntu 10.10 y 11.04 me fue muy fácil instalar la impresora que tenemos compartida aquí en el área de trabajo, solamente me dirigía al programa para agregar impresoras, le daba click en Agregar y seleccionaba que quería buscar la impresora de red y ponía la IP para buscarla (Imagen de abajo) y la encontraba fácilmente y procedía con los pasos del asistente.



En la nueva versión de Ubuntu 11.10 haciendo los pasos de arriba no se porqué no me encuentra la impresora, cabe mencionar que la red donde se encuentran los equipos es la IP: 192.168.2.XXX

Y yo estoy detrás de un Router que me da IPs del rango 192.168.0.XXX pero si puedo hacer ping a las IPs del rango 192.168.2.XXX

Aquí en el departamento la mayoría tiene Windows y la impresora esta instalada y compartida en un equipo con XP, así que buscando formas de instalar la impresora encontré que si busco la impresora con la opción de hasta abajo que dice: Impresora Windows vía SAMBA y pongo los datos como los de la imagen siguiente:


smb://GRUPO_TRABAJO/ip_equipo_impresora/NOMBRECOMPARTIDO

Si pude conectar con la impresora y con eso proseguir con el asistente de seleccionar la marca y modelo de la impresora como se ve en las siguientes imágenes.



Espero que te sea de utilidad esta información y nos leemos pronto... :)



Instalando Java 6 de Oracle (antes de Sun) cambiando a OpenJDK en Ubuntu 11.10

Aquí algunos pasos para tener instalado Java 6 de Oracle (antes Sun) en cuenta de OpenJDK que viene instalado por default en Ubuntu 11.10.

Primeramente comentar que parte de la información comentada aquí se tomó de WEB UPD8 donde también podemos encontrar cómo instalar de forma manual la versión 7 de Java de Oracle (antes Sun).

Bueno pues manos a la obra: tenemos que agregar el repositorio ppa:ferramroberto/java para después instalar los paquetes de Java que nos servirán para remplazar a OpenJDK, podemos hacerlo desde consola con el siguiente comando:

sudo add-apt-repository ppa:ferramroberto/java

Después, tenemos que actualizar la información de los repositorios con:


sudo apt-get update

Y por último instalar los paquetes con:

sudo apt-get install sun-java6-jdk sun-java6-plugin

O si ya tenemos agregado el repositorio, la instalación de los paquetes también se pueden hacer desde el Centro de Software de Ubuntu como se muestra en la siguiente imagen:


Una vez que ya tenemos instalado el paquete si procedemos a ejecutar desde la terminal:

java -version

Nos daremos cuenta que nos indica que aún estamos utilizando la versión OpenJDK como se muestra en la siguiente figura:


Por lo que tenemos que ejecutar la siguiente instrucción para especificar que queremos utilizar la versión de Java 6 de Oracle:

sudo update-alternatives --config java

Con lo que nos mostrará un menú con las opciones que existen, es ahí donde seleccionamos el cambio, en mi ejemplo seleccioné el número 2:



Una vez efectuado el cambio, si ejecutamos nuevamente la instrucción:

java -version

Nos mostrará que ya estamos ejecutando la nueva selección como se muestra:


Para finalizar tenemos que agregar la variable $JAVA_HOME al PATH para que en cualquier directorio donde nos encontremos podamos compilar los programas con javac, por lo que tenemos que editar el siguiente archivo:

sudo gedit /etc/bash.bashrc

Y agregar al final del archivo las siguientes líneas:

export JAVA_HOME=/usr/lib/jvm/java-6-sun
export PATH=$PATH:$JAVA_HOME/bin

Para que la variable $JAVA_HOME se refleje sin tener que reiniciar el equipo tenemos que ejecutar lo siguiente:

source /etc/bash.bashrc

Con eso podemos comprobar que la variable ya cuenta con la información de la ruta donde se encuentran los programas de Java:

echo $JAVA_HOME

Bueno, por hoy es todo y espero que sea de utilidad para que nos iniciemos a programar con Java desde nuestro Ubuntu.

Error antes de terminar de instalar Ubuntu

Resulta que en la última actualización que hice de Ubuntu para pasar de la versión 11.04 a la 11.10 "Oneiric Ocelot" no finalizó correctamente y sólo faltaba el último paso de la instalación por lo que tuve que reiniciar el equipo :(

Al reiniciar se quedaba bloqueado en la pantalla de inicio, al presionar la tecla "ESC"ape y ver los mensajes de la consola vi que los mensajes decían OK todos pero que estaba en espera de algo y no terminaba.

Me propuse reiniciar 3 o 4 veces e igual y antes de reinstalar todo me percate que mandaba un error que decía:
Warning: Fake initctl called, doind nothing.

Por lo que decidí buscar un poco en la red y me encontré con esta buena solución que puso StellionCR en su blog y que ahora describo:

Reiniciar con el CD de instalación en modo Live!, abrimos el navegador de archivos y buscamos nuestra partición del disco duro donde instalamos Ubuntu.

Nos dirigimos a la carpeta / para después entrar al directorio sbin, dentro del directorio buscar el archivo initctl (aparecerán 2) initctl y initctl.REAL lo que hice, basándome en las instrucciones de StellionCR, es:

Renombrar el initctl por initctl.FAKE y renombrar el initctl.REAL por initctl  dejando una copia del initctl.REAL como se ve en la imagen de abajo.



Dese terminar para hacer una copia con otro nombre del archivo sería con el comando:

cp initctl.REAL initctl

Después de éso solo hay que reiniciar y listo! :)

Sólo pensamientos...

Pues sí, esta entrada no tiene que ver con programación ni nada por el estilo. No están para saberlo pero una de mis pasiones ocultas de vez en cuando es escribir (hago como que escribo para cantarlas) y a veces solamente escribo, no creo poner algo completo de lo que tengo porque será la primera vez que me anime a mostrarlo abiertamente, será por falta de confianza?, por temor a la crítica? no sé pero será la primera vez, a lo mejor la edad para mostrar eso ya esta llegando ja!...


DESEÁNDOTE JUNTO A MI (16-06-95)


Desperté deseándote junto a mi.
Desperté queriendo estar frente a ti.
Desperté queriendo ver tus ojos verdes.
Desperté deseando rozar tu piel.
Desperté queriendo besar tus labios.
Y escuchar que tu me quieres también...


EXTRAÑANDO (No recuerdo la fecha)


Hoy que no estas junto a mí
Toco mi guitarra y me pongo a escribir
Esta melodía que hago solo para ti
Para decirte que sin ti no puedo vivir.


No se, porque las cosas pasan sin saber porqué.
Tú me haces falta y no quisiera perderte.
Pero comprendo que nada es para siempre...


Sólo pensamientos (Sin fecha)


El silencio y mis sueños se mezclaron.
Pero al final apareciste tu y tu mirada.
El silencio se comió mis pensamientos,
Y en mis pensamientos te escuche.


Y después de de ello el silencio arrastro mis sueños e
Ilusiones detrás de tu mirada.

(5 de Marzo de 2003)

Nuevamente comienzo,
Es estar solo,
Aunque no todo es totalmente incorrecto,
Esta vez me encontraré.


En la búsqueda de lo incierto,
Nuevamente no lo hallé,
No bastó ni lancha, ni jet,
No seré superman otra vez.

Lo hubiese dado todo,
Si estuvieras decidida,
Yo lo hubiese descifrado,
Si lo hubieras intentado.

Si lo quisieras,
Otra rola cantaría,
No hay problema en intentar,
El problema es el temer.

Bueno, por hoy será todo, creo que puse muchas cosas y a veces eso es demasiado para compartir pero seguiré poniendo lo que tengo a medida que sea posible. Nos seguimos leyendo!

El Che poeta entre poetas!

Leyendo el libro: "CHE XXX VIVO" de Leopoldo Ayala de la Ed. Pablo de la Torriente en la página 55 me encuentro con una gran historia que me gustaría compartir, el título se llama Poeta entre poetas y cuenta la historia de cuando el poeta mexicano José Tiquet conoció al Che y dice así:


- Entonces yo no tenía interés en la política y menos en la ideología, no era el "ideologista" que soy ahora; pero con Ernesto había que hablar de política y de cuestiones ideológicas, sus conversaciones siempre caían en ese campo, aunque comenzáramos platicando sobre poesía. Mi interés era la poesía en sí misma, se lo hacía saber y él me reprochó que yo hablara solamente de la luna, del paisaje, del amor, desentendiéndome de todo lo demás que había en la vida. Me lo dijo con todas sus letras: "Che, ¿y el hombre?, ¿dónde está el hombre en tu poesía?; como poeta no olvides nunca al hombre de tu pueblo, es muy importante que en una obra de arte camine el hombre como en su propia casa, para eso es el arte", me reclamaba Ernesto. "El tenía una visión más amplia de carácter social, una formación sólida y a mi me impresionó muchísimo acabado de conocerlo", cuenta Tiquet y agrega sobre una de las primeras conversaciones suyas con el doctor Ernesto Guevara:

"Ernesto era un hombre muy educado, tierno, aunque no lo aparentara; era un poeta, conocía todas las reglas de la poesía, pero para él había que conocer al hombre profundamente para hacer poesía que valiera la pena."- 

Se los comparto para reflexionar y seguir divulgando las buenas ideas... hasta pronto!

Programando en lenguaje C sin conio.h

Después de un tiempo de no escribir regreso y es para comentar qué podemos hacer cuando estamos programando en C o C++ y no tenemos la biblioteca conio.h, la cuál contiene funciones muy útiles como la de gotoxy ( int x, int y ); que es una función que sirve para posicionar la salida en pantalla de los programas que se ejecutan desde la terminal (Linux) o consola (Windows).

Antes que nada comentar que conio.h es una biblioteca propietaria de la extinta Borland ( ahora Embarcadero Technologies ) por lo que cuando no utilizamos su compilador no vamos a encontrarla y nuestros programas no se podrán compilar, es por ello que buscando un poco en la red encontré estas dos formas de implementar la función gotoxy ( int x, int y ); y así no depender de una biblioteca propietaria.

Veamos el primer ejemplo el cual será ejecutado en Linux y mostrará en pantalla lo siguiente:



El código quedaría de la siguiente forma:

#include 
#include 

void gotoxy ( int x, int y );

int main(int argc, char **argv)
{
 int i;
 system("clear");
 for( i = 1; i <= 5; i++ )
 {
  gotoxy( i, 1 ); printf("*");
  gotoxy( i, 5 ); printf("*");
 }
 for( i = 2; i <= 5; i++ )
 {
  gotoxy( 5, i ); printf("*");
  gotoxy( 1, i ); printf("*");
 }
 return 0;
}

/* Implementación de la función */
void gotoxy ( int x, int y )
{
  printf("%c[%d;%df", 0x1B, y, x);
}

Para la ejecución de ese mismo programa en la consola de Windows la función gotoxy ( int x, int y ); quedaría de la siguiente forma:

void gotoxy ( int x, int y )
{
 COORD coord;
 coord.X=x;
 coord.Y=y;
 SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), coord );
}

Programando el Demo1 con Glade, GTK y C++

Nuestro primer programa Demo1 será una ventana que contendrá 2 botones y una etiqueta, cuando el usuario presione el botón 1 aparecerá en la etiqueta el texto “Botón1 – Clicked” y cuando el usuario presione el botón 2 aparecerá en la etiqueta el texto “Botón2 – Clicked”, en la Imagen 1 podemos ver el resultado que obtendremos.

Imagen 1

Iniciaremos nuestro Demo1 creando la interfaz de usuario con la ayuda de Glade, al iniciar Glade nos mostrara una ventana de preferencias como la que vemos en la Imagen 2.

Imagen 2

Si queremos que nuestro programa sea mas compatible con la mayoría de los sistemas operativos anteriores podemos seleccionar la versión 2.14 de GTK+ aunque desde Ubuntu 10.04 seguramente ya se cuenta con la versión 2.16, otra cosa que debemos notar es que debe estar seleccionada la opción GtkBuilder que será la forma en que crearemos las referencias a los objetos desde nuestro código.


Una vez que se cierre esa ventana podremos iniciar nuestro programa y agregaremos nuestro primer Widget al editor visual y será una ventana de nivel superior (Imagen 3), como se observa en la parte derecha aparecerá el nombre del Widget “window1”.

Imagen 3


Luego agregaremos el GtkVBox (caja vertical) a “window1”, ese Widget nos servirá para organizar la forma en que podremos agregar mas componentes a nuestra ventana (Imagen 4), escribiremos que dividiremos en 2 la ventana principal, en la parte de arriba agregaremos un Label.

Imagen 4

En la parte de abajo agregaremos un Widget “GtkHButtonBox” y pondremos que vamos a trabajar con 2 elementos (Imagen 5). 
Imagen 5


Una vez hecho el paso anterior podremos modificar algunas propiedades de la caja de botones horizontal como se muestra en la Imagen 6.

Imagen 6




Y después agregaremos los dos botones correspondientes a la caja hbuttonbox1 y después cambiaremos el nombre a mostrar en cada botón como se muestra en la Imagen 7.


Imagen 7


Como se puede observar, la etiqueta a mostrar tiene el texto “_Boton1” y en la parte de abajo se cambio la opción: Utilizar subrayado a “Si”, lo anterior, con la finalidad de que al momento de presionar la tecla ALT se resalte la letra B para simular la acción click del ratón sobre el botón 1. De la misma forma, se cambiará la propiedad del botón 2 cambiándole el nombre a “B_otón2” y poniendo la opción de Utilizar subrayado a “Si”.

Por último, vamos a mencionar lo que son las señales, las señales son las funciones que se lanzan cuando se hace alguna acción sobre un Widget, como queremos que cuando se presione la X de la ventana principal se termine el programa, entonces tenemos que seleccionar el Widget “window1” y nos vamos a la pestaña de señales y seleccionamos “GtkObject” y después “destroy” para que seleccionemos de la columna “Manipulador” la opción “on_window1_destroy”. (Imagen 8)

Imagen 8

De la misma forma vamos a crear una señal para el botón 1 como se muestra en la Imagen 9.

Imagen 9

Guardamos nuestro archivo Glade como “demo1.glade” en el directorio donde vamos a trabajar con nuestro archivo de código C++.

Para editar el código C++ estoy utilizando Geany (Imagen 10) ya que me pareció un editor liviano que no consume muchos recursos y funcional, además de que tiene soporte para otros lenguajes de programación.

Imagen 10

Iniciaremos nuestro código "main.c" mencionando que tenemos que incluir la biblioteca "gtk.h" y para manipular los Widgets diseñados en Glade utilizaremos un tipo de dato estructurado llamado Demo1, para ello utilizaré la palabra reservada struct, veamos el inicio de nuestro programa:


/* Se importa la biblioteca gtk.h */
#include 

/* Definimos la constante con el nombre del archivo creado en Glade */
#define FILEGLADE "demo1.glade"

/* Estructura para almacenar los widgets las cual se necesita para manipularlos */
typedef struct
{
GtkWidget       *window;
GtkWidget       *boton1;
GtkWidget       *boton2;
GtkWidget       *label1;
} Demo1;

/* Declaración de las cabeceras de las funciones necesarias */

/* Función que se ejecuta cuando se lanza la señal 'click' del boton2 */
void on_click_boton2(GtkWidget *widget, Demo1 *demo);

/* El nombre de esta función se puso en la pestaña de Señales en Glade
* y se enlaza automáticamente a nuestro código */
void on_button1_clicked(GtkWidget *widget, Demo1 *demo);

/* Función que se ejecuta cuando se cierra la ventana principal */
void on_window1_destroy (GtkObject *object, gpointer user_data);

void error_message (const gchar *message); 

A continuación veremos la función principal "main()" en donde crean las variables Demo1 *demo; y GtkBuilder *builder; dichas variables nos servirán para construir los objetos de la interfaz de usuario y para almacenar en la estructura las referencias a dichos objetos para poder manipularlos.

int main (int argc, char *argv[])
{
/* Declaramos las variables a utilizar */
Demo1       *demo;
GtkBuilder  *builder;
GError      *err=NULL;

/* Localidad de memoria utilizada para la estructura Tutorial */
demo = g_slice_new (Demo1);

gtk_init (&argc, &argv);

/* Creación del constructor (builder) para después crear los widgets a partir del archivo XML
* creado desde glade */
builder = gtk_builder_new ();
if ( gtk_builder_add_from_file (builder, FILEGLADE, &err) == 0 )
{
error_message (err->message);
g_error_free (err);
return (1);
}

/* Obtener las referencias a los Widgets para almacenarlos en la estructura y poder manipularlos */
/* Primero obtenemos la referencia a la ventana principal */
demo->window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
/* Primero obtenemos la referencia a los botones */
demo->boton1 = GTK_WIDGET (gtk_builder_get_object (builder, "button1"));
demo->boton2 = GTK_WIDGET (gtk_builder_get_object (builder, "button2"));
/* Obtenemos la referencia a la etiqueta */
demo->label1 = GTK_WIDGET (gtk_builder_get_object (builder, "label1"));

/* Se conectan las señales generadas por los objetos desde el builder con los widgets de la estructura */
gtk_builder_connect_signals (builder, demo);

/* Liberar memoria utilizada por el objeto GtkBuilder */
g_object_unref (G_OBJECT (builder));

gtk_widget_show (demo->window);

/* La otra forma de conectar a las señales directamente desde el código sin utilizar glade */
g_signal_connect(demo->boton2, "clicked", G_CALLBACK(on_click_boton2), demo);

gtk_main ();

/* Libera la memoria reservada para la estructura Demo1 */
g_slice_free (Demo1, demo);

return 0;
} 

El desarrollo de las funciones esta documentado sobre el mismo código que se pega a continuación:

/*
* Cuando el usuario presiona la X se ejecuta la opción gtk_main_quit()
* para salir de la función principal y terminar la aplicación.
*/ 
void on_window1_destroy (GtkObject *object, gpointer user_data)
{
/* Termina el ciclo gtk_main() */
gtk_main_quit ();
}

/*
* Señal que se ejecuta cuando el usuario dá click sobre el boton1
*/
void on_button1_clicked (GtkWidget *widget, Demo1 *demo)
{
/* función que agrega un texto a una etiqueta */
gtk_label_set_text(GTK_LABEL(demo->label1), "Botón 1 - Clicked");
}

/*
* Señal que se ejecuta cuando el usuario dá click sobre el boton2
*/ 
void on_click_boton2(GtkWidget *widget, Demo1 *demo)
{
/* función que agrega un texto a una etiqueta */
gtk_label_set_text(GTK_LABEL(demo->label1), "Botón 2 - Clicked");
}

/*
* Se llama error_message() cada vez que queremos mostrar un mensaje de error al usuario.
* Esto mostrará el mensaje de error en una ventana modal y también en la ventana de la terminal.
*/
void error_message (const gchar *message)
{
GtkWidget               *dialog;

/* Muestra el mensaje en la ventana (terminal) de comandos */
g_warning ("%s",message);

/* Crea un dialogo de mensaje de error y lo despliega de forma modal */
dialog = gtk_message_dialog_new (NULL, 
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",message);

gtk_window_set_title (GTK_WINDOW (dialog), "Error!");
gtk_dialog_run (GTK_DIALOG (dialog));      
gtk_widget_destroy (dialog);         
} 

Para finalizar les dejo la liga para descargar el código completo de la aplicación, recuerden compilarlo con la siguiente instrucción:


Compilar "main.c" usando el siguiente comando (Imagen 11):
  gcc -Wall -g -o demo1 main.c `pkg-config --cflags --libs gtk+-2.0` -export-dynamic

Imagen 11


Después ejecutar (Imagen 12):
  ./demo1


Cómo programar para GNU&Linux Gnome

Para el desarrollo de nuestro primer programa necesitaremos instalar Glade (Se encuentra en los repositorios de Ubuntu así que no tendremos problemas al querer instalarlo desde el Centro de Software. ver Imagen 1). Glade (Imagen 2) es una herramienta RAD (Desarrollo Rápido de Aplicaciones) visual para el modelado de interfases gráficas de usuario. Glade es independiente del lenguaje ya que no genera código fuente en ningún lenguaje en particular si no que se obtiene un archivo XML que puede ser importado (buscar GtkBuilder) y leído desde cualquier lenguaje compatible con GTK+ (Java, Python, C++, PHP, Ruby, por mencionar algunos).

Imagen 1

Imagen 2

Recomiendo instalar Devhelp ya que ahí encontraremos toda la información de la API (Interfase de Programación de Aplicaciones) GTK+.

También será necesario instalar “Archivos de desarrollo para libgklade2-dev” y si prefieres programar con Python también “python-gtk2-dev”.

GTK+ es una biblioteca de funciones para crear interfaces gráficas de usuario. Es funcional para muchas plataformas “UNIX-Like” y Windows. GTK+ tiene una arquitectura orientada a objetos basada en C que permite una máxima flexibilidad. GTK+ depende de las bibliotecas GLib, Pango, ATK, GdkPixbuf, GDK y GTK+.

En la siguiente entrada iniciaremos el desarrollo de nuestro primer programa Demo1.

Temas para fondos de escritorio en Ubuntu 10.04 y 10.10

Decidí iniciar un blog una vez que ya tengo un poco de material para dar a conocer y contribuir un poco con la comunidad desarrolladora de GNU&Linux, resulta que desde hace ya algunos años quería cambiarme del Sistema Operativo (SO) de las ventanas a GNU&Linux y por una u otra razón nunca hacía el cambio total, pero desde Septiembre del año pasado (2010) tomé esa decisión y no hubo vuelta atrás, me decidí por Ubuntu 10.04 y al poco tiempo cambié al 10.10 y en una siguiente entrada les comentaré más sobre la experiencia de cambio pero les puedo adelantar que no he regresado a las ventanas ni para tomar aire ni impulso ya que todo lo he encontrado en GNU&Linux.

El motivo de esta primera entrada es comentarles que encontré muy llamativa la opción que trae Ubuntu de poder seleccionar un grupo de imágenes (les llamé temas) como fondo de escritorio y que éstas se cambien automáticamente a medida que pasan algunos minutos, por default Ubuntu trae el grupo de imágenes del Cosmos (ver Captura 1) y las imágenes cambian cada 29 minutos con 5 segundos y se efectúa el cambio en los siguientes 5 segundos.

Captura 1

Debido a que me gustó esa opción de poder tener un grupo de imágenes me tomé la tarea de buscar un poco en Internet de cómo podría hacer mi propio tema de fondos de escritorio y encontré que si selecciono el tema de Cosmos y lo arrastro al escritorio (Captura 2) podría ver un archivo con formato XML (Archivo 1).

Captura 2

Información contenida en background-1.xml

  
    2009
    08
    04
    00
    00
    00
  

  
    1795.0
    /usr/share/backgrounds/cosmos/cloud.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/cloud.jpg
    /usr/share/backgrounds/cosmos/comet.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/comet.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/comet.jpg
    /usr/share/backgrounds/cosmos/earth-horizon.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/earth-horizon.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/earth-horizon.jpg
    /usr/share/backgrounds/cosmos/blue-marble-west.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/blue-marble-west.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/blue-marble-west.jpg
    /usr/share/backgrounds/cosmos/galaxy-ngc3370.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/galaxy-ngc3370.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/galaxy-ngc3370.jpg
    /usr/share/backgrounds/cosmos/helix-nebula.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/helix-nebula.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/helix-nebula.jpg
    /usr/share/backgrounds/cosmos/jupiter.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/jupiter.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/jupiter.jpg
    /usr/share/backgrounds/cosmos/sombrero.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/sombrero.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/sombrero.jpg
    /usr/share/backgrounds/cosmos/whirlpool.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/whirlpool.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/whirlpool.jpg
    /usr/share/backgrounds/cosmos/cloud.jpg
  

Archivo 1

Al analizar un poco el archivo me dí cuenta que podría cambiar la ruta de las imágenes (<file>/usr/share/backgrounds/cosmos/whirlpool.jpg</file>) que yo quiero agregar al nuevo tema y también podría cambiar el tiempo en que se presentan estáticas en la pantalla (
<static>
    <duration>1795.0</duration>
) y el tiempo en que se cambian (
<transition>
    <duration>5.0</duration>
) pero ese trámite es un poco engorroso para aquellos que no queremos editar algún archivo siguiendo algún formato por lo que me decidí a desarrollar un programa gráfico (le llamo MyImageDesktop ver Captura 3) que nos ayude a seleccionar las imágenes que queremos agregar a un tema y además que me permita seleccionar el tiempo que me gustaría que permanezca en la pantalla antes de cambiarla por la siguiente y así contribuir un poco con la comunidad para enriquecer este SO.

Captura 3

MyImageDesktop está en la primera parte (v0.2) después de efectuar algunas pruebas, podemos agregar imágenes seleccionando el botón "Añadir" o bien seleccionando del menú "Editar" la opción "Agregar". Con eso nos presentará una ventana (Captura 4) donde podemos seleccionar el archivo JPG o PNG (por el momento solo JPG pero pronto agregaré los PNG) y podemos ver una vista previa en la parte de la derecha de la esa ventana. 

Captura 4

También podemos cambiar el tiempo en segundos en que la imagen permanecerá estática hasta que se cambie a la siguiente y podemos guardar nuestro archivo en cualquier lugar que queramos con el nombre que nos guste pero con terminación xml, para después arrastrar el archivo creado a las preferencias de la pantalla en la pestaña de Fondos de escritorio.

En la segunda versión de MyImageDesktop nuestro amigo Heladio nos agregó la funcionalidad de "Subir" y "Bajar" una fila de la lista de archivos con la finalidad de ordenar nuestros archivos a nuestro gusto :)

Por el momento es todo, les dejo los archivos necesarios para ejecutar MyImageDesktop. Para ejecutarlo debes descargar el archivo correspondiente a tu tipo de SO y descargar también el archivo MyImageDesktop.glade y colocarlos en el mismo directorio para después ejecutar desde una ventana (terminal) de comandos en el directorio donde se encuentran los archivos la instrucción ./MyImageDesktop

Ejecutable Ubuntu_x86 y Ubuntu_amd64
Fuente en lenguaje C

Error al compilar en Android Studio 4.0: CIRCULAR REFERENCE:com.android.tools.r8.a: Invoke-customs are only supported starting with Android O

Resulta que estuviste construyendo tu APP desde Android Studio 4.0 y no te marcó ningún tipo de error de codificación pero al querer compila...