pidgin/purple-plugin-pack
Clone
Summary
Browse
Changes
Graph
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
"gtkdialogs.h"
#include
"gtkimhtml.h"
#include
"gtkprefs.h"
/* VARIABLE DEFINITIONS */
static
guint
queue_pref_cb
=
0
;
static
guint
sound_pref_cb
=
0
;
static
gboolean
ap_previously_away
=
FALSE
;
/* The list containing data on generated profiles / status messages */
static
GtkListStore
*
message_list
=
NULL
;
/* The general window */
static
GtkWidget
*
dialog
=
NULL
;
/* Progress bars */
typedef
struct
_ap_progress_bar
{
APUpdateType
type
;
GtkWidget
*
bar
;
guint
timeout
;
}
APProgressBar
;
static
GHashTable
*
progress_bars
=
NULL
;
/*--------------------------------------------------------------------------*
* Callback functions *
*--------------------------------------------------------------------------*/
static
void
hide_cb
(
GtkButton
*
button
,
gpointer
data
)
{
gtk_widget_hide_all
(
dialog
);
}
static
void
queue_cb
(
const
char
*
name
,
PurplePrefType
type
,
gconstpointer
val
,
gpointer
data
)
{
ap_update_queueing
();
}
static
void
sound_cb
(
const
char
*
name
,
PurplePrefType
type
,
gconstpointer
val
,
gpointer
data
)
{
GtkWidget
*
button
;
gboolean
value
;
button
=
(
GtkWidget
*
)
data
;
value
=
purple_prefs_get_bool
(
"/core/sound/while_away"
);
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
button
),
value
);
}
static
void
update_summary_visibility
()
{
const
gchar
*
summary_pref
;
// Decide whether or not to show window
summary_pref
=
purple_prefs_get_string
(
"/plugins/gtk/autoprofile/show_summary"
);
if
(
!
strcmp
(
summary_pref
,
"always"
))
{
gtk_widget_show_all
(
dialog
);
}
else
if
(
!
strcmp
(
summary_pref
,
"away"
)
&&
ap_is_currently_away
())
{
gtk_widget_show_all
(
dialog
);
}
else
{
gtk_widget_hide_all
(
dialog
);
}
ap_previously_away
=
ap_is_currently_away
();
}
/*--------------------------------------------------------------------------*
* Displayed message stuff *
*--------------------------------------------------------------------------*/
static
void
display_diff_msg
(
GtkTreeSelection
*
select
,
gpointer
data
)
{
GtkTreeModel
*
model
;
GtkTreeIter
iter
;
const
gchar
*
string
;
GtkWidget
*
imhtml
=
(
GtkWidget
*
)
data
;
if
(
gtk_tree_selection_get_selected
(
select
,
&
model
,
&
iter
))
{
gtk_tree_model_get
(
model
,
&
iter
,
3
,
&
string
,
-1
);
gtk_imhtml_clear
(
GTK_IMHTML
(
imhtml
));
if
(
string
!=
NULL
)
{
gtk_imhtml_append_text
(
GTK_IMHTML
(
imhtml
),
string
,
GTK_IMHTML_NO_SCROLL
);
gtk_imhtml_append_text
(
GTK_IMHTML
(
imhtml
),
"<BR>"
,
GTK_IMHTML_NO_SCROLL
);
}
}
}
/*--------------------------------------------------------------------------*
* Progress bar stuff *
*--------------------------------------------------------------------------*/
static
APProgressBar
*
progress_create
(
APUpdateType
type
,
GtkWidget
*
container
)
{
APProgressBar
*
progress_bar
;
progress_bar
=
(
APProgressBar
*
)
malloc
(
sizeof
(
APProgressBar
));
progress_bar
->
timeout
=
0
;
progress_bar
->
type
=
type
;
progress_bar
->
bar
=
gtk_progress_bar_new
();
gtk_progress_bar_set_bar_style
(
GTK_PROGRESS_BAR
(
progress_bar
->
bar
),
GTK_PROGRESS_CONTINUOUS
);
gtk_box_pack_start
(
GTK_BOX
(
container
),
progress_bar
->
bar
,
FALSE
,
FALSE
,
0
);
if
(
type
==
AP_UPDATE_PROFILE
)
{
gtk_progress_bar_set_text
(
GTK_PROGRESS_BAR
(
progress_bar
->
bar
),
_
(
"no updates made to profile"
));
}
else
if
(
type
==
AP_UPDATE_STATUS
)
{
gtk_progress_bar_set_text
(
GTK_PROGRESS_BAR
(
progress_bar
->
bar
),
_
(
"no updates made to status"
));
}
g_hash_table_insert
(
progress_bars
,
GINT_TO_POINTER
(
type
),
progress_bar
);
return
progress_bar
;
}
static
void
progress_update_stop
(
APProgressBar
*
progress_bar
)
{
if
(
progress_bar
->
timeout
)
{
purple_timeout_remove
(
progress_bar
->
timeout
);
progress_bar
->
timeout
=
0
;
}
gtk_progress_bar_set_fraction
(
GTK_PROGRESS_BAR
(
progress_bar
->
bar
),
1.0
);
if
(
progress_bar
->
type
==
AP_UPDATE_PROFILE
)
{
gtk_progress_bar_set_text
(
GTK_PROGRESS_BAR
(
progress_bar
->
bar
),
_
(
"waiting for new profile content"
));
}
else
if
(
progress_bar
->
type
==
AP_UPDATE_STATUS
)
{
gtk_progress_bar_set_text
(
GTK_PROGRESS_BAR
(
progress_bar
->
bar
),
_
(
"waiting for new status content"
));
}
}
#define BAH 500
static
gboolean
progress_update
(
gpointer
data
)
{
int
total_milliseconds
;
int
seconds_remaining
;
double
fraction_increment
;
double
cur_fraction
;
double
result
;
GString
*
text
;
APProgressBar
*
progress_bar
=
(
APProgressBar
*
)
data
;
// Update fraction on bar
total_milliseconds
=
purple_prefs_get_int
(
"/plugins/gtk/autoprofile/delay_update"
)
*
1000
;
fraction_increment
=
BAH
/
((
double
)
total_milliseconds
);
cur_fraction
=
gtk_progress_bar_get_fraction
(
GTK_PROGRESS_BAR
(
progress_bar
->
bar
));
result
=
cur_fraction
+
fraction_increment
;
if
(
result
>=
1
)
{
progress_update_stop
(
progress_bar
);
return
FALSE
;
}
gtk_progress_bar_set_fraction
(
GTK_PROGRESS_BAR
(
progress_bar
->
bar
),
result
);
// Update text on bar
seconds_remaining
=
(
int
)
(((
double
)
total_milliseconds
/
1000
)
-
(
cur_fraction
*
(
double
)
total_milliseconds
/
1000
));
text
=
g_string_new
(
""
);
if
(
progress_bar
->
type
==
AP_UPDATE_PROFILE
)
{
g_string_printf
(
text
,
_
(
"next profile update in %d seconds"
),
seconds_remaining
);
}
else
if
(
progress_bar
->
type
==
AP_UPDATE_STATUS
)
{
g_string_printf
(
text
,
_
(
"next status update in %d seconds"
),
seconds_remaining
);
}
gtk_progress_bar_set_text
(
GTK_PROGRESS_BAR
(
progress_bar
->
bar
),
text
->
str
);
g_string_free
(
text
,
TRUE
);
return
TRUE
;
}
static
void
ap_gtk_timeout_start
(
APUpdateType
type
)
{
APProgressBar
*
progress_bar
;
progress_bar
=
g_hash_table_lookup
(
progress_bars
,
GINT_TO_POINTER
(
type
));
if
(
progress_bar
->
timeout
)
{
purple_timeout_remove
(
progress_bar
->
timeout
);
}
gtk_progress_bar_set_fraction
(
GTK_PROGRESS_BAR
(
progress_bar
->
bar
),
0
);
progress_bar
->
timeout
=
purple_timeout_add
(
BAH
,
progress_update
,
progress_bar
);
progress_update
(
progress_bar
);
}
void
ap_gtk_set_progress_visible
(
APUpdateType
type
,
gboolean
visible
)
{
APProgressBar
*
progress_bar
;
progress_bar
=
g_hash_table_lookup
(
progress_bars
,
GINT_TO_POINTER
(
type
));
if
(
visible
)
gtk_widget_show
(
progress_bar
->
bar
);
else
gtk_widget_hide
(
progress_bar
->
bar
);
}
/*--------------------------------------------------------------------------*
* Create the main window *
*--------------------------------------------------------------------------*/
static
void
create_dialog
()
{
GtkTreeViewColumn
*
column
;
GtkCellRenderer
*
renderer
;
GtkTreeSelection
*
selection
;
GtkWidget
*
message_list_view
;
GtkWidget
*
vbox
,
*
vpane
,
*
hbox
,
*
config_vbox
;
GtkWidget
*
sw
,
*
imhtml
,
*
msg_window
,
*
button
;
imhtml
=
gtk_imhtml_new
(
NULL
,
NULL
);
/* Create main display window */
PIDGIN_DIALOG
(
dialog
);
gtk_window_set_title
(
GTK_WINDOW
(
dialog
),
_
(
"AutoProfile Summary"
));
gtk_widget_realize
(
dialog
);
vbox
=
gtk_vbox_new
(
FALSE
,
5
);
gtk_container_add
(
GTK_CONTAINER
(
dialog
),
vbox
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
vbox
),
5
);
/* Set up progress bar container */
progress_create
(
AP_UPDATE_PROFILE
,
vbox
);
progress_create
(
AP_UPDATE_STATUS
,
vbox
);
/* Set up list of past away messages */
vpane
=
gtk_vpaned_new
();
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
vpane
,
TRUE
,
TRUE
,
0
);
message_list
=
gtk_list_store_new
(
4
,
G_TYPE_STRING
,
G_TYPE_STRING
,
G_TYPE_STRING
,
G_TYPE_STRING
);
message_list_view
=
gtk_tree_view_new_with_model
(
GTK_TREE_MODEL
(
message_list
));
renderer
=
gtk_cell_renderer_text_new
();
column
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Time"
),
renderer
,
"markup"
,
0
,
NULL
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
message_list_view
),
column
);
gtk_tree_view_column_set_sort_column_id
(
column
,
0
);
column
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Type"
),
renderer
,
"markup"
,
1
,
NULL
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
message_list_view
),
column
);
gtk_tree_view_column_set_sort_column_id
(
column
,
1
);
renderer
=
gtk_cell_renderer_text_new
();
g_object_set
(
renderer
,
"ellipsize"
,
PANGO_ELLIPSIZE_END
,
NULL
);
column
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Text"
),
renderer
,
"markup"
,
2
,
NULL
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
message_list_view
),
column
);
gtk_tree_view_column_set_sizing
(
column
,
GTK_TREE_VIEW_COLUMN_FIXED
);
sw
=
gtk_scrolled_window_new
(
NULL
,
NULL
);
gtk_scrolled_window_set_policy
(
GTK_SCROLLED_WINDOW
(
sw
),
GTK_POLICY_NEVER
,
GTK_POLICY_ALWAYS
);
gtk_scrolled_window_set_shadow_type
(
GTK_SCROLLED_WINDOW
(
sw
),
GTK_SHADOW_IN
);
gtk_container_add
(
GTK_CONTAINER
(
sw
),
message_list_view
);
gtk_paned_add1
(
GTK_PANED
(
vpane
),
sw
);
selection
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
message_list_view
));
gtk_tree_selection_set_mode
(
selection
,
GTK_SELECTION_SINGLE
);
g_signal_connect
(
G_OBJECT
(
selection
),
"changed"
,
G_CALLBACK
(
display_diff_msg
),
imhtml
);
/* Set up the window to display away message in */
msg_window
=
gtk_scrolled_window_new
(
NULL
,
NULL
);
gtk_scrolled_window_set_policy
(
GTK_SCROLLED_WINDOW
(
msg_window
),
GTK_POLICY_NEVER
,
GTK_POLICY_AUTOMATIC
);
gtk_scrolled_window_set_shadow_type
(
GTK_SCROLLED_WINDOW
(
msg_window
),
GTK_SHADOW_IN
);
gtk_paned_add2
(
GTK_PANED
(
vpane
),
msg_window
);
gtk_container_add
(
GTK_CONTAINER
(
msg_window
),
imhtml
);
pidgin_setup_imhtml
(
imhtml
);
/* Bottom area */
hbox
=
gtk_hbox_new
(
FALSE
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
config_vbox
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
config_vbox
,
TRUE
,
TRUE
,
0
);
pidgin_prefs_checkbox
(
_
(
"Queue new messages while away"
),
"/plugins/gtk/autoprofile/queue_messages_when_away"
,
config_vbox
);
button
=
pidgin_prefs_checkbox
(
_
(
"Play sounds while away"
),
"/core/sound/while_away"
,
config_vbox
);
sound_pref_cb
=
purple_prefs_connect_callback
(
ap_get_plugin_handle
(),
"/core/sound/while_away"
,
sound_cb
,
button
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
gtk_vseparator_new
(),
FALSE
,
FALSE
,
0
);
config_vbox
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
config_vbox
,
TRUE
,
TRUE
,
0
);
ap_gtk_prefs_add_summary_option
(
config_vbox
);
button
=
gtk_button_new_with_label
(
_
(
"Hide summary now"
));
gtk_box_pack_start
(
GTK_BOX
(
config_vbox
),
button
,
FALSE
,
FALSE
,
0
);
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
hide_cb
),
NULL
);
/* Finish up */
g_signal_connect
(
G_OBJECT
(
dialog
),
"delete-event"
,
G_CALLBACK
(
gtk_widget_hide_on_delete
),
NULL
);
gtk_paned_set_position
(
GTK_PANED
(
vpane
),
250
);
gtk_window_set_default_size
(
GTK_WINDOW
(
dialog
),
430
,
430
);
}
/*--------------------------------------------------------------------------*
* PUBLIC FUNCTIONS *
*--------------------------------------------------------------------------*/
void
ap_gtk_add_message
(
APUpdateType
update_type
,
APMessageType
type
,
const
gchar
*
text
)
{
GtkTreeIter
iter
;
struct
tm
*
cur_time
;
char
*
time_string
,
*
simple_text
,
*
s
;
time_t
*
general_time
;
gchar
*
type_string
;
// Create the time string
general_time
=
(
time_t
*
)
malloc
(
sizeof
(
time_t
));
time
(
general_time
);
cur_time
=
ap_localtime
(
general_time
);
free
(
general_time
);
time_string
=
(
char
*
)
malloc
(
sizeof
(
char
[
32
]));
*
time_string
=
'\0'
;
strftime
(
time_string
,
31
,
"<b>%I:%M %p</b>"
,
cur_time
);
free
(
cur_time
);
// Create the type string
type_string
=
strdup
(
"<b>Status</b>"
);
switch
(
type
)
{
case
AP_MESSAGE_TYPE_PROFILE
:
type_string
=
strdup
(
_
(
"<b>User profile</b>"
));
break
;
case
AP_MESSAGE_TYPE_AWAY
:
type_string
=
strdup
(
_
(
"<b>Away message</b>"
));
break
;
case
AP_MESSAGE_TYPE_AVAILABLE
:
type_string
=
strdup
(
_
(
"<b>Available message</b>"
));
break
;
case
AP_MESSAGE_TYPE_STATUS
:
type_string
=
strdup
(
_
(
"<b>Status message</b>"
));
break
;
default
:
type_string
=
strdup
(
_
(
"<b>Other</b>"
));
break
;
}
// Simplify the text
if
(
text
!=
NULL
)
{
simple_text
=
strdup
(
text
);
// Only show the first line
s
=
(
gchar
*
)
purple_strcasestr
(
simple_text
,
"<br>"
);
if
(
s
!=
NULL
)
{
*
s
++
=
'.'
;
*
s
++
=
'.'
;
*
s
++
=
'.'
;
*
s
=
'\0'
;
}
// Strip HTML
s
=
simple_text
;
simple_text
=
purple_markup_strip_html
(
simple_text
);
free
(
s
);
}
else
{
simple_text
=
NULL
;
}
// Add it
gtk_list_store_prepend
(
message_list
,
&
iter
);
gtk_list_store_set
(
message_list
,
&
iter
,
0
,
time_string
,
1
,
type_string
,
2
,
simple_text
,
3
,
text
,
-1
);
free
(
type_string
);
free
(
time_string
);
if
(
simple_text
)
free
(
simple_text
);
// Delete if too many
if
(
gtk_tree_model_iter_nth_child
(
GTK_TREE_MODEL
(
message_list
),
&
iter
,
NULL
,
AP_GTK_MAX_MESSAGES
))
{
gtk_list_store_remove
(
message_list
,
&
iter
);
}
// Move the timeout bar
ap_gtk_timeout_start
(
update_type
);
// Check if it needs to be visible or not
if
(
type
!=
AP_MESSAGE_TYPE_PROFILE
&&
ap_is_currently_away
()
!=
ap_previously_away
)
{
update_summary_visibility
();
}
}
void
ap_gtk_make_visible
()
{
gtk_widget_show_all
(
dialog
);
gtk_window_present
(
GTK_WINDOW
(
dialog
));
}
void
ap_gtk_start
()
{
progress_bars
=
g_hash_table_new
(
NULL
,
NULL
);
// Message queueing
queue_pref_cb
=
purple_prefs_connect_callback
(
ap_get_plugin_handle
(),
"/plugins/gtk/autoprofile/queue_messages_when_away"
,
queue_cb
,
NULL
);
// Create window
create_dialog
();
update_summary_visibility
();
}
static
void
ap_gtk_finish_progress_bar
(
APUpdateType
type
)
{
APProgressBar
*
progress_bar
;
progress_bar
=
g_hash_table_lookup
(
progress_bars
,
GINT_TO_POINTER
(
type
));
if
(
progress_bar
)
{
if
(
progress_bar
->
timeout
)
{
purple_timeout_remove
(
progress_bar
->
timeout
);
}
free
(
progress_bar
);
g_hash_table_insert
(
progress_bars
,
GINT_TO_POINTER
(
type
),
NULL
);
}
}
void
ap_gtk_finish
()
{
// Kill the window and associated variables
gtk_widget_destroy
(
dialog
);
dialog
=
NULL
;
message_list
=
NULL
;
ap_gtk_finish_progress_bar
(
AP_UPDATE_PROFILE
);
ap_gtk_finish_progress_bar
(
AP_UPDATE_STATUS
);
// Disconnect queue message
purple_prefs_disconnect_callback
(
queue_pref_cb
);
queue_pref_cb
=
0
;
purple_prefs_disconnect_callback
(
sound_pref_cb
);
sound_pref_cb
=
0
;
g_hash_table_destroy
(
progress_bars
);
progress_bars
=
NULL
;
}