Linux QQ之客户端

客户端之登录UI

//client.c 客户端主函数

#include "const_global.h"
#include <signal.h>
#include "gui.h"

void mem_error(){
	format_record("Read or write memory error.");
	exit(0);
}

int main(int argc, char *argv[]) {
	gtk_init(&argc, &argv);
	signal(SIGSEGV, mem_error);
	land_interface();
	return EXIT_SUCCESS;
}
//gui.h 前台UI实现的头文件

#ifndef GUI_H
#define GUI_H

#include <gtk/gtk.h>

void close_window(GtkWidget *, gpointer);
void close_app(GtkWidget *, gpointer);
void on_logout_event(GtkWidget *window, gpointer data);
void on_login_event(GtkWidget *, gpointer);
void on_clear_entry_event(GtkWidget *, gpointer);
void on_changed_event(GtkWidget * , gpointer);
void on_send_event(GtkWidget *, gpointer );
gboolean on_2click_record_event(GtkWidget *, GdkEventButton *, gpointer);

static void init_chat_window(char *,char *);
static void destroy_all_chat_window();
guint get_chat_thread_index(char *);
void *receive_msg_thread();

void add_list_item(GtkWidget *,char *, int);
static GtkTreeModel *create_and_fill_model(void);
static GtkWidget *create_view_and_model(void);

void chat_1to1_ui(char *);
void land_ok_ui();
void land_interface();

void show_login_status(GtkWidget *, gpointer);
void set_widget_bg(GtkWidget *, const gchar *);


typedef struct {
	GtkWidget *username_entry; // uname input entry in land ui
	GtkWidget *password_entry; // passwd input entry in land ui
} UserInfoGtk;

typedef struct{
	guint      status;	// chat window status, 1:opened / 0:closed
//	int		 clientfd;  // connect server file describor
	char peer_uid[10];  // peer userid
	char peer_uname[20];// peer username
	GtkWidget *window;	// chat window
	GtkWidget  *input;	// send msg entry obj
	GtkWidget *output;	// show msg treeview obj
//	GtkStatusIcon *trayIcon; // chat window status icon
	char  address[25];
}ChatThread;

void show_msg(ChatThread *, char *, int);

static ChatThread *chat_thread[MAXFRIENDS];

static GtkWidget *window;
//static GtkStatusIcon *trayIcon;
static GtkStatusIcon *trayIcon;

//according user level to modify
static guint CURRENT_UID=0;

static pthread_t recv_msg_tid;

static int CLIENT_FD = -1;

#endif
//gui.c 前台UI的具体实现

#include "const_global.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include "gui.h"
#include "pub.h"

#define INIT 	0
#define REFRESH 1

void set_widget_bg(GtkWidget *widget, const gchar *img_file) {
	GtkStyle *style;
	GdkPixbuf *pixbuf;
	GdkPixmap *pixmap;
	gint width, height;

	pixbuf = gdk_pixbuf_new_from_file(img_file, NULL );
	width = gdk_pixbuf_get_width(pixbuf);
	height = gdk_pixbuf_get_height(pixbuf);
	pixmap = gdk_pixmap_new(NULL, width, height, 24);
	gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, NULL, 0);
	style = gtk_style_copy(GTK_WIDGET(widget)->style);

	if (style->bg_pixmap[GTK_STATE_NORMAL])
		g_object_unref(style->bg_pixmap[GTK_STATE_NORMAL]);

	style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref(pixmap);
	style->bg_pixmap[GTK_STATE_ACTIVE] = g_object_ref(pixmap);
	style->bg_pixmap[GTK_STATE_PRELIGHT] = g_object_ref(pixmap);
	style->bg_pixmap[GTK_STATE_SELECTED] = g_object_ref(pixmap);
	style->bg_pixmap[GTK_STATE_INSENSITIVE] = g_object_ref(pixmap);
	gtk_widget_set_style(GTK_WIDGET(widget), style);
	g_object_unref(style);
}

void close_window(GtkWidget *window, gpointer data) {
	gtk_widget_destroy(window);

	if (data != NULL) {
		((ChatThread *) data)->status = 0;
		((ChatThread *) data)->address[0] = '\0';
	}
}

void close_app(GtkWidget *window, gpointer data) {
	gtk_main_quit();
}

