cmdassist/src/panel.c
author asano
Mon, 27 Sep 2010 19:04:59 +0900
changeset 31 4d19a4859e94
parent 21 c6a79e6644e1
child 66 ce6069daf8a7
permissions -rw-r--r--
(for Jeffrey Chen) cmdassistant crash issue with Help invocation

/*
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
*/

/*
#
# Copyright (c) 2010. Oracle and/or its affiliates. All rights reserved.
# Use is subject to license terms.
#
*/

#include <locale.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <panel-applet.h>
#include <pthread.h>

#include "config.h"
#include "common.h"
#include "pre-dialog.h"
#include "applet.h"
#include "search.h"
#include "../config.h"
#include "service/service.h"

#define PANEL_WIDTH 380
#define PANEL_HIGH 38
#define PANEL_MAX_HIGH 500
#define PANEL_LINE_HIGH 50

GtkWidget *cmdassist_panel_input_entry;
cmdassist_config pre_conf;

extern GtkWidget *main_panel;

static GtkWidget *cmdassist_panel_treeview;
static GtkWidget *cmdassist_panel_loading_image;

static SearchResult cmdassist_command_list;

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

enum
{
  LIST_ICON = 0,
  LIST_ITEM = 1,
  N_COLUMNS
};

static void
List_remove_all(GtkWidget *list)
{
	GtkListStore *store;
	GtkTreeModel *model;
	GtkTreeIter  iter;

	store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (list)));

	model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));

	if (gtk_tree_model_get_iter_first(model, &iter) == FALSE) 
		return;

        debug_printf("start clean \n");
	gtk_list_store_clear(store);
        debug_printf("finish clean \n");


}

static void
add_to_result_tree(GtkListStore *store, gchar *command, gchar *title, gchar *icon_name)
{
	GtkTreeIter iter;

	gchar* name = g_strdup_printf ("%s/command_assistant_%s.png", CMDASSIST_PIXDIR, icon_name);
	GdkPixbuf* icon = gdk_pixbuf_new_from_file(name, NULL);

	gchar *str;
	str = g_markup_printf_escaped ("<b>%s</b>\n<i>%s</i>",
  				command, title);

	gtk_list_store_append(store, &iter);
	gtk_list_store_set(store, &iter, LIST_ICON, icon, LIST_ITEM, str, -1);

	g_free (str);
	if(icon != NULL) {
		g_object_unref (icon);
	}
	g_free (name);
}

static void
updateResultPanel(SearchResult *command){
	gint i = 0;
        debug_printf("add to list: %d \n", command->size);

	GtkWidget *treeview = cmdassist_panel_treeview;	

	List_remove_all(treeview);

	GtkListStore *store;
	store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)));

	if(command->size == 0) {
		add_to_result_tree(store, "No Result", "Change your search strings", "");
		command->size = 1;
		return;
	}
		
        while(command->size > i) {
        	debug_printf("%d: add to list: Command : %s title: %s type: %s\n", i, command->list[i].command, command->list[i].title, command->list[i].type);
		add_to_result_tree(store, command->list[i].command, command->list[i].title, command->list[i].type);
		i++;
        }
        debug_printf("%s Total result:%d\n\n\n", "finished!", command->size);
}

void updateResult(char *str){
	if(strcmp(str, "") == 0) {
		debug_printf("empty entry\n");
		gtk_window_resize (GTK_WINDOW (main_panel), PANEL_WIDTH, PANEL_HIGH);
		gtk_widget_queue_draw(main_panel);
		return;
	}

	if(cmdassist_command_list.list != NULL) {
		debug_printf("clean command_list\n");
		free(cmdassist_command_list.list);
		cmdassist_command_list.list = NULL;
	}
	cmdassist_command_list.size = 0;

	if(pre_conf.system.isServiceValid) {
		getResult(str, &pre_conf, &cmdassist_command_list);
	} else {
		doLocalSearch(str, &pre_conf, &cmdassist_command_list, pre_conf.criteria.result_size);
	}
	debug_printf("Succfully got data\n");

	gdk_threads_enter();
        updateResultPanel(&cmdassist_command_list);
	gdk_threads_leave();

	gint hight = PANEL_HIGH + PANEL_LINE_HIGH * cmdassist_command_list.size;
	if(hight > PANEL_MAX_HIGH) {
		hight = PANEL_MAX_HIGH;
	}

	debug_printf("Window high: %d\n", hight);
	gtk_window_resize (GTK_WINDOW (main_panel), PANEL_WIDTH, hight);
	gtk_widget_queue_draw(main_panel);

}

