final push
This commit is contained in:
@@ -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 ();
|
||||
|
@@ -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')]
|
||||
|
||||
|
672
src/staff_editor.vala
Normal file
672
src/staff_editor.vala
Normal file
@@ -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<Asociado> list_asociado = null;
|
||||
/**
|
||||
* A saved copy of the original RUN
|
||||
*/
|
||||
private string original_run;
|
||||
/**
|
||||
* A list of the cities from the database
|
||||
*/
|
||||
private List<Ciudad> cities;
|
||||
/**
|
||||
* A list of the regions from the database
|
||||
*/
|
||||
private List<Region> 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<Ciudad> 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<Region> 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<Asociado> 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
521
src/staff_list.vala
Normal file
521
src/staff_list.vala
Normal file
@@ -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<Guia> 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);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user