void on_login_event(GtkWidget *button, gpointer data) {
	const char *username_text = gtk_entry_get_text(
			GTK_ENTRY(((UserInfoGtk *) data)->username_entry));
	const char *passwd_text = gtk_entry_get_text(
			GTK_ENTRY(((UserInfoGtk *) data)->password_entry));
	char buf[MAXLINE], *login_result, *user_pet_name, *ip_port;
#ifndef DEBUG
	if(strlen(username_text) == 0 || strlen(passwd_text) == 0) {
		LOGIN_STATUS = LOGIN_FAILED;
		goto End;
	}
	memset(buf,'\0',MAXLINE);

	login_user(username_text, passwd_text, buf);
	if(!strlen(buf)) {
		LOGIN_STATUS = LOGIN_FAILED;
		goto End;
	}
	strtok(buf, split); 				// action type [LOGIN|FRESH]
	login_result = strtok(NULL, split); // login status [SUCCESS|FAILED] and USER_NAME
	user_pet_name = strtok(NULL, split);
	ip_port = strtok(NULL, split);

	LOGIN_STATUS = strcmp(login_result,"SUCCESS") == 0 ? LOGIN_SUCCESS : LOGIN_FAILED;

	if (LOGIN_STATUS == LOGIN_SUCCESS) {
		memset(USER_ID, '\0', sizeof(USER_ID));
		memset(USER_NAME,'\0',sizeof(USER_NAME));
		memset(ADDRESS,'\0',sizeof(ADDRESS));
		strcpy(USER_ID, username_text);
		strcpy(USER_NAME, user_pet_name);
		strcpy(ADDRESS, ip_port);
		CLIENT_FD = open_tcp_connection();
	}
#else
	LOGIN_STATUS = LOGIN_SUCCESS;
	strcpy(USER_ID, "00001");
	strcpy(USER_NAME, "debug");
	strcpy(ADDRESS, "127.0.0.1:8000");
#endif
	End:
		return;
}

void on_logout_event(GtkWidget *window, gpointer data) {
	int clientfd;
	char buf[50], *logout_result;

//	clientfd = open_tcp_connection();
	clientfd = CLIENT_FD;
	if( -1 == clientfd) {
		format_record("ERROR: Can not connect to server, quit failed.");
		return;
	}
	sprintf(buf, "LOGOUT%s%s%sNULL%sNULL", split, USER_ID, split, split);

	if (Write(clientfd, buf, sizeof(buf)) < 0) {
		format_record("ERROR: Write request to server to logout failed.");
		goto End;
	}
	memset(buf, '\0', sizeof(buf));
	if (Read(clientfd, buf, sizeof(buf)) < 0) {
		format_record("ERROR: Read return result from server of login failed.");
		goto End;
	}

	strtok(buf, split); 				 	// action type [LOGIN|REFRESH|LOGOUT]
	logout_result = strtok(NULL, split); 	// login status [SUCCESS|FAILED] and USER_NAME

	LOGIN_STATUS = strcmp(logout_result, "SUCCESS") == 0 ? LOGIN_OFF : LOGIN_SUCCESS;

	if (LOGIN_STATUS != LOGIN_OFF) {
		format_record("There is something wrong to read return result from server of logout.");
		goto End;
	}

	memset(USER_ID, '\0', sizeof(USER_ID));
	memset(USER_NAME,'\0',sizeof(USER_NAME));
	memset(ADDRESS,'\0',sizeof(ADDRESS));
	destroy_all_chat_window();
	close_app(window, data);

	End:
		Close(clientfd);
		CLIENT_FD = -1;
}

void on_clear_entry_event(GtkWidget *button, gpointer data) {
//	GtkTextBuffer *buffer;
//	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW( data));
//	gtk_text_buffer_set_text(buffer, "", -1);
	gtk_entry_set_text((GtkEntry *) data, "");
}

void on_changed_event(GtkWidget * widget, gpointer statusbar) {
	GtkTreeIter iter;
	GtkTreeModel *model;
	char *value = NULL;

	if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(widget), &model,
			&iter)) {
		gtk_tree_model_get(model, &iter, COL_NAME, &value, -1);
		if (value == NULL )
			return;
		gtk_statusbar_push(GTK_STATUSBAR(statusbar),
				gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), value),
				value);
		g_free(value);
	}
}

