diff --git a/data/ui/meson.build b/data/ui/meson.build index d76ae89..165a514 100644 --- a/data/ui/meson.build +++ b/data/ui/meson.build @@ -17,6 +17,12 @@ tourist_gresource = gnome.compile_resources('tourist_gresource', c_name: meson.project_name() + '_resource_tourist', export: true, install_header: true) +staff_gresource = gnome.compile_resources('staff_gresource', + 'staff.gresource.xml', + source_dir: '.', + c_name: meson.project_name() + '_resource_staff', + export: true, + install_header: true) place_gresource = gnome.compile_resources('place_gresource', 'place.gresource.xml', source_dir: '.', diff --git a/data/ui/staff.editor.ui b/data/ui/staff.editor.ui new file mode 100644 index 0000000..049f8c7 --- /dev/null +++ b/data/ui/staff.editor.ui @@ -0,0 +1,337 @@ + + + + + + diff --git a/data/ui/staff.gresource.xml b/data/ui/staff.gresource.xml new file mode 100644 index 0000000..0c4c28a --- /dev/null +++ b/data/ui/staff.gresource.xml @@ -0,0 +1,22 @@ + + + + + staff.list.ui + staff.editor.ui + staff.specialties.ui + staff.specialty.editor.ui + + diff --git a/data/ui/staff.list.ui b/data/ui/staff.list.ui new file mode 100644 index 0000000..fb03aa2 --- /dev/null +++ b/data/ui/staff.list.ui @@ -0,0 +1,235 @@ + + + + + + + diff --git a/data/ui/staff.specialties.ui b/data/ui/staff.specialties.ui new file mode 100644 index 0000000..cfcad6d --- /dev/null +++ b/data/ui/staff.specialties.ui @@ -0,0 +1,149 @@ + + + + + + + diff --git a/data/ui/staff.specialty.editor.ui b/data/ui/staff.specialty.editor.ui new file mode 100644 index 0000000..1918d38 --- /dev/null +++ b/data/ui/staff.specialty.editor.ui @@ -0,0 +1,129 @@ + + + + + + diff --git a/lib/db/guia.vala b/lib/db/guia.vala index 8e0ed2c..251a442 100644 --- a/lib/db/guia.vala +++ b/lib/db/guia.vala @@ -62,8 +62,9 @@ namespace LibSernatur { * Get all tuples and fields from database * @param conn The database connection to use * @return Returns a list of Guia + * @throws PostgresError If there is a problem with with escaping strings */ - public static List get_all_guias (Connection conn) { + public static List get_all_guias (Connection conn) throws PostgresError { var res = conn.db.exec (" SELECT G.rut_guia, G.nombre_guia, G.calle, G.numero, C.id_ciudad, C.nombre_ciudad, @@ -109,6 +110,109 @@ JOIN region R ON (C.id_region = R.id_region) } return list; } + + /** + * Get a tuple and fields from database + * @param conn The database connection to use + * @return Returns a Guia + * @throws PostgresError If there is a problem with with escaping strings + */ + public static Guia? get_guia_by_run (Connection conn, string run) throws PostgresError { + var res = conn.db.exec (" +SELECT G.rut_guia, G.nombre_guia, G.calle, G.numero, +C.id_ciudad, C.nombre_ciudad, +R.id_region, R.nombre_region +FROM guia G +JOIN ciudad C ON (G.id_ciudad = C.id_ciudad) +JOIN region R ON (C.id_region = R.id_region) +WHERE rut_guia = '" + conn.escape (run) + "' + "); + if (res.get_status () != ExecStatus.TUPLES_OK) { + #if DEBUG + error (conn.db.get_error_message ()); + #else + warning (conn.db.get_error_message ()); + return null; + #endif + } + + var wra = new ResultWrapper (res); + Guia guia = null; + int n = res.get_n_tuples (); + for (int i = 0; i < n; i++) { + try { + guia = new Guia (wra.get_string_n (i, "rut_guia"), + wra.get_string_n (i, "nombre_guia"), + wra.get_string_n (i, "calle"), + wra.get_int_n (i, "numero"), + new Ciudad (wra.get_int_n (i, "id_ciudad"), + wra.get_string_n (i, "nombre_ciudad"), + new Region (wra.get_int_n (i, "id_region"), + wra.get_string_n (i, "nombre_region") + ) + ) + ); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + } + return guia; + } + + /** + * Insert a staff member in the database + * @param conn The database connection + * @param guia The staff member to insert + * @throws PostgresError Thrown if there is a problem with escaping strings + */ + public static void insert_illness (Connection conn, Guia guia) throws PostgresError { + var res = conn.db.exec (" +INSERT INTO guia +(rut_guia, nombre_guia, calle, numero, id_ciudad) +VALUES +( +'" + conn.escape (guia.rut_guia) + "', +'" + conn.escape (guia.nombre_guia) + "', +'" + conn.escape (guia.calle) + "', +" + guia.numero.to_string () + ", +" + guia.ciudad.id_ciudad.to_string () + " +) + "); + if (res.get_status () != ExecStatus.COMMAND_OK) { + #if DEBUG + error (conn.db.get_error_message ()); + #else + warning (conn.db.get_error_message ()); + #endif + } + } + + /** + * Delete a staff member in the database + * @param conn The database connection + * @param guia The staff member to delete + * @throws PostgresError Thrown if there is a problem with escaping strings + */ + public static void delete_staff (Connection conn, Guia guia) throws PostgresError { + var res = conn.db.exec (" +DELETE FROM guia +WHERE ( +rut_guia = '" + conn.escape (guia.rut_guia) + "' +) + "); + if (res.get_status () != ExecStatus.COMMAND_OK) { + #if DEBUG + error (conn.db.get_error_message ()); + #else + warning (conn.db.get_error_message ()); + #endif + } + } } } } diff --git a/po/POTFILES b/po/POTFILES index f25eda1..cd92198 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -18,6 +18,10 @@ src/tourist_list.vala src/tourist_editor.vala src/tourist_illnesses.vala src/tourist_illness_editor.vala +src/staff_list.vala +src/staff_editor.vala +#src/staff_specialties.vala +#src/staff_specialty_editor.vala src/query_window.vala data/ui/main.window.ui data/ui/main.splash.ui @@ -30,6 +34,10 @@ data/ui/tourist.list.ui data/ui/tourist.editor.ui data/ui/tourist.illnesses.ui data/ui/tourist.illness.editor.ui +data/ui/staff.list.ui +data/ui/staff.editor.ui +data/ui/staff.specialties.ui +data/ui/staff.specialty.editor.ui data/ui/place.editor.ui data/ui/query.window.ui data/ui/query.tree.ui diff --git a/po/es.po b/po/es.po index 93b8c41..7f19ac0 100644 --- a/po/es.po +++ b/po/es.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: sernatur\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-01-21 00:47-0300\n" -"PO-Revision-Date: 2019-01-21 00:57-0300\n" +"POT-Creation-Date: 2019-01-21 03:25-0300\n" +"PO-Revision-Date: 2019-01-21 03:28-0300\n" "Last-Translator: Chris Cromer \n" "Language-Team: none\n" "Language: es\n" @@ -93,16 +93,20 @@ msgstr "" msgid "SERNATUR version: " msgstr "Versión de SERNATUR: " -#: src/main_window.vala:227 +#: src/main_window.vala:238 msgid "Error: Could not connect to the database!" msgstr "Error: No se puede conectar al base de datos!" -#: src/main_window.vala:239 src/tour_list.vala:233 src/tour_editor.vala:231 +#: src/main_window.vala:250 src/tour_list.vala:233 src/tour_editor.vala:231 #: src/tour_editor.vala:248 src/tour_editor.vala:280 src/tour_editor.vala:297 #: src/tour_editor.vala:329 src/tour_editor.vala:346 #: src/tour_assign_vehicle.vala:99 src/tourist_list.vala:206 #: src/tourist_editor.vala:99 src/tourist_editor.vala:112 #: src/tourist_editor.vala:128 src/tourist_editor.vala:141 +#: src/staff_editor.vala:227 src/staff_editor.vala:240 +#: src/staff_editor.vala:256 src/staff_editor.vala:269 +#: src/staff_editor.vala:291 src/staff_editor.vala:308 +#: src/staff_editor.vala:340 src/staff_editor.vala:357 msgid "Error" msgstr "Error" @@ -132,20 +136,20 @@ msgstr "Error: El nombre del tour no puede estar en blanco!" msgid "Error: A tour named \"%s\" already exists!" msgstr "Error: Un tour con el nombre \"%s\" ya existe!" -#: src/tour_editor.vala:276 +#: src/tour_editor.vala:276 src/staff_editor.vala:287 msgid "Error: City name cannot be left blank!" msgstr "Error: El nombre de la ciudad no puede estar en blanco!" -#: src/tour_editor.vala:293 +#: src/tour_editor.vala:293 src/staff_editor.vala:304 #, c-format msgid "Error: A city named \"%s\" already exists!" msgstr "Error: Una ciudad con el nombre \"%s\" ya existe!" -#: src/tour_editor.vala:325 +#: src/tour_editor.vala:325 src/staff_editor.vala:336 msgid "Error: Region name cannot be left blank!" msgstr "Error: El nombre de la región no puede estar en blanco!" -#: src/tour_editor.vala:342 +#: src/tour_editor.vala:342 src/staff_editor.vala:353 #, c-format msgid "Error: A region named \"%s\" already exists!" msgstr "Error: Una región con el nombre \"%s\" ya existe!" @@ -175,7 +179,7 @@ msgstr "" "Error: No se puede borrar la turista \"%s\" porque hay información asociado " "con la turista!" -#: src/tourist_editor.vala:95 +#: src/tourist_editor.vala:95 src/staff_editor.vala:223 msgid "Error: Tourist name cannot be left blank!" msgstr "Error: El nombre de la turista no puede estar en blanco!" @@ -183,7 +187,7 @@ msgstr "Error: El nombre de la turista no puede estar en blanco!" msgid "Error: Tourist RUN cannot be left blank!" msgstr "Error: El RUN de la turista no puede estar en blanco!" -#: src/tourist_editor.vala:124 +#: src/tourist_editor.vala:124 src/staff_editor.vala:252 msgid "Error: The RUN entered is invalid!" msgstr "Error: El RUN ingresado es invalido!" @@ -201,6 +205,23 @@ msgid "Are you sure you wish to delete these illnesses from this tourist?" msgstr "" "¿Usted está seguro que quiere borrar estos enfermedades de esta turista?" +#: src/staff_list.vala:190 +msgid "Are you sure you wish to delete this staff member?" +msgstr "¿Usted está seguro que quiere borrar esta guía?" + +#: src/staff_list.vala:197 +msgid "Are you sure you wish to delete these staff members?" +msgstr "¿Usted está seguro que quiere borrar estas guías?" + +#: src/staff_editor.vala:236 +msgid "Error: Staff member RUN cannot be left blank!" +msgstr "Error: El RUN de la guía no puede estar en blanco!" + +#: src/staff_editor.vala:265 +#, c-format +msgid "Error: A staff member with the RUN \"%s\" already exists!" +msgstr "Error: Una guía con el RUN \"%s\" ya existe!" + #: src/query_window.vala:290 data/ui/main.window.ui:105 msgid "(Q1) Regions with discounts" msgstr "(Q1) Regiones sin descuentos" @@ -229,7 +250,7 @@ msgstr "_Menú" msgid "Tours" msgstr "Tours" -#: data/ui/main.window.ui:61 +#: data/ui/main.window.ui:61 data/ui/staff.list.ui:23 msgid "Staff" msgstr "Empleados" @@ -267,16 +288,19 @@ msgid "Minimum People" msgstr "Mínima Personas" #: data/ui/tour.list.ui:124 data/ui/tour.editor.ui:186 +#: data/ui/staff.list.ui:124 data/ui/staff.editor.ui:161 #: data/ui/place.editor.ui:150 msgid "City" msgstr "Ciudad" #: data/ui/tour.list.ui:138 data/ui/tour.editor.ui:134 +#: data/ui/staff.list.ui:138 data/ui/staff.editor.ui:111 #: data/ui/place.editor.ui:116 msgid "Region" msgstr "Región" #: data/ui/tour.list.ui:170 data/ui/tourist.list.ui:128 +#: data/ui/staff.list.ui:170 msgid "Edit" msgstr "Editar" @@ -285,7 +309,7 @@ msgid "Edit selected tour." msgstr "Editar el tour seleccionado." #: data/ui/tour.list.ui:185 data/ui/tour.places.ui:212 -#: data/ui/tourist.list.ui:143 +#: data/ui/tourist.list.ui:143 data/ui/staff.list.ui:185 msgid "New" msgstr "Nuevo" @@ -294,7 +318,8 @@ msgid "Create a new tour." msgstr "Crear un tour nuevo." #: data/ui/tour.list.ui:199 data/ui/tourist.list.ui:157 -#: data/ui/tourist.illnesses.ui:128 +#: data/ui/tourist.illnesses.ui:128 data/ui/staff.list.ui:199 +#: data/ui/staff.specialties.ui:128 msgid "Delete" msgstr "Borrar" @@ -304,13 +329,16 @@ msgstr "Borrar el tour seleccionado." #: data/ui/tour.list.ui:214 data/ui/tour.places.ui:198 #: data/ui/tourist.list.ui:172 data/ui/tourist.illnesses.ui:114 -#: data/ui/tourist.illness.editor.ui:73 data/ui/query.window.ui:66 +#: data/ui/tourist.illness.editor.ui:73 data/ui/staff.list.ui:214 +#: data/ui/staff.specialties.ui:114 data/ui/staff.specialty.editor.ui:73 +#: data/ui/query.window.ui:66 msgid "Close" msgstr "Cerrar" #: data/ui/tour.list.ui:218 data/ui/tour.places.ui:202 #: data/ui/tourist.list.ui:176 data/ui/tourist.illnesses.ui:118 -#: data/ui/tourist.illness.editor.ui:77 +#: data/ui/tourist.illness.editor.ui:77 data/ui/staff.list.ui:218 +#: data/ui/staff.specialties.ui:118 data/ui/staff.specialty.editor.ui:77 msgid "Close this window." msgstr "Cerrar esta ventana." @@ -318,17 +346,19 @@ msgstr "Cerrar esta ventana." msgid "Tour Editor" msgstr "Editor de Tour" -#: data/ui/tour.editor.ui:233 data/ui/place.editor.ui:197 +#: data/ui/tour.editor.ui:233 data/ui/staff.editor.ui:185 +#: data/ui/place.editor.ui:197 msgid "Create a new region by typing here." msgstr "Crear una nueva región con escribir aquí." -#: data/ui/tour.editor.ui:261 data/ui/place.editor.ui:225 +#: data/ui/tour.editor.ui:261 data/ui/staff.editor.ui:213 +#: data/ui/place.editor.ui:225 msgid "Create a new city by typing here." msgstr "Crear una nueva ciudad con escribir aquí." #: data/ui/tour.editor.ui:286 data/ui/tour.place.editor.ui:149 #: data/ui/tour.assign.vehicle.ui:67 data/ui/tourist.editor.ui:131 -#: data/ui/place.editor.ui:250 +#: data/ui/staff.editor.ui:238 data/ui/place.editor.ui:250 msgid "Cancel" msgstr "Cancelar" @@ -354,7 +384,7 @@ msgstr "Asignar un vehículo a este tour." #: data/ui/tour.editor.ui:343 data/ui/tour.place.editor.ui:168 #: data/ui/tour.assign.vehicle.ui:86 data/ui/tourist.editor.ui:169 -#: data/ui/place.editor.ui:269 +#: data/ui/staff.editor.ui:276 data/ui/place.editor.ui:269 msgid "Save" msgstr "Guardar" @@ -391,7 +421,8 @@ msgid "Departure Time" msgstr "Hora de Salida" #: data/ui/tour.places.ui:184 data/ui/tourist.illnesses.ui:100 -#: data/ui/tourist.illness.editor.ui:92 +#: data/ui/tourist.illness.editor.ui:92 data/ui/staff.specialties.ui:100 +#: data/ui/staff.specialty.editor.ui:92 msgid "Add" msgstr "Agregar" @@ -424,7 +455,7 @@ msgid "Cancel the modification of this place." msgstr "Cancelar la modificación de este lugar." #: data/ui/tour.place.editor.ui:172 data/ui/tourist.illness.editor.ui:96 -#: data/ui/place.editor.ui:273 +#: data/ui/staff.specialty.editor.ui:96 data/ui/place.editor.ui:273 msgid "Save this place." msgstr "Guardar este lugar." @@ -520,10 +551,12 @@ msgid "The licence plate, make, year, and capacity of the vehicle." msgstr "La patente, marca, año y capacidad del vehículo." #: data/ui/tourist.list.ui:68 data/ui/tourist.editor.ui:60 +#: data/ui/staff.list.ui:68 data/ui/staff.editor.ui:46 msgid "RUN" msgstr "RUN" #: data/ui/tourist.list.ui:82 data/ui/tourist.editor.ui:93 +#: data/ui/staff.list.ui:82 data/ui/staff.editor.ui:79 msgid "Name" msgstr "Nombre" @@ -552,6 +585,7 @@ msgid "Cancel the modification of this tourist." msgstr "Cancelar la modificación de esta turista." #: data/ui/tourist.editor.ui:150 data/ui/tourist.illnesses.ui:23 +#: data/ui/staff.specialties.ui:23 msgid "Illnesses" msgstr "Enfermedades" @@ -564,21 +598,62 @@ msgid "Save this tourist." msgstr "Guardar esta turista." #: data/ui/tourist.illnesses.ui:68 data/ui/tourist.illness.editor.ui:53 +#: data/ui/staff.specialties.ui:68 data/ui/staff.specialty.editor.ui:53 msgid "Illness" msgstr "Enfermedad" -#: data/ui/tourist.illnesses.ui:104 +#: data/ui/tourist.illnesses.ui:104 data/ui/staff.specialties.ui:104 msgid "Add new illnesses." msgstr "Agregar nuevo enfermedades." -#: data/ui/tourist.illnesses.ui:132 +#: data/ui/tourist.illnesses.ui:132 data/ui/staff.specialties.ui:132 msgid "Delete illnesses." msgstr "Borrar enfermedades." -#: data/ui/tourist.illness.editor.ui:22 +#: data/ui/tourist.illness.editor.ui:22 data/ui/staff.specialty.editor.ui:22 msgid "Add Illness" msgstr "Agregar Enfermedad" +#: data/ui/staff.list.ui:96 data/ui/staff.editor.ui:95 +msgid "Street" +msgstr "Calle" + +#: data/ui/staff.list.ui:110 data/ui/staff.editor.ui:309 +msgid "Number" +msgstr "Numero" + +#: data/ui/staff.list.ui:175 +msgid "Edit selected staff member." +msgstr "Editar la guía seleccionada." + +#: data/ui/staff.list.ui:189 +msgid "Create a new staff member." +msgstr "Crear una guía nueva." + +#: data/ui/staff.list.ui:204 +msgid "Delete selected staff member." +msgstr "Borrar la guía seleccionada." + +#: data/ui/staff.editor.ui:22 +msgid "Staff Editor" +msgstr "Editor de Staff" + +#: data/ui/staff.editor.ui:242 +msgid "Cancel the modification of this guide." +msgstr "Cancelar la modificación de esta guia." + +#: data/ui/staff.editor.ui:257 +msgid "Specialties" +msgstr "Especialidades" + +#: data/ui/staff.editor.ui:261 +msgid "Add specialties to this guide." +msgstr "Agregar especialidades a este guia." + +#: data/ui/staff.editor.ui:280 +msgid "Save this guide." +msgstr "Guardar esta guia." + #: data/ui/place.editor.ui:27 msgid "Place Editor" msgstr "Editor de Lugar" diff --git a/po/es_CL.po b/po/es_CL.po index 0d9d3be..48467bb 100644 --- a/po/es_CL.po +++ b/po/es_CL.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: sernatur\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-01-21 00:47-0300\n" -"PO-Revision-Date: 2019-01-21 00:57-0300\n" +"POT-Creation-Date: 2019-01-21 03:25-0300\n" +"PO-Revision-Date: 2019-01-21 03:29-0300\n" "Last-Translator: Chris Cromer \n" "Language-Team: none\n" "Language: es\n" @@ -93,16 +93,20 @@ msgstr "" msgid "SERNATUR version: " msgstr "Versión de SERNATUR: " -#: src/main_window.vala:227 +#: src/main_window.vala:238 msgid "Error: Could not connect to the database!" msgstr "Puta la wea: No se puede conectar al base de datos!" -#: src/main_window.vala:239 src/tour_list.vala:233 src/tour_editor.vala:231 +#: src/main_window.vala:250 src/tour_list.vala:233 src/tour_editor.vala:231 #: src/tour_editor.vala:248 src/tour_editor.vala:280 src/tour_editor.vala:297 #: src/tour_editor.vala:329 src/tour_editor.vala:346 #: src/tour_assign_vehicle.vala:99 src/tourist_list.vala:206 #: src/tourist_editor.vala:99 src/tourist_editor.vala:112 #: src/tourist_editor.vala:128 src/tourist_editor.vala:141 +#: src/staff_editor.vala:227 src/staff_editor.vala:240 +#: src/staff_editor.vala:256 src/staff_editor.vala:269 +#: src/staff_editor.vala:291 src/staff_editor.vala:308 +#: src/staff_editor.vala:340 src/staff_editor.vala:357 msgid "Error" msgstr "Puta la wea" @@ -132,20 +136,20 @@ msgstr "Error: El nombre de la wea no puede estar en blanco!" msgid "Error: A tour named \"%s\" already exists!" msgstr "Error: Una wea con el nombre \"%s\" ya existe!" -#: src/tour_editor.vala:276 +#: src/tour_editor.vala:276 src/staff_editor.vala:287 msgid "Error: City name cannot be left blank!" msgstr "Error: El nombre de la wea no puede estar en blanco!" -#: src/tour_editor.vala:293 +#: src/tour_editor.vala:293 src/staff_editor.vala:304 #, c-format msgid "Error: A city named \"%s\" already exists!" msgstr "Error: Una wea con el nombre \"%s\" ya existe!" -#: src/tour_editor.vala:325 +#: src/tour_editor.vala:325 src/staff_editor.vala:336 msgid "Error: Region name cannot be left blank!" msgstr "Error: El nombre de la wea no puede estar en blanco!" -#: src/tour_editor.vala:342 +#: src/tour_editor.vala:342 src/staff_editor.vala:353 #, c-format msgid "Error: A region named \"%s\" already exists!" msgstr "Error: Una wea con el nombre \"%s\" ya existe!" @@ -175,7 +179,7 @@ msgstr "" "Error: No se puede borrar la turista \"%s\" porque hay información asociado " "con la turista!" -#: src/tourist_editor.vala:95 +#: src/tourist_editor.vala:95 src/staff_editor.vala:223 msgid "Error: Tourist name cannot be left blank!" msgstr "Error: El nombre de la turista no puede estar en blanco!" @@ -183,7 +187,7 @@ msgstr "Error: El nombre de la turista no puede estar en blanco!" msgid "Error: Tourist RUN cannot be left blank!" msgstr "Error: El RUN de la turista no puede estar en blanco!" -#: src/tourist_editor.vala:124 +#: src/tourist_editor.vala:124 src/staff_editor.vala:252 msgid "Error: The RUN entered is invalid!" msgstr "Error: El RUN ingresado es invalido!" @@ -201,6 +205,23 @@ msgid "Are you sure you wish to delete these illnesses from this tourist?" msgstr "" "¿Usted está seguro que quiere borrar estos enfermedades de esta turista?" +#: src/staff_list.vala:190 +msgid "Are you sure you wish to delete this staff member?" +msgstr "¿Usted está seguro que quiere borrar esta guía?" + +#: src/staff_list.vala:197 +msgid "Are you sure you wish to delete these staff members?" +msgstr "¿Usted está seguro que quiere borrar estas guías?" + +#: src/staff_editor.vala:236 +msgid "Error: Staff member RUN cannot be left blank!" +msgstr "Error: El RUN de la guía no puede estar en blanco!" + +#: src/staff_editor.vala:265 +#, c-format +msgid "Error: A staff member with the RUN \"%s\" already exists!" +msgstr "Error: Una guía con el RUN \"%s\" ya existe!" + #: src/query_window.vala:290 data/ui/main.window.ui:105 msgid "(Q1) Regions with discounts" msgstr "(Q1) Regiones sin descuentos" @@ -229,7 +250,7 @@ msgstr "_Menú" msgid "Tours" msgstr "Tours" -#: data/ui/main.window.ui:61 +#: data/ui/main.window.ui:61 data/ui/staff.list.ui:23 msgid "Staff" msgstr "Weones flojos" @@ -267,16 +288,19 @@ msgid "Minimum People" msgstr "Mínima de Weones" #: data/ui/tour.list.ui:124 data/ui/tour.editor.ui:186 +#: data/ui/staff.list.ui:124 data/ui/staff.editor.ui:161 #: data/ui/place.editor.ui:150 msgid "City" msgstr "Ciudad" #: data/ui/tour.list.ui:138 data/ui/tour.editor.ui:134 +#: data/ui/staff.list.ui:138 data/ui/staff.editor.ui:111 #: data/ui/place.editor.ui:116 msgid "Region" msgstr "Región" #: data/ui/tour.list.ui:170 data/ui/tourist.list.ui:128 +#: data/ui/staff.list.ui:170 msgid "Edit" msgstr "Editar la wea" @@ -285,7 +309,7 @@ msgid "Edit selected tour." msgstr "Editar la wea seleccionado." #: data/ui/tour.list.ui:185 data/ui/tour.places.ui:212 -#: data/ui/tourist.list.ui:143 +#: data/ui/tourist.list.ui:143 data/ui/staff.list.ui:185 msgid "New" msgstr "Nueva wea" @@ -294,7 +318,8 @@ msgid "Create a new tour." msgstr "Crear una wea nueva." #: data/ui/tour.list.ui:199 data/ui/tourist.list.ui:157 -#: data/ui/tourist.illnesses.ui:128 +#: data/ui/tourist.illnesses.ui:128 data/ui/staff.list.ui:199 +#: data/ui/staff.specialties.ui:128 msgid "Delete" msgstr "Borrar la wea" @@ -304,13 +329,16 @@ msgstr "Borrar la wea seleccionado." #: data/ui/tour.list.ui:214 data/ui/tour.places.ui:198 #: data/ui/tourist.list.ui:172 data/ui/tourist.illnesses.ui:114 -#: data/ui/tourist.illness.editor.ui:73 data/ui/query.window.ui:66 +#: data/ui/tourist.illness.editor.ui:73 data/ui/staff.list.ui:214 +#: data/ui/staff.specialties.ui:114 data/ui/staff.specialty.editor.ui:73 +#: data/ui/query.window.ui:66 msgid "Close" msgstr "Cerrar la wea" #: data/ui/tour.list.ui:218 data/ui/tour.places.ui:202 #: data/ui/tourist.list.ui:176 data/ui/tourist.illnesses.ui:118 -#: data/ui/tourist.illness.editor.ui:77 +#: data/ui/tourist.illness.editor.ui:77 data/ui/staff.list.ui:218 +#: data/ui/staff.specialties.ui:118 data/ui/staff.specialty.editor.ui:77 msgid "Close this window." msgstr "Cerrar la wea." @@ -318,17 +346,19 @@ msgstr "Cerrar la wea." msgid "Tour Editor" msgstr "Editor de la Wea" -#: data/ui/tour.editor.ui:233 data/ui/place.editor.ui:197 +#: data/ui/tour.editor.ui:233 data/ui/staff.editor.ui:185 +#: data/ui/place.editor.ui:197 msgid "Create a new region by typing here." msgstr "Crear una nueva wea con escribir aquí." -#: data/ui/tour.editor.ui:261 data/ui/place.editor.ui:225 +#: data/ui/tour.editor.ui:261 data/ui/staff.editor.ui:213 +#: data/ui/place.editor.ui:225 msgid "Create a new city by typing here." msgstr "Crear una nueva wea con escribir aquí." #: data/ui/tour.editor.ui:286 data/ui/tour.place.editor.ui:149 #: data/ui/tour.assign.vehicle.ui:67 data/ui/tourist.editor.ui:131 -#: data/ui/place.editor.ui:250 +#: data/ui/staff.editor.ui:238 data/ui/place.editor.ui:250 msgid "Cancel" msgstr "Cancelar la wea" @@ -354,7 +384,7 @@ msgstr "Asignar un vehículo a esta wea." #: data/ui/tour.editor.ui:343 data/ui/tour.place.editor.ui:168 #: data/ui/tour.assign.vehicle.ui:86 data/ui/tourist.editor.ui:169 -#: data/ui/place.editor.ui:269 +#: data/ui/staff.editor.ui:276 data/ui/place.editor.ui:269 msgid "Save" msgstr "Guardar la wea" @@ -391,7 +421,8 @@ msgid "Departure Time" msgstr "Hora de Salida" #: data/ui/tour.places.ui:184 data/ui/tourist.illnesses.ui:100 -#: data/ui/tourist.illness.editor.ui:92 +#: data/ui/tourist.illness.editor.ui:92 data/ui/staff.specialties.ui:100 +#: data/ui/staff.specialty.editor.ui:92 msgid "Add" msgstr "Agregar una wea" @@ -424,7 +455,7 @@ msgid "Cancel the modification of this place." msgstr "Cancelar la modificación de esta wea." #: data/ui/tour.place.editor.ui:172 data/ui/tourist.illness.editor.ui:96 -#: data/ui/place.editor.ui:273 +#: data/ui/staff.specialty.editor.ui:96 data/ui/place.editor.ui:273 msgid "Save this place." msgstr "Guardar esta wea." @@ -520,10 +551,12 @@ msgid "The licence plate, make, year, and capacity of the vehicle." msgstr "La patente, marca, año y capacidad de la wea." #: data/ui/tourist.list.ui:68 data/ui/tourist.editor.ui:60 +#: data/ui/staff.list.ui:68 data/ui/staff.editor.ui:46 msgid "RUN" msgstr "RUN" #: data/ui/tourist.list.ui:82 data/ui/tourist.editor.ui:93 +#: data/ui/staff.list.ui:82 data/ui/staff.editor.ui:79 msgid "Name" msgstr "Nombre" @@ -552,6 +585,7 @@ msgid "Cancel the modification of this tourist." msgstr "Cancelar la modificación de esta turista." #: data/ui/tourist.editor.ui:150 data/ui/tourist.illnesses.ui:23 +#: data/ui/staff.specialties.ui:23 msgid "Illnesses" msgstr "Enfermedades" @@ -564,21 +598,62 @@ msgid "Save this tourist." msgstr "Guardar esta turista." #: data/ui/tourist.illnesses.ui:68 data/ui/tourist.illness.editor.ui:53 +#: data/ui/staff.specialties.ui:68 data/ui/staff.specialty.editor.ui:53 msgid "Illness" msgstr "Enfermedad" -#: data/ui/tourist.illnesses.ui:104 +#: data/ui/tourist.illnesses.ui:104 data/ui/staff.specialties.ui:104 msgid "Add new illnesses." msgstr "Agregar nuevo enfermedades." -#: data/ui/tourist.illnesses.ui:132 +#: data/ui/tourist.illnesses.ui:132 data/ui/staff.specialties.ui:132 msgid "Delete illnesses." msgstr "Borrar enfermedades." -#: data/ui/tourist.illness.editor.ui:22 +#: data/ui/tourist.illness.editor.ui:22 data/ui/staff.specialty.editor.ui:22 msgid "Add Illness" msgstr "Agregar Enfermedad" +#: data/ui/staff.list.ui:96 data/ui/staff.editor.ui:95 +msgid "Street" +msgstr "Calle" + +#: data/ui/staff.list.ui:110 data/ui/staff.editor.ui:309 +msgid "Number" +msgstr "Numero" + +#: data/ui/staff.list.ui:175 +msgid "Edit selected staff member." +msgstr "Editar la guía seleccionada." + +#: data/ui/staff.list.ui:189 +msgid "Create a new staff member." +msgstr "Crear una guía nueva." + +#: data/ui/staff.list.ui:204 +msgid "Delete selected staff member." +msgstr "Borrar la guía seleccionada." + +#: data/ui/staff.editor.ui:22 +msgid "Staff Editor" +msgstr "Editor de Staff" + +#: data/ui/staff.editor.ui:242 +msgid "Cancel the modification of this guide." +msgstr "Cancelar la modificación de esta guia." + +#: data/ui/staff.editor.ui:257 +msgid "Specialties" +msgstr "Especialidades" + +#: data/ui/staff.editor.ui:261 +msgid "Add specialties to this guide." +msgstr "Agregar especialidades a este guia." + +#: data/ui/staff.editor.ui:280 +msgid "Save this guide." +msgstr "Guardar esta guia." + #: data/ui/place.editor.ui:27 msgid "Place Editor" msgstr "Editor de la Wea" diff --git a/po/sernatur.pot b/po/sernatur.pot index ca17821..83422d5 100644 --- a/po/sernatur.pot +++ b/po/sernatur.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: sernatur\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-01-21 00:47-0300\n" +"POT-Creation-Date: 2019-01-21 03:25-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -88,16 +88,20 @@ msgstr "" msgid "SERNATUR version: " msgstr "" -#: src/main_window.vala:227 +#: src/main_window.vala:238 msgid "Error: Could not connect to the database!" msgstr "" -#: src/main_window.vala:239 src/tour_list.vala:233 src/tour_editor.vala:231 +#: src/main_window.vala:250 src/tour_list.vala:233 src/tour_editor.vala:231 #: src/tour_editor.vala:248 src/tour_editor.vala:280 src/tour_editor.vala:297 #: src/tour_editor.vala:329 src/tour_editor.vala:346 #: src/tour_assign_vehicle.vala:99 src/tourist_list.vala:206 #: src/tourist_editor.vala:99 src/tourist_editor.vala:112 #: src/tourist_editor.vala:128 src/tourist_editor.vala:141 +#: src/staff_editor.vala:227 src/staff_editor.vala:240 +#: src/staff_editor.vala:256 src/staff_editor.vala:269 +#: src/staff_editor.vala:291 src/staff_editor.vala:308 +#: src/staff_editor.vala:340 src/staff_editor.vala:357 msgid "Error" msgstr "" @@ -125,20 +129,20 @@ msgstr "" msgid "Error: A tour named \"%s\" already exists!" msgstr "" -#: src/tour_editor.vala:276 +#: src/tour_editor.vala:276 src/staff_editor.vala:287 msgid "Error: City name cannot be left blank!" msgstr "" -#: src/tour_editor.vala:293 +#: src/tour_editor.vala:293 src/staff_editor.vala:304 #, c-format msgid "Error: A city named \"%s\" already exists!" msgstr "" -#: src/tour_editor.vala:325 +#: src/tour_editor.vala:325 src/staff_editor.vala:336 msgid "Error: Region name cannot be left blank!" msgstr "" -#: src/tour_editor.vala:342 +#: src/tour_editor.vala:342 src/staff_editor.vala:353 #, c-format msgid "Error: A region named \"%s\" already exists!" msgstr "" @@ -166,7 +170,7 @@ msgid "" "associated with them!" msgstr "" -#: src/tourist_editor.vala:95 +#: src/tourist_editor.vala:95 src/staff_editor.vala:223 msgid "Error: Tourist name cannot be left blank!" msgstr "" @@ -174,7 +178,7 @@ msgstr "" msgid "Error: Tourist RUN cannot be left blank!" msgstr "" -#: src/tourist_editor.vala:124 +#: src/tourist_editor.vala:124 src/staff_editor.vala:252 msgid "Error: The RUN entered is invalid!" msgstr "" @@ -191,6 +195,23 @@ msgstr "" msgid "Are you sure you wish to delete these illnesses from this tourist?" msgstr "" +#: src/staff_list.vala:190 +msgid "Are you sure you wish to delete this staff member?" +msgstr "" + +#: src/staff_list.vala:197 +msgid "Are you sure you wish to delete these staff members?" +msgstr "" + +#: src/staff_editor.vala:236 +msgid "Error: Staff member RUN cannot be left blank!" +msgstr "" + +#: src/staff_editor.vala:265 +#, c-format +msgid "Error: A staff member with the RUN \"%s\" already exists!" +msgstr "" + #: src/query_window.vala:290 data/ui/main.window.ui:105 msgid "(Q1) Regions with discounts" msgstr "" @@ -219,7 +240,7 @@ msgstr "" msgid "Tours" msgstr "" -#: data/ui/main.window.ui:61 +#: data/ui/main.window.ui:61 data/ui/staff.list.ui:23 msgid "Staff" msgstr "" @@ -257,16 +278,19 @@ msgid "Minimum People" msgstr "" #: data/ui/tour.list.ui:124 data/ui/tour.editor.ui:186 +#: data/ui/staff.list.ui:124 data/ui/staff.editor.ui:161 #: data/ui/place.editor.ui:150 msgid "City" msgstr "" #: data/ui/tour.list.ui:138 data/ui/tour.editor.ui:134 +#: data/ui/staff.list.ui:138 data/ui/staff.editor.ui:111 #: data/ui/place.editor.ui:116 msgid "Region" msgstr "" #: data/ui/tour.list.ui:170 data/ui/tourist.list.ui:128 +#: data/ui/staff.list.ui:170 msgid "Edit" msgstr "" @@ -275,7 +299,7 @@ msgid "Edit selected tour." msgstr "" #: data/ui/tour.list.ui:185 data/ui/tour.places.ui:212 -#: data/ui/tourist.list.ui:143 +#: data/ui/tourist.list.ui:143 data/ui/staff.list.ui:185 msgid "New" msgstr "" @@ -284,7 +308,8 @@ msgid "Create a new tour." msgstr "" #: data/ui/tour.list.ui:199 data/ui/tourist.list.ui:157 -#: data/ui/tourist.illnesses.ui:128 +#: data/ui/tourist.illnesses.ui:128 data/ui/staff.list.ui:199 +#: data/ui/staff.specialties.ui:128 msgid "Delete" msgstr "" @@ -294,13 +319,16 @@ msgstr "" #: data/ui/tour.list.ui:214 data/ui/tour.places.ui:198 #: data/ui/tourist.list.ui:172 data/ui/tourist.illnesses.ui:114 -#: data/ui/tourist.illness.editor.ui:73 data/ui/query.window.ui:66 +#: data/ui/tourist.illness.editor.ui:73 data/ui/staff.list.ui:214 +#: data/ui/staff.specialties.ui:114 data/ui/staff.specialty.editor.ui:73 +#: data/ui/query.window.ui:66 msgid "Close" msgstr "" #: data/ui/tour.list.ui:218 data/ui/tour.places.ui:202 #: data/ui/tourist.list.ui:176 data/ui/tourist.illnesses.ui:118 -#: data/ui/tourist.illness.editor.ui:77 +#: data/ui/tourist.illness.editor.ui:77 data/ui/staff.list.ui:218 +#: data/ui/staff.specialties.ui:118 data/ui/staff.specialty.editor.ui:77 msgid "Close this window." msgstr "" @@ -308,17 +336,19 @@ msgstr "" msgid "Tour Editor" msgstr "" -#: data/ui/tour.editor.ui:233 data/ui/place.editor.ui:197 +#: data/ui/tour.editor.ui:233 data/ui/staff.editor.ui:185 +#: data/ui/place.editor.ui:197 msgid "Create a new region by typing here." msgstr "" -#: data/ui/tour.editor.ui:261 data/ui/place.editor.ui:225 +#: data/ui/tour.editor.ui:261 data/ui/staff.editor.ui:213 +#: data/ui/place.editor.ui:225 msgid "Create a new city by typing here." msgstr "" #: data/ui/tour.editor.ui:286 data/ui/tour.place.editor.ui:149 #: data/ui/tour.assign.vehicle.ui:67 data/ui/tourist.editor.ui:131 -#: data/ui/place.editor.ui:250 +#: data/ui/staff.editor.ui:238 data/ui/place.editor.ui:250 msgid "Cancel" msgstr "" @@ -344,7 +374,7 @@ msgstr "" #: data/ui/tour.editor.ui:343 data/ui/tour.place.editor.ui:168 #: data/ui/tour.assign.vehicle.ui:86 data/ui/tourist.editor.ui:169 -#: data/ui/place.editor.ui:269 +#: data/ui/staff.editor.ui:276 data/ui/place.editor.ui:269 msgid "Save" msgstr "" @@ -381,7 +411,8 @@ msgid "Departure Time" msgstr "" #: data/ui/tour.places.ui:184 data/ui/tourist.illnesses.ui:100 -#: data/ui/tourist.illness.editor.ui:92 +#: data/ui/tourist.illness.editor.ui:92 data/ui/staff.specialties.ui:100 +#: data/ui/staff.specialty.editor.ui:92 msgid "Add" msgstr "" @@ -414,7 +445,7 @@ msgid "Cancel the modification of this place." msgstr "" #: data/ui/tour.place.editor.ui:172 data/ui/tourist.illness.editor.ui:96 -#: data/ui/place.editor.ui:273 +#: data/ui/staff.specialty.editor.ui:96 data/ui/place.editor.ui:273 msgid "Save this place." msgstr "" @@ -510,10 +541,12 @@ msgid "The licence plate, make, year, and capacity of the vehicle." msgstr "" #: data/ui/tourist.list.ui:68 data/ui/tourist.editor.ui:60 +#: data/ui/staff.list.ui:68 data/ui/staff.editor.ui:46 msgid "RUN" msgstr "" #: data/ui/tourist.list.ui:82 data/ui/tourist.editor.ui:93 +#: data/ui/staff.list.ui:82 data/ui/staff.editor.ui:79 msgid "Name" msgstr "" @@ -542,6 +575,7 @@ msgid "Cancel the modification of this tourist." msgstr "" #: data/ui/tourist.editor.ui:150 data/ui/tourist.illnesses.ui:23 +#: data/ui/staff.specialties.ui:23 msgid "Illnesses" msgstr "" @@ -554,21 +588,62 @@ msgid "Save this tourist." msgstr "" #: data/ui/tourist.illnesses.ui:68 data/ui/tourist.illness.editor.ui:53 +#: data/ui/staff.specialties.ui:68 data/ui/staff.specialty.editor.ui:53 msgid "Illness" msgstr "" -#: data/ui/tourist.illnesses.ui:104 +#: data/ui/tourist.illnesses.ui:104 data/ui/staff.specialties.ui:104 msgid "Add new illnesses." msgstr "" -#: data/ui/tourist.illnesses.ui:132 +#: data/ui/tourist.illnesses.ui:132 data/ui/staff.specialties.ui:132 msgid "Delete illnesses." msgstr "" -#: data/ui/tourist.illness.editor.ui:22 +#: data/ui/tourist.illness.editor.ui:22 data/ui/staff.specialty.editor.ui:22 msgid "Add Illness" msgstr "" +#: data/ui/staff.list.ui:96 data/ui/staff.editor.ui:95 +msgid "Street" +msgstr "" + +#: data/ui/staff.list.ui:110 data/ui/staff.editor.ui:309 +msgid "Number" +msgstr "" + +#: data/ui/staff.list.ui:175 +msgid "Edit selected staff member." +msgstr "" + +#: data/ui/staff.list.ui:189 +msgid "Create a new staff member." +msgstr "" + +#: data/ui/staff.list.ui:204 +msgid "Delete selected staff member." +msgstr "" + +#: data/ui/staff.editor.ui:22 +msgid "Staff Editor" +msgstr "" + +#: data/ui/staff.editor.ui:242 +msgid "Cancel the modification of this guide." +msgstr "" + +#: data/ui/staff.editor.ui:257 +msgid "Specialties" +msgstr "" + +#: data/ui/staff.editor.ui:261 +msgid "Add specialties to this guide." +msgstr "" + +#: data/ui/staff.editor.ui:280 +msgid "Save this guide." +msgstr "" + #: data/ui/place.editor.ui:27 msgid "Place Editor" msgstr "" diff --git a/src/main_window.vala b/src/main_window.vala index 49e4d5d..dc7ef6c 100644 --- a/src/main_window.vala +++ b/src/main_window.vala @@ -38,6 +38,11 @@ namespace Sernatur { */ [GtkChild] private Gtk.MenuItem tours; + /** + * The staff menu item + */ + [GtkChild] + private Gtk.MenuItem staff; /** * The tourists menu item */ @@ -135,7 +140,13 @@ namespace Sernatur { tour_list.initialize (); tour_list.show_all (); } - if (menu_item == tourists) { + else if (menu_item == staff) { + var staff_list = new StaffList (application, conn); + staff_list.set_transient_for (this); // Set this window as the parent of the new window + staff_list.initialize (); + staff_list.show_all (); + } + else if (menu_item == tourists) { var tourist_list = new TouristList (application, conn); tourist_list.set_transient_for (this); // Set this window as the parent of the new window tourist_list.initialize (); diff --git a/src/meson.build b/src/meson.build index 3480cc9..21178d0 100644 --- a/src/meson.build +++ b/src/meson.build @@ -25,6 +25,8 @@ vala_sources = files( 'tourist_editor.vala', 'tourist_illnesses.vala', 'tourist_illness_editor.vala', + 'staff_list.vala', + 'staff_editor.vala', 'place_editor.vala', 'queries.vala', 'query_window.vala') @@ -33,6 +35,7 @@ sources = vala_sources sources += main_gresource sources += tour_gresource sources += tourist_gresource +sources += staff_gresource sources += place_gresource sources += query_gresource sources += config_data_file @@ -41,6 +44,7 @@ vala_args = ['--vapidir=' + join_paths(meson.source_root(), 'vapi')] vala_args += ['--gresources=' + join_paths(meson.source_root(), 'data/ui/main.gresource.xml')] vala_args += ['--gresources=' + join_paths(meson.source_root(), 'data/ui/tour.gresource.xml')] vala_args += ['--gresources=' + join_paths(meson.source_root(), 'data/ui/tourist.gresource.xml')] +vala_args += ['--gresources=' + join_paths(meson.source_root(), 'data/ui/staff.gresource.xml')] vala_args += ['--gresources=' + join_paths(meson.source_root(), 'data/ui/place.gresource.xml')] vala_args += ['--gresources=' + join_paths(meson.source_root(), 'data/ui/query.gresource.xml')] diff --git a/src/staff_editor.vala b/src/staff_editor.vala new file mode 100644 index 0000000..55b7e7b --- /dev/null +++ b/src/staff_editor.vala @@ -0,0 +1,672 @@ +/* + * Copyright 2018-2019 Chris Cromer + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +namespace Sernatur { + using LibSernatur.DB; + using LibSernatur.Misc; + + /** + * The staff editor window class + */ + [GtkTemplate (ui = "/cl/cromer/ubb/sernatur/staff.editor.ui")] + public class StaffEditor : Gtk.ApplicationWindow { + /** + * The open database connection + */ + private Connection conn; + /** + * The staff to edit + */ + private Guia staff; + /** + * The city data stored in the list store + */ + private enum CityColumn { + /** + * The city name + */ + CITY_NAME, + /** + * The city object + */ + CITY, + /** + * The number of colums in this enum + */ + N_COLUMNS + } + /** + * The region data stored in the list store + */ + private enum RegionColumn { + /** + * The region name + */ + REGION_NAME, + /** + * The region object + */ + REGION, + /** + * The number of colums in this enum + */ + N_COLUMNS + } + /** + * The staff run + */ + [GtkChild] + private Gtk.Entry run; + /** + * The staff name + */ + [GtkChild] + private Gtk.Entry guide_name; + /** + * The street + */ + [GtkChild] + private Gtk.Entry street; + /** + * The number + */ + [GtkChild] + private Gtk.Entry number; + /** + * The region + */ + [GtkChild] + private Gtk.ComboBoxText region; + /** + * The city + */ + [GtkChild] + private Gtk.ComboBoxText city; + /** + * The city entry + */ + [GtkChild] + private Gtk.Entry city_entry; + /** + * The save button + */ + [GtkChild] + private Gtk.Button save; + /** + * The illnesses button + */ + [GtkChild] + private Gtk.Button specialties; + /** + * The cancel button + */ + [GtkChild] + private Gtk.Button cancel; + /** + * The list that stores the regions for the combo box + */ + private Gtk.ListStore region_list_store; + /** + * The list that stores the cities for the combo box + */ + private Gtk.ListStore city_list_store = null; + /** + * A list of associated places, this is only used in the case of a new staff + */ + //private List list_asociado = null; + /** + * A saved copy of the original RUN + */ + private string original_run; + /** + * A list of the cities from the database + */ + private List cities; + /** + * A list of the regions from the database + */ + private List regions; + /** + * This signal is called when a staff is saved + */ + public signal void save_staff (); + + /** + * Called when a combobox changes + * @param combobox The combobox that changed + */ + [GtkCallback] + public void on_changed_combobox (Gtk.ComboBox combobox) { + if (combobox == region) { + Gtk.TreeIter iter; + region.get_active_iter (out iter); + Region temp_region; + if (region_list_store.iter_is_valid (iter)) { + // The region is from the list, not typed + region_list_store.get (iter, + RegionColumn.REGION, out temp_region); + staff.ciudad.region = temp_region; + if (city_list_store != null && staff.ciudad.region.id_region != 0) { + reset_city (); + } + } + } + } + + /** + * Reset the city dropdown + */ + private void reset_city () { + try { + cities = Ciudad.get_all_ciudades_in_region (conn, staff.ciudad.region.id_region); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + + if (cities.length () > 0) { + cities.sort_with_data ((a, b) => { + return strcmp (a.nombre_ciudad, b.nombre_ciudad); + }); + + if (city_list_store.iter_n_children (null) > 0) { + // If there are more than 0 rows clear it + city_list_store.clear (); + } + cities.foreach ((entry) => { + Gtk.TreeIter iter; + city_list_store.append (out iter); + city_list_store.set (iter, + CityColumn.CITY_NAME, entry.nombre_ciudad, + CityColumn.CITY, entry); + if (staff.ciudad.id_ciudad == 0) { + staff.ciudad.id_ciudad = entry.id_ciudad; + staff.ciudad.nombre_ciudad = entry.nombre_ciudad; + } + else { + if (entry.id_ciudad == staff.ciudad.id_ciudad) { + city.set_active_iter (iter); + } + } + }); + } + + city.set_active (-1); + city_entry.set_text (""); + } + + /** + * Validate the staff data before trying to insert it into the database + * @return Returns true if the data is valid + */ + private bool validate_staff_data () { + if (staff.nombre_guia.strip () == "") { + var msg = new Gtk.MessageDialog (this, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, + Gtk.ButtonsType.CLOSE, + _ ("Error: Tourist name cannot be left blank!")); + msg.response.connect ((response_id) => { + msg.destroy (); + }); + msg.set_title (_ ("Error")); + msg.run (); + return false; + } + if (staff.rut_guia.strip () == "") { + var msg = new Gtk.MessageDialog (this, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, + Gtk.ButtonsType.CLOSE, + _ ("Error: Staff member RUN cannot be left blank!")); + msg.response.connect ((response_id) => { + msg.destroy (); + }); + msg.set_title (_ ("Error")); + msg.run (); + return false; + } + try { + new Rut (staff.rut_guia.strip ()); + } + catch (Error e) { + var msg = new Gtk.MessageDialog (this, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, + Gtk.ButtonsType.CLOSE, + _ ("Error: The RUN entered is invalid!")); + msg.response.connect ((response_id) => { + msg.destroy (); + }); + msg.set_title (_ ("Error")); + msg.run (); + return false; + } + if (staff_exists () && staff.rut_guia != original_run) { + var msg = new Gtk.MessageDialog (this, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, + Gtk.ButtonsType.CLOSE, + _ ("Error: A staff member with the RUN \"%s\" already exists!"), staff.rut_guia); + msg.response.connect ((response_id) => { + msg.destroy (); + }); + msg.set_title (_ ("Error")); + msg.run (); + return false; + } + return true; + } + + /** + * Validate the city data before trying to insert it into the database + * @param ciudad The city to validate + * @return Returns true if the data is valid + */ + private bool validate_city_data (Ciudad ciudad) { + if (ciudad.nombre_ciudad.strip () == "") { + var msg = new Gtk.MessageDialog (this, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, + Gtk.ButtonsType.CLOSE, + _ ("Error: City name cannot be left blank!")); + msg.response.connect ((response_id) => { + msg.destroy (); + }); + msg.set_title (_ ("Error")); + msg.run (); + return false; + } + bool list_success = true; + try { + List list = Ciudad.get_all_ciudades (conn); + list.foreach ((entry) => { + if (ciudad.nombre_ciudad.down () == entry.nombre_ciudad.down ()) { + var msg = new Gtk.MessageDialog (this, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, + Gtk.ButtonsType.CLOSE, + _ ("Error: A city named \"%s\" already exists!"), entry.nombre_ciudad); + msg.response.connect ((response_id) => { + msg.destroy (); + }); + msg.set_title (_ ("Error")); + msg.run (); + list_success = false; + } + }); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + return false; + #endif + } + return list_success; + } + + /** + * Validate the region data before trying to insert it into the database + * @param region The region to validate + * @return Returns true if the data is valid + */ + private bool validate_region_data (Region region) { + if (region.nombre_region.strip () == "") { + var msg = new Gtk.MessageDialog (this, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, + Gtk.ButtonsType.CLOSE, + _ ("Error: Region name cannot be left blank!")); + msg.response.connect ((response_id) => { + msg.destroy (); + }); + msg.set_title (_ ("Error")); + msg.run (); + return false; + } + bool list_success = true; + try { + List list = Region.get_all_regiones (conn); + list.foreach ((entry) => { + if (region.nombre_region.down () == entry.nombre_region.down ()) { + var msg = new Gtk.MessageDialog (this, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, + Gtk.ButtonsType.CLOSE, + _ ("Error: A region named \"%s\" already exists!"), entry.nombre_region); + msg.response.connect ((response_id) => { + msg.destroy (); + }); + msg.set_title (_ ("Error")); + msg.run (); + list_success = false; + } + }); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + return false; + #endif + } + return list_success; + } + + private bool staff_exists () { + try { + staff.rut_guia = new Rut (run.get_text ().strip ()).get_clean_rut (); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + try { + Guia guia = Guia.get_guia_by_run (conn, staff.rut_guia); + if (guia == null) { + return false; + } + else { + return true; + } + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + return false; + #endif + } + } + + /** + * This callback is called when a button is clicked + * @param button The button that was clicked + */ + [GtkCallback] + public void on_clicked_button (Gtk.Button button) { + if (button == save) { + if (update_staff_instance () && validate_staff_data ()) { + if (!staff_exists () && original_run == null) { + /*try { + Guia.insert_staff (conn, staff); + save_staff (); // Signal the parent to update itself + this.close (); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + }*/ + } + else { + /*try { + Guia.update_staff (conn, staff, original_run); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + finally { + save_staff (); // Signal the parent to update itself + this.close (); + }*/ + } + } + } + else if (button == specialties) { + /*var staff_illnesses = new TouristIllnesses (application, conn, staff); + staff_illnesses.set_transient_for (this); // Set this window as the parent of the new window + staff_illnesses.initialize (); + staff_illnesses.show_all ();*/ + //staff_illnesses.save_places.connect (on_save_places); + } + else if (button == cancel) { + this.close (); + } + } + + /** + * Called when some associated places are saved and a staff id doesn't exist yet + * @param staff_places The TouristPlaces instance that called this signal + * @param list_asociado The list of new associations + */ + /*private void on_save_places (TouristPlaces staff_places, List list_asociado) { + this.list_asociado = list_asociado.copy (); + places.sensitive = false; + }*/ + + /** + * Called when a vehcile is assigned to the staff, and the staff is not in the database yet + * @param staff_assign_vehicle The TouristAssignVehicle instance that called this signal + * @param requerir_auto The vehicle to assign to this staff + */ + /*private void on_save_vehicle (TouristAssignVehicle staff_assign_vehicle, RequerirAuto? requerir_auto) { + if (requerir_auto != null) { + this.requerir_auto = requerir_auto; + vehicle.sensitive = false; + } + }*/ + + /** + * Update the the staff object with new info from the editor + * @return Returns false if the information is not valid + */ + private bool update_staff_instance () { + staff.rut_guia = run.get_text ().strip (); + staff.nombre_guia = guide_name.get_text ().strip (); + + if (region.get_active () == -1) { + Region new_region = new Region (0, region.get_active_text ().strip ()); + try { + if (validate_region_data (new_region)) { + new_region.id_region = Region.insert_region (conn, new_region); + return update_staff_instance_city (new_region); + } + else { + return false; + } + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + } + else { + Region new_region; + Gtk.TreeIter iter; + region.get_active_iter (out iter); + if (region_list_store.iter_is_valid (iter)) { + region_list_store.get (iter, + RegionColumn.REGION, out new_region); + } + else { + new_region = new Region (); + } + return update_staff_instance_city (new_region); + } + return true; + } + + /** + * This method updates the city part of the tour instance + * @param new_region The region to insert into the city object + * @return Returns false if the information is not valid + */ + private bool update_staff_instance_city (Region new_region) { + Ciudad ciudad; + if (city.get_active () == -1) { + ciudad = new Ciudad (0, city.get_active_text ().strip ()); + ciudad.region = new_region; + try { + if (validate_city_data (ciudad)) { + ciudad.id_ciudad = Ciudad.insert_city (conn, ciudad); + } + else { + return false; + } + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + finally { + staff.ciudad = ciudad; + } + } + else { + Gtk.TreeIter iter; + city.get_active_iter (out iter); + if (city_list_store.iter_is_valid (iter)) { + city_list_store.get (iter, + CityColumn.CITY, out ciudad); + ciudad.region = new_region; + staff.ciudad = ciudad; + } + } + return true; + } + + /** + * Initialize the staff editor class + * @param application The application used to make the GLib object + * @param conn The database connection to use + * @param staff The staff to edit + */ + public StaffEditor (Gtk.Application application, Connection conn, Guia? staff) { + Object (application: application); + this.conn = conn; + this.staff = staff; + } + + /** + * Initialize what is needed for this window + */ + public void initialize () { + try { + regions = Region.get_all_regiones (conn); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + + regions.sort_with_data ((a, b) => { + return strcmp (a.nombre_region, b.nombre_region); + }); + + region_list_store = new Gtk.ListStore (RegionColumn.N_COLUMNS, + typeof (string), + typeof (Region)); + + region.set_model (region_list_store); + + specialties.destroy (); + if (staff != null) { + original_run = staff.rut_guia; + try { + run.set_text (new Rut (staff.rut_guia).get_rut ()); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + guide_name.set_text (staff.nombre_guia); + street.set_text (staff.calle); + number.set_text (staff.numero.to_string ()); + } + else { + //specialties.destroy (); + staff = new Guia (); + staff.ciudad = new Ciudad (); + staff.ciudad.region = new Region (); + } + + regions.foreach ((entry) => { + Gtk.TreeIter iter; + region_list_store.append (out iter); + region_list_store.set (iter, + RegionColumn.REGION_NAME, entry.nombre_region, + RegionColumn.REGION, entry); + if (entry.id_region == staff.ciudad.region.id_region) { + region.set_active_iter (iter); + } + }); + + region.set_entry_text_column (RegionColumn.REGION_NAME); + + city_list_store = new Gtk.ListStore (CityColumn.N_COLUMNS, + typeof (string), + typeof (Ciudad)); + + city.set_model (city_list_store); + + try { + cities = Ciudad.get_all_ciudades_in_region (conn, staff.ciudad.region.id_region); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + + if (cities.length () > 0) { + cities.sort_with_data ((a, b) => { + return strcmp (a.nombre_ciudad, b.nombre_ciudad); + }); + + cities.foreach ((entry) => { + Gtk.TreeIter iter; + city_list_store.append (out iter); + city_list_store.set (iter, + CityColumn.CITY_NAME, entry.nombre_ciudad, + CityColumn.CITY, entry); + if (entry.id_ciudad == staff.ciudad.id_ciudad) { + city.set_active_iter (iter); + } + }); + } + } + } +} diff --git a/src/staff_list.vala b/src/staff_list.vala new file mode 100644 index 0000000..3e558da --- /dev/null +++ b/src/staff_list.vala @@ -0,0 +1,521 @@ +/* + * Copyright 2018-2019 Chris Cromer + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +namespace Sernatur { + using LibSernatur.Misc; + using LibSernatur.DB; + + /** + * The staff list window class + */ + [GtkTemplate (ui = "/cl/cromer/ubb/sernatur/staff.list.ui")] + public class StaffList : Gtk.ApplicationWindow { + /** + * The open database connection + */ + private Connection conn; + /** + * The columns of the tree view + */ + private enum Column { + /** + * The staff's run + */ + RUN, + /** + * The staff's name + */ + NAME, + /** + * The staff's street + */ + STREET, + /** + * The staff's number + */ + NUMBER, + /** + * The name of the city + */ + CITY, + /** + * The name of the region + */ + REGION, + /** + * The staff object + */ + STAFF, + /** + * The number of colums in this enum + */ + N_COLUMNS + } + /** + * The list that stores the contents in the tree view + */ + private Gtk.ListStore list_store; + /** + * The list of staffs + */ + private List staff_list; + /** + * The tree view widget + */ + [GtkChild] + private Gtk.TreeView staff_tree; + /** + * Thew new staff button + */ + [GtkChild] + private Gtk.Button new_staff; + /** + * The edit staff button + */ + [GtkChild] + private Gtk.Button edit_staff; + /** + * The delete staff button + */ + [GtkChild] + private Gtk.Button delete_staff; + /** + * The close staff button + */ + [GtkChild] + private Gtk.Button close_staff; + /** + * The staff's RUN + */ + [GtkChild] + private Gtk.TreeViewColumn run; + /** + * The staff's name + */ + [GtkChild] + private Gtk.TreeViewColumn guide_name; + /** + * The street + */ + [GtkChild] + private Gtk.TreeViewColumn street; + /** + * The number + */ + [GtkChild] + private Gtk.TreeViewColumn number; + /** + * The row selection + */ + [GtkChild] + private Gtk.TreeSelection selection; + /** + * The city column + */ + [GtkChild] + private Gtk.TreeViewColumn city; + /** + * The region column + */ + [GtkChild] + private Gtk.TreeViewColumn region; + /** + * This callback is called when the user clicks on a row + * @param selection The selection object + */ + [GtkCallback] + private void on_changed_selection(Gtk.TreeSelection selection) { + if (selection.count_selected_rows () == 1) { + edit_staff.sensitive = true; + delete_staff.sensitive =true; + } + else if (selection.count_selected_rows () > 1) { + edit_staff.sensitive = false; + delete_staff.sensitive = true; + } + else { + edit_staff.sensitive = false; + delete_staff.sensitive = false; + } + } + + /** + * This callback is run when the user clicks on a button + * @param button The button that was clicked + */ + [GtkCallback] + private void on_clicked_button (Gtk.Button button) { + if (button == new_staff) { + var staff_editor = new StaffEditor (application, conn, null); + staff_editor.set_transient_for (this); // Set this window as the parent of the new window + staff_editor.initialize (); + staff_editor.show_all (); + staff_editor.save_staff.connect (on_save); + } + else if (button == edit_staff) { + Gtk.TreeModel model; + var path = selection.get_selected_rows (out model); + path.foreach ((entry) => { + var tree_row_reference = new Gtk.TreeRowReference (model, entry); + Gtk.TreeIter iter; + list_store.get_iter (out iter, tree_row_reference.get_path ()); + Guia staff; + model.get (iter, + Column.STAFF, out staff); + var staff_editor = new StaffEditor (application, conn, staff); + staff_editor.set_transient_for (this); // Set this window as the parent of the new window + staff_editor.initialize (); + staff_editor.show_all (); + staff_editor.save_staff.connect (on_save); + }); + } + else if (button == delete_staff) { + Gtk.MessageDialog msg; + if (selection.count_selected_rows () == 1) { + msg = new Gtk.MessageDialog (this, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, + Gtk.ButtonsType.YES_NO, + _ ("Are you sure you wish to delete this staff member?")); + } + else { + msg = new Gtk.MessageDialog (this, + Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, + Gtk.ButtonsType.YES_NO, + _ ("Are you sure you wish to delete these staff members?")); + } + msg.response.connect ((response_id) => { + switch (response_id) { + case Gtk.ResponseType.YES: + Gtk.TreeModel model; + var path = selection.get_selected_rows (out model); + path.foreach ((entry) => { + var tree_row_reference = new Gtk.TreeRowReference (model, entry); + Gtk.TreeIter iter; + list_store.get_iter (out iter, tree_row_reference.get_path ()); + Guia staff; + model.get (iter, + Column.STAFF, out staff); + try { + Guia.delete_staff (conn, staff); + } + catch (PostgresError e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + }); + edit_staff.sensitive = false; + delete_staff.sensitive = false; + reset_columns (); + + list_store.clear (); + + update_list_store (); + break; + } + msg.destroy (); + }); + msg.show (); + } + else if (button == close_staff) { + this.close (); + } + } + + /** + * Called when a new or old staff is saved + * @param staff_editor The editor that saved the staff + */ + public void on_save(StaffEditor staff_editor) { + edit_staff.sensitive = false; + delete_staff.sensitive = false; + reset_columns (); + + list_store.clear (); + + update_list_store (); + } + + /** + * This callback is run when the user clicks on a column to reorder the rows + * @param column The column that was clicked + */ + [GtkCallback] + private void on_clicked_column (Gtk.TreeViewColumn column) { + edit_staff.sensitive = false; + delete_staff.sensitive = false; + if (column == run) { + if (!run.sort_indicator) { + reset_columns (); + run.sort_indicator = true; + } + + if (run.sort_order == Gtk.SortType.ASCENDING) { + run.sort_order = Gtk.SortType.DESCENDING; + } + else { + run.sort_order = Gtk.SortType.ASCENDING; + } + + staff_list.sort_with_data ((a, b) => { + if (run.sort_order == Gtk.SortType.ASCENDING) { + return strcmp (a.rut_guia, b.rut_guia); + } + else { + return strcmp (b.rut_guia, a.rut_guia); + } + }); + } + else if (column == guide_name) { + if (!guide_name.sort_indicator) { + reset_columns (); + guide_name.sort_indicator = true; + } + + if (guide_name.sort_order == Gtk.SortType.ASCENDING) { + guide_name.sort_order = Gtk.SortType.DESCENDING; + } + else { + guide_name.sort_order = Gtk.SortType.ASCENDING; + } + + staff_list.sort_with_data ((a, b) => { + if (guide_name.sort_order == Gtk.SortType.ASCENDING) { + return strcmp (a.nombre_guia, b.nombre_guia); + } + else { + return strcmp (b.nombre_guia, a.nombre_guia); + } + }); + } + else if (column == street) { + if (!street.sort_indicator) { + reset_columns (); + street.sort_indicator = true; + } + + if (street.sort_order == Gtk.SortType.ASCENDING) { + street.sort_order = Gtk.SortType.DESCENDING; + } + else { + street.sort_order = Gtk.SortType.ASCENDING; + } + + staff_list.sort_with_data ((a, b) => { + if (street.sort_order == Gtk.SortType.ASCENDING) { + return strcmp (a.calle, b.calle); + } + else { + return strcmp (b.calle, a.calle); + } + }); + } + else if (column == number) { + if (!number.sort_indicator) { + reset_columns (); + number.sort_indicator = true; + } + + if (number.sort_order == Gtk.SortType.ASCENDING) { + number.sort_order = Gtk.SortType.DESCENDING; + } + else { + number.sort_order = Gtk.SortType.ASCENDING; + } + + staff_list.sort_with_data ((a, b) => { + if (number.sort_order == Gtk.SortType.ASCENDING) { + if (a.numero < b.numero) { + return -1; + } + else if (a.numero == b.numero) { + return 0; + } + else { + return 1; + } + } + else { + if (a.numero < b.numero) { + return 1; + } + else if (a.numero == b.numero) { + return 0; + } + else { + return -1; + } + } + }); + } + else if (column == city) { + if (!city.sort_indicator) { + reset_columns (); + city.sort_indicator = true; + } + + if (city.sort_order == Gtk.SortType.ASCENDING) { + city.sort_order = Gtk.SortType.DESCENDING; + } + else { + city.sort_order = Gtk.SortType.ASCENDING; + } + + staff_list.sort_with_data ((a, b) => { + if (city.sort_order == Gtk.SortType.ASCENDING) { + return strcmp (a.ciudad.nombre_ciudad, b.ciudad.nombre_ciudad); + } + else { + return strcmp (b.ciudad.nombre_ciudad, a.ciudad.nombre_ciudad); + } + }); + } + else if (column == region) { + if (!region.sort_indicator) { + reset_columns (); + region.sort_indicator = true; + } + + if (region.sort_order == Gtk.SortType.ASCENDING) { + region.sort_order = Gtk.SortType.DESCENDING; + } + else { + region.sort_order = Gtk.SortType.ASCENDING; + } + + staff_list.sort_with_data ((a, b) => { + if (region.sort_order == Gtk.SortType.ASCENDING) { + return strcmp (a.ciudad.region.nombre_region, b.ciudad.region.nombre_region); + } + else { + return strcmp (b.ciudad.region.nombre_region, a.ciudad.region.nombre_region); + } + }); + } + + list_store.clear (); + staff_list.foreach ((entry) => { + Gtk.TreeIter iter; + list_store.append (out iter); + try { + list_store.set (iter, + Column.RUN, new Rut (entry.rut_guia).get_rut (), + Column.NAME, entry.nombre_guia, + Column.STREET, entry.calle, + Column.NUMBER, entry.numero, + Column.CITY, entry.ciudad.nombre_ciudad, + Column.REGION, entry.ciudad.region.nombre_region, + Column.STAFF, entry); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + }); + } + + /** + * Reset the sort indicator and order of all the columns + */ + private void reset_columns () { + run.sort_indicator = false; + run.sort_order = Gtk.SortType.DESCENDING; + guide_name.sort_indicator = false; + guide_name.sort_order = Gtk.SortType.DESCENDING; + street.sort_indicator = false; + street.sort_order = Gtk.SortType.DESCENDING; + number.sort_indicator = false; + number.sort_order = Gtk.SortType.DESCENDING; + city.sort_indicator = false; + city.sort_order = Gtk.SortType.DESCENDING; + region.sort_indicator = false; + region.sort_order = Gtk.SortType.DESCENDING; + } + + /** + * Update the list store with the data from the database + */ + private void update_list_store () { + try { + staff_list = Guia.get_all_guias (conn); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + + staff_list.foreach ((entry) => { + Gtk.TreeIter iter; + list_store.append (out iter); + try { + list_store.set (iter, + Column.RUN, new Rut (entry.rut_guia).get_rut (), + Column.NAME, entry.nombre_guia, + Column.STREET, entry.calle, + Column.NUMBER, entry.numero, + Column.CITY, entry.ciudad.nombre_ciudad, + Column.REGION, entry.ciudad.region.nombre_region, + Column.STAFF, entry); + } + catch (Error e) { + #if DEBUG + error (e.message); + #else + warning (e.message); + #endif + } + }); + } + + /** + * Initialize the staff list class + * @param application The application used to make the GLib object + * @param conn The database connection to use + */ + public StaffList (Gtk.Application application, Connection conn) { + Object (application: application); + this.conn = conn; + + this.set_visible (true); // This fixes: Gtk-CRITICAL **: 23:58:22.139: gtk_box_gadget_distribute: assertion 'size >= 0' failed in GtkScrollbar + } + + /** + * Initialize what is needed for this window + */ + public void initialize () { + list_store = new Gtk.ListStore (Column.N_COLUMNS, + typeof (string), + typeof (string), + typeof (string), + typeof (uint), + typeof (string), + typeof (string), + typeof (Guia)); + + update_list_store (); + + staff_tree.set_model (list_store); + } + } +}