X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=main.c;h=cf37b318c0d0ef9c38733502b1699796a151ba2d;hb=0b9477affd8b7978768ee76bc5631adbec3a2dcf;hp=b4a3607a54f70e90e8b97e9ab73b9e637741304e;hpb=432ef642869fbbac2d6f6d111d80137cc5e7b119;p=ovirt-viewer.git diff --git a/main.c b/main.c index b4a3607..cf37b31 100644 --- a/main.c +++ b/main.c @@ -59,9 +59,15 @@ static void connect_to_wui (GtkWidget *, gpointer); static void login_to_wui (GtkWidget *, gpointer); static gboolean delete_event (GtkWidget *widget, GdkEvent *event, gpointer data); static void destroy (GtkWidget *widget, gpointer data); +static void clear_connectmenu (void); /* For any widgets accessed from multiple functions. */ static GtkWidget *window; +static GtkWidget *connectitem; +static GtkWidget *connectmenu; +static GtkWidget *no_connections; +static GtkWidget *refresh_vmlist; +static GtkWidget *refresh_vmlist_separator; static GtkWidget *connection_area; static GtkWidget *ca_hostname; static GtkWidget *ca_button; @@ -70,11 +76,14 @@ static GtkWidget *login_area; static GtkWidget *la_username; static GtkWidget *la_password; static GtkWidget *la_button; +static GtkWidget *notebook; +static GtkWidget *statusbar; +static guint statusbar_ctx; static GdkCursor *busy_cursor; /* Menus. */ enum menuNums { - FILE_MENU, + CONNECT_MENU, VIEW_MENU, SEND_KEY_MENU, WINDOW_MENU, @@ -89,7 +98,7 @@ struct menuItem { }; static struct menuItem menuItems[] = { - { FILE_MENU, NULL, "_File", "File" }, + { CONNECT_MENU, NULL, "_Connect", "Connect" }, { VIEW_MENU, NULL, "_View", "View" }, { SEND_KEY_MENU, NULL, "_Send Key", "Send Key" }, { WINDOW_MENU, NULL, "_Window", "Window" }, @@ -203,8 +212,6 @@ start_ui (void) { GtkWidget *vbox; GtkWidget *menubar; - GtkWidget *file; - GtkWidget *filemenu; GtkWidget *view; GtkWidget *viewmenu; GtkWidget *sendkey; @@ -217,7 +224,6 @@ start_ui (void) GtkWidget *ca_hbox; GtkWidget *ca_label; GtkWidget *la_hbox; - GtkWidget *notebook; DEBUG ("creating viewer windows and menus"); @@ -245,9 +251,22 @@ start_ui (void) /* Menubar. */ menubar = gtk_menu_bar_new (); - file = menu_item_new (FILE_MENU); - filemenu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (file), filemenu); + connectitem = menu_item_new (CONNECT_MENU); + connectmenu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (connectitem), connectmenu); + + no_connections = gtk_menu_item_new_with_label ("Not connected"); + gtk_menu_append (GTK_MENU (connectmenu), no_connections); + gtk_widget_set_sensitive (no_connections, FALSE); + + /* This is not added to the menu yet, but will be when we are + * connected. + */ + refresh_vmlist = + gtk_menu_item_new_with_label ("Refresh list of virtual machines"); + g_object_ref (refresh_vmlist); + refresh_vmlist_separator = gtk_separator_menu_item_new (); + g_object_ref (refresh_vmlist_separator); #if 0 screenshot = gtk_menu_item_new_with_mnemonic ("_Screenshot"); @@ -272,7 +291,7 @@ start_ui (void) helpmenu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (help), helpmenu); - gtk_menu_bar_append (GTK_MENU_BAR (menubar), file); + gtk_menu_bar_append (GTK_MENU_BAR (menubar), connectitem); gtk_menu_bar_append (GTK_MENU_BAR (menubar), view); gtk_menu_bar_append (GTK_MENU_BAR (menubar), sendkey); gtk_menu_bar_append (GTK_MENU_BAR (menubar), wind); @@ -319,10 +338,16 @@ start_ui (void) /* Tabbed notebook. */ notebook = gtk_notebook_new (); - gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_LEFT); + /*gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_LEFT);*/ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), TRUE); gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE); + /* Status bar. */ + statusbar = gtk_statusbar_new (); + statusbar_ctx = gtk_statusbar_get_context_id (GTK_STATUSBAR (statusbar), + "context"); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), statusbar_ctx, ""); + /* Packing. */ gtk_container_add (GTK_CONTAINER (window), vbox); gtk_container_add_with_properties (GTK_CONTAINER (vbox), menubar, @@ -333,6 +358,8 @@ start_ui (void) "expand", FALSE, "fill", TRUE, NULL); gtk_container_add_with_properties (GTK_CONTAINER (vbox), notebook, "expand", TRUE, NULL); + gtk_container_add_with_properties (GTK_CONTAINER (vbox), statusbar, + "expand", FALSE, NULL); /* Show widgets. */ gtk_widget_show_all (window); @@ -344,7 +371,7 @@ start_ui (void) } static GtkWidget * -menu_item_new(int which_menu) +menu_item_new (int which_menu) { GtkWidget *widget; GtkWidget *label; @@ -352,14 +379,14 @@ menu_item_new(int which_menu) text = menuItems[which_menu].ungrabbed_text; - widget = gtk_menu_item_new(); - label = g_object_new(GTK_TYPE_ACCEL_LABEL, NULL); - gtk_label_set_text_with_mnemonic(GTK_LABEL(label), text); - gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + widget = gtk_menu_item_new (); + label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL); + gtk_label_set_text_with_mnemonic (GTK_LABEL (label), text); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_container_add(GTK_CONTAINER(widget), label); - gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(label), widget); - gtk_widget_show(label); + gtk_container_add (GTK_CONTAINER (widget), label); + gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), widget); + gtk_widget_show (label); menuItems[which_menu].label = label; @@ -410,6 +437,71 @@ login_to_wui (GtkWidget *widget, gpointer data) wui_thread_send_login (username, password); } +/* Connect to a virtual machine. This callback is called from the + * connect menu. It searches the notebook of gtk-vnc widgets to see + * if we have already connected to this machine, and if not it + * makes a new connection. + */ +static void +connect_to_vm (GtkWidget *widget, gpointer _vm) +{ + struct vm *vm = (struct vm *) _vm; + int n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)); + int i, uuidlen, len; + GtkWidget *child; + const char *label; + char *label2; + + DEBUG ("searching tabs for uuid %s", vm->uuid); + + uuidlen = strlen (vm->uuid); + + /* Search the tabs for this UUID, and if found, switch to it and return. */ + for (i = 0; i < n; ++i) { + child = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i); + label = gtk_notebook_get_tab_label_text (GTK_NOTEBOOK (notebook), child); + len = strlen (label); + if (len >= uuidlen && + STREQ (label + len - uuidlen, vm->uuid)) { + DEBUG ("found on tab %d", i); + gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), i); + return; + } + } + + DEBUG ("not found, creating new tab"); + + /* This VM isn't in the notebook already, so create a new console. */ + len = strlen (vm->description) + 1 + strlen (vm->uuid) + 1; + label2 = g_alloca (len); + snprintf (label2, len, "%s %s", vm->description, vm->uuid); + + child = gtk_label_new (label2); /* XXX */ + + /* NB. We have to do this before adding it to the notebook. */ + gtk_widget_show (child); + + i = gtk_notebook_append_page (GTK_NOTEBOOK (notebook), child, NULL); + gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (notebook), child, label2); + gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), i); + + DEBUG ("finished creating new tab"); +} + +/* Remove all menu items from the Connect menu. */ +static void +remove_menu_item (GtkWidget *menu_item, gpointer data) +{ + gtk_container_remove (GTK_CONTAINER (connectmenu), menu_item); +} + +static void +clear_connectmenu (void) +{ + DEBUG ("clear Connect menu"); + gtk_container_foreach (GTK_CONTAINER (connectmenu), remove_menu_item, NULL); +} + /* The WUI thread has changed its state to connected. */ gboolean main_connected (gpointer data) @@ -434,6 +526,11 @@ main_disconnected (gpointer data) gtk_widget_show (connection_area); gtk_widget_hide (login_area); + + clear_connectmenu (); + gtk_menu_append (GTK_MENU (connectmenu), no_connections); + gtk_widget_show_all (connectmenu); + return FALSE; } @@ -525,7 +622,7 @@ main_login_error (gpointer _str) ASSERT_IS_MAIN_THREAD (); /* - gtk_label_set_text (GTK_LABEL (ca_error), str); + gtk_label_set_text (GTK_LABEL (la_error), str); */ g_free (str); @@ -543,20 +640,65 @@ main_status_error (gpointer _str) DEBUG ("status error: %s", str); ASSERT_IS_MAIN_THREAD (); - /* - gtk_label_set_text (GTK_LABEL (ca_error), str); - */ + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), statusbar_ctx); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), statusbar_ctx, str); g_free (str); return FALSE; } -/* The WUI thread has updated the vm list. */ +/* The WUI thread has updated the vm list. Here in the main thread + * we keep our own copy of the vmlist. + */ +static GSList *vmlist = NULL; + +static void add_vm_to_connectmenu (gpointer _vm, gpointer data); + gboolean main_vmlist_updated (gpointer data) { + GSList *new_vmlist; + DEBUG ("vmlist updated"); ASSERT_IS_MAIN_THREAD (); + /* Get the new vmlist. */ + if (wui_thread_get_vmlist (&new_vmlist)) { + /* Free the previous vmlist. This invalidates all the vm pointers + * contained in the Connect menu callbacks, but we're going to + * delete those callbacks and create news ones in a moment anyway ... + */ + free_vmlist (vmlist); + + vmlist = new_vmlist; + + clear_connectmenu (); + + gtk_menu_append (GTK_MENU (connectmenu), refresh_vmlist); + + if (vmlist != NULL) { + gtk_menu_append (GTK_MENU (connectmenu), refresh_vmlist_separator); + g_slist_foreach (vmlist, add_vm_to_connectmenu, NULL); + } + + /* Grrrr Gtk is stupid. */ + gtk_widget_show_all (connectmenu); + } + return FALSE; } + +static void +add_vm_to_connectmenu (gpointer _vm, gpointer data) +{ + struct vm *vm = (struct vm *) _vm; + GtkWidget *item; + + DEBUG ("adding %s to Connect menu", vm->description); + + item = gtk_menu_item_new_with_label (vm->description); + gtk_menu_append (GTK_MENU (connectmenu), item); + + g_signal_connect (G_OBJECT (item), "activate", + G_CALLBACK (connect_to_vm), vm); +}