void on_send_event(GtkWidget *widget, gpointer data) {
	char *peer_ip, *peer_port, *address;
	char words[130];
	if (strlen(gtk_entry_get_text(GTK_ENTRY(((ChatThread *) data)->input)))) {
		sprintf(words, "%s%s%s%s%s", USER_ID, split, USER_NAME, split, gtk_entry_get_text(GTK_ENTRY(((ChatThread *) data)->input)));
//begin: send msg to peer user
		address = (char *)malloc(25);
		strcpy(address,((ChatThread *) data)->address);
		peer_ip = strtok(address,":");
		peer_port = strtok(NULL,":");
		send_udp_msg(peer_ip, atoi(peer_port), words);
		free(address);
//	end: send msg to peer user

//	begin: save msg to server
		memset(words,'\0',sizeof(words));
		sprintf(words, "SAVE_MSG%s%s%s%s%s%s",
				split,USER_ID,
				split,gtk_entry_get_text(GTK_ENTRY(((ChatThread *) data)->input)),
				split,((ChatThread *) data)->peer_uid);
		save_tcp_msg(words);
//		save_tcp_msg(CLIENT_FD,words);
//	end: save msg to server

//  begin: show msg in chat window
		memset(words,'\0',sizeof(words));
		sprintf(words,"%s :[%s]",gtk_entry_get_text(GTK_ENTRY(((ChatThread *) data)->input)), USER_NAME);
		on_clear_entry_event(widget, GTK_ENTRY(((ChatThread *) data)->input));
		show_msg((ChatThread *) data, words, SELF_ALIGN);
//	end: show msg in chat window
	} else {
		format_record("Can not send null character.");
	}
}

void add_list_item(GtkWidget *list, char *item_text, int alignment) {
	GtkWidget *list_item, *label;
	if (strlen(item_text)) {
//		gtk_container_add(GTK_CONTAINER(list),gtk_list_item_new_with_label(item_text));
		label = gtk_label_new(item_text);
		list_item = gtk_list_item_new();
		gtk_misc_set_alignment(GTK_MISC(label),alignment,0);
		// left/up alignment
//		gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
		// right/up alignment
//		gtk_misc_set_alignment(GTK_MISC(label),1,0);
		gtk_container_add(GTK_CONTAINER(list_item), label);
		gtk_container_add(GTK_CONTAINER(list), list_item);
	} else {
		format_record("No data!");
	}
}

static void destroy_all_chat_window(){
	int index = 0;
	for (index=CURRENT_UID-1; index >= 0; index--)
		free(chat_thread[index]);
	CURRENT_UID = 0;
}

static void init_chat_window(char *peer_uid, char *peer_uname){
	chat_thread[CURRENT_UID] = (ChatThread *) malloc(sizeof(ChatThread));
	memset(chat_thread[CURRENT_UID], '\0', sizeof(ChatThread));
	strcpy(chat_thread[CURRENT_UID]->peer_uid, peer_uid);
	strcpy(chat_thread[CURRENT_UID]->peer_uname, peer_uname);
	chat_thread[CURRENT_UID]->status = 0;
//	chat_thread[CURRENT_UID]->clientfd = -1;
//	chat_thread[CURRENT_UID]->trayIcon = gtk_status_icon_new_from_file("ico/qq2.ico");
	CURRENT_UID++;
}

guint get_chat_thread_index(char *uid) {
	int index;
	for(index=0; index < MAXFRIENDS; index++){
		if(!strcmp(chat_thread[index]->peer_uid, uid)) break;
	}
	if (index >= MAXFRIENDS){
		format_record("ERROR: Can not find proper uid for chat_thread.");
	}
	return index;
}

void show_msg(ChatThread *chat_thread, char *msg, int alignment){
	add_list_item(GTK_WIDGET(chat_thread->output), msg, alignment);
	gtk_widget_show_all(GTK_WIDGET(chat_thread->output));
}

void show_dialog(char *msgtip){
	GtkWidget *dialog;
	dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK,"%s",msgtip);
	gtk_window_set_title(GTK_WINDOW(dialog), "Information");
	gtk_dialog_run(GTK_DIALOG(dialog));
	gtk_widget_destroy(dialog);
}

/*icon******代码**********开始*/

guint change_icon(gpointer data) {
	char text[10];
	strcpy(text, gtk_status_icon_get_tooltip_text(trayIcon));
	if (strcmp(text, USER_NAME) != 0) {
		gtk_status_icon_set_from_file(trayIcon, "ico/qq.ico");
		gtk_status_icon_set_tooltip(trayIcon, USER_NAME);
	} else {
		gtk_status_icon_set_from_file(trayIcon, "ico/qq2.ico");
		gtk_status_icon_set_tooltip(trayIcon, (((ChatThread *)data)->peer_uid));
	}
	return 1;
}

