/*
#
# 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;
}