static void 
*key_press_thread(const char *str) {
	GtkWidget *input_entry = cmdassist_panel_input_entry;
	GtkWidget *loading_image = cmdassist_panel_loading_image;

	gchar *pre_str = malloc((strlen(str) + 1) * sizeof(gchar));
	strcpy(pre_str, str);

	gtk_widget_show(loading_image);
	//usleep(400000);
	struct timespec tv;
	tv.tv_sec = 0;
	tv.tv_nsec = 6 * 100 * 1000 * 1000;
	/* Sleep for the time specified in tv. If interrupted by a
	signal, place the remaining time left to sleep back into tv. */
	nanosleep (&tv, &tv);

	const char *cur_str = gtk_entry_get_text(input_entry);
	debug_printf("cur_str: %s, pre_str: %s, \n", cur_str, pre_str);
	if(strcmp(cur_str, pre_str) == 0) {
		pthread_mutex_lock(&mutex);
		updateResult(cur_str);
		pthread_mutex_unlock(&mutex);
	}
	g_free(pre_str);

	gtk_widget_hide(loading_image);
}

static gboolean
on_entry_key_press_cb (GtkWidget   *widget,
			GdkEventKey *event,
			gpointer     user_data)
{
	GtkWidget *input_entry = cmdassist_panel_input_entry;
	const char *str = gtk_entry_get_text(input_entry);
  
	pthread_t pid;
	pthread_attr_t attr;
	gint ret;

	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	ret = pthread_create(&pid, &attr, key_press_thread, str);
	if(ret != 0){
		debug_printf ("Create pthread error!\n");
		exit (1);
	}

	return FALSE;
}

static gboolean try_service() {
	gboolean rs = FALSE;
	struct timespec tv;
	tv.tv_sec = 6;
	tv.tv_nsec = 0;

	GList *doc_list = NULL;
	if(test_service(doc_list, &pre_conf)) {
		rs = TRUE;
	}
	nanosleep (&tv, &tv);
	return rs;
}

static void
*check_service_thread() {

	while(TRUE) {
		pre_conf.system.isServiceValid = try_service();
		debug_printf("%d\n", pre_conf.system.isServiceValid);
	}
}

static gboolean
check_service ()
{
        pthread_t pid;
        pthread_attr_t attr;
        gint ret;

        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        ret = pthread_create(&pid, &attr, check_service_thread, NULL);
        if(ret != 0){
                debug_printf ("Create check_service pthread error!\n");
                exit (1);
        }

        return FALSE;
}

static void
item_cell_data_func (GtkTreeViewColumn *col,
                    GtkCellRenderer   *renderer,
                    GtkTreeModel      *model,
                    GtkTreeIter       *iter,
                    gpointer           user_data)
{
	gchar *item_text;

	gtk_tree_model_get(model, iter, LIST_ITEM, &item_text, -1);

	g_object_set(renderer, "markup", item_text, NULL);

	g_free(item_text);	

}

static void
init_list(GtkWidget *list)
{

	GtkCellRenderer *renderer;
	GtkTreeViewColumn *column_icon;
	GtkTreeViewColumn *column_item;
	GtkListStore *store;

	renderer = gtk_cell_renderer_pixbuf_new ();
	column_icon = gtk_tree_view_column_new_with_attributes("Icon",
		renderer, "pixbuf", LIST_ICON, NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW(list), column_icon);

	renderer = gtk_cell_renderer_text_new();
	column_item = gtk_tree_view_column_new_with_attributes("Command",
        	renderer, "text", LIST_ITEM, NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW(list), column_item);
	gtk_tree_view_column_set_cell_data_func(column_item, renderer, item_cell_data_func, NULL, NULL);

	store = gtk_list_store_new(N_COLUMNS,GDK_TYPE_PIXBUF, G_TYPE_STRING);

	gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store));

	g_object_unref(store);
}