guint change_self_icon() {
	gtk_status_icon_set_from_file(trayIcon, "ico/qq.ico");
	gtk_status_icon_set_tooltip(trayIcon, USER_NAME);
	return 1;
}

void trayView(GtkMenuItem *item, gpointer window){
	gtk_window_present(GTK_WINDOW(window));
}

void show_about(GtkMenuItem *item, gpointer window){
	show_dialog("Personal chat software.\nProblems call QQ:393608596.\nThank you!");
}

void trayIconActivated(GObject *trayIcon, gpointer data){
	char peer_uid[10];
	strcpy(peer_uid, gtk_status_icon_get_tooltip_text(GTK_STATUS_ICON(trayIcon)));
	if(strcmp(peer_uid,USER_NAME) != 0){
		chat_1to1_ui(peer_uid);
		gtk_status_icon_set_blinking(GTK_STATUS_ICON(trayIcon), FALSE);
		change_self_icon(GTK_STATUS_ICON(trayIcon));
	}else{
		gtk_window_present(GTK_WINDOW(data));
	}
}

void trayIconPopup(GtkStatusIcon *status_icon, guint button, guint32 activate_time, gpointer popUpMenu){
	gtk_menu_popup(GTK_MENU(popUpMenu), NULL, NULL, gtk_status_icon_position_menu, status_icon, button, activate_time);
}

gboolean delete_event(GtkWidget *window, GdkEvent *event, gpointer data){
	return FALSE;
}

gboolean window_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer trayIcon) {
	if (event->changed_mask == GDK_WINDOW_STATE_ICONIFIED
			&& (event->new_window_state == GDK_WINDOW_STATE_ICONIFIED
					|| event->new_window_state
							== (GDK_WINDOW_STATE_ICONIFIED
									| GDK_WINDOW_STATE_MAXIMIZED))) {
		gtk_widget_hide(GTK_WIDGET(widget));
	} else if (event->changed_mask == GDK_WINDOW_STATE_WITHDRAWN
			&& (event->new_window_state == GDK_WINDOW_STATE_ICONIFIED
					|| event->new_window_state
							== (GDK_WINDOW_STATE_ICONIFIED
									| GDK_WINDOW_STATE_MAXIMIZED))) {
	}
	return TRUE;
}

guint show_trayicon(GtkWidget *window) {
	GtkWidget *menu, *menuItemView, *menuItemExit, *about;

	trayIcon = gtk_status_icon_new_from_file("ico/qq.ico");
	menu = gtk_menu_new();

	menuItemView = gtk_menu_item_new_with_label("Window");
	about = gtk_menu_item_new_with_label("About");
	menuItemExit = gtk_menu_item_new_with_label("Exit");

	g_signal_connect(G_OBJECT(menuItemView), "activate", G_CALLBACK(trayView), window);
	g_signal_connect(G_OBJECT(about), "activate", G_CALLBACK(show_about), window);
	g_signal_connect(G_OBJECT(menuItemExit), "activate", G_CALLBACK(close_app), NULL);

	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItemView);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), about);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItemExit);
	gtk_widget_show_all(menu);

	gtk_status_icon_set_tooltip(trayIcon, USER_NAME);
	gtk_status_icon_set_visible(trayIcon, TRUE);
	g_signal_connect(GTK_STATUS_ICON(trayIcon), "activate",
			GTK_SIGNAL_FUNC(trayIconActivated), window);
	g_signal_connect(GTK_STATUS_ICON(trayIcon), "popup_menu",
			GTK_SIGNAL_FUNC(trayIconPopup), menu);

	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(close_app), NULL);
	g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_event), trayIcon);
	g_signal_connect(G_OBJECT(window), "window_state_event", G_CALLBACK(window_state_event), trayIcon);

	return 0;
}

