X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=main.c;h=9c992f6cac1009bf033c957b209f53037ed9e577;hb=7e9794277b619bb232ffc874ee7efa4ead8ddb8e;hp=8509f431972b6cd215d16c2cf4f93402dbae684f;hpb=7389cc56d30d68a5ca9c57bbf691f4bf05d1a2f9;p=ovirt-viewer.git diff --git a/main.c b/main.c index 8509f43..9c992f6 100644 --- a/main.c +++ b/main.c @@ -22,11 +22,351 @@ #include #include #include +#include +#include #include #include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_SYS_UN_H +#include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif + +#ifndef G_THREADS_ENABLED +#error "This program requires GLib threads, and cannot be compiled without." +#endif + +#include "internal.h" + +/*#define HTTPS "https"*/ +#define HTTPS "http" + +gboolean debug = 0; + +/* Private functions. */ +static void start_ui (void); +static GtkWidget *menu_item_new (int which_menu); +static void connect_to_wui (GtkWidget *, gpointer); +static gboolean delete_event (GtkWidget *widget, GdkEvent *event, gpointer data); +static void destroy (GtkWidget *widget, gpointer data); + +/* For any widgets accessed from multiple functions. */ +static GtkWidget *connection_area; +static GtkWidget *ca_hostname; +static GtkWidget *ca_button; +static GtkWidget *login_area; +static GtkWidget *la_username; +static GtkWidget *la_password; +static GtkWidget *la_button; + +/* Menus. */ +enum menuNums { + FILE_MENU, + VIEW_MENU, + SEND_KEY_MENU, + WINDOW_MENU, + HELP_MENU, +}; + +struct menuItem { + guint menu; + GtkWidget *label; + const char *ungrabbed_text; + const char *grabbed_text; +}; + +static struct menuItem menuItems[] = { + { FILE_MENU, NULL, "_File", "File" }, + { VIEW_MENU, NULL, "_View", "View" }, + { SEND_KEY_MENU, NULL, "_Send Key", "Send Key" }, + { WINDOW_MENU, NULL, "_Window", "Window" }, + { HELP_MENU, NULL, "_Help", "Help" } +}; + +/* Window title. */ +static const char *title = "oVirt Viewer"; + +/* Gtk widget styles. Avoid installation hassles by keeping this + * inside the binary. It can still be overridden by the user (who + * will do that?). + */ +static const char *styles = + "\ +style \"ovirt-viewer-yellow-box\"\n\ +{\n\ + bg[NORMAL] = shade (1.5, \"yellow\")\n\ +}\n\ +widget \"*.ovirt-viewer-connection-area\" style \"ovirt-viewer-yellow-box\"\n\ +"; + +/* Command-line arguments. */ +static int print_version = 0; + +static const char *help_msg = + "Use '" PACKAGE " --help' to see a list of available command line options"; + +static const GOptionEntry options[] = { + { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, + "turn on debugging messages", NULL }, + { "version", 'V', 0, G_OPTION_ARG_NONE, &print_version, + "display version and exit", NULL }, + { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } +}; + int main (int argc, char *argv[]) { + GOptionContext *context; + GError *error = NULL; + + /* Initialize GLib threads before anything else. + * + * There is one main thread, which is used for all Gtk interactions + * and to keep the UI responsive, and one WUI thread. The WUI + * thread is used to connect to the WUI, log in, and maintain the list + * of virtual machines. The WUI thread is the only thread allowed + * to use the CURL library. + * + * The main thread sends instructions to the WUI thread (like "connect", + * "disconnect", etc.) using a simple message-passing protocol and + * a GAsyncQueue. + * + * The WUI thread keeps the UI updated by adding idle events which are + * processed in the main thread - see: + * http://mail.gnome.org/archives/gtk-app-devel-list/2007-March/msg00232.html + */ + if (!g_thread_supported ()) { + g_thread_init (NULL); + gdk_threads_init (); + } else { + fprintf (stderr, "GLib threads not supported or not working."); + exit (1); + } + + gtk_init (&argc, &argv); + + /* Parse command-line options. */ + context = g_option_context_new ("oVirt viewer"); + g_option_context_add_main_entries (context, options, NULL); + g_option_context_add_group (context, gtk_get_option_group (TRUE)); + g_option_context_add_group (context, vnc_display_get_option_group ()); + g_option_context_parse (context, &argc, &argv, &error); + + if (error) { + g_print ("%s\n%s\n", error->message, help_msg); + g_error_free (error); + exit (1); + } + + if (print_version) { + printf ("%s %s\n", PACKAGE, VERSION); + exit (0); + } + + start_wui_thread (); + start_ui (); + + gtk_main (); + + stop_wui_thread (); + + exit (0); +} + +/* Create the viewer window, menus. */ +static void +start_ui (void) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *menubar; + GtkWidget *file; + GtkWidget *filemenu; + GtkWidget *view; + GtkWidget *viewmenu; + GtkWidget *sendkey; + GtkWidget *sendkeymenu; + GtkWidget *wind; + GtkWidget *windmenu; + GtkWidget *help; + GtkWidget *helpmenu; + GtkWidget *ca_vbox; + GtkWidget *ca_hbox; + GtkWidget *ca_label; + GtkWidget *la_hbox; + GtkWidget *notebook; + + /* Parse styles. */ + gtk_rc_parse_string (styles); + + /* Window. */ + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size (GTK_WINDOW (window), 800, 600); + gtk_window_set_resizable (GTK_WINDOW (window), TRUE); + gtk_window_set_title (GTK_WINDOW (window), title); + + g_signal_connect (G_OBJECT (window), "delete_event", + G_CALLBACK (delete_event), NULL); + g_signal_connect (G_OBJECT (window), "destroy", + G_CALLBACK (destroy), NULL); + + /* VBox for layout within the window. */ + vbox = gtk_vbox_new (FALSE, 0); + + /* 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); + +#if 0 + screenshot = gtk_menu_item_new_with_mnemonic ("_Screenshot"); + gtk_menu_append (GTK_MENU (filemenu), screenshot); + g_signal_connect (screenshot, "activate", + GTK_SIGNAL_FUNC (take_screenshot), NULL); +#endif + + view = menu_item_new (VIEW_MENU); + viewmenu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (view), viewmenu); + + sendkey = menu_item_new (SEND_KEY_MENU); + sendkeymenu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (sendkey), sendkeymenu); + + wind = menu_item_new (WINDOW_MENU); + windmenu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (wind), windmenu); + + help = menu_item_new (HELP_MENU); + 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), view); + gtk_menu_bar_append (GTK_MENU_BAR (menubar), sendkey); + gtk_menu_bar_append (GTK_MENU_BAR (menubar), wind); + gtk_menu_bar_append (GTK_MENU_BAR (menubar), help); + + /* For login dialogs, etc., usually invisible. */ + connection_area = gtk_event_box_new (); + ca_vbox = gtk_vbox_new (FALSE, 0); + ca_label = gtk_label_new ("Give the name of the oVirt management server:"); + ca_hbox = gtk_hbox_new (FALSE, 0); + ca_hostname = gtk_entry_new (); + gtk_entry_set_width_chars (GTK_ENTRY (ca_hostname), 24); + ca_button = gtk_button_new_with_label ("Connect"); + gtk_box_pack_start (GTK_BOX (ca_hbox), ca_hostname, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (ca_hbox), ca_button, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (ca_vbox), ca_label, FALSE, FALSE, 4); + gtk_box_pack_start (GTK_BOX (ca_vbox), ca_hbox, TRUE, FALSE, 4); + gtk_container_add (GTK_CONTAINER (connection_area), ca_vbox); + + gtk_widget_set_name (connection_area, "ovirt-viewer-connection-area"); + + g_signal_connect (G_OBJECT (ca_button), "clicked", + G_CALLBACK (connect_to_wui), NULL); + + login_area = gtk_event_box_new (); + la_hbox = gtk_hbox_new (FALSE, 0); + la_username = gtk_entry_new (); + gtk_entry_set_width_chars (GTK_ENTRY (la_username), 12); + la_password = gtk_entry_new (); + gtk_entry_set_width_chars (GTK_ENTRY (la_password), 12); + gtk_entry_set_visibility (GTK_ENTRY (la_password), FALSE); + la_button = gtk_button_new_with_label ("Login"); + gtk_container_add (GTK_CONTAINER (la_hbox), la_username); + gtk_container_add (GTK_CONTAINER (la_hbox), la_password); + gtk_container_add (GTK_CONTAINER (la_hbox), la_button); + gtk_container_add (GTK_CONTAINER (login_area), la_hbox); + + gtk_widget_set_name (login_area, "ovirt-viewer-login-area"); + + /* Tabbed notebook. */ + notebook = gtk_notebook_new (); + 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); + + /* Packing. */ + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_container_add_with_properties (GTK_CONTAINER (vbox), menubar, + "expand", FALSE, NULL); + gtk_container_add_with_properties (GTK_CONTAINER (vbox), connection_area, + "expand", FALSE, "fill", TRUE, NULL); + gtk_container_add_with_properties (GTK_CONTAINER (vbox), login_area, + "expand", FALSE, "fill", TRUE, NULL); + gtk_container_add_with_properties (GTK_CONTAINER (vbox), notebook, + "expand", TRUE, NULL); + + /* Show widgets. */ + gtk_widget_show_all (window); + + if (wui_thread_is_connected ()) + gtk_widget_hide (connection_area); + if (!wui_thread_is_connected () || wui_thread_is_logged_in ()) + gtk_widget_hide (login_area); +} + +static GtkWidget * +menu_item_new(int which_menu) +{ + GtkWidget *widget; + GtkWidget *label; + const char *text; + + 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); + + 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; + + return widget; +} + +static gboolean +delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) +{ + DEBUG ("delete_event"); + return FALSE; +} + +static void +destroy (GtkWidget *widget, gpointer data) +{ + DEBUG ("destroy"); + gtk_main_quit (); +} + +static void +connect_to_wui (GtkWidget *widget, gpointer data) +{ + const char *hostname; + char *uri; + int len; + + hostname = gtk_entry_get_text (GTK_ENTRY (ca_hostname)); + if (STREQ (hostname, "")) return; + + /* https:// + hostname + /ovirt + \0 */ + len = 8 + strlen (hostname) + 6 + 1; + uri = alloca (len); + snprintf (uri, len, HTTPS "://%s/ovirt", hostname); + + wui_thread_send_connect (uri); }