EGong

git clone git://xatko.vsos.ethz.ch/EGong.git
Log | Files | Refs

GTK.c (10505B)


      1 #include <EGong/Interfaces/GTK.h>
      2 #include <EGong/Interfaces.h>
      3 #include <EGong/Util/Misc.h>
      4 #include <EGong/Util/Log.h>
      5 #include <EGong/Util/Waiter.h>
      6 #include <EGong/Main.h>
      7 #include <EGong/Interfaces.h>
      8 #include <EGong/Interfaces/GUI.h>
      9 #include <gtk/gtk.h>
     10 #include <EGong/Util/Config_Compiletime.h>
     11 #include <EGong/Util/Config.h>
     12 #include <stdlib.h>
     13 #ifdef USE_LIBNOTIFY
     14 	#include <libnotify/notify.h>
     15 #endif
     16 
     17 GtkWidget *Egong_if_gtk_root=NULL;
     18 GdkPixbuf *EGong_if_gtk_icon=NULL;
     19 unsigned short int EGong_if_gtk_have_libnotify=0;
     20 
     21 unsigned int EGong_if_gtk_initialized;
     22 struct EGong_if_ptrtbl EGong_if_gtk_ptrtbl={
     23 		.setup=&EGong_if_gtk_setup, 
     24 		.cycle=&EGong_if_gtk_cycle, 
     25 		.display=&EGong_if_gtk_display, 
     26 		.shutdown=&EGong_if_gtk_shutdown,
     27 		.sock_watch=&EGong_gtk_waiter_add,
     28 		.loop=&EGong_if_gtk_main
     29 };
     30 int EGong_if_gtk_main(void){
     31 	gtk_main();
     32 	return 1;
     33 }
     34 int EGong_if_gtk_setup(struct EGong_interface *interface){
     35 	gtk_init(&EGong_global_argc, &EGong_global_argv);
     36 	#ifdef USE_LIBNOTIFY
     37 	if(!notify_init("EGong")){
     38 		do_log("Couldn't setup libnotify", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
     39 	}
     40 	else{
     41 		EGong_if_gtk_have_libnotify=1;
     42 	}
     43 	#endif
     44 	GError *err=NULL;
     45 	EGong_if_gtk_icon=gdk_pixbuf_new_from_file(EGONG_INSTALL_PREFIX"/share/EGong.ico", &err);
     46 	if(EGong_if_gtk_icon==NULL){
     47 		do_log("Couldn't open iconfile", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
     48 		return EGONG_INTERFACE_RETURN_ERROR;
     49 	}
     50 	return EGONG_INTERFACE_RETURN_OK;
     51 }
     52 int EGong_if_gtk_cycle(struct EGong_interface *interface, String *msg, char **dest){
     53 	return EGONG_INTERFACE_RETURN_OK;
     54 	interface->funcs->cycle=NULL; //Prevent any further execution
     55 	EGong_interfaces_userstreams--; //GTK takes over the job of cycling the interfaces.
     56 	gtk_main();
     57 	return EGONG_INTERFACE_RETURN_EXIT;
     58 }
     59 
     60 int EGong_if_gtk_display_window(struct EGong_interface *interface, const String *msg){
     61 	do_log("Displaying message in window", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
     62 	GtkWidget *win=gtk_message_dialog_new(GTK_WINDOW(Egong_if_gtk_root), (Egong_if_gtk_root==NULL) ? 0 : GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "EGong Nachricht");
     63 	if(win==NULL){
     64 		do_log("Couldn't create messagebox", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
     65 	}
     66 	GtkWidget *img=gtk_image_new_from_pixbuf(EGong_if_gtk_icon);
     67 	if(img==NULL){
     68 		do_log("ERRIR", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
     69 	}
     70 	else{
     71 		gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(win), img);
     72 	}
     73 	gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(win), msg->data);
     74 	g_signal_connect_swapped(GTK_WIDGET(win), "response", G_CALLBACK(gtk_widget_destroy), win);
     75 	gtk_widget_show_all(GTK_WIDGET(win));
     76 }
     77 int EGong_if_gtk_display_notify(struct EGong_interface *interface, const String *msg){
     78 	do_log("Displaying message with libnotify", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
     79 	#ifdef USE_LIBNOTIFY
     80 	if(EGong_if_gtk_have_libnotify==0){
     81 		do_log("Libnotify not initialized", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
     82 	}
     83 	NotifyNotification *notify=notify_notification_new("Egong Nachricht", msg->data, NULL);
     84 	notify_notification_set_image_from_pixbuf(notify, EGong_if_gtk_icon);
     85 	GError *err=NULL;
     86 	if(!notify_notification_show(notify, &err)){
     87 		do_log("Couldn't display notification", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
     88 	}
     89 	#else
     90 		do_log("Libnotify not compiled in...", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
     91 	#endif
     92 }
     93 int EGong_if_gtk_display(struct EGong_interface *interface, const String *msg){
     94 	do_log("Displaying message", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
     95 	if((EGong_global_configuration.gui.destinations&EGONG_CONFIG_GUI_DEST_NOTIFY)>0){
     96 		EGong_if_gtk_display_notify(interface, msg);
     97 	}
     98 	if((EGong_global_configuration.gui.destinations&EGONG_CONFIG_GUI_DEST_WINDOW)>0){
     99 		EGong_if_gtk_display_window(interface, msg);
    100 	}
    101 	return EGONG_INTERFACE_RETURN_OK;
    102 }
    103 
    104 int EGong_if_gtk_shutdown(struct EGong_interface *interface){
    105 	gtk_main_quit();
    106 	return EGONG_INTERFACE_RETURN_OK;
    107 }
    108 void EGong_if_gtk_tray_popup(GtkStatusIcon *icon, guint button, guint activation_time, gpointer data){
    109 	gtk_menu_popup(GTK_MENU(data),NULL,NULL,gtk_status_icon_position_menu, icon, button, activation_time);
    110 }
    111 void EGong_if_gtk_widget_toggle(GtkWidget *caller){
    112 	if(gtk_widget_get_visible(caller)){
    113 		gtk_widget_hide_all(caller);
    114 	}
    115 	else{
    116 		gtk_widget_show_all(caller);
    117 	}
    118 }
    119 void EGong_if_gtk_show_element(struct EGong_GUI_item *itm){
    120 	gtk_widget_show(GTK_WIDGET(itm->itemptr));
    121 }
    122 static void EGong_if_gtk_event_callback(GtkWidget *caller, struct EGong_if_gtk_callbackparam *param){
    123 	EGong_GUI_event_callback(param->caller, param->event);
    124 }
    125 GtkWidget *EGong_if_gtk_create_gui(struct EGong_GUI_item *parent, struct EGong_GUI_item *this){
    126 	unsigned int i;
    127 	GtkWidget *element=NULL;
    128 	GtkWidget *submenu;
    129 	struct EGong_GUI_item **children=this->child;
    130 	char *eventdefault;
    131 	switch(this->type){
    132 		case EGONG_GUI_WINDOW:
    133 			element=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    134 			g_signal_connect_swapped(element, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), (gpointer)element);
    135 			if(this->text!=NULL){
    136 				gtk_window_set_title(GTK_WINDOW(element),this->text);
    137 			}
    138 			gtk_window_set_icon(GTK_WINDOW(element), EGong_if_gtk_icon);
    139 			eventdefault="activate-focus";
    140 		break;
    141 		case EGONG_GUI_TEXT:
    142 			element=gtk_entry_new();
    143 			if(this->text!=NULL){
    144 				gtk_entry_set_text(GTK_ENTRY(element),this->text);
    145 			}
    146 			eventdefault="activate";
    147 		break;
    148 		case EGONG_GUI_TOGGLE_BUTTON:
    149 			element=(this->text!=NULL) ? gtk_toggle_button_new_with_label(this->text) : gtk_toggle_button_new();
    150 			eventdefault="toggled";
    151 		break;
    152 		case EGONG_GUI_BUTTON:
    153 			element=(this->text!=NULL) ? gtk_button_new_with_label(this->text) : gtk_button_new();
    154 			eventdefault="clicked";
    155 		break;
    156 		case EGONG_GUI_LABEL:
    157 			element=gtk_label_new(this->text);
    158 		break;
    159 		case EGONG_GUI_MENU:
    160 			submenu=element=gtk_menu_new();
    161 		break;
    162 		case EGONG_GUI_HBOX:
    163 			element=gtk_hbox_new(TRUE, 1);
    164 		break;
    165 		case EGONG_GUI_VBOX:
    166 			element=gtk_vbox_new(TRUE, 1);
    167 		break;
    168 		case EGONG_GUI_MENUITEM_IMAGE:
    169 		case EGONG_GUI_MENUITEM:
    170 			
    171 			if(this->type==EGONG_GUI_MENUITEM_IMAGE){
    172 				gchar *stockid;
    173 				switch((unsigned int)(intptr_t)this->extra){
    174 					case EGUI_MIMG_EXIT:
    175 						stockid=GTK_STOCK_QUIT;
    176 					break;
    177 				}
    178 				element=gtk_image_menu_item_new_with_label(this->text);
    179 				gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(element),gtk_image_new_from_icon_name((const gchar *)stockid,GTK_ICON_SIZE_MENU));
    180 			}
    181 			else{
    182 				element=gtk_menu_item_new_with_label(this->text);
    183 			}
    184 			if(this->child!=NULL){	//Menuitem has submenus
    185 				struct EGong_GUI_item subm={
    186 					.type=EGONG_GUI_MENU, .text=NULL, .tooltip=NULL, .child=this->child
    187 				};
    188 				submenu=EGong_if_gtk_create_gui(this, &subm);
    189 				gtk_menu_item_set_submenu(GTK_MENU_ITEM(element), submenu);
    190 				children=NULL; //Children have been processed
    191 			}
    192 			eventdefault="activate";
    193 		break;
    194 		case EGONG_GUI_SYSTRAY:
    195 			element=(GtkWidget *)gtk_status_icon_new_from_pixbuf(EGong_if_gtk_icon);
    196 			eventdefault="activate";
    197 		break;
    198 		default:
    199 			do_log("Unknown GUI-Type specified", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
    200 			return NULL;
    201 	}
    202 	if(element==NULL){
    203 		do_log("Couldn't initialize element", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
    204 		return NULL;
    205 	}
    206 	if(this->tooltip!=NULL){
    207 		if(this->type==EGONG_GUI_SYSTRAY) gtk_status_icon_set_tooltip(GTK_STATUS_ICON(element),this->tooltip);
    208 		else gtk_widget_set_tooltip_text(element,this->tooltip);
    209 	}
    210 	if(this->events!=NULL){
    211 		struct EGong_GUI_event *ev;
    212 		for(i=0;this->events[i]!=NULL; i++){
    213 			struct EGong_if_gtk_callbackparam *param=malloc(sizeof(struct EGong_if_gtk_callbackparam));
    214 			param->caller=this;
    215 			param->event=this->events[i];
    216 			g_signal_connect(element, eventdefault, G_CALLBACK(EGong_if_gtk_event_callback), (gpointer)param);
    217 		}
    218 	}
    219 	if(children!=NULL){
    220 		GtkWidget *child_widget;
    221 		for(i=0;children[i]!=NULL; i++){
    222 			child_widget=EGong_if_gtk_create_gui(this, children[i]);
    223 			if(child_widget!=NULL){
    224 				if(children[i]->type==EGONG_GUI_WINDOW){
    225 					if(this->type==EGONG_GUI_SYSTRAY){
    226 						g_signal_connect_swapped(GTK_STATUS_ICON(element), "activate", G_CALLBACK(EGong_if_gtk_widget_toggle), child_widget);
    227 					}
    228 					else{
    229 						g_signal_connect_swapped(GTK_STATUS_ICON(element), "activate", G_CALLBACK(gtk_widget_show_all), child_widget);
    230 					}
    231 				}
    232 				else{
    233 					switch(this->type){
    234 						case EGONG_GUI_MENU:
    235 						case EGONG_GUI_MENUITEM:
    236 							gtk_menu_shell_append(GTK_MENU_SHELL(submenu), child_widget);
    237 						break;
    238 						case EGONG_GUI_HBOX:
    239 						case EGONG_GUI_VBOX:
    240 							gtk_box_pack_start(GTK_BOX(element), child_widget, TRUE, TRUE, 1);
    241 						break;
    242 						case EGONG_GUI_SYSTRAY:
    243 							if(children[i]->type==EGONG_GUI_MENU){
    244 								g_signal_connect(GTK_STATUS_ICON(element), "popup-menu", G_CALLBACK(EGong_if_gtk_tray_popup), child_widget);
    245 							}
    246 							else{
    247 								do_log("Unknown mapping from systray", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
    248 								gtk_widget_destroy(GTK_WIDGET(child_widget));
    249 							}
    250 						break;
    251 						default:
    252 							do_log("Assigning default", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
    253 							gtk_container_add(GTK_CONTAINER(element), child_widget);
    254 						break;
    255 					}
    256 					gtk_widget_show(child_widget);
    257 				}
    258 			}
    259 			else{
    260 				do_log("Couldn't initialize child Element", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
    261 			}
    262 		}
    263 	}
    264 	if(parent==NULL&&Egong_if_gtk_root==NULL&&this->type!=EGONG_GUI_SYSTRAY){
    265 		Egong_if_gtk_root=element;
    266 	}
    267 	this->itemptr=(void *)element;
    268 	return element;
    269 }
    270 void *EGong_gtk_get_item_value(struct EGong_GUI_item *itm){
    271 	void *ret=NULL;
    272 	switch(itm->type){
    273 		case EGONG_GUI_TEXT:
    274 			ret=(void *)gtk_entry_get_text(itm->itemptr);
    275 		break;
    276 		case EGONG_GUI_WINDOW:
    277 			ret=(void *)itm->itemptr;
    278 		break;
    279 		case EGONG_GUI_TOGGLE_BUTTON:
    280 			ret=(void *)(intptr_t)(unsigned int)(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(itm->itemptr)) ? 1 : 0);
    281 		break;
    282 		default:
    283 			do_log("Event datasource specified where no data can be obtained", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR);
    284 		break;
    285 	}
    286 	return ret;
    287 }
    288 void EGong_if_gtk_free_item_value(struct EGong_GUI_item *itm, void *element){
    289 	return;
    290 }
    291 gboolean Egong_waiter_gtk_callback(GIOChannel *source, GIOCondition condition, gpointer data){
    292 	if(EGong_interface_cycle()!=0){
    293 		EGong_if_gtk_shutdown(NULL);
    294 	}
    295 	return G_SOURCE_CONTINUE;
    296 }
    297 int EGong_gtk_waiter_add(int sock, unsigned short int type){
    298 	do_log("Adding sockwatch", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG);
    299 	GIOChannel *new=g_io_channel_unix_new(sock);
    300 	g_io_add_watch(new,G_IO_IN|G_IO_ERR|G_IO_HUP, Egong_waiter_gtk_callback, NULL);
    301 	return 0;
    302 }