void *receive_msg_thread(){
	int socketfd;
	guint uindex;
	char *buf_return, *peer_uid, *peer_uname, *buf_stream;
	socketfd = open_udp_server_running(ADDRESS);
	buf_return = (char *) malloc(MAXLINE);
	buf_stream = (char *) malloc(MAXLINE);
	while (1) {
		memset(buf_return, '\0', MAXLINE);
		memset(buf_stream, '\0', MAXLINE);
		receive_udp_msg(socketfd, buf_return);
		if (strlen(buf_return) <= 0) break;
		peer_uid = strtok(buf_return, split);
		peer_uname = strtok(NULL, split);
		sprintf(buf_stream, "[%s]: ", peer_uname);
		strcat(buf_stream, strtok(NULL, split));
/*
 * show the offline msg about save msg of db
 * read one record one by one
 * do connect db server then get records by recycling output
 */
		uindex = get_chat_thread_index(peer_uid);
//		check peer user chat window status[0:closed 1:opened]
		if (chat_thread[uindex]->status == 0) {
			change_icon(chat_thread[uindex]);
			gtk_status_icon_set_blinking(GTK_STATUS_ICON(trayIcon), TRUE);
		} else {
			show_msg(chat_thread[uindex], buf_stream, PEER_ALIGN);
		}
	}
	free(buf_return);
	free(buf_stream);
	Close(socketfd);
	pthread_exit(0);
}

void fill_model_data(GtkTreeStore *treestore, int opt) {
	GtkTreeIter toplevel, child;
	int clientfd;
	char buf[MAXLINE], *action_type, *role_type, *group_name,
		*friend_id, *friend_name, *friend_status;

	clientfd = open_tcp_connection();
	if (-1 == clientfd) {
		return ;
	}
	sprintf(buf, "FRESH%s%s%sNULL%sNULL", split, USER_ID, split, split);

	if (Write(clientfd, buf, sizeof(buf)) < 0) {
		format_record(
				"ERROR: Write request to server to fresh friend list failed.");
		return ;
	}
	memset(buf, 0, sizeof(buf));
	action_type = (char *) malloc(10);
	role_type = (char *) malloc(10);
	group_name = (char *) malloc(10);
	friend_id = (char *) malloc(10);
	friend_name = (char *) malloc(20);
	friend_status = (char *) malloc(2);

	while (1) {
		if (Read(clientfd, buf, sizeof(buf)) > 0) {
			strcpy(action_type, strtok(buf, split));
			strcpy(role_type, strtok(NULL, split));
			if (strcmp(role_type, "GROUP") == 0) {
				strcpy(group_name, strtok(NULL, split));
				gtk_tree_store_append(treestore, &toplevel, NULL );
				gtk_tree_store_set(treestore, &toplevel, 0, group_name, -1);
			} else if (strcmp(role_type, "FRIEND") == 0) {
				gtk_tree_store_append(treestore, &child, &toplevel);

				strcpy(friend_id, strtok(NULL, split));
				gtk_tree_store_set(treestore, &child, COL_ID, friend_id, -1);
				strcpy(friend_name, strtok(NULL, split));
				gtk_tree_store_set(treestore, &child, COL_NAME, friend_name, -1);
				strcpy(friend_status, strtok(NULL, split));
				gtk_tree_store_set(treestore, &child, COL_STATUS,
						(atoi(friend_status) == 1) ? "Online" : "Offline", -1);

				if(INIT == opt) init_chat_window(friend_id, friend_name);

			} else if (strcmp(role_type, "NULL") == 0) {
				break;
			} else {
				// do else
				break;
			}
		} else
			break;
	}
	free(action_type);
	free(role_type);
	free(group_name);
	free(friend_id);
	free(friend_name);
	free(friend_status);
	Close(clientfd);
}

guint refresh_tree_store(GtkWidget *view) {
	GtkTreeStore *treestore;
	treestore = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(view)));
	gtk_tree_store_clear(treestore);
	fill_model_data(treestore, REFRESH);
	return 1;
}

static GtkTreeModel *create_and_fill_model(void) {
	GtkTreeStore *treestore;
	treestore = gtk_tree_store_new(NUM_COLS, G_TYPE_STRING, G_TYPE_STRING,
			G_TYPE_STRING);
	fill_model_data(treestore, INIT);
	return GTK_TREE_MODEL(treestore);
}

