客户端之登录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 uiGtkWidget *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 describorchar peer_uid[10];  // peer useridchar peer_uname[20];// peer usernameGtkWidget *window;    // chat windowGtkWidget  *input;    // send msg entry objGtkWidget *output; // show msg treeview obj
//  GtkStatusIcon *trayIcon; // chat window status iconchar  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 1void 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 DEBUGif(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_NAMEuser_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();}
#elseLOGIN_STATUS = LOGIN_SUCCESS;strcpy(USER_ID, "00001");strcpy(USER_NAME, "debug");strcpy(ADDRESS, "127.0.0.1:8000");
#endifEnd: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_NAMELOGIN_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 useraddress = (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 servermemset(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 windowmemset(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 elsebreak;}} elsebreak;}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 DEBUGid = get_chat_thread_index(peer_uid);if (chat_thread[id]->status) return;
#elseid = 0;chat_thread[id] = (ChatThread *)malloc(sizeof(ChatThread));strcpy(chat_thread[id]->peer_uname, "TestPeer");
#endifchat_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 DEBUGrequest_peer_user_address(peer_uid, chat_thread[id]->address);
#elsestrcpy(chat_thread[id]->address, "10.10.10.1:1234");
#endifg_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 DEBUGmemset(ok_ui_title,'\0',sizeof(ok_ui_title));sprintf(ok_ui_title,"%s(%s)",USER_NAME,USER_ID);
#endifland_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 taskbargtk_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 DEBUGview = 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);
#elseg_signal_connect(G_OBJECT(land_ok_window), "destroy", G_CALLBACK(gtk_main_quit),NULL);
#endifshow_trayicon(land_ok_window);
#ifndef DEBUGpthread_create(&recv_msg_tid, NULL, receive_msg_thread, NULL);
#endifgtk_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)下次贴出。

Linux QQ之客户端相关推荐

  1. linux qq多进程客户端,基于多进程QQ聊天软件设计.doc

    基于多进程QQ聊天软件设计 基于多进程的QQ聊天程序设计功能需求描述用户名登陆聊天,人与人之间交流是必不可少的.私聊,与特定的用户聊天群聊,向所有的用户发送消息,大家一起聊欢乐多 server端 输入 ...

  2. linux做一个客户端与WemosD1作为服务器的无线通信(局域网通信)

    参考:linux做一个客户端与WemosD1作为服务器的无线通信(局域网通信) 作者:枕上 发布时间:2021-07-19 23:33:44 网址:https://blog.csdn.net/jinc ...

  3. 第四十期:十年生死两茫茫,Linux QQ突然复活!

    就在 1024 将将过去的深夜,突然,有人在 QQ 群内丢了一个链接和一句话"Linux QQ 发布了",顿时在静悄悄的 QQ 群内,大家纷纷冒了出来.一时间,群内就和开了锅一样热 ...

  4. linux可用机场客户端,Linux系统可用的6款Bittorrent客户端

    大家都知道迅雷目前尚不支持Linux系统,其实使用Bittorrent客户端进行下载未尝不是一个好的选择,这里给大家介绍6款Linux可用Bittorrent客户端,方便经常需要进行文件下载的Linu ...

  5. Linux QQ 2.0.0 Beta2 发布

    腾讯QQ Linux版迎来最新版发布,详细版本号为v2.0.0 Beta2,上一个版本2.0.0 Beta发布于去年10月24日,时隔160天又迎来了更新.本次升级主要是增加多人聊天会话支持,修复使用 ...

  6. qq邮箱日历同步服务器,科技教程:qq邮箱客户端怎么使用exchange服务同步日历?...

    如今越来越多的小伙伴对于qq邮箱客户端怎么使用exchange服务同步日历?这方面的问题开始感兴趣,看似平静的每一天,在每个人身上都在发生着各种各样的故事,因为大家现在都是想要了解到此类的信息,那么既 ...

  7. qq离线linux,QQ For Linux 我哭了,官方版

    昨天是10月24日,也是1024程序员节.作为极!客!>群体的重要一员,程序员们很多离不开Linux系统,没想到腾讯时隔11年发布了Linux QQ 2.0 beta,宣告Linux版QQ回归. ...

  8. linux qq x64,QQ Linux 版时隔多年再次更新,支持 x64、ARM64 等多种架构

    昨天 10.24,都喜欢称作是程序员节,其实也没什么特殊含义.但是没想到昨天 QQ 居然发布了 QQ Linux 版本的更新.上次版本已经不知道是什么时候了,这次再次更新,确实是个惊喜.本次更新支持多 ...

  9. servercat IOS Linux监控 SSH客户端

    servercat IOS Linux监控 SSH客户端 iOS 平台上新出的一个挺有趣的服务器监控 + SSH 客户端. 监控服务器状态,内存.CPU.网络 还能对Docker容器进行监控 价格:¥ ...

  10. linux中mysql客户端命令行连接不了 docker 创建的mysql

    linux中mysql客户端命令行连接不了 docker 创建的mysql 问题 :如题 a@z:~$ mysql -h localhost -p ERROR 2002 (HY000): Can't ...

最新文章

  1. 04 | 内存快照:宕机后, Redis 如何实现快速恢复
  2. asp.net 研发,测试,或现网....非本机环境采用附加进程的方式在本地调试
  3. 如何写登录的记住账号
  4. Android 实现指纹识别demo
  5. find_path、find_library备忘录
  6. xmpp安装到Linux服务器,在Ubuntu 18.04/16.04系统中安装Ejabberd XMPP Server的方法
  7. 如何写好一份专利交底书?
  8. 输入法分类总结与优缺点
  9. 关于使用CKplayer播放m3u8视频出现没有视频的问题分析
  10. amos调节变量怎么画_AMOS结构方程教程,调节效应分析操作与结果的详细解读 ——【杏花开生物医药统计】...
  11. Telink BLE SIG Mesh GATT 配网功能
  12. 无网络rpm包安装相关依赖包
  13. [STM32F1]STM32 低功耗待机模式与RTC周期唤醒
  14. 单片机外围电路设计攻略(全)!
  15. 中国智慧停车市场运营调研及投资前景方向预测报告2022年版
  16. Chomp game博弈游戏
  17. 使用keil软件创建一个STM32工程
  18. malloclab 实验详解(动态分配器如何设计)
  19. sql 查询除某列之外的数据
  20. Linux系统编程之网络编程(socket)

热门文章

  1. AP课程选课建议及如何规划学习
  2. 跨境电商独立站搭建-跨境电商源码网站开发部署,独立站技术
  3. 算法(二):汽车振动部件目标检测与跟踪(计算机视觉)
  4. ASEMI代理韦达可控硅2P4M参数,2P4M图片,2P4M大小
  5. 致nbsp;正奋斗在路上的你
  6. UnityDecal——贴花方法总结
  7. 文化中国 系列四:解密《红楼梦》
  8. java项目中的banner生成网址
  9. 学习笔记-springmvc映射配置类v1.22
  10. 围绕计算机三人主题英语,求以环保为主题的 三人英语口语对话