pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
sf patch #1644019, from good ol' Ka-Hing Cheung
2007-01-25, Mark Doliner
e2f0d7323124
sf patch #1644019, from good ol' Ka-Hing Cheung
"fix compiling on gtk 2.4. xmppconsole.c is the culprit.
gtk_combo_box_get_active_text is defined in gtk 2.6 but not 2.4."
/**
* @file gtklog.c GTK+ Log viewer
* @ingroup gtkui
*
* gaim
*
* Gaim is the legal property of its developers, whose names are too numerous
* to list here. 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
"internal.h"
#include
"gtkgaim.h"
#include
"account.h"
#include
"gtkblist.h"
#include
"gtkimhtml.h"
#include
"gtklog.h"
#include
"gtkutils.h"
#include
"log.h"
#include
"notify.h"
#include
"util.h"
static
GHashTable
*
log_viewers
=
NULL
;
static
void
populate_log_tree
(
GaimGtkLogViewer
*
lv
);
static
GaimGtkLogViewer
*
syslog_viewer
=
NULL
;
struct
log_viewer_hash_t
{
GaimLogType
type
;
char
*
screenname
;
GaimAccount
*
account
;
GaimContact
*
contact
;
};
static
guint
log_viewer_hash
(
gconstpointer
data
)
{
const
struct
log_viewer_hash_t
*
viewer
=
data
;
if
(
viewer
->
contact
!=
NULL
)
return
g_direct_hash
(
viewer
->
contact
);
return
g_str_hash
(
viewer
->
screenname
)
+
g_str_hash
(
gaim_account_get_username
(
viewer
->
account
));
}
static
gboolean
log_viewer_equal
(
gconstpointer
y
,
gconstpointer
z
)
{
const
struct
log_viewer_hash_t
*
a
,
*
b
;
int
ret
;
char
*
normal
;
a
=
y
;
b
=
z
;
if
(
a
->
contact
!=
NULL
)
{
if
(
b
->
contact
!=
NULL
)
return
(
a
->
contact
==
b
->
contact
);
else
return
FALSE
;
}
else
{
if
(
b
->
contact
!=
NULL
)
return
FALSE
;
}
normal
=
g_strdup
(
gaim_normalize
(
a
->
account
,
a
->
screenname
));
ret
=
(
a
->
account
==
b
->
account
)
&&
!
strcmp
(
normal
,
gaim_normalize
(
b
->
account
,
b
->
screenname
));
g_free
(
normal
);
return
ret
;
}
static
void
select_first_log
(
GaimGtkLogViewer
*
lv
)
{
GtkTreeModel
*
model
;
GtkTreeIter
iter
,
it
;
GtkTreePath
*
path
;
model
=
GTK_TREE_MODEL
(
lv
->
treestore
);
if
(
!
gtk_tree_model_get_iter_first
(
model
,
&
iter
))
return
;
path
=
gtk_tree_model_get_path
(
model
,
&
iter
);
if
(
gtk_tree_model_iter_children
(
model
,
&
it
,
&
iter
))
{
gtk_tree_view_expand_row
(
GTK_TREE_VIEW
(
lv
->
treeview
),
path
,
TRUE
);
path
=
gtk_tree_model_get_path
(
model
,
&
it
);
}
gtk_tree_selection_select_path
(
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
lv
->
treeview
)),
path
);
gtk_tree_path_free
(
path
);
}
static
const
char
*
log_get_date
(
GaimLog
*
log
)
{
if
(
log
->
tm
)
return
gaim_date_format_full
(
log
->
tm
);
else
return
gaim_date_format_full
(
localtime
(
&
log
->
time
));
}
static
void
search_cb
(
GtkWidget
*
button
,
GaimGtkLogViewer
*
lv
)
{
const
char
*
search_term
=
gtk_entry_get_text
(
GTK_ENTRY
(
lv
->
entry
));
GList
*
logs
;
if
(
!
(
*
search_term
))
{
/* reset the tree */
gtk_tree_store_clear
(
lv
->
treestore
);
populate_log_tree
(
lv
);
g_free
(
lv
->
search
);
lv
->
search
=
NULL
;
gtk_imhtml_search_clear
(
GTK_IMHTML
(
lv
->
imhtml
));
select_first_log
(
lv
);
return
;
}
if
(
lv
->
search
!=
NULL
&&
!
strcmp
(
lv
->
search
,
search_term
))
{
/* Searching for the same term acts as "Find Next" */
gtk_imhtml_search_find
(
GTK_IMHTML
(
lv
->
imhtml
),
lv
->
search
);
return
;
}
gaim_gtk_set_cursor
(
lv
->
window
,
GDK_WATCH
);
g_free
(
lv
->
search
);
lv
->
search
=
g_strdup
(
search_term
);
gtk_tree_store_clear
(
lv
->
treestore
);
gtk_imhtml_clear
(
GTK_IMHTML
(
lv
->
imhtml
));
for
(
logs
=
lv
->
logs
;
logs
!=
NULL
;
logs
=
logs
->
next
)
{
char
*
read
=
gaim_log_read
((
GaimLog
*
)
logs
->
data
,
NULL
);
if
(
read
&&
*
read
&&
gaim_strcasestr
(
read
,
search_term
))
{
GtkTreeIter
iter
;
GaimLog
*
log
=
logs
->
data
;
gtk_tree_store_append
(
lv
->
treestore
,
&
iter
,
NULL
);
gtk_tree_store_set
(
lv
->
treestore
,
&
iter
,
0
,
log_get_date
(
log
),
1
,
log
,
-1
);
}
g_free
(
read
);
}
select_first_log
(
lv
);
gaim_gtk_clear_cursor
(
lv
->
window
);
}
static
void
destroy_cb
(
GtkWidget
*
w
,
gint
resp
,
struct
log_viewer_hash_t
*
ht
)
{
GaimGtkLogViewer
*
lv
=
syslog_viewer
;
#ifdef _WIN32
if
(
resp
==
GTK_RESPONSE_HELP
)
{
char
*
logdir
=
g_build_filename
(
gaim_user_dir
(),
"logs"
,
NULL
);
gtkwgaim_shell_execute
(
logdir
,
"explore"
,
NULL
);
g_free
(
logdir
);
return
;
}
#endif
if
(
ht
!=
NULL
)
{
lv
=
g_hash_table_lookup
(
log_viewers
,
ht
);
g_hash_table_remove
(
log_viewers
,
ht
);
g_free
(
ht
->
screenname
);
g_free
(
ht
);
}
else
syslog_viewer
=
NULL
;
g_list_foreach
(
lv
->
logs
,
(
GFunc
)
gaim_log_free
,
NULL
);
g_list_free
(
lv
->
logs
);
g_free
(
lv
->
search
);
g_free
(
lv
);
gtk_widget_destroy
(
w
);
}
static
void
log_row_activated_cb
(
GtkTreeView
*
tv
,
GtkTreePath
*
path
,
GtkTreeViewColumn
*
col
,
GaimGtkLogViewer
*
viewer
)
{
if
(
gtk_tree_view_row_expanded
(
tv
,
path
))
gtk_tree_view_collapse_row
(
tv
,
path
);
else
gtk_tree_view_expand_row
(
tv
,
path
,
FALSE
);
}
static
gboolean
search_find_cb
(
gpointer
data
)
{
GaimGtkLogViewer
*
viewer
=
data
;
gtk_imhtml_search_find
(
GTK_IMHTML
(
viewer
->
imhtml
),
viewer
->
search
);
return
FALSE
;
}
static
void
log_select_cb
(
GtkTreeSelection
*
sel
,
GaimGtkLogViewer
*
viewer
)
{
GtkTreeIter
iter
;
GValue
val
;
GtkTreeModel
*
model
=
GTK_TREE_MODEL
(
viewer
->
treestore
);
GaimLog
*
log
=
NULL
;
GaimLogReadFlags
flags
;
char
*
read
=
NULL
;
if
(
!
gtk_tree_selection_get_selected
(
sel
,
&
model
,
&
iter
))
return
;
val
.
g_type
=
0
;
gtk_tree_model_get_value
(
model
,
&
iter
,
1
,
&
val
);
log
=
g_value_get_pointer
(
&
val
);
g_value_unset
(
&
val
);
if
(
log
==
NULL
)
return
;
gaim_gtk_set_cursor
(
viewer
->
window
,
GDK_WATCH
);
if
(
log
->
type
!=
GAIM_LOG_SYSTEM
)
{
char
*
title
;
if
(
log
->
type
==
GAIM_LOG_CHAT
)
title
=
g_strdup_printf
(
_
(
"<span size='larger' weight='bold'>Conversation in %s on %s</span>"
),
log
->
name
,
log_get_date
(
log
));
else
title
=
g_strdup_printf
(
_
(
"<span size='larger' weight='bold'>Conversation with %s on %s</span>"
),
log
->
name
,
log_get_date
(
log
));
gtk_label_set_markup
(
GTK_LABEL
(
viewer
->
label
),
title
);
g_free
(
title
);
}
read
=
gaim_log_read
(
log
,
&
flags
);
viewer
->
flags
=
flags
;
gtk_imhtml_clear
(
GTK_IMHTML
(
viewer
->
imhtml
));
gtk_imhtml_set_protocol_name
(
GTK_IMHTML
(
viewer
->
imhtml
),
gaim_account_get_protocol_name
(
log
->
account
));
gaim_signal_emit
(
gaim_gtk_log_get_handle
(),
"log-displaying"
,
viewer
,
log
);
gtk_imhtml_append_text
(
GTK_IMHTML
(
viewer
->
imhtml
),
read
,
GTK_IMHTML_NO_COMMENTS
|
GTK_IMHTML_NO_TITLE
|
GTK_IMHTML_NO_SCROLL
|
((
flags
&
GAIM_LOG_READ_NO_NEWLINE
)
?
GTK_IMHTML_NO_NEWLINE
:
0
));
g_free
(
read
);
if
(
viewer
->
search
!=
NULL
)
{
gtk_imhtml_search_clear
(
GTK_IMHTML
(
viewer
->
imhtml
));
g_idle_add
(
search_find_cb
,
viewer
);
}
gaim_gtk_clear_cursor
(
viewer
->
window
);
}
/* I want to make this smarter, but haven't come up with a cool algorithm to do so, yet.
* I want the tree to be divided into groups like "Today," "Yesterday," "Last week,"
* "August," "2002," etc. based on how many conversation took place in each subdivision.
*
* For now, I'll just make it a flat list.
*/
static
void
populate_log_tree
(
GaimGtkLogViewer
*
lv
)
/* Logs are made from trees in real life.
This is a tree made from logs */
{
const
char
*
month
;
char
prev_top_month
[
30
]
=
""
;
GtkTreeIter
toplevel
,
child
;
GList
*
logs
=
lv
->
logs
;
while
(
logs
!=
NULL
)
{
GaimLog
*
log
=
logs
->
data
;
month
=
gaim_utf8_strftime
(
_
(
"%B %Y"
),
log
->
tm
?
log
->
tm
:
localtime
(
&
log
->
time
));
if
(
strcmp
(
month
,
prev_top_month
)
!=
0
)
{
/* top level */
gtk_tree_store_append
(
lv
->
treestore
,
&
toplevel
,
NULL
);
gtk_tree_store_set
(
lv
->
treestore
,
&
toplevel
,
0
,
month
,
1
,
NULL
,
-1
);
strncpy
(
prev_top_month
,
month
,
sizeof
(
prev_top_month
));
}
/* sub */
gtk_tree_store_append
(
lv
->
treestore
,
&
child
,
&
toplevel
);
gtk_tree_store_set
(
lv
->
treestore
,
&
child
,
0
,
log_get_date
(
log
),
1
,
log
,
-1
);
logs
=
logs
->
next
;
}
}
static
GaimGtkLogViewer
*
display_log_viewer
(
struct
log_viewer_hash_t
*
ht
,
GList
*
logs
,
const
char
*
title
,
GdkPixbuf
*
pixbuf
,
int
log_size
)
{
GaimGtkLogViewer
*
lv
;
GtkWidget
*
title_box
;
char
*
text
;
GtkWidget
*
pane
;
GtkWidget
*
sw
;
GtkCellRenderer
*
rend
;
GtkTreeViewColumn
*
col
;
GtkTreeSelection
*
sel
;
GtkWidget
*
vbox
;
GtkWidget
*
frame
;
GtkWidget
*
hbox
;
GtkWidget
*
find_button
;
GtkWidget
*
size_label
;
if
(
logs
==
NULL
)
{
/* No logs were found. */
const
char
*
log_preferences
=
NULL
;
if
(
ht
==
NULL
)
{
if
(
!
gaim_prefs_get_bool
(
"/core/logging/log_system"
))
log_preferences
=
_
(
"System events will only be logged if the
\"
Log all status changes to system log
\"
preference is enabled."
);
}
else
{
if
(
ht
->
type
==
GAIM_LOG_IM
)
{
if
(
!
gaim_prefs_get_bool
(
"/core/logging/log_ims"
))
log_preferences
=
_
(
"Instant messages will only be logged if the
\"
Log all instant messages
\"
preference is enabled."
);
}
else
if
(
ht
->
type
==
GAIM_LOG_CHAT
)
{
if
(
!
gaim_prefs_get_bool
(
"/core/logging/log_chats"
))
log_preferences
=
_
(
"Chats will only be logged if the
\"
Log all chats
\"
preference is enabled."
);
}
}
gaim_notify_info
(
NULL
,
title
,
_
(
"No logs were found"
),
log_preferences
);
return
NULL
;
}
lv
=
g_new0
(
GaimGtkLogViewer
,
1
);
lv
->
logs
=
logs
;
if
(
ht
!=
NULL
)
g_hash_table_insert
(
log_viewers
,
ht
,
lv
);
/* Window ***********/
lv
->
window
=
gtk_dialog_new_with_buttons
(
title
,
NULL
,
0
,
GTK_STOCK_CLOSE
,
GTK_RESPONSE_CLOSE
,
NULL
);
#ifdef _WIN32
/* Steal the "HELP" response and use it to trigger browsing to the logs folder */
gtk_dialog_add_button
(
GTK_DIALOG
(
lv
->
window
),
_
(
"_Browse logs folder"
),
GTK_RESPONSE_HELP
);
#endif
gtk_container_set_border_width
(
GTK_CONTAINER
(
lv
->
window
),
GAIM_HIG_BOX_SPACE
);
gtk_dialog_set_has_separator
(
GTK_DIALOG
(
lv
->
window
),
FALSE
);
gtk_box_set_spacing
(
GTK_BOX
(
GTK_DIALOG
(
lv
->
window
)
->
vbox
),
0
);
g_signal_connect
(
G_OBJECT
(
lv
->
window
),
"response"
,
G_CALLBACK
(
destroy_cb
),
ht
);
gtk_window_set_role
(
GTK_WINDOW
(
lv
->
window
),
"log_viewer"
);
/* Icon *************/
if
(
pixbuf
!=
NULL
)
{
GdkPixbuf
*
scale
;
GtkWidget
*
icon
;
title_box
=
gtk_hbox_new
(
FALSE
,
GAIM_HIG_BOX_SPACE
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
title_box
),
GAIM_HIG_BOX_SPACE
);
gtk_box_pack_start
(
GTK_BOX
(
GTK_DIALOG
(
lv
->
window
)
->
vbox
),
title_box
,
FALSE
,
FALSE
,
0
);
scale
=
gdk_pixbuf_scale_simple
(
pixbuf
,
16
,
16
,
GDK_INTERP_BILINEAR
);
icon
=
gtk_image_new_from_pixbuf
(
scale
);
gtk_box_pack_start
(
GTK_BOX
(
title_box
),
icon
,
FALSE
,
FALSE
,
0
);
g_object_unref
(
G_OBJECT
(
pixbuf
));
g_object_unref
(
G_OBJECT
(
scale
));
}
else
title_box
=
GTK_DIALOG
(
lv
->
window
)
->
vbox
;
/* Label ************/
lv
->
label
=
gtk_label_new
(
NULL
);
text
=
g_strdup_printf
(
"<span size='larger' weight='bold'>%s</span>"
,
title
);
gtk_label_set_markup
(
GTK_LABEL
(
lv
->
label
),
text
);
gtk_misc_set_alignment
(
GTK_MISC
(
lv
->
label
),
0
,
0
);
gtk_box_pack_start
(
GTK_BOX
(
title_box
),
lv
->
label
,
FALSE
,
FALSE
,
0
);
g_free
(
text
);
/* Pane *************/
pane
=
gtk_hpaned_new
();
gtk_container_set_border_width
(
GTK_CONTAINER
(
pane
),
GAIM_HIG_BOX_SPACE
);
gtk_box_pack_start
(
GTK_BOX
(
GTK_DIALOG
(
lv
->
window
)
->
vbox
),
pane
,
TRUE
,
TRUE
,
0
);
/* List *************/
sw
=
gtk_scrolled_window_new
(
NULL
,
NULL
);
gtk_scrolled_window_set_shadow_type
(
GTK_SCROLLED_WINDOW
(
sw
),
GTK_SHADOW_IN
);
gtk_scrolled_window_set_policy
(
GTK_SCROLLED_WINDOW
(
sw
),
GTK_POLICY_NEVER
,
GTK_POLICY_ALWAYS
);
gtk_paned_add1
(
GTK_PANED
(
pane
),
sw
);
lv
->
treestore
=
gtk_tree_store_new
(
2
,
G_TYPE_STRING
,
G_TYPE_POINTER
);
lv
->
treeview
=
gtk_tree_view_new_with_model
(
GTK_TREE_MODEL
(
lv
->
treestore
));
rend
=
gtk_cell_renderer_text_new
();
col
=
gtk_tree_view_column_new_with_attributes
(
"time"
,
rend
,
"markup"
,
0
,
NULL
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
lv
->
treeview
),
col
);
gtk_tree_view_set_headers_visible
(
GTK_TREE_VIEW
(
lv
->
treeview
),
FALSE
);
gtk_container_add
(
GTK_CONTAINER
(
sw
),
lv
->
treeview
);
populate_log_tree
(
lv
);
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
lv
->
treeview
));
g_signal_connect
(
G_OBJECT
(
sel
),
"changed"
,
G_CALLBACK
(
log_select_cb
),
lv
);
g_signal_connect
(
G_OBJECT
(
lv
->
treeview
),
"row-activated"
,
G_CALLBACK
(
log_row_activated_cb
),
lv
);
gaim_set_accessible_label
(
lv
->
treeview
,
lv
->
label
);
/* Log size ************/
if
(
log_size
)
{
char
*
sz_txt
=
gaim_str_size_to_units
(
log_size
);
text
=
g_strdup_printf
(
"<span weight='bold'>%s</span> %s"
,
_
(
"Total log size:"
),
sz_txt
);
size_label
=
gtk_label_new
(
NULL
);
gtk_label_set_markup
(
GTK_LABEL
(
size_label
),
text
);
/* gtk_paned_add1(GTK_PANED(pane), size_label); */
gtk_misc_set_alignment
(
GTK_MISC
(
size_label
),
0
,
0
);
gtk_box_pack_end
(
GTK_BOX
(
GTK_DIALOG
(
lv
->
window
)
->
vbox
),
size_label
,
FALSE
,
FALSE
,
0
);
g_free
(
sz_txt
);
g_free
(
text
);
}
/* A fancy little box ************/
vbox
=
gtk_vbox_new
(
FALSE
,
GAIM_HIG_BOX_SPACE
);
gtk_paned_add2
(
GTK_PANED
(
pane
),
vbox
);
/* Viewer ************/
frame
=
gaim_gtk_create_imhtml
(
FALSE
,
&
lv
->
imhtml
,
NULL
,
NULL
);
gtk_widget_set_name
(
lv
->
imhtml
,
"gaim_gtklog_imhtml"
);
gtk_widget_set_size_request
(
lv
->
imhtml
,
320
,
200
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
frame
,
TRUE
,
TRUE
,
0
);
gtk_widget_show
(
frame
);
/* Search box **********/
hbox
=
gtk_hbox_new
(
FALSE
,
GAIM_HIG_BOX_SPACE
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
lv
->
entry
=
gtk_entry_new
();
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
lv
->
entry
,
TRUE
,
TRUE
,
0
);
find_button
=
gtk_button_new_from_stock
(
GTK_STOCK_FIND
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
find_button
,
FALSE
,
FALSE
,
0
);
g_signal_connect
(
GTK_ENTRY
(
lv
->
entry
),
"activate"
,
G_CALLBACK
(
search_cb
),
lv
);
g_signal_connect
(
GTK_BUTTON
(
find_button
),
"clicked"
,
G_CALLBACK
(
search_cb
),
lv
);
select_first_log
(
lv
);
gtk_widget_show_all
(
lv
->
window
);
return
lv
;
}
void
gaim_gtk_log_show
(
GaimLogType
type
,
const
char
*
screenname
,
GaimAccount
*
account
)
{
struct
log_viewer_hash_t
*
ht
;
GaimGtkLogViewer
*
lv
=
NULL
;
const
char
*
name
=
screenname
;
char
*
title
;
g_return_if_fail
(
account
!=
NULL
);
g_return_if_fail
(
screenname
!=
NULL
);
ht
=
g_new0
(
struct
log_viewer_hash_t
,
1
);
ht
->
type
=
type
;
ht
->
screenname
=
g_strdup
(
screenname
);
ht
->
account
=
account
;
if
(
log_viewers
==
NULL
)
{
log_viewers
=
g_hash_table_new
(
log_viewer_hash
,
log_viewer_equal
);
}
else
if
((
lv
=
g_hash_table_lookup
(
log_viewers
,
ht
)))
{
gtk_window_present
(
GTK_WINDOW
(
lv
->
window
));
g_free
(
ht
->
screenname
);
g_free
(
ht
);
return
;
}
if
(
type
==
GAIM_LOG_CHAT
)
{
GaimChat
*
chat
;
chat
=
gaim_blist_find_chat
(
account
,
screenname
);
if
(
chat
!=
NULL
)
name
=
gaim_chat_get_name
(
chat
);
title
=
g_strdup_printf
(
_
(
"Conversations in %s"
),
name
);
}
else
{
GaimBuddy
*
buddy
;
buddy
=
gaim_find_buddy
(
account
,
screenname
);
if
(
buddy
!=
NULL
)
name
=
gaim_buddy_get_contact_alias
(
buddy
);
title
=
g_strdup_printf
(
_
(
"Conversations with %s"
),
name
);
}
display_log_viewer
(
ht
,
gaim_log_get_logs
(
type
,
screenname
,
account
),
title
,
gaim_gtk_create_prpl_icon
(
account
,
0.5
),
gaim_log_get_total_size
(
type
,
screenname
,
account
));
g_free
(
title
);
}
void
gaim_gtk_log_show_contact
(
GaimContact
*
contact
)
{
struct
log_viewer_hash_t
*
ht
=
g_new0
(
struct
log_viewer_hash_t
,
1
);
GaimBlistNode
*
child
;
GaimGtkLogViewer
*
lv
=
NULL
;
GList
*
logs
=
NULL
;
char
*
filename
;
GdkPixbuf
*
pixbuf
;
const
char
*
name
=
NULL
;
char
*
title
;
int
total_log_size
=
0
;
g_return_if_fail
(
contact
!=
NULL
);
ht
->
type
=
GAIM_LOG_IM
;
ht
->
contact
=
contact
;
if
(
log_viewers
==
NULL
)
{
log_viewers
=
g_hash_table_new
(
log_viewer_hash
,
log_viewer_equal
);
}
else
if
((
lv
=
g_hash_table_lookup
(
log_viewers
,
ht
)))
{
gtk_window_present
(
GTK_WINDOW
(
lv
->
window
));
g_free
(
ht
);
return
;
}
for
(
child
=
contact
->
node
.
child
;
child
;
child
=
child
->
next
)
{
if
(
!
GAIM_BLIST_NODE_IS_BUDDY
(
child
))
continue
;
logs
=
g_list_concat
(
gaim_log_get_logs
(
GAIM_LOG_IM
,
((
GaimBuddy
*
)
child
)
->
name
,
((
GaimBuddy
*
)
child
)
->
account
),
logs
);
total_log_size
+=
gaim_log_get_total_size
(
GAIM_LOG_IM
,
((
GaimBuddy
*
)
child
)
->
name
,
((
GaimBuddy
*
)
child
)
->
account
);
}
logs
=
g_list_sort
(
logs
,
gaim_log_compare
);
filename
=
g_build_filename
(
DATADIR
,
"pixmaps"
,
"gaim"
,
"icons"
,
"online.png"
,
NULL
);
pixbuf
=
gdk_pixbuf_new_from_file
(
filename
,
NULL
);
g_free
(
filename
);
if
(
contact
->
alias
!=
NULL
)
name
=
contact
->
alias
;
else
if
(
contact
->
priority
!=
NULL
)
name
=
gaim_buddy_get_contact_alias
(
contact
->
priority
);
title
=
g_strdup_printf
(
_
(
"Conversations with %s"
),
name
);
display_log_viewer
(
ht
,
logs
,
title
,
pixbuf
,
total_log_size
);
g_free
(
title
);
}
void
gaim_gtk_syslog_show
()
{
GList
*
accounts
=
NULL
;
GList
*
logs
=
NULL
;
if
(
syslog_viewer
!=
NULL
)
{
gtk_window_present
(
GTK_WINDOW
(
syslog_viewer
->
window
));
return
;
}
for
(
accounts
=
gaim_accounts_get_all
();
accounts
!=
NULL
;
accounts
=
accounts
->
next
)
{
GaimAccount
*
account
=
(
GaimAccount
*
)
accounts
->
data
;
if
(
gaim_find_prpl
(
gaim_account_get_protocol_id
(
account
))
==
NULL
)
continue
;
logs
=
g_list_concat
(
gaim_log_get_system_logs
(
account
),
logs
);
}
logs
=
g_list_sort
(
logs
,
gaim_log_compare
);
syslog_viewer
=
display_log_viewer
(
NULL
,
logs
,
_
(
"System Log"
),
NULL
,
0
);
}
/****************************************************************************
* GTK+ LOG SUBSYSTEM *******************************************************
****************************************************************************/
void
*
gaim_gtk_log_get_handle
(
void
)
{
static
int
handle
;
return
&
handle
;
}
void
gaim_gtk_log_init
(
void
)
{
void
*
handle
=
gaim_gtk_log_get_handle
();
gaim_signal_register
(
handle
,
"log-displaying"
,
gaim_marshal_VOID__POINTER_POINTER
,
NULL
,
2
,
gaim_value_new
(
GAIM_TYPE_BOXED
,
"GaimGtkLogViewer *"
),
gaim_value_new
(
GAIM_TYPE_SUBTYPE
,
GAIM_SUBTYPE_LOG
));
}
void
gaim_gtk_log_uninit
(
void
)
{
gaim_signals_unregister_by_instance
(
gaim_gtk_log_get_handle
());
}