Documentos de Académico
Documentos de Profesional
Documentos de Cultura
TFG DavidMorenoAntón
TFG DavidMorenoAntón
Director
Javier Urricelqui Polvorinos
A mis compañeros del grupo por hacerme amenas todas las mañanas con esas llamadas
para almorzar. Espero seguir compartiendo más momentos junto a vosotros.
I
Ubuntu. La comunicación entre el ordenador y el equipo interrogador se realiza por
conexión serie.
II
Índice general
Resumen ........................................................................................................................... 1
1.2.2. Python....................................................................................................... 11
1.3.2. Netbeans................................................................................................... 16
1.4.1. GTK+.......................................................................................................... 17
C. Programación ............................................................................................................. 81
IV
Capítulo 0
Introducción al trabajo fin de grado
Motivación del trabajo
1
determinados protocolos de seguridad, protegiendo de esta manera la integridad de la
estructura y de su entorno.
El objetivo general de este trabajo fin de grado es el diseño y desarrollo de una aplicación
basada en sistemas Linux para el correcto funcionamiento de los equipos interrogadores
desarrollados por el grupo de investigación de la Universidad Pública de Navarra y
explotados por la empresa Uptech Sensing. Dicha aplicación se basa en un interfaz
gráfico de usuario el cual permita el control y manejo presencial de equipos
interrogadores.
En base a estas consideraciones se establecieron unas líneas de trabajo las cuales seguir
para la consecución del objetivo marcado:
2
Estructura de la memoria
Capítulo 1
Capítulo 2
Capítulo 3
Capítulo 4
3
4
Capítulo 1
Introducción al desarrollo del GUI
Antes de entrar en detalle en los siguientes aspectos, hace falta contextualizar y analizar
el proyecto en el que se encuentra el desarrollo de esta aplicación/GUI. El núcleo central
de este trabajo reside en la programación de un interfaz gráfico de usuario (del inglés
Graphical User Interface, GUI). Su principal uso, en un contexto del proceso de interac-
ción persona-computadora, consiste en proporcionar un entorno visual sencillo para
permitir la comunicación con el sistema operativo de una máquina o computadora, en
nuestro caso, el equipo interrogador.
Windows, Mac OS o distribuciones de Linux son los tres sistemas operativos que, en
general, se puede encontrar fácilmente en cualquier ordenador que se encuentre en
ejecución. En este Proyecto Fin de Grado, se ha trabajado con una de las distribuciones
Linux más conocidas por los usuarios. A continuación, se mostrarán las ventajas de Linux
y algunas de las distribuciones más populares.
Uno de los puntos por los que es importante empezar hablando son las diferentes
categorías de software existente. Existen básicamente dos tipos de software:
5
propietario y libre de uso bajo licencia [1]. Parece algo obvio que el software privativo o
software no libre somete a los usuarios al poder de los desarrolladores del software
además de tener que pagar por adquirir licencias de uso. Por el contrario, el movimiento
del software libre es aquel que respeta la libertad de los usuarios y la comunidad. Dicho
software permite que los usuarios ejerzan el control de sus propias tareas de
computación y tienen la libertad de ejecutar, copiar, distribuir, estudiar, modificar y
mejorar el software. Este es uno de los puntos clave para el uso del sistema GNU/Linux.
En dicho sistema, Linux es el núcleo y está modelado como un sistema operativo tipo
Unix [2]. Nadie es dueño de Linux, a diferencia de otros sistemas operativos, con Linux
no hay que preocuparse de comprarlo, puesto que ni habrá que pagar para obtener el
sistema ni para actualizarlo y cuyos desarrolladores se han comprometido a seguir las
pautas para distribuciones de sistemas libres. Esto significa que las distribuciones
incluirán y propondrán exclusivamente software libre rechazando así las aplicaciones,
plataformas de programación, controladores, firmware, juegos y cualquier otro
software que no sea libre. Afortunadamente en Linux además del soporte que pueda
ofrecer el desarrollador de la distribución, contaremos con un soporte técnico
conformado por los diferentes usuarios de plataformas Linux de casi todas las partes del
globo, poniendo en común sus conocimientos y experiencias.
Linux es uno de los sistemas operativos que menos recursos consume [3] y, por tanto,
otorga mayor rendimiento. Además, gracias a la gran comunidad de usuarios dispuestos
a ayudar, las vulnerabilidades son detectadas y corregidas más rápidamente que en
otros sistemas operativos. En el ámbito de la seguridad, es interesante destacar que la
mayoría de los virus tienen como objetivo sistemas Windows y MacOS dada la
popularidad de estos sistemas [4] tal y como vemos en la Figura 1.1 y Figura 1.2.
Figura 1.1: Gráfica SO más utilizados actualmente. Eje X: Año-Mes; Eje Y: Porcentaje.
6
Figura 1.2: Tabla de porcentaje SO más utilizados en la actualidad.
Hay numerosas distribuciones Linux libres [5], de las cuales destacamos las más
conocidas a continuación, ya sea por su estabilidad, seguridad o facilidad de uso.
Ubuntu
Fedora
Debian
7
Kali Linux
Como se observa, existen diversas distribuciones de Linux sobre las que poder trabajar.
En este caso, gracias a la gran popularidad de Ubuntu [6], tal y como se observa en la
Figura 1.3, hemos optado por usar una versión de Ubuntu con soporte a actualizaciones
durante 4 años, concretamente Ubuntu 16.04.03 LTS lanzada en Agosto del año 2017
con soporte hasta Abril del año 2021. Por motivos que se explicarán posteriormente en
el apartado 2.1, la versión de kernel que se instaló fue la 4.4.
8
1.2. Lenguajes de programación
1.2.1. C++
Descripción general
Ventajas e inconvenientes
9
• Potencia: C++ no requiere un tiempo de ejecución especial para su ejecución,
se puede crear cualquier tipo de programa, desde la programación de sistemas
de bajo nivel hasta las GUI complicadas.
• Velocidad: C++ gana mucha velocidad al ser un lenguaje compilado. Los
lenguajes no compilados deben interpretarse en tiempo de ejecución, lo que
significa que cada acción es un proceso de 2 pasos.
10
1.2.2. Python
Descripción general
Ventajas e inconvenientes
11
• Acceso BD y multi-core: Tiene limitaciones con el acceso a la base de datos y no
es bueno para el trabajo multi-procesador/multi-core siendo este un punto muy
a su desfavor en cuanto al tipo de aplicación que necesitamos.
1.2.3. Java
Descripción general
Ventajas e inconvenientes
12
• Facilidad de uso: De entre todos los lenguajes de programación y todos los
métodos para crear aplicaciones, programas de software, páginas webs y demás
elementos digitales, destaca Java como uno de los más sencillos de utilizar y de
los más fáciles de dominar.
• Muy extendido: A su favor hay que decir que es uno de los más extendidos y de
los más conocidos por su plataforma y por sus herramientas y sus ventajas para
los usuarios, los cuales, siendo conscientes o no, lo utilizan mediante contenido
en internet y/o al utilizar ciertas aplicaciones y programas.
13
1.2.4. Selección del lenguaje de programación
14
1.3.1. Eclipse
Eclipse es uno de tantos entornos de desarrollo integrados gratuitos, el cual está basado
en Java y fue desarrollado por IBM. El IDE fue supervisado inicialmente por un consorcio
de proveedores de software que buscaban crear y fomentar una nueva comunidad que
complementara la comunidad de código abierto de Apache.
Hoy en día, Eclipse es administrado por Eclipse Foundation [17], una corporación sin
fines de lucro cuyos miembros estratégicos incluyen CA Technologies, IBM, Oracle y SAP.
La fundación proporciona servicios de administración de infraestructura y propiedad
intelectual (IP) a la comunidad de Eclipse y ayuda a los miembros de la comunidad a
promocionar y comercializar productos de software comercial basados en Eclipse.
Los widgets de Eclipse están implementados por una herramienta para Java llamada
Standard Widget Toolkit, a diferencia de la mayoría de las aplicaciones Java, que usan
las opciones estándar Abstract Window Toolkit (AWT) o Swing. El entorno de desarrollo
integrado de Eclipse emplea módulos para proporcionar toda su funcionalidad al frente
de la plataforma de cliente enriquecido, a diferencia de otros entornos monolíticos
donde las funcionalidades están todas incluidas, las necesite el usuario o no. Hoy en día,
Eclipse es capaz de usar otros lenguajes de programación como son C/C++ y Python, y
trabajar con lenguajes para procesado de texto como LaTeX, aplicaciones en red como
Telnet y Sistema de gestión de base de datos.
Finalmente, se debe mencionar que está diseñado para ejecutarse en múltiples sistemas
operativos, donde los complementos pueden programarse en las API portátiles de
Eclipse y ejecutarse sin cambios en cualquiera de los sistemas operativos admitidos.
15
1.3.2. Netbeans
En principio, una diferencia a tener en cuenta es que NetBeans trae por defecto un edi-
tor visual con el que podrás crear pantallas de una forma muy sencilla e intuitiva y Eclipse
no lo trae (se le puede añadir como plugin) aunque este punto no se tuvo en cuenta ya
que teníamos decidido abarcar este tipo de acción mediante GTK+ y Glade.
En cuanto al soporte no se encontró mucha diferencia entre ambos dado que ambos
cuentan con soporte multiplataforma, así como soporte para múltiples idiomas como
pueden ser C/C++, Java, JavaScript y PHP.
16
Figura 1.5: Entornos de desarrollo integrados
En este punto nos basamos básicamente en gustos. Eclipse en su versión Oxygen fue el
entorno de desarrollo elegido debido a su anterior uso durante el grado y a su facilidad
de uso del SVN local [Apéndice B] además de trabajar con distintas perspectivas, con lo
que puedes tener distintas configuraciones de tu pantalla de trabajo según tu tipo de
proyecto o según la acción que vayas a desarrollar en ese momento (debuggear, sincro-
nizar con SVN, escribir código...). Puedes personalizar cada perspectiva y crear nuevas.
La GUI es un tipo de interfaz de usuario que permite a los usuarios interactuar con
dispositivos electrónicos a través de iconos gráficos e indicadores visuales. Está formado
por imágenes y objetos gráficos, que representan la información y acciones que se
encuentran en la interfaz. Su objetivo es el de crear un entorno visual fácil de usar para
que fluya la comunicación con el sistema operativo.
1.4.1. GTK+
17
GTK+ además de contar con una API fácil de usar, es software libre y parte del Proyecto
GNU. Los términos de la licencia de GTK+ permiten que todos los desarrolladores,
incluso aquellos que desarrollan software propietario, lo utilicen sin ningún tipo de
licencia o royalties.
Widgets
GTK + tiene una colección completa de widgets e interfaces para usar en su aplicación.
Algunos de ellos se destacan a continuación:
18
• Editor de texto multilínea
• Visor de árbol y lista (con representadores personalizables y separación de
modelo/vista)
• Cuadro combinado (con o sin una entrada)
• Menús (con imágenes, botones de radio y elementos de verificación)
• Barras de herramientas (con botones de radio, botones de alternar y botones de
menú)
• GtkBuilder (crea su interfaz de usuario desde XML)
• Selectores (selección de color, selector de archivo, selección de fuente)
• Diseños (widget tabulado, widget de tabla, widget de expansión, marcos,
separadores y más)
• Icono de estado (área de notificación en Linux, icono de bandeja en Windows)
• Documentos utilizados recientemente (menú, diálogo y administrador)
1.4.2. Glade
19
Figura 1.7: Interfaz de Glade.
En la zona superior tenemos una paleta con herramientas típicas como puede ser nuevo
archivo, abrir archivo, guardar, deshacer y rehacer, copiar, cortar, pegar…
La zona principal es la que tenemos en el centro de Glade. En esta zona se irán añadiendo
los widgets que vayamos seleccionando y podremos ir poco a poco viendo cómo vamos
construyendo nuestro interfaz.
20
Capítulo 2
Desarrollo del GUI
Dicho equipo, utiliza la topología BOTDA (Brillouin optical time domain analysis), el cual,
es el sensor distribuido más usado y evolucionado. Las resoluciones espaciales que se
consiguen pueden llegar hasta el centímetro, y las distancias que son capaces de medir
llegan a varias decenas de kilómetros con un solo sensor, obteniendo por ejemplo
50.000 puntos de medida en 50 km con una resolución espacial de 1 m.
21
La onda continua (continuous wave, CW) se propaga con una frecuencia 𝑣𝑆 y los pulsos
ópticos a una frecuencia 𝑣𝑃 tal que la diferencia frecuencial entre ambas ondas sea la
correspondiente al desplazamiento en frecuencia Brillouin de la fibra, 𝑣𝐵 = 𝑣𝑃 − 𝑣𝑆 .
Como consecuencia, la CW será amplificada por SBS con las características del punto de
la fibra donde interaccione con el pulso. La señal BOTDA resultante del aumento en
potencia de la onda continua, se recibirá como función del tiempo tal y como se observa
en la Figura 2.2 Esta función puede traducirse al dominio espacial con la siguiente
fórmula:
𝑐𝑡
𝑧=
2𝑛
22
señal correspondiente a otra frecuencia del espectro en ganancia Brillouin.
Consecuentemente, mediante variaciones de la frecuencia de una de las dos ondas se
puede reconstruir el espectro Brillouin para cada punto de la fibra. El valor de las
magnitudes temperatura y deformación unitaria se encuentra inspeccionando el valor
del desplazamiento del máximo del espectro Brillouin (BFS).
23
Necesidades de configuración y control de los equipos
interrogadores desde el GUI
24
2.2. Descripción de tipos de elementos para el desarrollo de un
GUI
Durante el transcurso del trabajo se han utilizado numerosos widgets de GTK+ para el
diseño y desarrollo de la aplicación. Estos widgets nos dan fácil acceso a funciones
frecuentemente usadas y nos proveen de información visual interesante para nuestra
aplicación. De aquí en adelante nos centraremos es una breve explicación de cada uno
de los elementos utilizados para el desarrollo del software, no sin antes, dar a conocer
la descripción XML generada automáticamente por Glade.
El código base de esta descripción se basa en las siguientes líneas donde queda descrita
la versión XML, la codificación y la librería usada y su versión. Es a partir de aquí donde
Glade va añadiendo los widgets conforme son utilizados.
25
También se tienen diversas propiedades de este objeto que se podrán ir cambiando
como ya se ha explicado anteriormente en Glade.
Dentro de estos objetos se irán añadiendo sin límite diferentes widgets mediante la
etiqueta <child>. Se debe tener en cuenta que ciertos widgets no podrán ser añadidos
dentro de otros, es decir, no podrás añadir una ventana dentro de una etiqueta de texto
como es obvio. Este último apunte es debido a que es posible modificar el archivo XML
a nuestro antojo, pero siempre manteniendo un criterio especifico. La descripción XML
resumida de un par de objetos quedaría de la siguiente manera:
<child>
<object class="GtkBox" id="box3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkToolbar" id="toolbar1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="show_arrow">False</property>
.
.
.
</object>
</child>
</object>
</child>
Como se ha visto, la descripción que nos aporta Glade es sencilla y muy efectiva ante la
compatibilidad de lenguajes de programación. Independientemente del lenguaje en que
se está programando, se permite la comunicación con la descripción XML sin ningún
problema. Este aspecto es de gran ayuda en caso de que en un futuro se quisiera portar
el código de C++ a otro que pudiese ser de mayor interés.
26
2.2.2. Descripción elementos GTK+
GtkApplication
La filosofía de GtkApplication resuelve que a las aplicaciones se les informe qué debe
suceder y cuándo debe suceder en respuesta a las acciones del usuario. Con este fin,
GtkApplication expone un conjunto de señales a las que una aplicación debe responder,
aunque en nuestro caso no se han utilizado todas. Este conjunto de señales son las
siguientes:
• startup: Configura la aplicación cuando comienza por primera vez
• shutdown: Realiza tareas de apagado
• activate: Muestra la primera ventana predeterminada de la aplicación. Esto
corresponde a la aplicación lanzada por el entorno de escritorio.
• open: abre archivos y los muestra en una nueva ventana.
27
En el fichero fuente se han aplicado las funciones correspondientes.
void ApplicationScript::on_startup(){ … }
void ApplicationScript::on_activate(){ … }
GtkBuilder
Un GtkBuilder es un objeto auxiliar que lee las descripciones textuales de una interfaz
de usuario y crea una instancia de los objetos descritos [24]. En el caso de este proyecto,
en el fichero fuente de GtkApplication se procede de la siguiente manera:
m_refBuilder = Gtk::Builder::create();
m_refBuilder->add_from_file("MainWindow/Glade/main.glade");
m_mainWin = nullptr;
m_refBuilder->get_widget_derived("MainWindow", m_mainWin);
add_window(*m_mainWin);
Se ha creado un objeto builder donde cargamos los ficheros Glade de las ventanas con
add_from_file(). Tras ello se definen los punteros de cada ventana para que carguen los
datos correspondientes y para finalizar se añaden las ventanas mediante add_window().
Con esto definido, sería tan sencillo como cargar los widgets al builder de la ventana
siendo el primer argumento el id del widget en el archivo XML y el segundo argumento
el nombre del puntero que hemos definido en el fichero de cabecera.
builder->get_widget("ent_fiberdistance", ent_fiberdistance);
28
Tras conocer estos dos principios básicos de toda aplicación GTK+, se continuará con la
descripción general de los widgets. Para desarrollar el proyecto, según la disposición de
estos widgets en Glade, tenemos diferentes tipos: de nivel superior, contenedores,
control y exhibición, widgets compuestos, etc. Cada uno de estos widgets tiene unas
propiedades comunes y otras propias de cada widget.
NIVELES SUPERIORES
GtkWindow
Una GtkWindow [25] es una ventana de nivel superior que puede contener otros
widgets. Normalmente, las ventanas presentan decoraciones que están bajo el control
del sistema de ventanas y permiten al usuario manipular la ventana (redimensionarla,
moverla, cerrarla, ...). En Glade se añade pulsando en el botón de la Figura 2.6.
29
GtkApplicationWindow
GtkDialog
Los cuadros de diálogo son una forma conveniente de solicitar al usuario una pequeña
cantidad de entrada, por ejemplo, para mostrar un mensaje o hacer una pregunta [27].
En nuestro caso ha sido usado como entrada de valores de configuración del sensor, de
medidas, selección de dispositivo para importación y exportación de archivos, etc. Su
correspondiente botón en Glade y un ejemplo podemos verlo en la Figura 2.8.
30
// Con este while(true) lo que conseguimos es que el diálogo aparezca
siempre hasta que se rellenen los valores, se presione cancelar o la X
while (true)
{
//Mostramos diálogo y esperamos respuesta del usuario
int result = NewConfigurationDialog->run();
//Manejador de la respuesta
switch(result)
{
case(0): // Accept clicked
{
…
return;
}
case(1): // Cancel clicked
{
…
return;
}
default: // X clicked
{
…
return;
}
}
}
Cómo vemos en el código fuente descrito, se lanza el diálogo esperando una respuesta
mediante la estructura de control switch. En función del botón pulsado por el usuario se
podrá realizar diferentes acciones. Los id de las respuestas se han aplicado mediante
una propiedad de los botones en Glade.
GtkFileChooserDialog
31
Figura 2.10: Diálogo de selección de ficheros.
Este widget al ser de tipo diálogo se aplica el mismo método de estructura de control
que en GtkDialog. Para la apertura de ficheros se ha aplicado un filtro GtkFileFilter para
archivos dmac y dmam que será explicado más adelante.
GtkMessageDialog
GtkBox [30] es un contenedor que organiza otros widgets en un área rectangular. Dentro
de este contenedor podrás dividirlo en pequeños contenedores horizontales o
verticales. GtkBox utiliza una noción de embalaje, el cual, se refiere a agregar widgets
con referencia a una posición particular en un contenedor(GtkContainer). En el diálogo
de la Figura 2.12 se ve un GtkBox con dos elementos (en este caso, botones) dispuestos
en vertical.
Figura 2.12: Botón GtkBox en Glade y diálogo ejemplo de dos botones en vertical.
A este tipo de widget se le añaden tantos contenedores como se necesiten mediante las
propiedades generales del GtkBox en Glade. Cómo se ve en la Figura 2.13 la orientación
está en vertical correspondiendo con la figura superior.
GtkNoteBook
GtkToolbar
GtkToolbar genera barras de botones y otros widgets [32]. Los elementos de la barra de
herramientas se pueden agrupar visualmente al agregar instancias de
GtkSeparatorToolItem. De forma predeterminada, una barra de herramientas puede
reducirse, sobre lo cual se agregará un botón de flecha para mostrar un menú de
desbordamiento que ofrece acceso a cualquier elemento secundario.
Se pueden añadir tantos elementos como se quiera y el propio contenedor tiene una
librería de iconos y separadores. En cuanto al código necesario cabe destacar que para
usar cada botón se añade una acción a una función descrita. El nombre de la acción
deberá ser del estilo win.nombre para que la ventana pueda utilizar dicha acción.
34
GtkScrolledWindow
GtkAlignment
35
CONTROL Y EXHIBICIÓN
GtkButton
El widget GtkButton [35] generalmente se utiliza para activar una función que se invoca
cuando se presiona el botón ya que emite una señal cuando se hace clic en él. GtkButton
puede contener casi cualquier otro GtkWidget hijo estándar. El hijo más comúnmente
usado es GtkLabel. En la Figura 2.19 se ven dos botones de un diálogo.
Los botones pueden recoger respuesta mediante un id aplicado con las propiedades de
los botones en Glade o mediante una señal, normalmente un clic, añadida a una función
como se ve a continuación.
btn_applyConfMeasure->signal_clicked().connect(sigc::mem_fun(*this,
&MainWindow::on_confmeasurement_apply));
GtkCheckButton
36
Este tipo de botón tiene dos posiciones: activo o desactivo; y se puede manejar
mediante una función propia del widget la cual devolverá una variable de tipo booleano,
verdadero en caso de que esté activo y falso en caso de no estarlo.
checkbuttonDelConfig->get_active();
GtkSwitch
GtkSwitch [37] es un widget que tiene dos estados: encendido o apagado. El usuario
puede controlar qué estado debe estar activo haciendo clic en el área vacía o
arrastrando el controlador. Un ejemplo lo tenemos en la figura.
Al igual que pasa con los botones anteriores, el GtkSwitch tiene dos posiciones que se
pueden alcanzar mediante la misma función. Además, ambos widgets tienen una
función muy utilizada durante la aplicación y es la de darle un estado inicial, es decir, al
iniciar cierto diálogo que el switch esté desactivado por defecto. Para esto usamos
set_active(). True para active y false para desactivo.
swrepeatdaily->set_active(false);
GtkEntry
El widget GtkEntry [38] es un widget de entrada de texto de una sola línea. Si el texto
ingresado es más largo que la asignación del widget, el widget se desplazará para que la
posición del cursor sea visible. En la Figura 2.22 ejemplo vemos un GtkEntry con la
palabra “Entry” escrita en su interior.
37
Figura 2.22: Botón GtkEntry en Glade y ejemplo de entrada.
En este tipo de widgets es necesario la obtención del texto introducido para su posterior
uso. Este tipo de adquisición del texto se realiza mediante la función get_text() propia
de GtkEntry.
info->get_text();
GtkSpinButton
En el caso que respecta, se utilizan dos GtkAdjustment para no dejar que el usuario
añadiese valores no deseados. Al tratarse de horas del día, de 0 a 23 horas y de 0 a 59
minutos respectivamente.
38
GtkComboBox
ent_choosetypemeasurement->get_active_id()
GtkImage
El widget GtkImage [41] muestra una imagen. Varios tipos de objetos pueden mostrarse
como una imagen como por ejemplo GdkPixbuf ("buffer de píxeles") aunque en este
proyecto se van a cargar imágenes .png. Un ejemplo se presenta en el recuadro rojo de
la Figura 2.25 añadido mediante las propiedades de GtkImage en Glade.
39
GtkLabel
El widget GtkLabel [42] muestra una pequeña cantidad de texto. La mayoría de las eti-
quetas se utilizan para etiquetar otro widget como GtkButton, GtkMenuItem o GtkCom-
boBox.
Este es uno de los elemento más utilizados y más sencillos de usar. Básicamente con una
función propia de GtkLabel se puede asignar cualquier texto además de formatearlo.
Label1.set_text(“Esto es un ejemplo”);
Label2.set_markup("<b>"+nombre+"</b> \n");
GtkSeparator
40
GtkCalendar
Para manejar este widget se ha utilizado unas funciones propias que han sido añadidas
al Apéndice C pero cabe destacar la señal del doble clic sobre un día del calendario
aplicándole una función.
Calendario->signal_day_selected_double_click().con-
nect(sigc::mem_fun(*this, &MainWindow::on_calendarpress_event));
GtkInfoBar
GtkInfoBar [45] es un widget que te permite mostrar un mensaje al usuario sin tener
que mostrar un diálogo. Normalmente se muestra en la parte superior o inferior de un
documento. Como vemos en la Figura 2.29, mostramos un mensaje para avisar al
usuario de algo sin cambiar de diálogo.
41
Figura 2.29: Botón GtkInfoBar en Glade y ejemplo en diálogo.
infobarconfig->show();
GtkTreeView
Cada GtkTreeView [46] tiene un GtkTreeModel asociado, que contiene los datos
mostrados por el GtkTreeView. Cada GtkTreeModel puede ser utilizado por más de un
GtkTreeView. Normalmente se utiliza las clases de modelo GtkListStore o GtkTreeStore,
las cuales implementan la interfaz GtkTreeModel. GtkListStore contiene filas simples de
datos, y cada fila no tiene hijos, mientras que GtkTreeStore contiene filas de datos, y
cada fila puede tener filas secundarias. Para agregar datos al modelo usamos
GtkListStore.append() o GtkTreeStore.append(), dependiendo de qué tipo de modelo se
creó.
42
que GtkTreeView utiliza para organizar las columnas verticales en la vista de árbol. En
este proyecto se ha hecho una clase propia con una columna y esta clase al crear el
modelo se la he añadido. Mediante GtkTreeModel::Row podemos ir añadiendo filas a
esta columna. Un ejemplo con el modelo GtkTreeStore se puede ver en la Figura 2.30.
Todo lo anteriormente explicado se puede ver más claro en el ejemplo de código, el cual,
añade los ficheros de configuración al TreeView. Para añadir los ficheros de
configuración de medida se procede de la misma manera.
43
Al hacer clic derecho en uno de los elementos del TreeView se mostrará un GtkMenu
[47] que básicamente es un GtkMenuShell que implementa un menú desplegable que
consiste en una lista de objetos GtkMenuItem que pueden ser navegados y activados
por el usuario para realizar funciones de la aplicación. Para añadir elementos a este
menú se procede de la siguiente forma, descrita a continuación.
...
m_Menu_Popup.accelerate(*this);
m_Menu_Popup.show_all(); Figura 2.31: Popup menú.
VARIOS
GtkAdjustment
El objeto GtkAdjustment [48] representa un valor que tiene un límite inferior y superior
asociado, junto con incrementos de paso y página, y un tamaño de página. Se usa en
varios widgets GTK +, incluidos GtkSpinButton, GtkViewport y GtkRange.
Cómo podemos ver en la Figura 2.33 para realizar un ajuste en las horas
correspondientes a las medidas, en el GtkSpinButton hemos aplicado un GtkAdjustment
de 24 horas que tiene un día.
44
Figura 2.33: Atributo de ajuste del SpinButton y propiedades del ajuste.
GtkFileFilter
Un GtkFileFilter [49] se puede usar para restringir los archivos que se muestran en un
GtkFileChooser. Los archivos se pueden filtrar en función de su nombre, en su tipo de
mime o mediante una función de filtro personalizada. Un ejemplo lo tenemos en la
Figura 2.34.
Figura 2.34: Botón GtkFileFilter en Glade y ajustes del filtro archivos dmac y dmam.
45
La estructura que se ha llevado a cabo es un sistema de carpetas y ficheros por el que
sea intuitivo moverse. En un primer lugar, la carpeta configure tiene el fichero
configure.cpp el cual nos dirá que tarjetas de adquisición hay instaladas. La aplicación
tiene dos pantallas principales donde se ha optado por hacer una carpeta para cada una,
en cuyo interior podemos encontrar el código C++ pertinente para el control de esta,
más el archivo Glade que describe la interfaz gráfica de la ventana. Además de tener las
carpetas correspondientes a cada una de las ventanas, también tenemos otras carpetas
como Objects o Functions donde se almacenan ficheros más genéricos o que van a ser
usados por más de una ventana en un futuro. Finalmente, para organizar los datos de
configuración y medidas se optó por una carpeta Data donde guardar los ficheros.
Configure
46
#include <vector>
#include <string>
#include <sys/stat.h>
#include <iostream>
#include <fstream> //ofstream
int main()
{
vector<string> headerFiles;
headerFiles.push_back("/usr/include/AgMD1.h");
headerFiles.push_back("AGMD1_EXISTS_");
headerFiles.push_back("/usr/include/AlazarApi.h");
headerFiles.push_back("ALAZARTECH_EXISTS_");
return 0;
}
Main
47
#include "ApplicationScript.h"
ApplicationScript
Existen dos partes que son importantes dentro de este código y que merecen ser
comentadas con especial interés. La primera es la función on_startup. En esta función
se carga el menubar a través del objeto builder de GTK+, que será el que posteriormente
también se use para cargar todas las interfaces gráficas generadas por Glade. Además
de cargarse el menubar y configurarlo como menú de la aplicación, se asocian funciones
para cada una de las opciones descritas en el menubar a partir de la función add_action
propia de GTK+.
//Creamos el builder que vamos a usar en todas las ventanas para gene-
rarlas a partir de los ficheros glade
m_refBuilder = Gtk::Builder::create();
try
{
//Cogemos la información de la barra de menú del siguiente fichero
m_refBuilder->add_from_file("Glade/menu.ui");
}
catch (const Glib::Error& ex)
{
std::cerr << "Building menus failed: " << ex.what();
}
48
//Obtenemos el objeto mediante el id del archivo XML, obtenemos el
menú a partir del objeto creado de menú, y lo añadimos a la aplica-
ción.
auto object = m_refBuilder->get_object("menuBar_global");
auto gmenu = Glib::RefPtr<Gio::Menu>::cast_dynamic(object);
if (!(gmenu)) {
g_warning("GMenu or AppMenu not found");
}
else
{
set_menubar(gmenu);
}
La otra función interesante y que merece ser comentada se llama on_activate. En esta
función, a partir del builder se carga la información de las interfaces gráficas generadas
por Glade y se pasa a las clases propias de cada ventana (usando la función de GTK+
get_widget_derived descrita más atrás) para que puedan trabajar con ella. Tras haber
generado las funciones y haberles pasado a los objetos de cada ventana la información
de sus respectivas interfaces de usuario se añaden estas ventanas al sistema de ventanas
de la aplicación y se lanza la principal.
// Aquí cargamos todos los ficheros Glade de todas las ventanas para
ya tenerlos en el m_refBuilder y no tener que recargar
m_refBuilder->add_from_file("AdminWindow/Glade/adminWindow.glade");
m_refBuilder->add_from_file("MainWindow/Glade/main.glade");
// Definimos los punteros de cada ventana para que carguen los datos
correspondientes
// Admin
m_adminWin = nullptr;
m_refBuilder->get_widget_derived("AdminWindow", m_adminWin);
// MainWin
m_mainWin = nullptr;
m_refBuilder->get_widget_derived("MainWindow", m_mainWin);
// Admin Dialog
m_refBuilder->get_widget("dialog_AdminPassword", m_adminDialog);
m_refBuilder->get_widget("ent_adminPassword", ent_adminPassword);
m_refBuilder->get_widget("lbl_wrongPassword", lbl_wrongPassword);
49
Es interesante también conocer que en esta clase hay una variable global
(m_contVentanas) que se encarga de contar cuantas ventanas hay abiertas (nunca
puede haber más de 1 abierta) para que en el momento que dicho contador llegue a
cero se pueda cerrar la aplicación, abortando todos los procesos que están en ejecución.
Además de esta variable global hay otras variables globales (una por cada ventana) para
saber si estas están activas en ese momento. Dichas variables realizan la llamada propia
de GTK+ property_is_active() para obtener en estas variables una variable de tipo
booleano de si están o no abiertas.
Por último, se debe comentar que para hacer la visualización del pdf de ayuda de usuario
se usa la aplicación evince de visualización de pdfs.
AdminWindow
Esta es la carpeta que contiene los archivos que se encargan de generar la pantalla de
Admin y todas sus funcionalidades. Debido a que es una pantalla orientada a
administradores, se ha realizado un sistema de autenticación mediante una contraseña.
Además, esta pantalla está dividida en 4 partes claramente diferenciables; una pantalla
de dibujado donde se presentarán los datos capturados por la tarjeta, un área donde
podemos seleccionar los parámetros de captura de la tarjeta bajo la pantalla. Y en la
mitad derecha de la pantalla se encuentra el área de encendido del equipo y bajo él, un
área de texto que actúa como terminal y por el que se van sacando avisos varios para
guiar al administrador de la aplicación. Todo esto se puede ver en la Figura 2.36.
50
Figura 2.36: Ventana de administrador.
• Sha256
51
MainWindow
MainWindow tiene ciertas funciones que merecen ser comentadas para una mayor
comprensión del uso de la ventana. La creación de configuración de sensor y de medidas
son dos funciones similares que ambas desembocan en la función save_files guardando
los ficheros en las rutas Data/Configurations y Data/ConfMeasurement
respectivamente. Las variables de tipo booleano de la función save_files describen si los
datos pasados son nuevos o editables/clonados/importados y si son de sensor o de
medida. Además de guardar los ficheros, añade mediante las funciones
add_configuration y add_measurement el nombre del fichero al TreeView. En la parte
de nueva configuración del sensor hay una función llamada check_if_filled la cual
comprueba que todos los campos de la configuración estén correctamente rellenados.
52
Consecuentemente, la aplicación consta de una función para editar estos datos ya
creados. Esta función edit_files() es parecida a las anteriores a diferencia de que la
diferenciación de sensor y medida se hace dentro de la misma y no en funciones
separadas. En la función save_files() se puede observar el primer booleano como false,
indicando así que es un archivo editable, clonado o importado. Además, la última cadena
ya no es pasado en blanco, sino que se le pasa el nombre del archivo que vamos a editar.
53
La función open_files() lanzará un diálogo de elección de ficheros el cual solo mostrará
los ficheros dmac y dmam. Una vez seleccionado el fichero correspondiente y pulsado
en aceptar, diferenciamos entre configuración de sensor o de medida y lo añadimos a
su zona correspondiente del TreeView.
54
La importación de archivos mediante USB es un tanto más compleja que la apertura y la
exportación. En Import_files al pulsar sobre el botón correspondiente de elección de
dispositivo externo del cual importar, la función fileUsb recorrerá el dispositivo en busca
de archivos dmac y dmam. Una vez seleccionado el fichero deseado por el usuario y
pulsado en Ok, la función on_devicesfiles_import se encarga de llamar a las siguientes
funciones responsables de buscar el fichero (importFilesUsb), guardarlo (save_files) y
añadirlo al TreeView (add_configuration).
AboutWindow
Además, esta carpeta contiene un archivo pdf que es la guía de uso de la aplicación y el
equipo. La visualización de esta guía de ayuda al usuario, como ya se ha comentado en
este documento, se realiza mediante evince.
55
56
Capítulo 3
Uso de la aplicación
El software desarrollado hasta el momento consta de dos ventanas (Admin y Main)
además de un diálogo de ayuda (About). Estas dos ventanas y el diálogo de ayuda están
controladas desde una clase central (ApplicationScript) que se encarga de la correcta
apertura de las ventanas, así como de la transmisión de datos entre ellas y generación
de objetos compartidos.
57
3.1 Barra de herramientas
58
En caso de pulsar en Measurement, se abrirá el diálogo de nueva configuración de
medida el cual tiene diversos tipos de medida que se pueden seleccionar mediante un
desplegable en la parte superior derecha del diálogo. La primera opción por defecto es
la de una medida. Al pulsar sobre una configuración de sensor en el panel de la izquierda
y en aceptar guadaremos un fichero con extensión dmam correspondiente a ese tipo de
configuración de sensor.
59
La tercera opción nos da opción a realizar la medida periodicamente un número
especifico de veces. En las entradas de texto ponemos respectivamente el número de
medidas que se quieran realizar y la periodicidad deseada.
La cuarta y última opción nos presenta un calendario el cual muestra la fecha actual y es
posible seleccionar un día marcandolo y accionando otros campos vistos en la figura x.x.
En estos campos podemos seleccionar la hora de la medida además de repetir
diariamente o semanalmente. Además, hay opción de hacer un ajuste después de
realizar la medida.
60
El segundo elemento es Open, el cual lanza el diálogo de apertura de ficheros. Este
diálogo tiene un filtro de extensión de ficheros para solo mostrar los correspondientes
a la aplicación, en este caso dmac y dmam. Además, dentro del código fuente hay
implementada una función la cual guarda el directorio del último fichero abierto
permitiendo la próxima vez que se abra el diálogo estar en esa misma carpeta.
61
Figura 3.10: Botón de importar ficheros y su correspondiente diálogo.
Una vez seleccionando el dispositivo del cual queremos importar y pulsado en aceptar,
se lanza otro diálogo el cuál muestra todos los ficheros con la extensión dmac sin
distinción de si están en una carpeta u en otra, son mostrados en forma de lista.
62
Figura 3.12: Botón de exportar ficheros y su correspondiente diálogo.
El sexto y séptimo elementos son dos botones no activos por el momento y aunque las
rutinas ya están escritas, no se han incluido al programa. Los botones de Run y Stop son
los correspondientes al lanzamiento de una medida y a la parada de esta
respectivamente. En un futuro próximo serán implementados.
63
El octavo elemento es Settings y se corresponde con las opciones disponibles en la
aplicación. Al pulsar sobre él se observa un diálogo con varias pestañas en su interior, la
primera corresponde con las unidades de medida de la aplicación y la segunda con la
cuota de disco.
64
El décimo y último elemento es About y se corresponde con el menú de ayuda. La
ventana de About nos enseña un diálogo el cual muestra una imagen de Uptech Sensing,
la versión del software, la página web de la empresa y el año de desarrollo.
65
El primer botón del menú es Edit, el cual abre un diálogo de edición de datos
correspondientes a la configuración de sensor (ver Figura 3.18) o medida (ver Figura
3.18).
Figura 3.18: Edición de configuración de sensor. Figura 3.19: Edición de configuración de medida.
El segundo botón del menú llamado View abre un diálogo de visualización de los datos
de configuración de sensor (ver Figura 3.20) o de medida (ver Figura 3.20).
Figura 3.20: Visualización de configuración de sensor. Figura 3.21: Edición de configuración de medida.
66
El tercer botón llamado Clone básicamente hace una copia del archivo seleccionado
añadiéndole al nombre “_Clone” y lo guarda en el mismo directorio que el archivo
original.
67
3.4 MenuBar
El menú de la aplicación es un elemento que destacar ya que está en todas las ventanas
de la aplicación. Las funcionalidades del menú son las mismas que las comentadas más
atrás en la barra de herramientas y se pueden ver a continuación las figuras
correspondientes.
Las funciones de editar y visualizar ficheros descritas más atrás son accesibles como se
ve en la Figura 3.24 desde el menú de la aplicación.
68
El menú de la aplicación también tiene un elemento de ‘Settings’ el cual contiene dos
elementos: Login y Options explicados más atrás.
Help es un elemento el cual posee dos opciones, una guía de usuario que es abierta
mediante evince como se describió en este documento más atrás. About también ha
sido descrito con anterioridad.
69
70
Capítulo 4
Conclusiones y líneas abiertas
4.1. Conclusiones
Los interfaces gráficos de usuario (GUI) son un medio muy interesante para la
representación de las medidas distribuidas y dinámicas de deformación unitaria y
temperatura realizadas por un equipo interrogador. La realización de una aplicación de
estas características para este tipo de equipamientos nos aporta una gran productividad
ya que permite el manejo y el orden de todos los recursos e información aportados por
el equipo interrogador, facilitando así al usuario poder identificar los puntos clave en
cada activo y así poder realizar un correcto mantenimiento del mismo. Además, el
control de los datos de un equipo de tales características desde una aplicación hace
posible implementar una correcta gestión de alertas que permitan activar determinados
protocolos de seguridad, protegiendo de esta manera la integridad de la estructura y de
su entorno. Este tipo de monitorización debe ser sencilla para un usuario cualquiera y
es en la consecución de estos aspectos en lo que se centra el desarrollo de esta
aplicación realizada en este trabajo fin de grado. Durante la realización del mismo, se ha
trabajado en varias líneas de desarrollo que mejoran la comunicación usuario-equipo.
72
➢ Una vez conseguida la conexión con el área de dibujado y comprobar que
funciona, realizar algún tipo de función capaz de hacer zoom-in y zoom-out en el
dibujado, permitiendo así al usuario poder observar las trazas representadas
mejor.
➢ La implementación de una papelera en cuyo directorio guardar los archivos
borrados por el usuario, la cual, sea accesible por el administrador para poder
recuperar ciertos ficheros que por cualquier situación se necesiten.
➢ La posibilidad de cambiar el directorio de guardado de ficheros es una opción
futura a tener en cuenta ya que es posible que un usuario del software desee
guardar los ficheros en algún lugar concreto del sistema.
➢ En el diálogo de settings, la posibilidad de cambiar las unidades es un hecho, pero
sin función escrita en código fuente actualmente. En un futuro próximo
implementar funciones para manejar las unidades. Por ejemplo,
//Función para pasar grados fahrenheit a celsius
void MainWindow::FtoC(float fahrenheit)
{
cel = (fahrenheit - 32) * 5/9;
}
➢ El panel visualización tiene tres botones en la zona superior que deben ser
excluyentes entre sí, pudiendo visualizar diferentes tipos de gráficos según esté
la correspondiente casilla seleccionada.
➢ La realización de un explorador de archivos en los dispositivos externos
conectados para conseguir que sea mejor visualmente que el diálogo con
TreeView simple actual.
➢ Un instalador de la aplicación para en un futuro próximo tener el software en un
disco de instalación el cual poder distribuirlo junto con el equipo interrogador.
73
74
Apéndices
75
76
Apéndice A
Importación del proyecto en IDE
A la hora de la importación del proyecto programado mediante C/C++ en el IDE Eclipse
se ha llevado a cabo unos rigurosos pasos que se describen a continuación.
Una vez creado, se pulsa sobre el proyecto y en el menú superior: Project > Properties.
Primero, en C/C++ Build en la pestaña Builder Settings se marca "Generate Makefiles
automatically". Segundo, en C/C++ Build > Settings en la pestaña Build Artifact se pone
Artifact Type Executable. Tercero, en C/C++ Build en la pestaña Configuration se clica en
Manage Configurations > New y se pone un nombre a la carpeta donde se van a crear
los makefiles. Tras crearla se activa mediante Set Active.
77
Cuarto y último, en C/C++ Build > Settings, pestaña Tool Settings se aplica lo siguiente:
• En GCC C++ Compiler se pone lo siguiente al final de Command line pattern: `pkg-
config gtkmm-3.0 --cflags --libs`
• En GCC C++ Compiler > Dialect se pone lo siguiente: -std=c++11
• En GCC C++ Compiler > Preprocessor se añade en Defined symbols (-D) lo
siguiente: _LINUX
• En GCC C++ Compiler > Optimization y se pone Optimization Level -03
• En GCC C++ Compiler > Miscellaneous se borra fmessage-lenght=0 dejando el -c
del principio
• En GCC C++ Compiler los warnings(-Wall) y el flag(-c) se deja de momento por
defecto.
• En GCC C++ Linker se pone lo siguiente al final en Command line pattern: `pkg-
config gtkmm-3.0 --cflags --libs`
• En GCC C++ Linker > Libraries se añade en Libraries(-l) las librerias que se utilicen
al compilar.
• En GCC C++ Linker > Libraries se añade en Libraries search path lo siguiente:
/usr/local/lib
Para hacerla correr en Run > Run Configurations > New Configuration se selecciona la
aplicación que va a correr y listo.
78
Apéndice B
Configuración de GIT
Este tipo de sistema de control llamado EGit es utilizado de manera local en el proyecto
siendo propio del IDE utilizado. Cómo ya se explicó más atrás en este documento, se
puede trabajar con distintas perspectivas con lo que puedes tener distintas
configuraciones de tu pantalla de trabajo según tu tipo de proyecto o según la acción
que vayas desarrollar en ese momento. Una de estas perspectivas es la del SVN local el
cual es de gran ayuda para proyectos de gran envergadura y en los que vayan a trabajar
varios desarrolladores.
EGit ya está incluido en Eclipse Oxygen [50], por lo que no es necesario su instalación. Si
usa una versión anterior a Eclipse Juno tendrá que instalar el software abriendo el
Asistente de Eclipse y pulsando en ‘Help -> Install new software’.
79
Una ventaja importante de Git es que puede crear fácilmente repositorios locales,
incluso antes de compartirlos con otras personas. De esta forma, puede versionar su
trabajo localmente para tener un constante control del avance de la aplicación. Primero,
debe crear un proyecto en Eclipse que desee compartir a través de su repositorio local.
El repositorio recién creado estará vacío, aunque el proyecto esté asignado a él. Antes
de que se pueda comprometer los archivos al repositorio, hay que agregarlos.
Simplemente haga clic derecho en el proyecto compartido y navegue a Team -> Add.
Después de esta operación, el signo de interrogación debería cambiar a un símbolo más.
Lo último que debe hacer es comprometer el proyecto haciendo clic con el botón
derecho en el nodo del proyecto y seleccionando Team -> Commit desde el menú
contextual. En el asistente de confirmación, todos los archivos deben seleccionarse
automáticamente. Ingrese un mensaje de confirmación (la primera línea debe ser similar
a un titular, como aparecerá en la vista del historial) y presione el botón Confirm. Si la
confirmación salió correctamente, los símbolos más se abran convertido en símbolos de
repositorio.
80
Apéndice C
Programación
En cuanto a la programación cabe destacar el uso de ciertas funciones realizadas a lo
largo del proyecto para el correcto funcionamiento de la aplicación desarrollada. Estas
funciones creadas no tienen por qué estar implementadas de la mejor manera posible y
es muy probable que haya formas de mejorarlas.
Cuota de disco
class HardDisk {
public:
long memtotal;
long memusada;
long memlibre;
long memporc;
};
81
//Leemos línea a línea mientras no sea el final del fichero
while(!fileI.eof()){
//Miramos que no sea USB ni fichero
if(!(token.find("/media/")!=string::npos) && !(token.find("fi-
cheros")!=string::npos)){
istringstream ss(token);
//Añadimos a la clase los datos del disco leido
while(ss >> word){
if(aux==1) harddisk[num_disp].memtotal = stol(word);
if(aux==2) harddisk[num_disp].memusada = stol(word);
if(aux==3) harddisk[num_disp].memlibre = stol(word);
if(aux==4) harddisk[num_disp].memporc = stol(word);
aux++;
}
aux=0;
num_disp++;
}
getline(fileI,token);
}
fileI.close();
Fecha actual
82
//Asignamos a cada variable su valor de fecha
dia << put_time(&now_tm, "%d");
mes << put_time(&now_tm, "%m");
ano << put_time(&now_tm, "%Y");
horas << put_time(&now_tm, "%H");
minutos << put_time(&now_tm, "%M");
segundos << put_time(&now_tm, "%S");
Fecha válida
return true;
}
83
Cadena es un número
Función que retorna true si todos los campos (Configuración Sensor) están
correctamente rellenados.
84
}
}
85
infobarconfig->show();
return false;
}
double freqstart;
istringstream(configuracion[5]) >> freqstart;
double freqstop;
istringstream(configuracion[6]) >> freqstop;
infobarconfig->hide();
NewConfigurationDialog->hide();
for (int i=0; i<15; i++)
{
if(i==0){info[i]->set_text("");}
else if(i==1){ent_choosesamplinginterval->set_ac-
tive_text("");}
else{info[i-1]->set_text("");}
}
return true;
}
Calendario
void MainWindow::on_calendarpress_event()
{
int day = Calendario->property_day();
86
spinhour->set_value(0);
spinmin->set_value(0);
swrepeatdaily->set_active(false);
swrepeatweekly->set_active(false);
checkbuttonFitSP->set_active(false);
} else {
boxOptionsCalendar->show();
btn_applyConfMeasure->set_sensitive(true);
Calendario->mark_day(day);
imageLogoMeasurement->hide();
}
}
void MainWindow::on_confmeasurement_apply()
{
Glib::ustring nameFile;
// Fit //
string fit;
if(checkbuttonFitSP->get_active()) fit = "Yes";
else fit ="No";
// Sensor //
auto refSelection = treeviewDialog->get_selection();
if(refSelection)
{
Gtk::TreeModel::iterator iter = refSelection->get_selected();
if(iter)
{
nameFile = (*iter)[m_Columns.m_col_name];
}
}
// Hora //
string hour = to_string(spinhour->get_value_as_int());
if(hour.length()==1) hour = "0" + hour;
string min = to_string(spinmin->get_value_as_int());
if(min.length()==1) min = "0" + min;
string hora = hour + ":" + min;
string repeat;
// Repetición diaria/semanal //
if(swrepeatdaily->get_active() & swrepeatweekly->get_active()) re-
peat = "Daily and Weekly";
else if (swrepeatdaily->get_active()) repeat = "Daily";
else if (swrepeatweekly->get_active()) repeat = "Weekly";
else repeat = "None";
87
if(Calendario->get_day_is_marked(day)){
Calendario->unmark_day(day);
} else {
Calendario->mark_day(day);
}
// Sumamos una medida para tener constancia del tamaño del array
auxiliarConfMeasure++;
}
ent_adminPassword->grab_focus();
88
{
m_adminDialog->hide();
return true;
}
else
{
lbl_wrongPassword->show();
break;
}
}
case(1): // Cancel clicked
{
std::cout << "Cancel clicked." << std::endl;
std::cout << "Result: " << result << std::endl;
m_adminDialog->hide();
return false;
}
default: // X clicked
{
std::cout << "Unexpected button clicked." <<
std::endl;
m_adminDialog->hide();
return false;
}
}
}
}
89
90
Lista de Figuras
Figura 1.1: Gráfica SO más utilizados actualmente. Eje X: Año-Mes; Eje Y: Porcentaje. . 6
Figura 1.4: Lenguajes de programación. De izquierda a derecha: C++, Java y Python. ... 9
Figura 2.12: Botón GtkBox en Glade y diálogo ejemplo de dos botones en vertical. .... 33
91
Figura 2.13: Atributos del GtkBox. ................................................................................. 33
Figura 2.23: Botón GtkSpinButton en Glade y ejemplo usado en formato hora. .......... 38
Figura 2.33: Atributo de ajuste del SpinButton y propiedades del ajuste. .................... 45
Figura 2.34: Botón GtkFileFilter en Glade y ajustes del filtro archivos dmac y dmam. . 45
92
Figura 2.38: Organización de la función de editar ficheros. ........................................... 53
93
Figura 3.21: Edición de configuración de medida. ......................................................... 66
Figura 3.23: Sección File del menú de la aplicación y nueva configuración .................. 68
Figura 3.25: Elemento del menú correspondiente con los ajustes. ............................... 69
94
Bibliografía
95
[12] Calibre [En línea]. https://calibre-ebook.com/. [08/18].
96
[24] GtkBuilder [En línea]. https://developer.gnome.org/gtk3/stable/GtkBuilder.html.
[06/18].
97
[34] GtkAlignment [En línea]. https://developer.gnome.org/gtk3/stable/GtkAlign-
ment.html. [07/18].
98
[44] GtkCalendar [En línea]. https://developer.gnome.org/gtk3/stable/Gtk-
Calendar.html. [07/18].
99