Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/CeibalEncuesta/CeibalEncuesta.py
diff options
context:
space:
mode:
Diffstat (limited to 'CeibalEncuesta/CeibalEncuesta.py')
-rw-r--r--CeibalEncuesta/CeibalEncuesta.py479
1 files changed, 419 insertions, 60 deletions
diff --git a/CeibalEncuesta/CeibalEncuesta.py b/CeibalEncuesta/CeibalEncuesta.py
index 1e637a4..8d0e856 100644
--- a/CeibalEncuesta/CeibalEncuesta.py
+++ b/CeibalEncuesta/CeibalEncuesta.py
@@ -18,18 +18,50 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# Notas:
+# Las listas de Encuestados se abren desde un archivo csv.
+# Las encuestas sin Responder se abren desde un archivo slv (shelve) o json.
+# Las Encuestas respondidas o parcialmente respondidas se guardan en archivos .encuesta (json)
+
import os
import sys
import gi
from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GObject
from Widgets import Panel
from Widgets import My_FileChooser
+from Widgets import My_Alert_Dialog
import Globales as G
PATH = os.path.dirname(__file__)
+HOME = os.environ["HOME"]
+WORKPATH = os.path.join(HOME, "CeibalEncuesta")
+TEMPPATH = os.path.join(WORKPATH, 'temp.encuesta')
+
+if not os.path.exists(WORKPATH):
+ os.mkdir(WORKPATH)
+ os.chmod(WORKPATH, 0755)
+
+archivo = open(TEMPPATH, 'w')
+archivo.close()
+
+screen = Gdk.Screen.get_default()
+css_provider = Gtk.CssProvider()
+style_path = os.path.join(PATH, "CssStyle.css")
+css_provider.load_from_path(style_path)
+context = Gtk.StyleContext()
+
+context.add_provider_for_screen(
+ screen,
+ css_provider,
+ Gtk.STYLE_PROVIDER_PRIORITY_USER)
+
+GObject.threads_init()
+Gdk.threads_init()
class CeibalEncuesta(Gtk.Window):
@@ -45,69 +77,179 @@ class CeibalEncuesta(Gtk.Window):
self.set_resizable(True)
self.set_size_request(640, 480)
- self.set_border_width(2)
+ self.set_border_width(5)
self.set_position(Gtk.WindowPosition.CENTER)
+ self.path = TEMPPATH
+
+ self.out_dict = {} # keys = Encuestados, Values = Encuesta respondida
+
box = Gtk.VBox()
self.panel = Panel()
- box.pack_start(self.get_menu(), False, False, 0)
+ # menuitems
+ self.guardar = None
+ self.exportar = None
+
+ box.pack_start(self.__get_menu(), False, False, 0)
box.pack_start(self.panel, True, True, 0)
self.add(box)
self.show_all()
+ self.panel.hide()
+
self.panel.connect("new", self.__change)
+ self.panel.connect("text", self.__set_text)
self.panel.connect("new-selection", self.__new_selection)
+
self.connect("destroy", self.__salir)
- self.out_dict = None
+ def do_draw(self, context):
+ """
+ Pinta una imagen si no se ha cargado una lista
+ a encuestar o una encuesta a aplicar.
+ """
+
+ if self.panel.get_visible(): return False
+
+ from gi.repository import GdkPixbuf
+ from gi.repository import Gdk
+
+ import cairo
+
+ archivo = os.path.join(PATH,
+ "Iconos", "screen.svg")
- def __change(self, widget, new_dict):
- """Recibe los cambios en la encuesta."""
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file(archivo)
- if self.out_dict == None:
- self.out_dict = {}
+ rect = self.get_allocation()
+ x, y, w, h = (rect.x, rect.y, rect.width, rect.height)
+ ww, hh = pixbuf.get_width(), pixbuf.get_height()
+
+ scaledPixbuf = pixbuf.scale_simple(
+ w, h, GdkPixbuf.InterpType.BILINEAR)
+
+ surface = cairo.ImageSurface(
+ cairo.FORMAT_ARGB32,
+ scaledPixbuf.get_width(),
+ scaledPixbuf.get_height())
+
+ tmpcontext = cairo.Context(surface)
+ Gdk.cairo_set_source_pixbuf(tmpcontext, scaledPixbuf, 0, 0)
+ tmpcontext.paint()
+ context.set_source_surface(surface)
+ context.paint()
+
+ def __set_text(self, widget,
+ encuestado, id_grupo, id_pregunta, id_opcion, text):
+ """
+ Cuando se ingresa texto en una opción
+ del tipo Entry. (caso particular).
+ """
+
+ user = ''
+ for item in encuestado:
+ user += ' %s' % item
+
+ encuestado = user.strip()
+
+ if text:
+ self.out_dict[encuestado][id_grupo]['fields'][id_pregunta]['options'][id_opcion]['newtext'] = text
+
+ else:
+ del self.out_dict[encuestado][id_grupo]['fields'][id_pregunta]['options'][id_opcion]['newtext']
+
+ self.__save_json(path = self.path)
+
+ def __change(self, widget, encuestado,
+ indice_grupo, grupo_name,
+ indice_pregunta, dict_pregunta):
+ """
+ Recibe los cambios en la encuesta y
+ almacena los datos.
+ """
+
+ user = ''
+ for item in encuestado:
+ user += ' %s' % item
+
+ encuestado = user.strip()
+
+ # Entrada para encuestado
+ if not encuestado in self.out_dict.keys():
+ self.out_dict[encuestado] = {}
- self.out_dict[new_dict.keys()[0]] = new_dict[new_dict.keys()[0]]
+ # Entrada para grupo
+ if not indice_grupo in self.out_dict[encuestado].keys():
+ self.out_dict[encuestado][indice_grupo] = {}
+
+ # Entrada para pregunta
+ if not 'fields' in self.out_dict[encuestado][indice_grupo].keys():
+ self.out_dict[encuestado][indice_grupo]['fields'] = {}
+
+ self.out_dict[encuestado][indice_grupo]['name'] = grupo_name
+
+ self.out_dict[encuestado][indice_grupo]['fields'][indice_pregunta] = dict_pregunta
- #print self.out_dict
+ self.__save_json(path = self.path)
def __new_selection(self, widget, data):
- """Cuando el usuario cambia de Encuestado."""
+ """
+ Cuando el usuario cambia de Encuestado.
+ """
- if self.out_dict != None:
- if data in self.out_dict.keys():
- self.panel.update(self.out_dict[data])
+ if data in self.out_dict.keys():
+ self.panel.update(self.out_dict[data])
- def get_menu(self):
- """Crea y devuelve el menú de la aplicación."""
+ def __get_menu(self):
+ """
+ Crea y devuelve el menú de la aplicación.
+ """
menu_bar = Gtk.MenuBar()
menu_bar.show()
file_menu = Gtk.Menu()
- alumnos = Gtk.MenuItem("Cargar Encuestados")
- encuesta = Gtk.MenuItem("Cargar Encuesta")
- #guardar = Gtk.MenuItem("Guardar")
+ encuestados = Gtk.MenuItem("Nueva Lista . . .")
+ encuesta = Gtk.MenuItem("Nueva Encuesta . . .")
+ recuperar = Gtk.MenuItem("Abrir Encuesta . . .")
+ self.guardar = Gtk.MenuItem("Guardar Encuesta . . .")
+ self.exportar = Gtk.MenuItem("Exportar Encuesta . . .")
salir = Gtk.MenuItem("Salir")
- file_menu.append(alumnos)
+ encuestados.set_tooltip_text(
+ "Cargar una Nueva Lista a Encuestar.")
+ encuesta.set_tooltip_text(
+ "Cargar una Nueva Encuesta para ser Aplicada a la Lista.")
+ recuperar.set_tooltip_text(
+ "Abrir una Encuesta Total o Parcialmente Respondida.")
+ self.guardar.set_tooltip_text(
+ "Guardar la Encuesta Actual.")
+ self.exportar.set_tooltip_text(
+ "Exportar Encuesta a Formato csv")
+ salir.set_tooltip_text(
+ "Salir de la Aplicación.")
+
+ file_menu.append(encuestados)
file_menu.append(encuesta)
- #file_menu.append(guardar)
+ file_menu.append(recuperar)
+ file_menu.append(self.guardar)
+ #file_menu.append(self.exportar)
file_menu.append(salir)
- alumnos.connect_object ("activate", self.__cargar_alumnos, '')
- encuesta.connect_object ("activate", self.__cargar_encuesta, '')
- #guardar.connect_object ("activate", self.__guardar, '')
- salir.connect_object ("activate", self.__salir, '')
+ encuestados.connect_object("activate", self.__cargar_encuestados, '')
+ encuesta.connect_object("activate", self.__cargar_encuesta, '')
+ recuperar.connect_object("activate", self.__recuperar_encuesta, '')
+ self.guardar.connect_object("activate", self.__guardar_encuesta, '')
+ self.exportar.connect_object("activate", self.__exportar_encuesta, '')
+ salir.connect_object("activate", self.__salir, '')
- alumnos.show()
- #guardar.show()
+ encuestados.show()
salir.show()
file_item = Gtk.MenuItem("Archivo")
@@ -116,44 +258,233 @@ class CeibalEncuesta(Gtk.Window):
file_item.set_submenu(file_menu)
menu_bar.append(file_item)
+ self.guardar.set_sensitive(False)
+ self.exportar.set_sensitive(False)
+
return menu_bar
- def __cargar_alumnos(self, widget = None, senial = None):
- """Abre Filechooser para cargar el archivo con la
- lista de alumnos a encuestar."""
+ def __exportar_encuesta(self, widget = None, senial = None):
+ """
+ Abre Filechooser para Exportar la encuesta a un
+ archivo csv.
+ """
+
+ filechooser = My_FileChooser(
+ parent_window = self,
+ action_type = Gtk.FileChooserAction.SAVE,
+ filter_type = 'text/csv',
+ title = "Exportar Encuesta")
+
+ filechooser.connect('load', self.__export_encuesta)
+
+ def __export_encuesta(self, widget, archivo):
+ """
+ Exporta la encuesta a un archivo csv.
+ """
+
+ name, ext = os.path.splitext(archivo)
+
+ if ext:
+ if ext != "csv":
+ ext = ".csv"
+
+ else:
+ ext = ".csv"
+
+ archivo = "%s%s" % (name, ext)
+
+ print "Exportar:", archivo
+
+ def __guardar_encuesta(self, widget = None, senial = None):
+ """
+ Abre Filechooser para guardar la
+ encuesta respondida o parcialmente respondida.
+ """
+
+ filechooser = My_FileChooser(
+ parent_window = self,
+ action_type = Gtk.FileChooserAction.SAVE,
+ filter_type = 'text/encuesta',
+ title = "Guardar Encuesta")
+
+ filechooser.connect('load', self.__save_encuesta)
+
+ def __save_encuesta(self, widget, archivo):
+ """
+ Guarda encuesta en formato json.
+ """
+
+ name, ext = os.path.splitext(archivo)
+
+ if ext:
+ if ext != "encuesta":
+ ext = ".encuesta"
+
+ else:
+ ext = ".encuesta"
+
+ archivo = "%s%s" % (name, ext)
+
+ self.__save_json(path = os.path.join(archivo))
+
+ # FIXME: A partir de este momento, la encuesta se
+ # guardará automáticamente en este archivo, analizar
+ # mejor si esto debe hacerse así o solo debe guardarse
+ # acá cuando el usuario lo decide.
+
+ def __recuperar_encuesta(self, widget = None, senial = None):
+ """
+ Abre Filechooser para cargar el archivo con la
+ encuesta respondida o parcialmente respondida.
+ """
+
+ if self.panel.lista and self.panel.encuesta:
+ dialog = My_Alert_Dialog(parent_window = self,
+ label = "¿ Proceder sin Guardar ?")
+
+ response = dialog.run()
+
+ dialog.destroy()
+
+ if Gtk.ResponseType(response) == Gtk.ResponseType.CANCEL:
+ return
+
+ filechooser = My_FileChooser(
+ parent_window = self,
+ action_type = Gtk.FileChooserAction.OPEN,
+ #filter_type = 'text/encuesta',
+ title = "Recuperar Encuesta")
+
+ filechooser.connect('load', self.__load_encuesta_respondida)
+
+ def __load_encuesta_respondida(self, widget, archivo):
+ """
+ Carga una encuesta parcial o totalmente
+ respondida, desde un archivo json.
+ """
+
+ if os.path.exists(TEMPPATH):
+ os.remove(TEMPPATH)
+
+ self.path = archivo
+ extension = os.path.splitext(os.path.split(archivo)[1])[1]
+
+ if 'encuesta' in extension:
+ import json
+ import codecs
+
+ archivo = codecs.open(archivo, "r", "utf-8")
+ enc = json.JSONDecoder("utf-8").decode(archivo.read())
+
+ self.out_dict = enc['groups']
+ self.panel.load_encuesta(enc['encuesta'])
+ self.panel.load_encuestados(enc['encuestados'])
+
+ def __cargar_encuestados(self, widget = None, senial = None):
+ """
+ Abre Filechooser para cargar el archivo con la
+ lista a encuestar.
+ """
+
+ if self.panel.lista and self.panel.encuesta:
+ dialog = My_Alert_Dialog(parent_window = self,
+ label = "¿ Proceder sin Guardar ?")
+
+ response = dialog.run()
+
+ dialog.destroy()
+
+ if Gtk.ResponseType(response) == Gtk.ResponseType.CANCEL:
+ return
+
filechooser = My_FileChooser(
parent_window = self,
action_type = Gtk.FileChooserAction.OPEN,
- filter_type = 'text/csv')
+ filter_type = 'text/csv',
+ title = "Cargar Lista a Encuestar")
- filechooser.connect('load', self.__load_alumnos)
-
- def __load_alumnos(self, widget, archivo):
- """Recibe archivo csv con la lista de alumnos a encuestar y
- la manda cargar en la aplicación."""
+ filechooser.connect('load', self.__load_encuestados)
+
+ def __load_encuestados(self, widget, archivo):
+ """
+ Recibe archivo csv con la lista a encuestar
+ y la manda cargar en la aplicación.
+ """
- self.out_dict = None
+ if os.path.exists(TEMPPATH):
+ os.remove(TEMPPATH)
- alumnos = G.cargar_alumnos(os.path.join(archivo))
- self.panel.load_alumnos(alumnos)
+ self.path = TEMPPATH
+
+ arch = open(self.path, 'w')
+ arch.close()
+
+ self.out_dict = {}
+ encuestados = G.cargar_encuestados(os.path.join(archivo))
+
+ for encue in encuestados[1:]:
+ user = ''
+
+ for item in encue:
+ user += ' %s' % item
+
+ encuestado = user.strip()
+
+ if not encuestado in self.out_dict.keys():
+ self.out_dict[encuestado] = {}
+
+ self.panel.load_encuestados(encuestados)
+
+ GObject.idle_add(self.__save_json, self.path)
+
+ self.__check_sensitive()
def __cargar_encuesta(self, widget = None, senial = None):
- """Abre Filechooser para cargar el
- archivo con la encuesta."""
+ """
+ Abre Filechooser para cargar el
+ archivo con la encuesta.
+ """
+
+ if self.panel.lista and self.panel.encuesta:
+ dialog = My_Alert_Dialog(parent_window = self,
+ label = "¿ Proceder sin Guardar ?")
+
+ response = dialog.run()
+
+ dialog.destroy()
+
+ if Gtk.ResponseType(response) == Gtk.ResponseType.CANCEL:
+ return
filechooser = My_FileChooser(
parent_window = self,
action_type = Gtk.FileChooserAction.OPEN,
- filter_type = None)
+ filter_type = None,
+ title = "Cargar Nueva Encuesta")
filechooser.connect('load', self.__load_encuesta)
-
+
def __load_encuesta(self, widget, archivo):
- """Carga una encuesta almacenada en
- un archivo json o en un archivo shelve."""
+ """
+ Carga una encuesta almacenada en
+ un archivo json o shelve.
+ """
- self.out_dict = None
+ if os.path.exists(TEMPPATH):
+ os.remove(TEMPPATH)
+
+ self.path = TEMPPATH
+
+ arch = open(self.path, 'w')
+ arch.close()
+
+ # Mantiene la lista de encuestados cargada actualmente.
+ encuestados = self.out_dict.keys()
+
+ for encuestado in encuestados:
+ self.out_dict[encuestado] = {}
+
encuesta = {}
extension = os.path.splitext(os.path.split(archivo)[1])[1]
@@ -163,35 +494,63 @@ class CeibalEncuesta(Gtk.Window):
import codecs
archivo = codecs.open(archivo, "r", "utf-8")
- encuesta = json.JSONDecoder("utf-8").decode(archivo.read())
+ enc = json.JSONDecoder("utf-8").decode(archivo.read())
+ encuesta = enc['groups']
elif 'slv' in extension:
-
import shelve
archivo = shelve.open(archivo)
- for key in archivo.keys():
- encuesta[key] = archivo[key]
+ enc = archivo['groups']
+
+ for key in enc.keys():
+ encuesta[key] = enc[key]
archivo.close()
-
+
self.panel.load_encuesta(encuesta)
- def __guardar(self, widget = None, senial = None):
- """Abre Filechooser para guardar la encuesta."""
+ GObject.idle_add(self.__save_json, self.path)
- filechooser = My_FileChooser(
- parent_window = self,
- action_type = Gtk.FileChooserAction.OPEN,
- filter_type = 'text/csv')
-
- #filechooser.connect('load', self.__load_alumnos)
-
+ self.__check_sensitive()
+
+ self.panel.update({})
+
+ def __check_sensitive(self):
+
+ if self.panel.encuesta and self.panel.lista:
+ self.guardar.set_sensitive(True)
+ self.exportar.set_sensitive(True)
+
+ else:
+ self.guardar.set_sensitive(False)
+ self.exportar.set_sensitive(False)
+
+ def __save_json(self, path = TEMPPATH):
+ """
+ Guarda encuesta en formato json.
+ """
+
+ self.path = path
+
+ salida = {
+ 'encuestados': self.panel.encuestados,
+ 'groups': self.out_dict,
+ 'encuesta': self.panel.encuesta}
+
+ import simplejson
+ archivo = open(self.path, 'w')
+ archivo.write(simplejson.dumps(salida))
+ archivo.close()
+
+ if os.path.exists(TEMPPATH):
+ if TEMPPATH != path:
+ os.remove(TEMPPATH)
+
def __salir(self, widget = None, senial = None):
sys.exit(0)
-
if __name__ == "__main__":