activitylist.c 10.9 KB
/*
 * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270  e X3270
 * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
 * aplicativos mainframe. Registro no INPI sob o nome G3270.
 *
 * Copyright (C) <2008> <Banco do Brasil S.A.>
 *
 * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
 * os termos da GPL v.2 - Licença Pública Geral  GNU,  conforme  publicado  pela
 * Free Software Foundation.
 *
 * Este programa é distribuído na expectativa de  ser  útil,  mas  SEM  QUALQUER
 * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou  de  ADEQUAÇÃO
 * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
 * obter mais detalhes.
 *
 * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
 * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
 * St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Este programa está nomeado como - e possui - linhas de código.
 *
 * Contatos:
 *
 * perry.werneck@gmail.com	(Alexandre Perry de Souza Werneck)
 * erico.mendonca@gmail.com	(Erico Mascarenhas Mendonça)
 *
 */

 #include <internals.h>
 #include "private.h"
 #include "marshal.h"

/*--[ Widget definition ]----------------------------------------------------------------------------*/

 enum _SIGNALS
 {
 	V3270_ACTIVITY_LIST_HAS_FILE_SIGNAL,	///< @brief Indicates if the list has a file name set.

 	V3270_ACTIVITY_LIST_LAST_SIGNAL
 };

 typedef struct _activities
 {

 }  Activities;

 struct _V3270FTActivityListClass
 {
 	GtkTreeViewClass parent_class;

 	struct
 	{
		void (*has_file)(GtkWidget *, gboolean);
 	} signal;

 };

 struct _V3270FTActivityList
 {
 	GtkTreeView parent;
 	gchar * filename;
 };

 G_DEFINE_TYPE(V3270FTActivityList, V3270FTActivityList, GTK_TYPE_TREE_VIEW);

 static guint v3270_activity_list_signals[V3270_ACTIVITY_LIST_LAST_SIGNAL] = { 0 };

