/******************************************************************** Copyright (C) 2001 Bassoukos Tassos This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "messages.h" #include "transaction.h" #include "protocol.h" #include "tasks.h" #include "tasklist.h" #include "smalltrans.h" enum { INITIALIZE_SIGNAL, REQUEST_SENT_SIGNAL, RESPONSE_RCVD_SIGNAL, LAST_SIGNAL }; static guint transaction_signals[LAST_SIGNAL]={0}; static GtkObjectClass *parent_class=NULL; static void transaction_finalize(GtkObject *o){ Transaction *t; g_return_if_fail(o!=NULL); g_return_if_fail(IS_TRANSACTION(o)); t=TRANSACTION(o); message_unref(t->request); if(t->response) message_unref(t->response); if(t->task){ gtk_object_destroy(GTK_OBJECT(t->task)); gtk_object_unref(GTK_OBJECT(t->task)); } parent_class->finalize(o); } static void transaction_klass_init(TransactionClass *klass){ GtkObjectClass *object_class=(GtkObjectClass*)klass; parent_class=gtk_type_class(GTK_TYPE_OBJECT); object_class->finalize=transaction_finalize; transaction_signals[INITIALIZE_SIGNAL]= gtk_signal_new("initialize", GTK_RUN_LAST|GTK_RUN_NO_RECURSE, object_class->type, GTK_SIGNAL_OFFSET(TransactionClass,initialize), gtk_marshal_NONE__OBJECT, GTK_TYPE_NONE,1,GTK_TYPE_OBJECT); transaction_signals[REQUEST_SENT_SIGNAL]= gtk_signal_new("request-sent", GTK_RUN_LAST|GTK_RUN_NO_RECURSE, object_class->type, GTK_SIGNAL_OFFSET(TransactionClass,request_sent), gtk_marshal_NONE__NONE, GTK_TYPE_NONE,0); transaction_signals[RESPONSE_RCVD_SIGNAL]= gtk_signal_new("response-received", GTK_RUN_LAST|GTK_RUN_NO_RECURSE, object_class->type, GTK_SIGNAL_OFFSET(TransactionClass,response_received), gtk_marshal_NONE__OBJECT, GTK_TYPE_NONE,1,GTK_TYPE_OBJECT); gtk_object_class_add_signals(object_class,transaction_signals,LAST_SIGNAL); klass->initialize=NULL; klass->request_sent=NULL; klass->response_received=NULL; } static void transaction_init(Transaction *t) { t->request_type=0; t->request=t->response=NULL; t->task=NULL; t->c=NULL; t->taskpos=0.0; } GtkType transaction_get_type(void){ static GtkType transaction_type=0; if(transaction_type==0){ static const GtkTypeInfo type_info={ "Transaction", sizeof(Transaction), sizeof(TransactionClass), (GtkClassInitFunc) transaction_klass_init, (GtkObjectInitFunc) transaction_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; transaction_type=gtk_type_unique(GTK_TYPE_OBJECT,&type_info); gtk_type_set_chunk_alloc(transaction_type,8); } return transaction_type; } /******************************************/ Transaction *transaction_new(Connection *c,int message_type){ Transaction *t; g_return_val_if_fail(c!=NULL,NULL); t=(Transaction *)gtk_type_new(TRANSACTION_TYPE); t->c=c; t->request_type=message_type; t->request=message_new(c,message_type); return t; } void transaction_set_task(Transaction *t,Task *task,gfloat mid){ g_return_if_fail(t!=NULL); g_return_if_fail(task!=NULL); g_return_if_fail(IS_TRANSACTION(t)); g_return_if_fail(IS_TASK(task)); t->task=task; t->taskpos=mid; gtk_object_ref(GTK_OBJECT(t->task)); if(t->request) message_set_task(t->request,t->task,0.0,mid); } void transaction_add_task(Transaction *t,char *text,char *icon,gfloat mid){ Task *task=task_new_for_connection(t->c,icon); task_set_postext(task,0.0,text); transaction_set_task(t,task,mid); } static void transaction_rcv(Connection *c,Message *m,gpointer dummy){ Transaction *t=dummy; g_return_if_fail(m!=NULL); g_return_if_fail(IS_MESSAGE(m)); g_return_if_fail(t!=NULL); g_return_if_fail(IS_TRANSACTION(t)); if(!message_is_complete(m)){ if(t->task) message_set_task(m,t->task,t->taskpos,1.0); } else { t->response=m; gtk_signal_emit(GTK_OBJECT(t),transaction_signals[RESPONSE_RCVD_SIGNAL],t->response); transaction_unref(t); } } void transaction_start(Transaction *t){ g_return_if_fail(t!=NULL); g_return_if_fail(IS_TRANSACTION(t)); gtk_signal_emit(GTK_OBJECT(t),transaction_signals[INITIALIZE_SIGNAL],t->request); connection_expect_reply(t->c,message_get_tasknum(t->request),transaction_rcv,t); message_send(t->request); gtk_signal_emit(GTK_OBJECT(t),transaction_signals[REQUEST_SENT_SIGNAL]); } static void transaction_check_error(Transaction *t,Message *m,char *msg){ if(message_is_error(m)){ HLObject *o=message_find_object(m,HLO_ERRORMSG); show_error((t->c->gui && t->c->gui->main_window) ? t->c : NULL, NULL, "%s\n%s", msg ? (char *)msg : "", o ? o->data.string : _("unspecified error")); } if(msg) free(msg); } void transaction_set_error_check(Transaction *t,char *msg){ gtk_signal_connect_after(GTK_OBJECT(t),"response-received", GTK_SIGNAL_FUNC(transaction_check_error),msg); }