pidgin/purple-plugin-pack

This took WAY too long to see. The logs shouldn't be sorted while we're
org.guifications.plugins
2008-08-03, rekkanoryo
f8496a6121df
This took WAY too long to see. The logs shouldn't be sorted while we're
still in the outer loop. Sort at the end once we've collected all the logs
we can.
/*----------------------------------------------------------------------------*
* AUTOPROFILE *
* *
* A Purple away message and profile manager that supports dynamic text *
* *
* AutoProfile is the legal property of its developers. Please refer to *
* the COPYRIGHT file distributed with this source distribution. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
*----------------------------------------------------------------------------*/
#include "autoprofile.h"
#include "request.h"
#include "component.h"
#include "utility.h"
enum {
QUOTATION_LIST_STORE = 1,
QUOTATION_FILE_SELECTOR,
QUOTATION_TREE_VIEW
};
/*--------------------------------------------------------------------------*
* Menu related things *
*--------------------------------------------------------------------------*/
static void append_quote (struct widget *w, GtkListStore *ls, gchar *quote)
{
GString *s;
GtkTreeIter iter;
gchar *quote_tmp;
GtkWidget *treeview;
GtkTreeSelection *selection;
gtk_list_store_append (ls, &iter);
quote_tmp = purple_markup_strip_html (quote);
s = g_string_new ("");
g_string_printf (s, "%ld bytes", g_utf8_strlen (quote, -1));
gtk_list_store_set (ls, &iter,
0, quote_tmp,
1, quote,
2, s->str,
-1);
g_free (quote_tmp);
g_string_free (s, TRUE);
treeview = (GtkWidget *) ap_widget_get_data (w, QUOTATION_TREE_VIEW);
if (treeview == NULL) return;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
gtk_tree_selection_select_iter (selection, &iter);
}
static void file_dialog_cb (GtkWidget *dialog, int response, struct widget *w)
{
GtkWidget *checkbox;
gchar *filename;
GList *quotes, *quotes_start, *new_quotes;
gboolean include_html;
GtkListStore *ls;
switch (response) {
case GTK_RESPONSE_ACCEPT:
ls = ap_widget_get_data (w, QUOTATION_LIST_STORE);
if (ls == NULL) break;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dialog));
checkbox = gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER(dialog));
g_object_get (checkbox, "active", &include_html, NULL);
quotes = ap_prefs_get_string_list (w, "quotes");
new_quotes = read_fortune_file (filename, !include_html);
g_free (filename);
quotes = g_list_concat (quotes, new_quotes);
ap_prefs_set_string_list (w, "quotes", quotes);
quotes_start = quotes;
for (quotes = new_quotes; quotes != NULL; quotes = quotes->next) {
append_quote (w, ls, quotes->data);
}
free_string_list (quotes_start);
break;
case GTK_RESPONSE_CANCEL:
case GTK_RESPONSE_DELETE_EVENT:
break;
}
ap_widget_set_data (w, QUOTATION_FILE_SELECTOR, NULL);
gtk_widget_destroy (dialog);
}
static void quotation_explain_fortune_file (GtkMenuItem *item, gpointer data)
{
purple_notify_formatted (NULL, _("Fortune files"),
_("A quick definition of a fortune file"), NULL,
_("A fortune file is a simple text file with a number of quotes. "
"The following is an example:<br><br>"
"<b>\"Glory is fleeing, but obscurity is forver.\"<br>"
"- Napoleon Bonaparte (1769-1821)<br>"
"%<br>"
"Blagggghhhh!<br>"
"%<br>"
"Yet another quote<br>"
"%<br></b><br>"
"Quotes can have any sort of text within them. They end when there "
"is a newline followed by a percent sign \"%\" on the next line.<br>"
"<br>Fortune files with pre-selected quotes can be found on the"
"internet."),
NULL, NULL);
}
static void quotation_select_import_file (GtkMenuItem *item, struct widget *w)
{
GtkWidget *dialog;
GtkWidget *checkbox;
dialog = gtk_file_chooser_dialog_new (
_("Select fortune file to import quotes from"),
NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
g_signal_connect (G_OBJECT(dialog), "response", G_CALLBACK (file_dialog_cb),
w);
ap_widget_set_data (w, QUOTATION_FILE_SELECTOR, dialog);
checkbox = gtk_check_button_new_with_label (
_("Interpret bracketed text (such as \"<br>\") as HTML tags"));
gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), checkbox);
gtk_widget_show_all (dialog);
}
static void quotation_edit_dialog_cb (struct widget *w, const char *quote)
{
GtkWidget *treeview;
GtkTreeSelection *selection;
GtkTreeIter iter;
GtkTreeModel *model;
treeview = (GtkWidget *) ap_widget_get_data (w, QUOTATION_TREE_VIEW);
if (treeview == NULL) return;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
GString *s;
gchar *quote_tmp, *old_quote;
GList *start, *node;
gtk_tree_model_get (model, &iter, 1, &old_quote, -1);
start = ap_prefs_get_string_list (w, "quotes");
/* FIXME: this could grab the wrong quote, if two quotes are identical */
for (node = start; node != NULL; node = node->next) {
if (!strcmp ((char *) node->data, old_quote)) {
/* Update saved prefs */
g_free (node->data);
node->data = strdup (quote);
ap_prefs_set_string_list (w, "quotes", start);
free_string_list (start);
g_free (old_quote);
/* Update list store */
quote_tmp = purple_markup_strip_html (quote);
s = g_string_new ("");
g_string_printf (s, "%ld bytes", g_utf8_strlen (quote, -1));
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
0, quote_tmp,
1, quote,
2, s->str,
-1);
g_free (quote_tmp);
g_string_free (s, TRUE);
return;
}
}
free_string_list (start);
g_free (old_quote);
} else {
purple_notify_error (NULL, NULL,
N_("Unable to edit quote"),
N_("No quote is currently selected"));
}
}
static void quotation_edit_dialog (struct widget *w, const gchar *quote)
{
purple_request_input (ap_get_plugin_handle (), NULL,
_("Edit quote"), NULL,
quote,
TRUE, FALSE, "html",
_("Save"), G_CALLBACK(quotation_edit_dialog_cb),
_("Cancel"), NULL, NULL, NULL, NULL,
w);
}
static void quotation_edit (GtkWidget *button, struct widget *w)
{
GtkWidget *treeview;
GtkTreeSelection *selection;
GtkTreeIter iter;
GtkTreeModel *model;
gchar *quote;
treeview = (GtkWidget *) ap_widget_get_data (w, QUOTATION_TREE_VIEW);
if (treeview == NULL) return;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
gtk_tree_model_get (model, &iter, 1, &quote, -1);
quotation_edit_dialog (w, quote);
g_free (quote);
} else {
purple_notify_error (NULL, NULL,
N_("Unable to edit quote"),
N_("No quote is currently selected"));
}
}
static void quotation_create (GtkWidget *button, struct widget *w)
{
GtkListStore *ls;
GList *quotes;
ls = ap_widget_get_data (w, QUOTATION_LIST_STORE);
if (ls == NULL) return;
append_quote (w, ls, "");
quotes = ap_prefs_get_string_list (w, "quotes");
quotes = g_list_append (quotes, strdup (""));
ap_prefs_set_string_list (w, "quotes", quotes);
free_string_list (quotes);
quotation_edit_dialog (w, "");
}
static void quotation_delete (GtkWidget *button, struct widget *w)
{
GtkWidget *treeview;
GtkTreeSelection *selection;
GtkTreeIter iter;
GtkTreeModel *model;
gchar *quote;
GList *start, *node;
treeview = (GtkWidget *) ap_widget_get_data (w, QUOTATION_TREE_VIEW);
if (treeview == NULL) return;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
gtk_tree_model_get (model, &iter, 1, &quote, -1);
start = ap_prefs_get_string_list (w, "quotes");
/* FIXME: this could grab the wrong quote, if two quotes are identical */
for (node = start; node != NULL; node = node->next) {
if (!strcmp ((char *) node->data, quote)) {
start = g_list_remove_link (start, node);
g_list_free_1 (node);
g_free (node->data);
ap_prefs_set_string_list (w, "quotes", start);
free_string_list (start);
g_free (quote);
gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
return;
}
}
free_string_list (start);
g_free (quote);
} else {
purple_notify_error (NULL, NULL,
N_("Unable to delete quote"),
N_("No quote is currently selected"));
}
}
static void quotation_delete_all_cb (struct widget *w)
{
GtkListStore *ls;
ls = ap_widget_get_data (w, QUOTATION_LIST_STORE);
if (ls == NULL) return;
gtk_list_store_clear (ls);
ap_prefs_set_string_list (w, "quotes", NULL);
}
static void quotation_delete_all (GtkMenuItem *item, struct widget *w)
{
purple_request_ok_cancel (ap_get_plugin_handle (),
NULL, _("Delete all quotes?"), NULL, 0, NULL, NULL,
NULL, w, G_CALLBACK(quotation_delete_all_cb), NULL);
}
static void quotation_more_menu (GtkWidget *button, struct widget *w)
{
GtkWidget *menu;
GtkWidget *menu_item;
menu = gtk_menu_new ();
menu_item = gtk_menu_item_new_with_label (_("Delete all quotes"));
gtk_menu_shell_append (GTK_MENU_SHELL(menu), menu_item);
g_signal_connect (G_OBJECT(menu_item), "activate",
G_CALLBACK(quotation_delete_all), w);
menu_item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL(menu), menu_item);
menu_item = gtk_menu_item_new_with_label (
_("Import quotes from from fortune file"));
gtk_menu_shell_append (GTK_MENU_SHELL(menu), menu_item);
g_signal_connect (G_OBJECT(menu_item), "activate",
G_CALLBACK(quotation_select_import_file), w);
menu_item = gtk_menu_item_new_with_label (
_("What is a fortune file?"));
gtk_menu_shell_append (GTK_MENU_SHELL(menu), menu_item);
g_signal_connect (G_OBJECT(menu_item), "activate",
G_CALLBACK(quotation_explain_fortune_file), NULL);
gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, w, 0,
gtk_get_current_event_time ());
gtk_widget_show_all (menu);
}
static void quotation_rate_changed (GtkSpinButton *spinner, struct widget *w)
{
int value = gtk_spin_button_get_value_as_int (spinner);
ap_prefs_set_int (w, "update_rate", value);
}
static void quotation_force_change (GtkButton *button, struct widget *w)
{
ap_prefs_set_int (w, "current_index",
ap_prefs_get_int (w, "current_index") + 1);
}
static gboolean
search_func(GtkTreeModel *model, gint column, const gchar *key,
GtkTreeIter *iter, gpointer search_data)
{
gboolean result;
char *haystack;
gtk_tree_model_get (model, iter, 1, &haystack, -1);
result = (purple_strcasestr(haystack, key) == NULL);
g_free(haystack);
return result;
}
static void menu_destroy_cb (GtkWidget *widget, struct widget *w)
{
GtkWidget *file_selector;
ap_widget_set_data (w, QUOTATION_LIST_STORE, NULL);
ap_widget_set_data (w, QUOTATION_TREE_VIEW, NULL);
file_selector = (GtkWidget *) ap_widget_get_data (w, QUOTATION_FILE_SELECTOR);
if (file_selector != NULL) {
file_dialog_cb (file_selector, GTK_RESPONSE_DELETE_EVENT, w);
}
}
static GtkWidget *quotation_menu (struct widget *w)
{
GtkWidget *ret, *hbox;
GtkWidget *button, *label, *spinner;
GtkWidget *sw;
GList *quotes, *quotes_start;
GtkWidget *treeview;
GtkListStore *ls;
GtkTreeViewColumn *col;
GtkCellRenderer *rend;
ret = gtk_vbox_new (FALSE, 6);
g_signal_connect (G_OBJECT(ret), "destroy", G_CALLBACK (menu_destroy_cb), w);
/* The main view */
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw),
GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX(ret), sw, TRUE, TRUE, 0);
ls = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
ap_widget_set_data (w, QUOTATION_LIST_STORE, ls);
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL(ls));
ap_widget_set_data (w, QUOTATION_TREE_VIEW, treeview);
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("Size"),
rend, "text", 2, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), col);
g_object_set (G_OBJECT(rend),
"cell-background-set", TRUE,
"cell-background", "gray",
NULL);
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("Quotes"),
rend, "text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), col);
/* Enable CTRL+F searching */
gtk_tree_view_set_search_column (GTK_TREE_VIEW(treeview), 0);
gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW(treeview),
search_func, NULL, NULL);
gtk_container_add (GTK_CONTAINER(sw), treeview);
/* Add in the original quotes */
quotes_start = ap_prefs_get_string_list (w, "quotes");
for (quotes = quotes_start; quotes != NULL; quotes = quotes->next) {
append_quote (w, ls, quotes->data);
}
free_string_list (quotes_start);
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(treeview), TRUE);
/* Bottom buttons */
hbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX(hbox),
GTK_BUTTONBOX_SPREAD);
gtk_box_pack_start (GTK_BOX(ret), hbox, FALSE, FALSE, 0);
button = gtk_button_new_with_label (_("New quote"));
gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT(button), "clicked",
G_CALLBACK(quotation_create), w);
button = gtk_button_new_with_label (_("Edit"));
gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT(button), "clicked",
G_CALLBACK(quotation_edit), w);
button = gtk_button_new_with_label (_("Delete"));
gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT(button), "clicked",
G_CALLBACK(quotation_delete), w);
button = gtk_button_new_with_label (_("More..."));
gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT(button), "clicked",
G_CALLBACK(quotation_more_menu), w);
/* Separator */
gtk_box_pack_start (GTK_BOX(ret), gtk_hseparator_new (), FALSE, FALSE, 0);
/* Behavior selection */
hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX(ret), hbox, FALSE, FALSE, 0);
label = gtk_label_new (_("Change quote every "));
gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
spinner = gtk_spin_button_new_with_range (0, G_MAXINT, 1);
gtk_box_pack_start (GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spinner),
ap_prefs_get_int (w, "update_rate"));
g_signal_connect (G_OBJECT(spinner), "value-changed",
G_CALLBACK(quotation_rate_changed), w);
label = gtk_label_new (_("hours (0: always show a new quote)"));
gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
button = gtk_button_new_with_label (_("Change quote now"));
gtk_box_pack_end (GTK_BOX(hbox), button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (quotation_force_change), w);
return ret;
}
/*--------------------------------------------------------------------------*
* Core quotation things *
*--------------------------------------------------------------------------*/
static gchar *quotation_generate (struct widget *w)
{
GList *quotes;
gchar *ret;
int num_quotes, index;
time_t cur_time, old_time;
char *time_string;
struct tm *t;
index = ap_prefs_get_int (w, "current_index");
quotes = ap_prefs_get_string_list (w, "quotes");
/* Sanity check the quotes */
num_quotes = g_list_length (quotes);
if (num_quotes == 0) {
return strdup (_("[ERROR: no quotes available]"));
}
/* Increment index if time has elapsed */
old_time = purple_str_to_time (ap_prefs_get_string (w, "last_update"), TRUE,
NULL, NULL, NULL);
cur_time = time (NULL);
if (difftime (cur_time, old_time) >
60.0 * 60.0 * (double) ap_prefs_get_int (w, "update_rate"))
{
ap_debug ("quote", "time interval elapsed, moving to new quote");
time_string = (char *)malloc(1000);
t = ap_gmtime (&cur_time);
strftime (time_string, 999, "%Y-%m-%dT%H:%M:%S+00:00", t);
free (t);
ap_prefs_set_string (w, "last_update", time_string);
free (time_string);
index++;
ap_prefs_set_int (w, "current_index", index);
}
/* Wrap around when last quote is reached */
if (index >= num_quotes) {
index = 0;
ap_prefs_set_int (w, "current_index", 0);
}
/* Choose and output the quote */
ret = strdup((gchar *) g_list_nth_data (quotes, index));
free_string_list (quotes);
return ret;
}
static void quotation_init (struct widget *w)
{
time_t the_time;
char *time_string;
time_string = (char *)malloc(1000);
the_time = time(NULL);
strftime (time_string, 999, "%Y-%m-%dT%H:%M:%S+00:00", gmtime (&the_time));
ap_prefs_add_string_list (w, "quotes", NULL);
ap_prefs_add_int (w, "current_index", 0);
ap_prefs_add_int (w, "update_rate", 0);
ap_prefs_add_string (w, "last_update", time_string);
free (time_string);
}
struct component quotation =
{
N_("Quotes"),
N_("Displays a quotation from a provided selection"),
"Quote",
&quotation_generate,
&quotation_init,
NULL,
NULL,
NULL,
&quotation_menu
};