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 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之客户端相关推荐
- linux qq多进程客户端,基于多进程QQ聊天软件设计.doc
基于多进程QQ聊天软件设计 基于多进程的QQ聊天程序设计功能需求描述用户名登陆聊天,人与人之间交流是必不可少的.私聊,与特定的用户聊天群聊,向所有的用户发送消息,大家一起聊欢乐多 server端 输入 ...
- linux做一个客户端与WemosD1作为服务器的无线通信(局域网通信)
参考:linux做一个客户端与WemosD1作为服务器的无线通信(局域网通信) 作者:枕上 发布时间:2021-07-19 23:33:44 网址:https://blog.csdn.net/jinc ...
- 第四十期:十年生死两茫茫,Linux QQ突然复活!
就在 1024 将将过去的深夜,突然,有人在 QQ 群内丢了一个链接和一句话"Linux QQ 发布了",顿时在静悄悄的 QQ 群内,大家纷纷冒了出来.一时间,群内就和开了锅一样热 ...
- linux可用机场客户端,Linux系统可用的6款Bittorrent客户端
大家都知道迅雷目前尚不支持Linux系统,其实使用Bittorrent客户端进行下载未尝不是一个好的选择,这里给大家介绍6款Linux可用Bittorrent客户端,方便经常需要进行文件下载的Linu ...
- Linux QQ 2.0.0 Beta2 发布
腾讯QQ Linux版迎来最新版发布,详细版本号为v2.0.0 Beta2,上一个版本2.0.0 Beta发布于去年10月24日,时隔160天又迎来了更新.本次升级主要是增加多人聊天会话支持,修复使用 ...
- qq邮箱日历同步服务器,科技教程:qq邮箱客户端怎么使用exchange服务同步日历?...
如今越来越多的小伙伴对于qq邮箱客户端怎么使用exchange服务同步日历?这方面的问题开始感兴趣,看似平静的每一天,在每个人身上都在发生着各种各样的故事,因为大家现在都是想要了解到此类的信息,那么既 ...
- qq离线linux,QQ For Linux 我哭了,官方版
昨天是10月24日,也是1024程序员节.作为极!客!>群体的重要一员,程序员们很多离不开Linux系统,没想到腾讯时隔11年发布了Linux QQ 2.0 beta,宣告Linux版QQ回归. ...
- linux qq x64,QQ Linux 版时隔多年再次更新,支持 x64、ARM64 等多种架构
昨天 10.24,都喜欢称作是程序员节,其实也没什么特殊含义.但是没想到昨天 QQ 居然发布了 QQ Linux 版本的更新.上次版本已经不知道是什么时候了,这次再次更新,确实是个惊喜.本次更新支持多 ...
- servercat IOS Linux监控 SSH客户端
servercat IOS Linux监控 SSH客户端 iOS 平台上新出的一个挺有趣的服务器监控 + SSH 客户端. 监控服务器状态,内存.CPU.网络 还能对Docker容器进行监控 价格:¥ ...
- linux中mysql客户端命令行连接不了 docker 创建的mysql
linux中mysql客户端命令行连接不了 docker 创建的mysql 问题 :如题 a@z:~$ mysql -h localhost -p ERROR 2002 (HY000): Can't ...
最新文章
- 04 | 内存快照:宕机后, Redis 如何实现快速恢复
- asp.net 研发,测试,或现网....非本机环境采用附加进程的方式在本地调试
- 如何写登录的记住账号
- Android 实现指纹识别demo
- find_path、find_library备忘录
- xmpp安装到Linux服务器,在Ubuntu 18.04/16.04系统中安装Ejabberd XMPP Server的方法
- 如何写好一份专利交底书?
- 输入法分类总结与优缺点
- 关于使用CKplayer播放m3u8视频出现没有视频的问题分析
- amos调节变量怎么画_AMOS结构方程教程,调节效应分析操作与结果的详细解读 ——【杏花开生物医药统计】...
- Telink BLE SIG Mesh GATT 配网功能
- 无网络rpm包安装相关依赖包
- [STM32F1]STM32 低功耗待机模式与RTC周期唤醒
- 单片机外围电路设计攻略(全)!
- 中国智慧停车市场运营调研及投资前景方向预测报告2022年版
- Chomp game博弈游戏
- 使用keil软件创建一个STM32工程
- malloclab 实验详解(动态分配器如何设计)
- sql 查询除某列之外的数据
- Linux系统编程之网络编程(socket)