/*--[ Implement ]------------------------------------------------------------------------------------*/

 static void dispose(GObject *object)
 {
	debug("activityList::%s(%p)",__FUNCTION__,object);

	V3270FTActivityList * list = GTK_V3270_FT_ACTIVITY_LIST(object);

	// Release filename
	debug("Freeing %s",list->filename);
	g_free(list->filename);
	list->filename = NULL;

	GtkTreeIter		  iter;
	GtkTreeModel	* model	= gtk_tree_view_get_model(GTK_TREE_VIEW(object));

	while(model && gtk_tree_model_get_iter_first(model,&iter))
	{
		GObject * activity = NULL;
		gtk_tree_model_get(model, &iter, 0, &activity, -1);

		gtk_list_store_remove(GTK_LIST_STORE(model),&iter);
		debug("Disposing activity %p",activity);

		g_clear_object(&activity);

	}


	G_OBJECT_CLASS(V3270FTActivityList_parent_class)->dispose(object);

 }

 static void V3270FTActivityList_has_file(GtkWidget G_GNUC_UNUSED(*widget), gboolean G_GNUC_UNUSED(has_file))
 {
 	debug("%s",__FUNCTION__);
 }

 static void V3270FTActivityList_class_init(V3270FTActivityListClass *klass)
 {
	GObjectClass * gobject_class = G_OBJECT_CLASS(klass);

	gobject_class->dispose = dispose;

	klass->signal.has_file = V3270FTActivityList_has_file;

	v3270_activity_list_signals[V3270_ACTIVITY_LIST_HAS_FILE_SIGNAL] =
		g_signal_new(	"has-file",
						G_OBJECT_CLASS_TYPE (gobject_class),
						G_SIGNAL_RUN_FIRST,
						G_STRUCT_OFFSET (V3270FTActivityListClass, signal.has_file),
						NULL, NULL,
						v3270ft_VOID__VOID_BOOLEAN,
						G_TYPE_NONE, 1, G_TYPE_BOOLEAN);


 }

 static void render_local(GtkTreeViewColumn G_GNUC_UNUSED(*tree_column), GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer G_GNUC_UNUSED(data))
 {
	GObject * activity;
	gtk_tree_model_get(tree_model, iter, 0, &activity, -1);
	g_object_set(G_OBJECT(cell),"text",v3270_ft_activity_get_local_filename(activity),NULL);
 }

 static void render_remote(GtkTreeViewColumn G_GNUC_UNUSED(*tree_column), GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer G_GNUC_UNUSED(data))
 {
	GObject * activity;
	gtk_tree_model_get(tree_model, iter, 0, &activity, -1);
	g_object_set(G_OBJECT(cell),"text",v3270_ft_activity_get_remote_filename(activity),NULL);
 }

 static void V3270FTActivityList_init(V3270FTActivityList *widget)
 {
	GtkTreeModel * model = GTK_TREE_MODEL(gtk_list_store_new(1,G_TYPE_POINTER));	// Using pointer type because I take care of refcounts.

	widget->filename = NULL;

	gtk_tree_view_set_model(GTK_TREE_VIEW(widget),model);
	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(widget),TRUE);
	gtk_tree_view_set_reorderable(GTK_TREE_VIEW(widget),TRUE);

	gtk_tree_view_insert_column_with_data_func(
		GTK_TREE_VIEW(widget),
		-1,
		_( "Local file" ),
		gtk_cell_renderer_text_new(),
		render_local,
		0, NULL
	);

	gtk_tree_view_insert_column_with_data_func(
		GTK_TREE_VIEW(widget),
		-1,
		_( "Remote file" ),
		gtk_cell_renderer_text_new(),
		render_remote,
		0, NULL
	);

 }

 GtkWidget * v3270_activity_list_new()
 {
	return g_object_new(GTK_TYPE_V3270_FT_ACTIVITY_LIST, NULL);
 }

 void v3270_activity_list_append(GtkWidget *widget, GObject *activity)
 {
 	GtkTreeModel * model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
	GtkTreeIter iter;
	gtk_list_store_append((GtkListStore *) model,&iter);
	gtk_list_store_set((GtkListStore *) model, &iter, 0, activity, -1);
	g_object_ref_sink(activity);

 }

 void v3270_activity_list_remove(GtkWidget *widget, GObject *activity)
 {
 	if(!activity)
		return;

 	GtkTreeModel * model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
	GtkTreeIter iter;

	if(gtk_tree_model_get_iter_first(model,&iter))
	{
		do
		{
			GObject * stored = NULL;
			gtk_tree_model_get(model, &iter, 0, &stored, -1);

			if(stored == activity)
			{
				debug("Removing activity %p",activity);
				gtk_list_store_remove(GTK_LIST_STORE(model),&iter);
				g_object_unref(stored);
				return;
			}


		}
		while(gtk_tree_model_iter_next(model,&iter));
	}

 }


 static void element_start(GMarkupParseContext *context, const gchar *element_name, const gchar G_GNUC_UNUSED(**names),const gchar G_GNUC_UNUSED(**values), V3270FTActivityList *widget, GError G_GNUC_UNUSED(**error))
 {
 	debug("%s(%s)",__FUNCTION__, element_name);
	if(!g_ascii_strcasecmp(element_name,"entry"))
	{
		// Create new activity
		GObject * activity = v3270_ft_activity_new();
		v3270_ft_activity_set_from_context(activity,context);
		v3270_activity_list_append(GTK_WIDGET(widget), activity);
	}

 }

 static void element_end(GMarkupParseContext *context, const gchar *element_name, G_GNUC_UNUSED void *info,G_GNUC_UNUSED  GError **error)
 {
 	debug("%s(%s)",__FUNCTION__, element_name);
	if(!g_ascii_strcasecmp(element_name,"entry"))
	{
		g_markup_parse_context_pop(context);
	}
 }

 static void reload(GtkWidget *widget)
 {
	static const GMarkupParser parser = {
		(void (*)(GMarkupParseContext *, const gchar *, const gchar **, const gchar **, gpointer, GError **)) element_start,
		(void (*)(GMarkupParseContext *, const gchar *, gpointer, GError **)) element_end,
		(void (*)(GMarkupParseContext *, const gchar *, gsize, gpointer, GError **)) NULL,
		(void (*)(GMarkupParseContext *, const gchar *, gsize,  gpointer, GError **)) NULL,
		(void (*)(GMarkupParseContext *, GError *, gpointer)) NULL
	};

	GError				* error	= NULL;
	g_autofree gchar	* text	= NULL;

	if(g_file_get_contents(GTK_V3270_FT_ACTIVITY_LIST(widget)->filename,&text,NULL,&error)) {

		GMarkupParseContext	* context =
			g_markup_parse_context_new(
				&parser,
				G_MARKUP_TREAT_CDATA_AS_TEXT|G_MARKUP_PREFIX_ERROR_POSITION,
				widget,
				NULL
			);

		g_markup_parse_context_parse(context,text,strlen(text),&error);
		g_markup_parse_context_free(context);

	}

 }

 void v3270_activity_list_load(GtkWidget *widget)
 {
	V3270FTActivityList * list = GTK_V3270_FT_ACTIVITY_LIST(widget);

	gchar * filename = v3270_select_file(
								widget,
								_("Load queue from file"),
								_("Load"), GTK_FILE_CHOOSER_ACTION_OPEN,
								"",
								N_("XML file"), "*.xml",
								NULL );

	if(filename) {
		g_free(list->filename);
		list->filename = filename;
	}

	reload(widget);

	g_signal_emit(widget, v3270_activity_list_signals[V3270_ACTIVITY_LIST_HAS_FILE_SIGNAL], 0, (list->filename == NULL ? FALSE : TRUE));


 }

 void v3270_activity_list_save(GtkWidget *widget)
 {
	V3270FTActivityList * list = GTK_V3270_FT_ACTIVITY_LIST(widget);
	GString * str	= g_string_new("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<filelist>\n");
	GError	* error	= NULL;
	size_t	  ix;

	debug("%s",__FUNCTION__);

	// Serialize activities.
	GtkTreeIter		  iter;
	GtkTreeModel	* model	= gtk_tree_view_get_model(GTK_TREE_VIEW(widget));

	if(gtk_tree_model_get_iter_first(model,&iter))
	{
		do
		{
			GObject * activity = NULL;
			gtk_tree_model_get(model, &iter, 0, &activity, -1);

			if(activity)
			{
				g_string_append(str,"\t<entry>\n");

				g_string_append_printf(str,"\t\t<file type=\'local\' path=\'%s\' />\n",v3270_ft_activity_get_local_filename(activity));
				g_string_append_printf(str,"\t\t<file type=\'remote\' path=\'%s\' />\n",v3270_ft_activity_get_remote_filename(activity));

				LIB3270_FT_OPTION options = v3270_ft_activity_get_options(activity);
				for(ix = 0; v3270_activity_list_options[ix].name; ix++)
				{
					if((options & v3270_activity_list_options[ix].option) == v3270_activity_list_options[ix].option)
						g_string_append_printf(str,"\t\t<option name=\'%s\' value=\'%s\' />\n",v3270_activity_list_options[ix].name,v3270_activity_list_options[ix].value);
				}

				for(ix=0;ix<LIB3270_FT_VALUE_COUNT;ix++)
				{
					g_string_append_printf(str,"\t\t<parameter name=\"%s\" value=\"%u\"/>\n",ft_value[ix].name,v3270_ft_activity_get_value(activity,(LIB3270_FT_VALUE) ix));
				}

				g_string_append(str,"\t</entry>\n");
			}

		}
		while(gtk_tree_model_iter_next(model,&iter));
	}

	g_string_append(str,"</filelist>\n");


	// Save activity list
	g_autofree gchar * text = g_string_free(str,FALSE);

	debug("Saving %s",list->filename);

	if(!g_file_set_contents(list->filename,text,-1,&error)) {

		GtkWidget *popup = gtk_message_dialog_new_with_markup(
			GTK_WINDOW(gtk_widget_get_toplevel(widget)),
			GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
			GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,
			_("Can't save %s"),list->filename
		);

		gtk_window_set_title(GTK_WINDOW(popup),_("Operation has failed"));

		gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(popup),"%s",error->message);
		g_error_free(error);

		gtk_dialog_run(GTK_DIALOG(popup));
		gtk_widget_destroy(popup);

	}


 }

 void v3270_activity_list_save_as(GtkWidget *widget)
 {
	V3270FTActivityList * list = GTK_V3270_FT_ACTIVITY_LIST(widget);

	gchar * filename = v3270_select_file(
								widget,
								_("Save queue to file"),
								_("Save"),
								GTK_FILE_CHOOSER_ACTION_SAVE,
								list->filename,
								N_("XML file"), "*.xml",
								NULL );

	if(filename) {
		g_free(list->filename);
		list->filename = filename;
		v3270_activity_list_save(widget);
	}

	g_signal_emit(widget, v3270_activity_list_signals[V3270_ACTIVITY_LIST_HAS_FILE_SIGNAL], 0, (list->filename == NULL ? FALSE : TRUE));

 }