static GtkWidget *create_view_and_model(void) {
	GtkTreeViewColumn *col[NUM_COLS];
	GtkCellRenderer *renderer;
	GtkWidget *view;
	GtkTreeModel *model;
	int col_index;
	view = gtk_tree_view_new();
	set_widget_bg(view, "ico/bg.jpg");

	renderer = gtk_cell_renderer_text_new();
	for (col_index = 0; col_index < NUM_COLS; col_index++) {
		col[col_index] = gtk_tree_view_column_new();
		gtk_tree_view_append_column(GTK_TREE_VIEW(view), col[col_index]);
		gtk_tree_view_column_pack_start(col[col_index], renderer, TRUE);
		gtk_tree_view_column_add_attribute(col[col_index], renderer, "text", col_index);
		gtk_tree_view_column_set_reorderable (col[col_index], TRUE);
	}
	gtk_tree_view_column_set_title(col[0], "Friends List");

	model = create_and_fill_model();
	gtk_tree_view_set_model(GTK_TREE_VIEW(view), model);
	g_object_unref(model);

	return view;
}

void chat_1to1_ui(char *peer_uid) {
	GtkWidget *table, *entry, *cancle;
	GtkWidget *send, *scrollwindow, *frame;
	GtkTooltips *tooltips;
	GtkAdjustment *horizontal, *vertical;
	guint id;

#ifndef DEBUG
	id = get_chat_thread_index(peer_uid);
	if (chat_thread[id]->status) return;
#else
	id = 0;
	chat_thread[id] = (ChatThread *)malloc(sizeof(ChatThread));
	strcpy(chat_thread[id]->peer_uname, "TestPeer");
#endif

	chat_thread[id]->status = 1;
	chat_thread[id]->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

	gtk_window_set_title(GTK_WINDOW(chat_thread[id]->window), chat_thread[id]->peer_uname);
	gtk_window_set_default_size(GTK_WINDOW(chat_thread[id]->window), 450, 450);
	gtk_container_set_border_width(GTK_CONTAINER(chat_thread[id]->window), 15);
	gtk_window_set_position(GTK_WINDOW(chat_thread[id]->window), GTK_WIN_POS_CENTER);

	table = gtk_table_new(CHAT_WINDOW_SIZE, CHAT_WINDOW_SIZE, TRUE);
	gtk_container_add(GTK_CONTAINER(chat_thread[id]->window), table);

	chat_thread[id]->output = gtk_list_new();
	vertical = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 1, 10, 0));
	horizontal = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 1, 10, 0));

	scrollwindow = gtk_scrolled_window_new(horizontal, vertical);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwindow),
			GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);

	frame = gtk_frame_new(NULL);
	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
	gtk_table_attach(GTK_TABLE(table), frame, 0, CHAT_WINDOW_SIZE, 0, 6,
			GTK_FILL, GTK_FILL, 0, 0);

	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwindow),
			chat_thread[id]->output);
	gtk_container_add(GTK_CONTAINER(frame), scrollwindow);
	gtk_list_scroll_vertical(GTK_LIST(chat_thread[id]->output), GTK_SCROLL_END, 1);

	chat_thread[id]->input = gtk_entry_new_with_max_length(100);
	gtk_widget_set_size_request(chat_thread[id]->input, 300, 40);
	gtk_table_attach_defaults(GTK_TABLE(table), chat_thread[id]->input, 0, 8, 6, 7);
	send = gtk_button_new_with_label("send");
	gtk_widget_set_size_request(send, 70, 30);
	gtk_table_attach(GTK_TABLE(table), send, 7, 8, 7, 8, 0, 0, 0, 0);
	cancle = gtk_button_new_with_label("cancle");
	gtk_widget_set_size_request(cancle, 70, 30);
	gtk_table_attach(GTK_TABLE(table), cancle, 6, 7, 7, 8, 0, 0, 0, 0);

	tooltips = gtk_tooltips_new();
	gtk_tooltips_set_tip(tooltips, chat_thread[id]->input, "发送内容不能为空", NULL );

#ifndef DEBUG
	request_peer_user_address(peer_uid, chat_thread[id]->address);
#else
	strcpy(chat_thread[id]->address, "10.10.10.1:1234");
#endif

	g_signal_connect(G_OBJECT(send), "clicked", G_CALLBACK(on_send_event),
			chat_thread[id]);
	g_signal_connect(G_OBJECT(cancle), "clicked", G_CALLBACK(on_clear_entry_event),
			chat_thread[id]->input);
	g_signal_connect(G_OBJECT(chat_thread[id]->input), "activate", G_CALLBACK(on_send_event),
			chat_thread[id]);
	g_signal_connect(G_OBJECT(chat_thread[id]->window), "destroy", G_CALLBACK(close_window),
			chat_thread[id]);

	gtk_widget_show_all(chat_thread[id]->window);
}