static void 
open_url(gchar *url) {
	GtkWidget *input_entry = cmdassist_panel_input_entry;

	gchar url_str[500];
	gchar *err = NULL;

	gchar *local_name = setlocale(LC_ALL, "");
	
	sprintf(url_str, "http://%s?q=%s&l=", url, gtk_entry_get_text(input_entry));
	strncat(url_str, local_name, 2);

	gtk_show_uri(gdk_screen_get_default(), url_str, GDK_CURRENT_TIME, &err);
	if(err != NULL)
	{
		g_error_free(err);
		return;
	}
}

static void
on_treeview_row_activated (GtkTreeView     *treeview)
{
	GtkTreeModel *model;
	GtkTreeSelection *selection;
	GtkTreeIter iter;
	GtkTreePath *path;

	g_return_if_fail (GTK_IS_TREE_VIEW (treeview));
	selection = gtk_tree_view_get_selection (treeview);
	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
		return;

	gchar *str_index = gtk_tree_model_get_string_from_iter (model, &iter);
	gint index = atoi(str_index);
	g_free(str_index);

	if(cmdassist_command_list.list != NULL) {
		open_url(cmdassist_command_list.list[index].url);
	}
}

GtkWidget *create_window() {
	GtkWidget *window;
	GtkWidget *frame;
        GtkWidget *vbox;
        GtkWidget *hbox;
        GtkWidget *label;
        GtkWidget *entry;
	GtkWidget *scrolledwindow;

        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_policy(window, TRUE, TRUE, TRUE);
        gtk_window_set_decorated (window, FALSE);
	//gtk_window_set_keep_above(window, TRUE);
	//gtk_window_set_modal (window, TRUE);

	frame = gtk_frame_new (NULL);
	gtk_widget_show(frame);
	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
	gtk_container_add (GTK_CONTAINER (window), frame);

	vbox = GTK_BOX (gtk_vbox_new (FALSE, 2));
	gtk_widget_show(vbox);
	gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
        gtk_container_add (GTK_CONTAINER (frame), vbox);

	hbox = GTK_BOX (gtk_hbox_new (FALSE, 2));
	gtk_widget_show(hbox);
        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2);
        label = gtk_label_new(_("Search: "));
	gtk_widget_show(label);
	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2);
        entry = gtk_entry_new();
	gtk_widget_set_size_request(entry, 265, 24);
	gtk_widget_show(entry);
	cmdassist_panel_input_entry = entry;
	gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 2);
	g_signal_connect ((gpointer) entry, "changed",
                    G_CALLBACK (on_entry_key_press_cb),
                    entry);

	gchar* name = g_strdup_printf ("%s/command_assistant_loading.gif", CMDASSIST_PIXDIR);
	cmdassist_panel_loading_image = gtk_image_new_from_file (name);
	g_free(name);
	gtk_box_pack_start (GTK_BOX (hbox), cmdassist_panel_loading_image, TRUE, TRUE, 2);

	scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
        gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 2);
	gtk_widget_show(scrolledwindow);
	gtk_scrolled_window_set_policy (scrolledwindow, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
	gtk_widget_set_name (scrolledwindow, "scrolledwindow");
	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_SHADOW_IN);


	cmdassist_panel_treeview = gtk_tree_view_new ();
	gtk_widget_show(cmdassist_panel_treeview);
	gtk_widget_set_name (cmdassist_panel_treeview, "treeview");
	gtk_container_add (GTK_CONTAINER (scrolledwindow), cmdassist_panel_treeview);
	gtk_container_set_border_width (GTK_CONTAINER (cmdassist_panel_treeview), 1);
	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (cmdassist_panel_treeview), FALSE);
	gtk_tree_view_set_enable_search (GTK_TREE_VIEW (cmdassist_panel_treeview), FALSE);
	g_signal_connect ((gpointer) cmdassist_panel_treeview, "row_activated",
			G_CALLBACK (on_treeview_row_activated),
			NULL);

	init_list(cmdassist_panel_treeview);

	gtk_window_set_default_size (GTK_WINDOW (window), PANEL_WIDTH, PANEL_HIGH);
	gtk_widget_grab_focus(entry);
        //gtk_widget_show_all(window);

	load_config(&pre_conf);

	cmdassist_command_list.list = NULL;

	gdk_threads_init();

	check_service ();

	return window;

}