/*************************************************************************** * aresponsewindow.cpp * * Sat Apr 23 19:59:43 2005 * Copyright 2005 User * Email ****************************************************************************/ #include "aresponsewindow.h" autoResponseWindow::autoResponseWindow(guint toSet) { helpWindow = NULL; statusToSet = toSet; wType = UE_AUTORESPONSESET; } autoResponseWindow::~autoResponseWindow() { delete manager; } GtkWidget* autoResponseWindow::createWindowContent() { GtkWidget *frame, *paned, *vbox1, *vbox2; GtkTextBuffer *buf; gchar *startText; // create the checkbox if (!((IMAutoResponseManager*)manager)->isOwnerManager) { customResponseCheckbox = gtk_check_button_new_with_mnemonic(tr("special auto response _active")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(customResponseCheckbox), TRUE); g_signal_connect_swapped(customResponseCheckbox, "toggled", G_CALLBACK(this->cb_customResponseCheckboxClicked), this); } // create the entry frame = u_createTextView(&tv); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tv), GTK_WRAP_WORD); // create a vbox containing the checkbox and the frame vbox1 = gtk_vbox_new(FALSE, 2); if (!((IMAutoResponseManager*)manager)->isOwnerManager) gtk_box_pack_start(GTK_BOX(vbox1), customResponseCheckbox, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox1), frame, TRUE, TRUE, 0); // add the vbox and the templates list into a paned view paned = gtk_hpaned_new(); gtk_paned_pack1(GTK_PANED(paned), createTemplatesbar(), FALSE, TRUE); gtk_paned_pack2(GTK_PANED(paned), vbox1, TRUE, FALSE); // add everything, including the button bar into a vbox vbox2 = gtk_vbox_new(FALSE, 10); gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); gtk_box_pack_start(GTK_BOX(vbox2), paned, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox2), createButtonbar(), FALSE, TRUE, 0); // restore the original text buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tv)); startText = ((IMAutoResponseManager*)manager)->getCustomResponse(); if (strlen(startText) == 0) { g_free(startText); startText = g_strdup(tr("I'm not available at the moment! You can leave me a message.")); if (!((IMAutoResponseManager*)manager)->isOwnerManager) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(customResponseCheckbox), FALSE); // gtk_widget_set_sensitive(okayButton, FALSE); gtk_widget_grab_focus(cancelButton); } else gtk_widget_grab_focus(okayButton); } gtk_text_buffer_set_text(buf, startText, strlen(startText)); g_free(startText); setWindowSize(400, 300); setWindowTitle("Set your auto response"); return vbox2; } GtkWidget* autoResponseWindow::createButtonbar() { GtkWidget *hbox, *helpButton; GtkSizeGroup *group; group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); okayButton = gtk_button_new_from_stock(GTK_STOCK_OK); gtk_size_group_add_widget(group, okayButton); g_signal_connect_swapped(G_OBJECT(okayButton), "clicked", G_CALLBACK(this->cb_okayButtonClicked), this); cancelButton = gtk_button_new_from_stock(GTK_STOCK_CANCEL); gtk_size_group_add_widget(group, cancelButton); g_signal_connect_swapped(G_OBJECT(cancelButton), "clicked", G_CALLBACK(this->cb_cancelButtonClicked), this); helpButton = gtk_button_new_from_stock(GTK_STOCK_HELP); gtk_size_group_add_widget(group, helpButton); g_signal_connect_swapped(G_OBJECT(helpButton), "clicked", G_CALLBACK(this->cb_helpButtonClicked), this); hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(hbox), helpButton, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(hbox), cancelButton, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(hbox), okayButton, FALSE, FALSE, 0); return hbox; } GtkWidget* autoResponseWindow::createTemplatesbar() { GtkWidget *scroll; GtkCellRenderer *renderer; GtkTreeViewColumn *column; scroll = gtk_scrolled_window_new(0, 0); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_IN); // create the store templatesStore = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_STRING); templatesTv = gtk_tree_view_new_with_model(GTK_TREE_MODEL(templatesStore)); g_signal_connect(templatesTv, "row-activated", G_CALLBACK(this->cb_templatesListActivated), this); g_signal_connect(templatesTv, "button_press_event", G_CALLBACK(this->cb_templatesListClicked), this); if (((IMAutoResponseManager*)manager)->isOwnerManager) addTemplatesGroupToStore(statusToSet, FALSE); else { addTemplatesGroupToStore(BUDDY_STATUS_AWAY, TRUE); addTemplatesGroupToStore(BUDDY_STATUS_NA, TRUE); addTemplatesGroupToStore(BUDDY_STATUS_DND, TRUE); addTemplatesGroupToStore(BUDDY_STATUS_OCC, TRUE); addTemplatesGroupToStore(BUDDY_STATUS_FFC, TRUE); } renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes(tr("Presets"), renderer, "markup", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(templatesTv), column); gtk_container_add(GTK_CONTAINER(scroll), templatesTv); gtk_widget_set_size_request(scroll, 150, -1); return scroll; } void autoResponseWindow::addTemplatesGroupToStore(guint state, gboolean createGroup) { GList *names, *contents, *search1, *search2; gchar *groupName, *fstr; GtkTreeIter *pIter, cIter; GtkTreePath *path; if (!((IMAutoResponseManager*)manager)->fetchTemplates(state, &contents, &names)) return; if (createGroup) { pIter = (GtkTreeIter*)g_malloc0(sizeof(GtkTreeIter)); groupName = ""; switch(state) { case BUDDY_STATUS_AWAY: groupName = tr("Away"); break; case BUDDY_STATUS_NA: groupName = tr("Not available"); break; case BUDDY_STATUS_OCC: groupName = tr("Busy"); break; case BUDDY_STATUS_DND: groupName = tr("Do not disturb"); break; case BUDDY_STATUS_FFC: groupName = tr("Free for chat"); break; } fstr = g_strdup_printf("%s", groupName); gtk_tree_store_append(templatesStore, pIter, NULL); gtk_tree_store_set(templatesStore, pIter, 0, fstr, -1); g_free(fstr); } else pIter = NULL; search1 = names; search2 = contents; while(search1) { gtk_tree_store_append(templatesStore, &cIter, pIter); gtk_tree_store_set(templatesStore, &cIter, 0, (gchar*)search1->data, 1, (gchar*)search2->data, -1); search1 = search1->next; search2 = search2->next; } if (pIter) { path = gtk_tree_model_get_path(GTK_TREE_MODEL(templatesStore), pIter); gtk_tree_view_expand_row(GTK_TREE_VIEW(templatesTv), path, FALSE); gtk_tree_path_free(path); g_free(pIter); } g_list_foreach(names, (GFunc)g_free, NULL); g_list_foreach(contents, (GFunc)g_free, NULL); g_list_free(names); g_list_free(contents); } void autoResponseWindow::destroyWindowContent() { } void autoResponseWindow::updateStatus(guint state) { if (state == statusToSet) return; statusToSet = state; gtk_tree_store_clear(templatesStore); addTemplatesGroupToStore(state, FALSE); } void autoResponseWindow::cb_templatesListActivated(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *column, autoResponseWindow* arw) { GtkTreeIter iter; // get current entry gtk_tree_model_get_iter(GTK_TREE_MODEL(arw->templatesStore), &iter, path); if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(arw->templatesStore), &iter)>0) { // a group was clicked -> expand or collapse it if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(arw->templatesTv), path)) gtk_tree_view_collapse_row(GTK_TREE_VIEW(arw->templatesTv), path); else gtk_tree_view_expand_row(GTK_TREE_VIEW(arw->templatesTv), path, FALSE); } } gboolean autoResponseWindow::cb_templatesListClicked(GtkTreeView* tList, GdkEventButton* event, autoResponseWindow* arw) { GtkTreePath *path; GtkTreeIter iter; gchar *text; if (event->button != 1) return FALSE; if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(arw->templatesTv), (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL)) return FALSE; // an item was clicked -> show its text in the tv gtk_tree_model_get_iter(GTK_TREE_MODEL(arw->templatesStore), &iter, path); gtk_tree_model_get(GTK_TREE_MODEL(arw->templatesStore), &iter, 1, &text, -1); gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(arw->tv)), text, strlen(text)); gtk_widget_grab_focus(arw->tv); gtk_tree_path_free(path); return FALSE; } void autoResponseWindow::cb_okayButtonClicked(autoResponseWindow* arw) { GtkTextIter startIter, endIter; IMAutoResponseManager *man; gchar *text; man = (IMAutoResponseManager*)arw->manager; if (!man->isOwnerManager && !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(arw->customResponseCheckbox))) { man->setCustomResponse(""); } else { gtk_text_buffer_get_bounds(gtk_text_view_get_buffer(GTK_TEXT_VIEW(arw->tv)), &startIter, &endIter); text = gtk_text_buffer_get_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(arw->tv)), &startIter, &endIter, FALSE); man->setCustomResponse(text); g_free(text); } arw->destroyWindow(); delete arw; } void autoResponseWindow::cb_cancelButtonClicked(autoResponseWindow* arw) { arw->destroyWindow(); delete arw; } void autoResponseWindow::cb_helpButtonClicked(autoResponseWindow* arw) { GtkWidget *text, *frame; GtkTextBuffer* buf; GtkTextIter iter; if (arw->helpWindow) { gtk_window_present(GTK_WINDOW(arw->helpWindow)); return; } // create the text frame = u_createTextView(&text); buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD); gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE); gtk_text_buffer_create_tag(buf, "hl", "size", 13*PANGO_SCALE, "weight", PANGO_WEIGHT_BOLD, "pixels-below-lines", 10, NULL); gtk_text_buffer_create_tag(buf, "l1" , "left-margin", 20, NULL); gtk_text_buffer_create_tag(buf, "l2" , "left-margin", 40, NULL); gtk_text_buffer_create_tag(buf, "ex" , "weight", PANGO_WEIGHT_BOLD, NULL); gtk_text_buffer_get_start_iter(buf, &iter); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, tr("Hints for setting your auto response\n"), -1, "hl", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, tr("\nYou can include any of the % expansions (described in the main hints page). " "Any line beginning with a pipe (|) will be treated as a command to be run. " "The line will be replaced by the output of the command. The command is parsed " "by /bin/sh so any shell commands or meta-characters are allowed. For security " "reasons, any \% expansions are automatically passed to the command surrounded by " "single quotes to prevent shell parsing of any meta-characters included in an " "alias.\n\n"), -1, "l1", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, tr("Examples of popular uses include:\n"), -1, "l1", "ex", NULL); // FIXME: this is so sophisticated ... can't we use some markup language here? gtk_text_buffer_insert_with_tags_by_name(buf, &iter, "|date: ", -1, "l2", "ex", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, tr("Will replace that line by the current date\n"), -1, "l2", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, "|fortune: ", -1, "l2", "ex", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, tr("Show a fortune, as a tagline for example\n"), -1, "l2", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, "|myscript.sh %u %a: ", -1, "l2", "ex", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, tr("Run a script, passing the uin and alias\n"), -1, "l2", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, "|myscript.sh %u %a > /dev/null: ", -1, "l2", "ex", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, tr("Run the same script but ignore the output (for tracking auto response checks or something)\n"), -1, "l2", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, "|if [ %u -lt 100000 ]; then echo \"You are special\"; fi: ", -1, "l2", "ex", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, tr("Useless, but shows how you can use shell script.\n"), -1, "l2", NULL); gtk_text_buffer_insert_with_tags_by_name(buf, &iter, tr("\nOf course, multiple \"|\" can appear in the auto response, and commands " "and regular text can be mixed line by line " "For more information, see the Licq webpage (http://www.licq.org)."), -1, "l1", NULL); gtk_container_set_border_width(GTK_CONTAINER(frame), 5); // create the window itself arw->helpWindow = gtk_dialog_new_with_buttons (tr("Licq - Hints"), GTK_WINDOW(arw->window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL); g_signal_connect_swapped (arw->helpWindow, "response", G_CALLBACK (gtk_widget_destroy), arw->helpWindow); g_signal_connect_after(arw->helpWindow, "destroy", G_CALLBACK (gtk_widget_destroyed), &arw->helpWindow); // g_signal_connect(helpWindow, "close", G_CALLBACK(aWdestroyHelpWindow), this); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(arw->helpWindow)->vbox), frame); gtk_window_set_default_size(GTK_WINDOW(arw->helpWindow), 450, 450); gtk_widget_show_all (arw->helpWindow); } void autoResponseWindow::cb_customResponseCheckboxClicked(autoResponseWindow* arw) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(arw->customResponseCheckbox))) { gtk_widget_set_sensitive(arw->templatesTv, TRUE); gtk_widget_set_sensitive(arw->tv, TRUE); // gtk_widget_set_sensitive(arw->okayButton, TRUE); } else { gtk_widget_set_sensitive(arw->templatesTv, FALSE); gtk_widget_set_sensitive(arw->tv, FALSE); // gtk_widget_set_sensitive(arw->okayButton, FALSE); } } // ============================================================================= fetchResponseWindow::fetchResponseWindow() { wType = UE_AUTORESPONSEGET; } fetchResponseWindow::~fetchResponseWindow() { delete manager; } GtkWidget* fetchResponseWindow::createWindowContent() { GtkWidget *frame, *vbox, *hbox1, *hbox2, *hbox3; gchar *titleText; // create the text view frame = u_createTextView(&tv); gtk_text_view_set_editable(GTK_TEXT_VIEW(tv), FALSE); // create the status line statusImg = gtk_image_new(); statusTxt = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(statusTxt), 0.0f, 0.5f); hbox1 = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(hbox1), statusImg, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox1), statusTxt, TRUE, TRUE, 0); // create the button bar waitAni = new processingAni(); waitAni->setupAnimation(i_getIcons()->images.searchingAni, 22, 22); refreshButton = gtk_button_new_from_stock(GTK_STOCK_REFRESH); g_signal_connect_swapped(refreshButton, "clicked", G_CALLBACK(this->cb_refreshButtonClicked), this); okayButton = gtk_button_new_from_stock(GTK_STOCK_OK); g_signal_connect_swapped(okayButton, "clicked", G_CALLBACK(this->cb_okayButtonClicked), this); hbox2 = gtk_hbutton_box_new(); gtk_box_set_spacing(GTK_BOX(hbox2), 3); gtk_box_pack_end(GTK_BOX(hbox2), refreshButton, FALSE, TRUE, 0); gtk_box_pack_end(GTK_BOX(hbox2), okayButton, FALSE, TRUE, 0); hbox3 = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(hbox3), waitAni->widget, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(hbox3), hbox2, TRUE, TRUE, 0); // pack everything together vbox = gtk_vbox_new(FALSE, 2); gtk_container_set_border_width(GTK_CONTAINER(vbox), 4); gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, TRUE, 2); gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, TRUE, 1); gtk_box_pack_start(GTK_BOX(vbox), hbox3, FALSE, TRUE, 0); setWindowSize(200, 200); titleText = g_strdup_printf(tr("Auto response from %s"), manager->info->alias); setWindowTitle(titleText); g_free(titleText); fetchAutoResponse(); return vbox; } void fetchResponseWindow::destroyWindowContent() { stopFetchAutoResponse(NULL, NULL); delete waitAni; } void fetchResponseWindow::focusWindow() { fetchAutoResponse(); } void fetchResponseWindow::fetchAutoResponse() { ((IMAutoResponseManager*)manager)->fetchAutoResponse(); waitAni->play(); gtk_widget_set_sensitive(tv, FALSE); gtk_widget_set_sensitive(refreshButton, FALSE); gtk_button_set_label(GTK_BUTTON(okayButton), GTK_STOCK_CANCEL); gtk_button_set_use_stock(GTK_BUTTON(okayButton), TRUE); gtk_image_set_from_stock(GTK_IMAGE(statusImg), GTK_STOCK_REFRESH, GTK_ICON_SIZE_SMALL_TOOLBAR); gtk_label_set_text(GTK_LABEL(statusTxt), tr("Updating ...")); } void fetchResponseWindow::stopFetchAutoResponse(gchar* txt, gchar* stockIcon) { ((IMAutoResponseManager*)manager)->cancelInitatedEvent(); waitAni->stop(); gtk_widget_set_sensitive(tv, TRUE); gtk_widget_set_sensitive(refreshButton, TRUE); gtk_button_set_label(GTK_BUTTON(okayButton), GTK_STOCK_OK); gtk_button_set_use_stock(GTK_BUTTON(okayButton), TRUE); gtk_image_set_from_stock(GTK_IMAGE(statusImg), stockIcon, GTK_ICON_SIZE_SMALL_TOOLBAR); gtk_label_set_text(GTK_LABEL(statusTxt), txt); } gboolean fetchResponseWindow::eventCallback(gint command, gint lastResult, gpointer info) { switch(command) { case UC_EVENT_FINISHED: case EVENT_REQUEST_ACCEPTED: if (lastResult == EVENT_RESULT_SUCCESS || lastResult == EVENT_RESULT_ACKED) { gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(tv)), (gchar*)info, strlen((gchar*)info)); stopFetchAutoResponse(tr("Successful!"), GTK_STOCK_APPLY); } else switch(lastResult) { case EVENT_RESULT_TIMEOUT: stopFetchAutoResponse(tr("No response!"), GTK_STOCK_DIALOG_ERROR); break; default: case EVENT_RESULT_FAILED: stopFetchAutoResponse(tr("Failed!"), GTK_STOCK_DIALOG_ERROR); break; } break; case EVENT_REQUEST_REFUSED: stopFetchAutoResponse(tr("Refused!"), GTK_STOCK_DIALOG_ERROR); break; } return TRUE; } void fetchResponseWindow::escPressed() { cb_okayButtonClicked(this); } void fetchResponseWindow::cb_okayButtonClicked(fetchResponseWindow* frw) { if (GTK_WIDGET_SENSITIVE(frw->tv)) { frw->destroyWindow(); delete frw; } else frw->stopFetchAutoResponse(tr("Cancel"), GTK_STOCK_STOP); } void fetchResponseWindow::cb_refreshButtonClicked(fetchResponseWindow* frw) { frw->fetchAutoResponse(); }