gboolean on_2click_record_event(GtkWidget *view, GdkEventButton *event, gpointer data) {
	GtkTreeIter iter;
	GtkTreeModel *model;
	GtkTreeSelection *selection;
	char *value1 = NULL, *value2 = NULL;

	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
	switch (event->type) {
	case GDK_2BUTTON_PRESS:
		if (event->button != MOUSE_LEFT_CLICK)
			break;
		if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection),
				&model, &iter)) {
			gtk_tree_model_get(model, &iter, COL_ID, &value1, COL_NAME, &value2, -1);
			if (value1 == NULL || value2 == NULL ) break;
//			chat_1to1_ui(value1, value2);
			chat_1to1_ui(value1);
			g_free(value1);
			g_free(value2);
		}
		break;
	case GDK_BUTTON_PRESS:
		break;
	default:
		format_record("No answer for this action.");
		break;
	}
	return FALSE;
}

void land_ok_ui() {
	GtkWidget *land_ok_window, *vbox, *statusbar;
	GtkWidget *view;
	GtkTreeSelection *selection;
	GtkWidget *image, *image_box, *name_label;

	char ok_ui_title[33];// len(id)[10] + len(name)[20] +'()'[2] +'\0'[1] = 33
#ifndef DEBUG
	memset(ok_ui_title,'\0',sizeof(ok_ui_title));
	sprintf(ok_ui_title,"%s(%s)",USER_NAME,USER_ID);
#endif

	land_ok_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_position(GTK_WINDOW(land_ok_window), GTK_WIN_POS_MOUSE);
	gtk_window_set_icon_from_file(GTK_WINDOW(land_ok_window), "ico/qq.ico", NULL);
	gtk_window_set_skip_taskbar_hint(GTK_WINDOW(land_ok_window), TRUE); // hide taskbar
	gtk_widget_set_size_request(land_ok_window, 280, 500);
	gtk_window_set_title(GTK_WINDOW(land_ok_window), ok_ui_title);

	vbox = gtk_vbox_new(FALSE, 2);
	gtk_container_add(GTK_CONTAINER(land_ok_window), vbox);

	name_label = gtk_label_new(USER_NAME);
	image = gtk_image_new_from_file("ico/qq.ico");
	image_box = gtk_hbox_new(FALSE, 10);
	gtk_box_pack_start(GTK_BOX(image_box), image, TRUE, FALSE, 0);
	gtk_box_pack_start(GTK_BOX(image_box), name_label, TRUE, FALSE, 0);
	gtk_box_pack_start(GTK_BOX(vbox), image_box, FALSE, FALSE, 0);
#ifndef DEBUG
	view = create_view_and_model();
	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
	gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 1);

	statusbar = gtk_statusbar_new();
	gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 1);

	g_signal_connect(selection, "changed", G_CALLBACK(on_changed_event), statusbar);
	g_signal_connect(view, "button_press_event", G_CALLBACK(on_2click_record_event),
			NULL );
	g_signal_connect(G_OBJECT(land_ok_window), "destroy", G_CALLBACK(on_logout_event),
			NULL );

	g_timeout_add(6000, (GtkFunction)refresh_tree_store, view);
#else
	g_signal_connect(G_OBJECT(land_ok_window), "destroy", G_CALLBACK(gtk_main_quit),
				NULL);
#endif

	show_trayicon(land_ok_window);
#ifndef DEBUG
	pthread_create(&recv_msg_tid, NULL, receive_msg_thread, NULL);
#endif
	gtk_widget_show_all(land_ok_window);
	gtk_main();
}

void show_login_status(GtkWidget *button, gpointer login_info_label) {
	const char *error_show =
			"<span foreground=\"red\"><b>Access denied!</b></span>";
	const char *info_show =
			"<span foreground=\"green\"><b>Access granted!</b></span>";
	if (LOGIN_STATUS == LOGIN_SUCCESS) {
//		gtk_label_set_markup(GTK_LABEL(login_info_label), info_show);
		close_window(window, NULL );
		land_ok_ui();
	} else {
		gtk_label_set_markup(GTK_LABEL(login_info_label), error_show);
	}
}

