Gnome: Desarrollo de aplicaciones. La aplicación
Gnome: Desarrollo de aplicaciones. Estructura de ficherosVamos a comenzar a construir el core de esta aplicación y al final de este artículo deberíamos poder compilar y ejecutar nuestra aplicación que nos debería mostrar una ventana con un mensaje de texto.
No hay un orden específico para configurar los ficheros, si has usado Builder de Gnome le habrás dado un nombre al proyecto y un id y te habrá generado todos estos ficheros. Cada fichero tiene su función dentro de la estructura de la aplicación.
Los ids de aplicaciones para Gnome llevan un formato de dominio invertido. Esto es para poder identificar de forma unívoca la app. En nuestro caso vamos a usar io.github.agustingv.example. (Si se tiene alojado el código en github y se quiere usar el dominio de github como parte del id de la aplicación hay que usar io en vez de com para que flatpak no lo rechace)
meson.build
Nuestro principal fichero de construcción en el vamos a definir como se va a compilar el proyecto, los argumentos de compilación y los subdirectorios que tiene que mirar. En cada subdirectorio que definamos debería existir otro fichero meson.build que defina las reglas, como las posibles dependencias, que necesita para realizar la construcción de la aplicación.
En este ejemplo solo accedemos a una propiedad definida en project que es meson.project_name()
project('example', 'vala', 'c',
version: '1.0',
meson_version: '>= 0.59.0',
default_options: [
'buildtype=debug',
'warning_level=2',
'default_library=static'
],
)
gnome = import('gnome')
i18n = import('i18n')
example_name = meson.project_name()
add_project_arguments(
['-DGETTEXT_PACKAGE="' + example_name + '"',
'-w'],
language: 'c',
)
subdir('data')
if find_program('msgfmt', required: false).found()
subdir('po')
endif
subdir('src')src/config.vala.in
Como ya hemos comentado en un artículo anterior, Vala genera código C que luego se compila y para las constantes de configuración vala necesita generar las instrucciones de preprocesador de C. Hay dos formas de realizar esto. Creando un VAPI o creando un namespace en Vala e indicando en el meson.build la definición de las constantes. En este caso, para simplificar las cosas vamos a usar el namespace.
namespace Config {
public const string GETTEXT_PACKAGE = "@GETTEXT_PACKAGE@";
public const string LOCALE_DIR = "@LOCALE_DIR@";
}data/ui/main-window.ui
Los ficheros ui contienen el xml que define la interfaz de usuario, en los xml se hace referencia a los objetos definidos por Gtk o propios de la aplicación.
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ExampleMainWindow" parent="AdwApplicationWindow">
<property name="title" translatable="yes">Example Application</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child>
<object class="GtkLabel" id="label">
<property name="label" translatable="yes">Hello</property>
</object>
</child>
</template>
</interface>
data/io.github.agustingv.example.gresource.xmlEste fichero registra los recursos de ui de la aplicación. En este caso solo tenemos data/ui/main-window.ui.
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/io/github/agustingv/example">
<file preprocess="xml-stripblanks">ui/main-window.ui</file>
</gresource>
</gresources>src/meson.build
Build de meson (ubicación de ficheros y dependencias) para el directorio src.
resources = gnome.compile_resources(
'example-resources',
'../data/io.github.agustingv.example.gresource.xml',
source_dir: '../data',
c_name: 'example',
)
config_vala = configure_file(
input: 'config.vala.in',
output: 'config.vala',
configuration: {
'GETTEXT_PACKAGE': meson.project_name(),
'LOCALE_DIR': get_option('prefix') / get_option('localedir'),
},
)
sources = files(
'main.vala',
'application.vala',
'main-window.vala'
) + [config_vala]
dependencies = [
dependency('gtk4'),
dependency('libadwaita-1', version: '>= 1.4'),
dependency('gmodule-2.0'),
meson.get_compiler('c').find_library('m', required: false),
]
executable('example',
sources + resources,
dependencies: dependencies,
vala_args: ['--target-glib=2.76', '--pkg=gmodule-2.0'],
install: true,
)src/main.vala
Archivo principal que se encarga de iniciar la aplicación. Se puede usar cualquier nombre de fichero para esto ya que es el propio código el que se define como main (Recordemos que esto se ejecuta como código C y en C la función main es la que inicia el programa)
int main (string[] args) {
GLib.Intl.setlocale (LocaleCategory.ALL, "");
GLib.Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALE_DIR);
GLib.Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8");
GLib.Intl.textdomain (Config.GETTEXT_PACKAGE);
var app = new Example.Application ();
return app.run (args);
}src/application.vala
Este va a ser nuestro archivo principal donde se define el comportamiento de nuestra aplicación y su ciclo de vida.
| Ciclo | Descripción |
|---|---|
| startup | Se ejecuta al arrancar la Adw.Application llama automáticamente a adw_init() en esta fase. Carga las hojas de estilos CSS personalizadas y define los atajos globales. |
| activate | Se dispara cuando la aplicación es lanzada o se invoca una nueva instancia sin argumentos principales. Es el momento adecuado para crear la ventana principal, asignarle contenido y llamar al método para mostrarla. |
| open | Se ejecuta si la aplicación se invoca desde la línea de comandos pasando archivos o parámetros para abrir directamente. |
| shutdown | Ocurre cuando la última ventana se cierra y la aplicación se dispone a salir del bucle principal. Momento para liberar recursos o guardar estados persistentes si no se hizo de forma automática. |
namespace Example
{
public class Application : Adw.Application
{
public Application ()
{
Object (
application_id: "io.github.agustingv.example",
flags: ApplicationFlags.DEFAULT_FLAGS
);
}
construct
{
}
protected override void activate ()
{
var win = this.active_window;
if (win == null) {
win = new Example.MainWindow (this);
}
win.present ();
}
}
}src/main-window.vala
Definición de la ventana principal
namespace Example {
[GtkTemplate (ui = "/io/github/agustingv/example/ui/main-window.ui")]
public class MainWindow : Adw.ApplicationWindow {
public MainWindow (Gtk.Application app) {
Object (application: app);
}
construct
{
}
}
}data/io.github.agustingv.example.desktop.in
Definición de nombre de la aplicación y icono para el escritorio y dock
[Desktop Entry]
Name=Example
Exec=Example
Icon=io.github.agustingv.example
Terminal=false
Type=Application
Categories=Utility;
Keywords=GTK;
StartupNotify=true
DBusActivatable=truedata/io.github.agustingv.example.gschema.xml
Este es fichero que va a tener la estructura de la configuración de nuestra aplicación que se puede almacenar, modificar y recuperar. En un principio no vamos a necesitar ninguna configuración pero aquí se podría definir, por ejemplo, la geometría de la ventana. Las configuraciones de una aplicación instalada se suelen almacenar en .local/share. Depende si usas flatpak o no estará en una ruta u otra dentro de .local/share.
<?xml version="1.0" encoding="UTF-8"?>
<schemalist gettext-domain="example">
<schema id="io.github.agustingv.example" path="/io/github/agustingv/example/">
</schema>
</schemalist>data/io.github.agustingv.example.metainfo.xml.in
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>io.github.agustingv.example</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<name>Example</name>
<summary>Keep the summary shorter, between 10 and 35 characters</summary>
<description>
<p>No description</p>
</description>
<developer id="tld.vendor">
<name>Developer name</name>
</developer>
<!-- Required: Should be a link to the upstream homepage for the component -->
<url type="homepage">https://example.org/</url>
<!-- Recommended: It is highly recommended for open-source projects to display the source code repository -->
<url type="vcs-browser">https://example.org/repository</url>
<!-- Should point to the software's bug tracking system, for users to report new bugs -->
<url type="bugtracker">https://example.org/issues</url>
<!-- Should link a FAQ page for this software, to answer some of the most-asked questions in detail -->
<!-- URLs of this type should point to a webpage where users can submit or modify translations of the upstream project -->
<url type="translate">https://example.org/translate</url>
<url type="faq">https://example.org/faq</url>
<!-- Should provide a web link to an online user's reference, a software manual or help page -->
<url type="help">https://example.org/help</url>
<!-- URLs of this type should point to a webpage showing information on how to donate to the described software project -->
<url type="donation">https://example.org/donate</url>
<!-- This could for example be an HTTPS URL to an online form or a page describing how to contact the developer -->
<url type="contact">https://example.org/contact</url>
<!-- URLs of this type should point to a webpage showing information on how to contribute to the described software project -->
<url type="contribute">https://example.org/contribute</url>
<translation type="gettext">example</translation>
<!-- All graphical applications having a desktop file must have this tag in the MetaInfo.
If this is present, appstreamcli compose will pull icons, keywords and categories from the desktop file. -->
<launchable type="desktop-id">io.github.agustingv.example.desktop</launchable>
<!-- Use the OARS website (https://hughsie.github.io/oars/generate.html) to generate these and make sure to use oars-1.1 -->
<content_rating type="oars-1.1" />
<!-- Applications should set a brand color in both light and dark variants like so -->
<branding>
<color type="primary" scheme_preference="light">#ff00ff</color>
<color type="primary" scheme_preference="dark">#993d3d</color>
</branding>
<screenshots>
<screenshot type="default">
<image>https://example.org/example1.png</image>
<caption>A caption</caption>
</screenshot>
<screenshot>
<image>https://example.org/example2.png</image>
<caption>A caption</caption>
</screenshot>
</screenshots>
<releases>
<release version="1.0.1" date="2024-01-18">
<url type="details">https://example.org/changelog.html#version_1.0.1</url>
<description translate="no">
<p>Release description</p>
<ul>
<li>List of changes</li>
<li>List of changes</li>
</ul>
</description>
</release>
</releases>
</component>data/io.github.agustingv.example.service.in
Definición del D-Bus para la comunicación de la aplicación. El D-bus se usa para comunicación entre aplicaciones, servicios y el entorno de escritorio. Por ejemplo; las notificaciones que muestran que te ha llegado un mail nuevo o que alguien te ha escrito un mensaje por slack se realizan a través del D-bus.
[D-BUS Service]
Name=io.github.agustingv.example
Exec=@bindir@/example --gapplication-service
po/LINGUAS
En este fichero se definen los lenguajes de uso de nuestra aplicació.
es
po/POTFILES
Ficheros que llevan textos traducidos. Todos los ficheros que usen gettext para traducir un texto deben ir definidos aquí.
data/ui/main-window.ui
po/es.po
Fichero de traducciones.
# UI strings — main window
msgid "Helo, my first Gnome app"
msgstr "Hola, mi primera app para Gnome"
po/meson.build
Poco más que definir el uso de la internacionalización.
i18n.gettext(meson.project_name(),
preset: 'glib',
)Compilar y ejecutar la aplicación.
Generar los ficheros en C y los guiones de compilación para ninja:
meson setup build
Compilar el proyecto con ninja:
ninja -C ./build
Ejecutar el proyecto:
./build/src/example[articulo slug="gnome-desarrollo-de-aplicaciones-menus-y-handlers"]
Artículos recientes
Artículo
Gnome: Desarrollo de aplicaciones. Pango
04/09/2026
Artículo
Gnome: Desarrollo de aplicaciones. VAPI
03/09/2026
Artículo
Gnome: Desarrollo de aplicaciones. MVVM
15/08/2026
Artículo
Gnome: Desarrollo de aplicaciones. Construyendo una nueva aplicación
10/08/2026
Artículo
Linux: Guía de iniciación a Linux
08/08/2026
Noticia
Wayland
08/08/2026