void land_interface() {
	GtkWidget *username_label, *password_label;
	GtkWidget *username_entry, *password_entry;
	GtkWidget *ok_button;
	GtkWidget *hbox1, *hbox2, *hbox3, *vbox;
	GtkWidget *left_blank_label, *right_blank_label, *login_info_label;
	UserInfoGtk user_info;

	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(window), "GtkLogin");
	gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
	gtk_window_set_default_size(GTK_WINDOW(window), 200, 150);
	gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

	g_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(close_app),
			NULL );

	username_label = gtk_label_new("Username:");
	password_label = gtk_label_new("Password:");
	user_info.username_entry = username_entry = gtk_entry_new_with_max_length(10);
	user_info.password_entry = password_entry = gtk_entry_new_with_max_length(10);
	gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE);

	left_blank_label = gtk_label_new("");
	right_blank_label = gtk_label_new("");
	ok_button = gtk_button_new_with_label("Login");
	login_info_label = gtk_label_new("");

	g_signal_connect(GTK_OBJECT(ok_button), "clicked",
			GTK_SIGNAL_FUNC(on_login_event), &user_info);
	g_signal_connect(G_OBJECT(username_entry), "activate",
			G_CALLBACK(on_login_event),&user_info);
	g_signal_connect(G_OBJECT(password_entry), "activate",
			G_CALLBACK(on_login_event),&user_info);
	g_signal_connect(GTK_OBJECT(ok_button), "clicked",
			GTK_SIGNAL_FUNC(show_login_status), login_info_label);
	g_signal_connect(GTK_OBJECT(ok_button), "clicked",
			GTK_SIGNAL_FUNC(on_clear_entry_event), password_entry);

	hbox1 = gtk_hbox_new(TRUE, 0);
	hbox2 = gtk_hbox_new(TRUE, 0);
	hbox3 = gtk_hbox_new(TRUE, 0);
	vbox = gtk_vbox_new(FALSE, 0);

	gtk_box_pack_start(GTK_BOX(hbox1), username_label, FALSE, FALSE, 5);
	gtk_box_pack_start(GTK_BOX(hbox1), username_entry, FALSE, FALSE, 5);

	gtk_box_pack_start(GTK_BOX(hbox2), password_label, FALSE, FALSE, 5);
	gtk_box_pack_start(GTK_BOX(hbox2), password_entry, FALSE, FALSE, 5);

	gtk_box_pack_start(GTK_BOX(hbox3), left_blank_label, FALSE, FALSE, 5);
	gtk_box_pack_start(GTK_BOX(hbox3), ok_button, TRUE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(hbox3), right_blank_label, FALSE, FALSE, 5);

	gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 5);
	gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 5);
	gtk_box_pack_start(GTK_BOX(vbox), hbox3, FALSE, FALSE, 5);

	gtk_box_pack_start(GTK_BOX(vbox), login_info_label, FALSE, FALSE, 3);

	gtk_container_add(GTK_CONTAINER(window), vbox);

	set_widget_bg(window, "ico/bg.jpg");

	gtk_widget_show_all(window);
	gtk_main();
}
//const_global.h 全局变量和通用头文件的包含头文件

#ifndef CONST_GLOBAL_H
#define CONST_GLOBAL_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
#include <sys/types.h>
#include <regex.h>
#include <memory.h>

#include "xini.h"

#define MOUSE_LEFT_CLICK 0x1
#define MOUSE_MIDDLE_CLICK 0x2
#define MOUSE_RIGHT_CLICK 0x3

#define CHAT_WINDOW_SIZE 8
#define MAXFRIENDS 10
#define MAX_SQL_LEN 180
#define MAXLINE 200

// define show the alignment
#define PEER_ALIGN 0
#define SELF_ALIGN 1
// peer: left
// self: right


#define CLIENT_CFG_FILE "config/client_cfg.ini"
#define SERVER_CFG_FILE "config/server_cfg.ini"

enum {
	LOGIN_OFF = 0, LOGIN_ON, LOGIN_SUCCESS, LOGIN_FAILED
};

enum {
	COL_ID = 0, COL_NAME, COL_STATUS, NUM_COLS
};

enum {
	REGISTER = 0, LOGIN, SEND_MEG, SEND_FILE, EXIT
};

static int LOGIN_STATUS = 0;
static char USER_ID[10];
static char USER_NAME[20];
static char ADDRESS[30]; //such as "IP:PORT"
static char split[10] = "#@@#";

static XINI ini ;

#endif

先发这些吧,通讯相关的(socket、pthread)下次贴出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值