grim/guifications2
Clone
Summary
Browse
Changes
Graph
well we compile somewhat successfully, but we don't load against 3.0.0-devel
2011-12-04, Gary Kramlich
3a8f4f41e93b
well we compile somewhat successfully, but we don't load against 3.0.0-devel
/*
* Guifications - The end all, be all, toaster popup plugin
* Copyright (C) 2003-2008 Gary Kramlich
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
*/
#include
<glib.h>
#include
<gtk/gtk.h>
#include
<gdk/gdk.h>
#include
<sys/stat.h>
#include
<sys/types.h>
#include
<unistd.h>
#include
<string.h>
#ifdef HAVE_CONFIG_H
#
include
"../gf_config.h"
#endif
#include
"gf_internal.h"
#include
<debug.h>
#include
<notify.h>
#include
<plugin.h>
#include
<prefs.h>
#include
<request.h>
#include
<util.h>
#include
<gtkutils.h>
#include
<gtkprefs.h>
#include
"gf_action.h"
#include
"gf_display.h"
#include
"gf_event.h"
#include
"gf_file.h"
#include
"gf_menu.h"
#include
"gf_preferences.h"
#include
"gf_stock.h"
#include
"gf_theme.h"
#include
"gf_theme_editor.h"
#include
"gf_theme_info.h"
enum
{
GF_THEME_COL_FILE
=
0
,
GF_THEME_COL_LOADED
,
GF_THEME_COL_NAME
,
GF_THEME_COL_VERSION
,
GF_THEME_COL_SUMMARY
,
GF_THEME_COL_DESCRIPTION
,
GF_THEME_COL_AUTHOR
,
GF_THEME_COL_WEBSITE
,
GF_THEME_COL_SUPPORTS
};
enum
{
GF_NOTIF_COL_SHOW
=
0
,
GF_NOTIF_COL_NAME
,
GF_NOTIF_COL_DESCRIPTION
,
GF_NOTIF_COL_TYPE
};
/*******************************************************************************
* Globals
******************************************************************************/
PurplePlugin
*
guifications
;
/*******************************************************************************
* callbacks
******************************************************************************/
static
void
option_menu_cb
(
GtkOptionMenu
*
option_menu
,
gchar
*
pref
)
{
purple_prefs_set_int
(
pref
,
gtk_option_menu_get_history
(
option_menu
));
}
static
void
mouse_option_menu_cb
(
GtkOptionMenu
*
option_menu
,
gchar
*
pref
)
{
const
gchar
*
name
;
name
=
gf_actions_get_nth_name
(
gtk_option_menu_get_history
(
option_menu
));
purple_prefs_set_string
(
pref
,
name
);
}
/***********************************************************************
* utilities
**********************************************************************/
static
GtkWidget
*
make_notebook_page
(
GtkNotebook
*
note
,
const
gchar
*
text
,
gint
position
)
{
GtkWidget
*
vbox
,
*
label
;
vbox
=
gtk_vbox_new
(
FALSE
,
6
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
vbox
),
12
);
gtk_widget_show
(
vbox
);
label
=
gtk_label_new_with_mnemonic
(
text
);
gtk_widget_show
(
label
);
gtk_notebook_insert_page
(
note
,
vbox
,
label
,
position
);
return
vbox
;
}
static
GtkWidget
*
make_label
(
const
gchar
*
text
,
GtkSizeGroup
*
sg
)
{
GtkWidget
*
label
;
label
=
gtk_label_new_with_mnemonic
(
text
);
gtk_misc_set_alignment
(
GTK_MISC
(
label
),
0
,
0
);
gtk_widget_show
(
label
);
if
(
sg
)
gtk_size_group_add_widget
(
sg
,
label
);
return
label
;
}
static
GtkWidget
*
make_bold_label
(
const
gchar
*
text
,
GtkSizeGroup
*
sg
)
{
GtkWidget
*
label
;
gchar
*
escaped
,
*
markup
;
escaped
=
g_markup_escape_text
(
text
,
strlen
(
text
));
markup
=
g_strdup_printf
(
"<b>%s:</b>"
,
escaped
);
g_free
(
escaped
);
label
=
gtk_label_new
(
NULL
);
gtk_label_set_markup_with_mnemonic
(
GTK_LABEL
(
label
),
markup
);
g_free
(
markup
);
gtk_misc_set_alignment
(
GTK_MISC
(
label
),
0.0
,
0.0
);
if
(
sg
)
gtk_size_group_add_widget
(
sg
,
label
);
return
label
;
}
static
GtkWidget
*
make_option_menu
(
const
gchar
*
text
,
gchar
*
pref
,
GtkSizeGroup
*
sg
,
GfMenuItemBuilder
builder
)
{
GtkWidget
*
hbox
,
*
option_menu
,
*
menu
,
*
label
;
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
if
(
text
)
{
label
=
make_label
(
text
,
sg
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
}
option_menu
=
gtk_option_menu_new
();
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
option_menu
,
FALSE
,
FALSE
,
0
);
menu
=
gf_menu_build
(
builder
,
NULL
);
gtk_option_menu_set_menu
(
GTK_OPTION_MENU
(
option_menu
),
menu
);
gtk_option_menu_set_history
(
GTK_OPTION_MENU
(
option_menu
),
purple_prefs_get_int
(
pref
));
g_signal_connect
(
G_OBJECT
(
option_menu
),
"changed"
,
G_CALLBACK
(
option_menu_cb
),
pref
);
gtk_widget_show_all
(
hbox
);
return
hbox
;
}
static
GtkWidget
*
make_mouse_option_menu
(
const
gchar
*
text
,
gchar
*
pref
,
GtkSizeGroup
*
sg
)
{
GfAction
*
action
=
NULL
;
GtkWidget
*
hbox
,
*
option_menu
,
*
menu
,
*
label
;
gint
position
=
-1
;
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
if
(
text
)
{
label
=
make_label
(
text
,
sg
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
}
option_menu
=
gtk_option_menu_new
();
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
option_menu
,
FALSE
,
FALSE
,
0
);
menu
=
gf_menu_build
(
gf_menu_mouse
,
NULL
);
gtk_option_menu_set_menu
(
GTK_OPTION_MENU
(
option_menu
),
menu
);
action
=
gf_action_find_with_name
(
purple_prefs_get_string
(
pref
));
if
(
action
&&
(
position
=
gf_action_get_position
(
action
))
>
-1
)
{
gtk_option_menu_set_history
(
GTK_OPTION_MENU
(
option_menu
),
position
);
}
g_signal_connect
(
G_OBJECT
(
option_menu
),
"changed"
,
G_CALLBACK
(
mouse_option_menu_cb
),
pref
);
gtk_widget_show_all
(
hbox
);
return
hbox
;
}
/*******************************************************************************
* General page stuff
******************************************************************************/
static
void
make_general_page
(
GtkWidget
*
notebook
)
{
GtkWidget
*
vbox
,
*
frame
,
*
spin
,
*
option
,
*
label
;
GtkSizeGroup
*
sg
;
vbox
=
make_notebook_page
(
GTK_NOTEBOOK
(
notebook
),
_
(
"General"
),
-1
);
gtk_widget_show
(
vbox
);
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
/* Display Options */
frame
=
pidgin_make_frame
(
vbox
,
_
(
"Display Options"
));
gtk_widget_show
(
frame
);
option
=
make_option_menu
(
_
(
"_Position:"
),
GF_PREF_APPEARANCE_POSITION
,
sg
,
gf_menu_position
);
gtk_box_pack_start
(
GTK_BOX
(
frame
),
option
,
FALSE
,
FALSE
,
0
);
label
=
pidgin_prefs_dropdown
(
frame
,
_
(
"_Stack:"
),
PURPLE_PREF_BOOLEAN
,
GF_PREF_APPEARANCE_VERTICAL
,
_
(
"Vertically"
),
TRUE
,
_
(
"Horizontally"
),
FALSE
,
NULL
);
gtk_misc_set_alignment
(
GTK_MISC
(
label
),
0
,
0
);
gtk_size_group_add_widget
(
sg
,
label
);
label
=
pidgin_prefs_dropdown
(
frame
,
_
(
"Show _while away:"
),
PURPLE_PREF_BOOLEAN
,
GF_PREF_BEHAVIOR_SHOW_WHILE_AWAY
,
_
(
"Yes"
),
TRUE
,
_
(
"No"
),
FALSE
,
NULL
);
gtk_misc_set_alignment
(
GTK_MISC
(
label
),
0
,
0
);
gtk_size_group_add_widget
(
sg
,
label
);
label
=
pidgin_prefs_dropdown
(
frame
,
_
(
"_Animate:"
),
PURPLE_PREF_BOOLEAN
,
GF_PREF_APPEARANCE_ANIMATE
,
_
(
"Yes"
),
TRUE
,
_
(
"No"
),
FALSE
,
NULL
);
gtk_misc_set_alignment
(
GTK_MISC
(
label
),
0
,
0
);
gtk_size_group_add_widget
(
sg
,
label
);
spin
=
pidgin_prefs_labeled_spin_button
(
frame
,
_
(
"_Display Time:"
),
GF_PREF_BEHAVIOR_DISPLAY_TIME
,
1
,
60
,
sg
);
label
=
make_label
(
_
(
"seconds"
),
NULL
);
gtk_box_pack_start
(
GTK_BOX
(
spin
),
label
,
FALSE
,
FALSE
,
0
);
/* Mouse Options */
frame
=
pidgin_make_frame
(
vbox
,
_
(
"Mouse"
));
gtk_widget_show
(
frame
);
option
=
make_mouse_option_menu
(
_
(
"_Left:"
),
GF_PREF_MOUSE_LEFT
,
sg
);
gtk_box_pack_start
(
GTK_BOX
(
frame
),
option
,
FALSE
,
FALSE
,
0
);
option
=
make_mouse_option_menu
(
_
(
"_Middle:"
),
GF_PREF_MOUSE_MIDDLE
,
sg
);
gtk_box_pack_start
(
GTK_BOX
(
frame
),
option
,
FALSE
,
FALSE
,
0
);
option
=
make_mouse_option_menu
(
_
(
"_Right:"
),
GF_PREF_MOUSE_RIGHT
,
sg
);
gtk_box_pack_start
(
GTK_BOX
(
frame
),
option
,
FALSE
,
FALSE
,
0
);
}
/*******************************************************************************
* Notification page stuff
******************************************************************************/
static
gint
notification_sort_show
(
GtkTreeModel
*
model
,
GtkTreeIter
*
a
,
GtkTreeIter
*
b
,
gpointer
data
)
{
gboolean
a_show
=
FALSE
,
b_show
=
FALSE
;
gtk_tree_model_get
(
model
,
a
,
GF_NOTIF_COL_SHOW
,
&
a_show
,
-1
);
gtk_tree_model_get
(
model
,
b
,
GF_NOTIF_COL_SHOW
,
&
b_show
,
-1
);
if
(
a_show
&&
!
b_show
)
return
1
;
else
if
(
!
a_show
&&
b_show
)
return
-1
;
else
return
0
;
}
static
gint
notification_sort_name
(
GtkTreeModel
*
model
,
GtkTreeIter
*
a
,
GtkTreeIter
*
b
,
gpointer
data
)
{
gchar
*
a_name
=
NULL
,
*
b_name
=
NULL
;
gchar
*
a_ckey
=
NULL
,
*
b_ckey
=
NULL
;
gint
ret
=
0
;
gtk_tree_model_get
(
model
,
a
,
GF_NOTIF_COL_NAME
,
&
a_name
,
-1
);
gtk_tree_model_get
(
model
,
b
,
GF_NOTIF_COL_NAME
,
&
b_name
,
-1
);
a_ckey
=
g_utf8_collate_key
(
a_name
,
g_utf8_strlen
(
a_name
,
-1
));
b_ckey
=
g_utf8_collate_key
(
b_name
,
g_utf8_strlen
(
b_name
,
-1
));
g_free
(
a_name
);
g_free
(
b_name
);
ret
=
strcmp
(
a_ckey
,
b_ckey
);
g_free
(
a_ckey
);
g_free
(
b_ckey
);
return
ret
;
}
static
gint
notification_sort_desc
(
GtkTreeModel
*
model
,
GtkTreeIter
*
a
,
GtkTreeIter
*
b
,
gpointer
data
)
{
gchar
*
a_desc
=
NULL
,
*
b_desc
=
NULL
;
gchar
*
a_ckey
=
NULL
,
*
b_ckey
=
NULL
;
gint
ret
=
0
;
gtk_tree_model_get
(
model
,
a
,
GF_NOTIF_COL_DESCRIPTION
,
&
a_desc
,
-1
);
gtk_tree_model_get
(
model
,
b
,
GF_NOTIF_COL_DESCRIPTION
,
&
b_desc
,
-1
);
a_ckey
=
g_utf8_collate_key
(
a_desc
,
g_utf8_strlen
(
a_desc
,
-1
));
b_ckey
=
g_utf8_collate_key
(
b_desc
,
g_utf8_strlen
(
b_desc
,
-1
));
g_free
(
a_desc
);
g_free
(
b_desc
);
ret
=
strcmp
(
a_ckey
,
b_ckey
);
g_free
(
a_ckey
);
g_free
(
b_ckey
);
return
ret
;
}
static
void
notification_show_cb
(
GtkCellRendererToggle
*
renderer
,
gchar
*
path
,
gpointer
data
)
{
GfEvent
*
event
;
GtkListStore
*
store
=
(
GtkListStore
*
)
data
;
GtkTreeIter
iter
;
gchar
*
type
=
NULL
;
gboolean
show
=
FALSE
;
gtk_tree_model_get_iter_from_string
(
GTK_TREE_MODEL
(
store
),
&
iter
,
path
);
gtk_tree_model_get
(
GTK_TREE_MODEL
(
store
),
&
iter
,
GF_NOTIF_COL_SHOW
,
&
show
,
GF_NOTIF_COL_TYPE
,
&
type
,
-1
);
event
=
gf_event_find_for_notification
(
type
);
if
(
event
)
{
gf_event_set_show
(
event
,
!
show
);
gf_events_save
();
}
g_free
(
type
);
gtk_list_store_set
(
store
,
&
iter
,
GF_NOTIF_COL_SHOW
,
!
show
,
-1
);
}
static
void
make_notification_list
(
GtkBox
*
parent
)
{
GtkWidget
*
list
,
*
sw
;
GtkListStore
*
store
;
GtkTreeSortable
*
sortable
;
GtkCellRenderer
*
renderer
;
GtkTreeViewColumn
*
col
;
const
GList
*
events
;
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_AUTOMATIC
,
GTK_POLICY_AUTOMATIC
);
gtk_box_pack_start
(
parent
,
sw
,
TRUE
,
TRUE
,
0
);
store
=
gtk_list_store_new
(
4
,
G_TYPE_BOOLEAN
,
G_TYPE_STRING
,
G_TYPE_STRING
,
G_TYPE_STRING
);
for
(
events
=
gf_events_get
();
events
;
events
=
events
->
next
)
{
GfEvent
*
event
;
GtkTreeIter
iter
;
const
gchar
*
type
;
event
=
GF_EVENT
(
events
->
data
);
type
=
gf_event_get_notification_type
(
event
);
if
(
type
&&
type
[
0
]
==
'!'
)
continue
;
gtk_list_store_append
(
store
,
&
iter
);
gtk_list_store_set
(
store
,
&
iter
,
GF_NOTIF_COL_SHOW
,
gf_event_show_notification
(
type
),
GF_NOTIF_COL_NAME
,
gf_event_get_name
(
event
),
GF_NOTIF_COL_DESCRIPTION
,
gf_event_get_description
(
event
),
GF_NOTIF_COL_TYPE
,
type
,
-1
);
}
sortable
=
GTK_TREE_SORTABLE
(
store
);
gtk_tree_sortable_set_sort_func
(
sortable
,
GF_NOTIF_COL_SHOW
,
notification_sort_show
,
NULL
,
NULL
);
gtk_tree_sortable_set_sort_func
(
sortable
,
GF_NOTIF_COL_NAME
,
notification_sort_name
,
NULL
,
NULL
);
gtk_tree_sortable_set_sort_func
(
sortable
,
GF_NOTIF_COL_DESCRIPTION
,
notification_sort_desc
,
NULL
,
NULL
);
gtk_tree_sortable_set_sort_column_id
(
sortable
,
GF_NOTIF_COL_NAME
,
GTK_SORT_ASCENDING
);
list
=
gtk_tree_view_new_with_model
(
GTK_TREE_MODEL
(
store
));
gtk_tree_view_set_rules_hint
(
GTK_TREE_VIEW
(
list
),
TRUE
);
gtk_widget_set_size_request
(
list
,
-1
,
150
);
gtk_container_add
(
GTK_CONTAINER
(
sw
),
list
);
renderer
=
gtk_cell_renderer_toggle_new
();
g_signal_connect
(
G_OBJECT
(
renderer
),
"toggled"
,
G_CALLBACK
(
notification_show_cb
),
store
);
col
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Show"
),
renderer
,
"active"
,
0
,
NULL
);
gtk_tree_view_column_set_sort_column_id
(
col
,
GF_NOTIF_COL_SHOW
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
list
),
col
);
renderer
=
gtk_cell_renderer_text_new
();
col
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Event"
),
renderer
,
"text"
,
1
,
NULL
);
gtk_tree_view_column_set_sort_column_id
(
col
,
GF_NOTIF_COL_NAME
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
list
),
col
);
renderer
=
gtk_cell_renderer_text_new
();
col
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Description"
),
renderer
,
"text"
,
2
,
NULL
);
gtk_tree_view_column_set_sort_column_id
(
col
,
GF_NOTIF_COL_DESCRIPTION
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
list
),
col
);
gtk_widget_show_all
(
sw
);
}
static
void
make_notifications_page
(
GtkWidget
*
notebook
)
{
GtkWidget
*
vbox
;
vbox
=
make_notebook_page
(
GTK_NOTEBOOK
(
notebook
),
_
(
"Notifications"
),
-1
);
gtk_widget_show
(
vbox
);
make_notification_list
(
GTK_BOX
(
vbox
));
}
/*******************************************************************************
* Theme page stuff
******************************************************************************/
struct
GfThemeListData
{
GtkWidget
*
tree
;
GtkListStore
*
store
;
GtkWidget
*
theme_new
;
GtkWidget
*
theme_edit
;
GtkWidget
*
theme_delete
;
GtkWidget
*
theme_copy
;
GtkWidget
*
theme_refresh
;
GtkWidget
*
theme_get_more
;
};
struct
ThemeInfoPane
{
GtkWidget
*
theme_name
;
GtkWidget
*
theme_version
;
GtkWidget
*
theme_description
;
GtkWidget
*
theme_author
;
GtkWidget
*
theme_website
;
GtkWidget
*
theme_supports
;
GtkWidget
*
theme_filename
;
};
static
struct
GfThemeListData
theme_data
;
static
struct
ThemeInfoPane
theme_info_pane
;
static
gint
theme_sort_loaded
(
GtkTreeModel
*
model
,
GtkTreeIter
*
a
,
GtkTreeIter
*
b
,
gpointer
data
)
{
gboolean
a_loaded
=
FALSE
,
b_loaded
=
FALSE
;
gtk_tree_model_get
(
model
,
a
,
GF_THEME_COL_LOADED
,
&
a_loaded
,
-1
);
gtk_tree_model_get
(
model
,
b
,
GF_THEME_COL_LOADED
,
&
b_loaded
,
-1
);
if
(
a_loaded
&&
!
b_loaded
)
return
1
;
else
if
(
!
a_loaded
&&
b_loaded
)
return
-1
;
else
return
0
;
}
static
gint
theme_sort_name
(
GtkTreeModel
*
model
,
GtkTreeIter
*
a
,
GtkTreeIter
*
b
,
gpointer
data
)
{
gchar
*
a_name
=
NULL
,
*
b_name
=
NULL
;
gchar
*
a_ckey
=
NULL
,
*
b_ckey
=
NULL
;
gint
ret
=
0
;
gtk_tree_model_get
(
model
,
a
,
GF_THEME_COL_NAME
,
&
a_name
,
-1
);
gtk_tree_model_get
(
model
,
b
,
GF_THEME_COL_NAME
,
&
b_name
,
-1
);
if
(
a_name
&&
!
b_name
)
return
1
;
else
if
(
!
a_name
&&
b_name
)
return
-1
;
a_ckey
=
g_utf8_collate_key
(
a_name
,
g_utf8_strlen
(
a_name
,
-1
));
b_ckey
=
g_utf8_collate_key
(
b_name
,
g_utf8_strlen
(
b_name
,
-1
));
g_free
(
a_name
);
g_free
(
b_name
);
ret
=
strcmp
(
a_ckey
,
b_ckey
);
g_free
(
a_ckey
);
g_free
(
b_ckey
);
return
ret
;
}
static
gint
theme_sort_summary
(
GtkTreeModel
*
model
,
GtkTreeIter
*
a
,
GtkTreeIter
*
b
,
gpointer
data
)
{
gchar
*
a_summ
=
NULL
,
*
b_summ
=
NULL
;
gchar
*
a_ckey
=
NULL
,
*
b_ckey
=
NULL
;
gint
ret
=
0
;
gtk_tree_model_get
(
model
,
a
,
GF_THEME_COL_SUMMARY
,
&
a_summ
,
-1
);
gtk_tree_model_get
(
model
,
b
,
GF_THEME_COL_SUMMARY
,
&
b_summ
,
-1
);
if
(
!
a_summ
&&
!
b_summ
)
return
0
;
if
(
a_summ
&&
!
b_summ
)
return
1
;
else
if
(
!
a_summ
&&
b_summ
)
return
-1
;
a_ckey
=
g_utf8_collate_key
(
a_summ
,
g_utf8_strlen
(
a_summ
,
-1
));
b_ckey
=
g_utf8_collate_key
(
b_summ
,
g_utf8_strlen
(
b_summ
,
-1
));
g_free
(
a_summ
);
g_free
(
b_summ
);
ret
=
strcmp
(
a_ckey
,
b_ckey
);
g_free
(
a_ckey
);
g_free
(
b_ckey
);
return
ret
;
}
static
void
theme_install_theme
(
char
*
path
,
char
*
extn
)
{
#ifndef _WIN32
gchar
*
command
,
*
escaped
;
#endif
gchar
*
destdir
;
gchar
*
tail
;
/* Just to be safe */
g_strchomp
(
path
);
/* I dont know what you are, get out of here */
if
(
extn
!=
NULL
)
tail
=
extn
;
else
if
((
tail
=
strrchr
(
path
,
'.'
))
==
NULL
)
return
;
destdir
=
g_build_filename
(
purple_user_dir
(),
"guifications"
,
"themes"
,
NULL
);
/* We'll check this just to make sure. This also lets us do something
* different on other platforms, if need be */
if
(
!
g_ascii_strcasecmp
(
tail
,
".gz"
)
||
!
g_ascii_strcasecmp
(
tail
,
".tgz"
))
{
#ifndef _WIN32
escaped
=
g_shell_quote
(
path
);
command
=
g_strdup_printf
(
"tar > /dev/null xzf %s -C %s"
,
escaped
,
destdir
);
g_free
(
escaped
);
#else
if
(
!
winpidgin_gz_untar
(
path
,
destdir
))
{
g_free
(
destdir
);
return
;
}
#endif
}
else
{
g_free
(
destdir
);
return
;
}
#ifndef _WIN32
/* Fire! */
system
(
command
);
g_free
(
command
);
#endif
g_free
(
destdir
);
gf_preferences_refresh_themes_list
();
}
static
void
theme_got_url
(
PurpleUtilFetchUrlData
*
url_data
,
void
*
data
,
const
char
*
themedata
,
size_t
len
,
const
gchar
*
err_msg
)
{
FILE
*
f
;
gchar
*
path
;
f
=
purple_mkstemp
(
&
path
,
FALSE
);
fwrite
(
themedata
,
len
,
1
,
f
);
fclose
(
f
);
theme_install_theme
(
path
,
data
);
g_unlink
(
path
);
g_free
(
path
);
}
static
void
theme_dnd_recv
(
GtkWidget
*
widget
,
GdkDragContext
*
dc
,
guint
x
,
guint
y
,
GtkSelectionData
*
sd
,
guint
info
,
guint
t
,
gpointer
data
)
{
gchar
*
name
=
(
gchar
*
)
sd
->
data
;
if
((
sd
->
length
>=
0
)
&&
(
sd
->
format
==
8
))
{
/* Well, it looks like the drag event was cool.
* Let's do something with it */
if
(
!
g_ascii_strncasecmp
(
name
,
"file://"
,
7
))
{
GError
*
converr
=
NULL
;
gchar
*
tmp
;
/* It looks like we're dealing with a local file. Let's
* just untar it in the right place */
if
(
!
(
tmp
=
g_filename_from_uri
(
name
,
NULL
,
&
converr
)))
{
purple_debug_error
(
"guifications"
,
"theme dnd %s
\n
"
,
(
converr
?
converr
->
message
:
"g_filename_from_uri error"
));
return
;
}
theme_install_theme
(
tmp
,
NULL
);
g_free
(
tmp
);
}
else
if
(
!
g_ascii_strncasecmp
(
name
,
"http://"
,
7
))
{
/* Oo, a web drag and drop. This is where things
* will start to get interesting */
gchar
*
tail
;
if
((
tail
=
strrchr
(
name
,
'.'
))
==
NULL
)
return
;
/* We'll check this just to make sure. This also lets us do something different on
* other platforms, if need be */
/* Q: shouldn't tgz be tail? */
/* A: no. */
purple_util_fetch_url
(
name
,
TRUE
,
NULL
,
FALSE
,
-1
,
theme_got_url
,
".tgz"
);
}
gtk_drag_finish
(
dc
,
TRUE
,
FALSE
,
t
);
}
gtk_drag_finish
(
dc
,
FALSE
,
FALSE
,
t
);
}
static
void
theme_load_cb
(
GtkCellRendererToggle
*
renderer
,
gchar
*
path
,
gpointer
data
)
{
GtkTreeIter
iter
;
gchar
*
filename
=
NULL
;
gboolean
loaded
=
FALSE
;
gtk_tree_model_get_iter_from_string
(
GTK_TREE_MODEL
(
theme_data
.
store
),
&
iter
,
path
);
gtk_tree_model_get
(
GTK_TREE_MODEL
(
theme_data
.
store
),
&
iter
,
GF_THEME_COL_LOADED
,
&
loaded
,
GF_THEME_COL_FILE
,
&
filename
,
-1
);
if
(
!
loaded
)
{
gf_theme_load
(
filename
);
}
else
{
GfTheme
*
theme
;
theme
=
gf_theme_find_theme_by_filename
(
filename
);
if
(
theme
)
gf_theme_unload
(
theme
);
}
gtk_list_store_set
(
theme_data
.
store
,
&
iter
,
GF_THEME_COL_LOADED
,
!
loaded
,
-1
);
if
(
filename
)
g_free
(
filename
);
gf_themes_save_loaded
();
}
static
void
theme_list_selection_cb
(
GtkTreeSelection
*
selection
,
gpointer
data
)
{
GtkTreeModel
*
model
;
GtkTreeIter
iter
;
gchar
*
name
=
NULL
,
*
version
=
NULL
,
*
description
=
NULL
;
gchar
*
author
=
NULL
,
*
website
=
NULL
,
*
filename
=
NULL
;
gchar
*
supports
=
NULL
;
if
(
gtk_tree_selection_get_selected
(
selection
,
&
model
,
&
iter
))
{
gtk_tree_model_get
(
model
,
&
iter
,
GF_THEME_COL_NAME
,
&
name
,
GF_THEME_COL_VERSION
,
&
version
,
GF_THEME_COL_DESCRIPTION
,
&
description
,
GF_THEME_COL_AUTHOR
,
&
author
,
GF_THEME_COL_WEBSITE
,
&
website
,
GF_THEME_COL_FILE
,
&
filename
,
GF_THEME_COL_SUPPORTS
,
&
supports
,
-1
);
if
(
filename
)
{
if
(
!
gf_file_access
(
filename
,
W_OK
))
{
gtk_widget_set_sensitive
(
theme_data
.
theme_edit
,
TRUE
);
gtk_widget_set_sensitive
(
theme_data
.
theme_delete
,
TRUE
);
}
else
{
gtk_widget_set_sensitive
(
theme_data
.
theme_edit
,
FALSE
);
gtk_widget_set_sensitive
(
theme_data
.
theme_delete
,
FALSE
);
}
}
gtk_widget_set_sensitive
(
theme_data
.
theme_copy
,
TRUE
);
}
else
{
gtk_widget_set_sensitive
(
theme_data
.
theme_copy
,
FALSE
);
}
gtk_label_set_text
(
GTK_LABEL
(
theme_info_pane
.
theme_name
),
name
);
gtk_label_set_text
(
GTK_LABEL
(
theme_info_pane
.
theme_version
),
version
);
gtk_label_set_text
(
GTK_LABEL
(
theme_info_pane
.
theme_description
),
description
);
gtk_label_set_text
(
GTK_LABEL
(
theme_info_pane
.
theme_author
),
author
);
gtk_label_set_text
(
GTK_LABEL
(
theme_info_pane
.
theme_website
),
website
);
gtk_label_set_text
(
GTK_LABEL
(
theme_info_pane
.
theme_supports
),
supports
);
gtk_label_set_text
(
GTK_LABEL
(
theme_info_pane
.
theme_filename
),
filename
);
g_free
(
name
);
g_free
(
version
);
g_free
(
description
);
g_free
(
author
);
g_free
(
website
);
g_free
(
supports
);
g_free
(
filename
);
}
static
GtkListStore
*
create_theme_store
()
{
GfTheme
*
theme
;
GfThemeInfo
*
info
;
GtkListStore
*
store
;
GtkTreeSortable
*
sortable
;
GtkTreeIter
iter
;
GList
*
l
;
gchar
*
supports
;
gboolean
loaded
=
FALSE
,
destroy
;
gf_themes_unprobe
();
gf_themes_probe
();
purple_debug_info
(
"Guifications"
,
"probes refreshed
\n
"
);
store
=
gtk_list_store_new
(
9
,
G_TYPE_STRING
,
G_TYPE_BOOLEAN
,
G_TYPE_STRING
,
G_TYPE_STRING
,
G_TYPE_STRING
,
G_TYPE_STRING
,
G_TYPE_STRING
,
G_TYPE_STRING
,
G_TYPE_STRING
);
for
(
l
=
gf_themes_get_all
();
l
;
l
=
l
->
next
)
{
gtk_list_store_append
(
store
,
&
iter
);
loaded
=
gf_theme_is_loaded
(
l
->
data
);
/* set the filename and if it's loaded */
gtk_list_store_set
(
store
,
&
iter
,
GF_THEME_COL_FILE
,
l
->
data
,
GF_THEME_COL_LOADED
,
loaded
,
-1
);
/* find the theme */
if
(
loaded
)
{
theme
=
gf_theme_find_theme_by_filename
(
l
->
data
);
destroy
=
FALSE
;
}
else
{
theme
=
gf_theme_new_from_file
(
l
->
data
);
destroy
=
TRUE
;
}
info
=
gf_theme_get_theme_info
(
theme
);
supports
=
gf_theme_get_supported_notifications
(
theme
);
gtk_list_store_set
(
store
,
&
iter
,
GF_THEME_COL_NAME
,
gf_theme_info_get_name
(
info
),
GF_THEME_COL_VERSION
,
gf_theme_info_get_version
(
info
),
GF_THEME_COL_SUMMARY
,
gf_theme_info_get_summary
(
info
),
GF_THEME_COL_DESCRIPTION
,
gf_theme_info_get_description
(
info
),
GF_THEME_COL_AUTHOR
,
gf_theme_info_get_author
(
info
),
GF_THEME_COL_WEBSITE
,
gf_theme_info_get_website
(
info
),
GF_THEME_COL_SUPPORTS
,
supports
,
-1
);
g_free
(
supports
);
if
(
destroy
)
gf_theme_destory
(
theme
);
}
sortable
=
GTK_TREE_SORTABLE
(
store
);
gtk_tree_sortable_set_sort_func
(
sortable
,
GF_THEME_COL_LOADED
,
theme_sort_loaded
,
NULL
,
NULL
);
gtk_tree_sortable_set_sort_func
(
sortable
,
GF_THEME_COL_NAME
,
theme_sort_name
,
NULL
,
NULL
);
gtk_tree_sortable_set_sort_func
(
sortable
,
GF_THEME_COL_SUMMARY
,
theme_sort_summary
,
NULL
,
NULL
);
gtk_tree_sortable_set_sort_column_id
(
sortable
,
GF_THEME_COL_NAME
,
GTK_SORT_ASCENDING
);
return
store
;
}
static
void
theme_list_refresh
()
{
if
(
theme_data
.
tree
)
{
GtkTreeSelection
*
sel
;
GtkTreeIter
iter
;
gtk_tree_view_set_model
(
GTK_TREE_VIEW
(
theme_data
.
tree
),
NULL
);
gtk_list_store_clear
(
theme_data
.
store
);
g_object_unref
(
G_OBJECT
(
theme_data
.
store
));
theme_data
.
store
=
create_theme_store
();
gtk_tree_view_set_model
(
GTK_TREE_VIEW
(
theme_data
.
tree
),
GTK_TREE_MODEL
(
theme_data
.
store
));
gtk_tree_model_get_iter_first
(
GTK_TREE_MODEL
(
theme_data
.
store
),
&
iter
);
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
GTK_TREE_VIEW
(
theme_data
.
tree
)));
gtk_tree_selection_select_iter
(
sel
,
&
iter
);
}
}
static
void
theme_list_refresh_cb
(
GtkWidget
*
w
,
gpointer
data
)
{
gf_preferences_refresh_themes_list
();
}
static
void
theme_list_new_cb
(
GtkWidget
*
w
,
gpointer
data
)
{
gf_theme_editor_show
(
NULL
);
}
static
void
theme_list_edit_cb
(
GtkWidget
*
w
,
gpointer
data
)
{
GtkTreeModel
*
model
;
GtkTreeSelection
*
sel
;
GtkTreeIter
iter
;
gchar
*
filename
;
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
theme_data
.
tree
));
gtk_tree_selection_get_selected
(
sel
,
&
model
,
&
iter
);
gtk_tree_model_get
(
model
,
&
iter
,
GF_THEME_COL_FILE
,
&
filename
,
-1
);
gf_theme_editor_show
(
filename
);
if
(
filename
)
g_free
(
filename
);
}
static
void
theme_list_delete_yes_cb
(
gpointer
data
,
gint
id
)
{
gchar
*
filename
,
*
path
;
filename
=
(
char
*
)
data
;
if
(
filename
)
{
if
(
gf_theme_is_loaded
(
filename
))
gf_theme_unload
(
gf_theme_find_theme_by_filename
(
filename
));
path
=
g_path_get_dirname
(
filename
);
g_free
(
filename
);
gf_file_remove_dir
(
path
);
g_free
(
path
);
gf_preferences_refresh_themes_list
();
}
}
static
void
theme_list_delete_no_cb
(
gpointer
data
,
gint
id
)
{
gchar
*
filename
=
(
char
*
)
data
;
g_free
(
filename
);
}
static
void
theme_list_delete_cb
(
GtkWidget
*
w
,
gpointer
data
)
{
GtkTreeSelection
*
sel
;
GtkTreeModel
*
model
;
GtkTreeIter
iter
;
gchar
*
filename
=
NULL
;
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
theme_data
.
tree
));
if
(
gtk_tree_selection_get_selected
(
sel
,
&
model
,
&
iter
))
gtk_tree_model_get
(
model
,
&
iter
,
GF_THEME_COL_FILE
,
&
filename
,
-1
);
if
(
!
filename
)
return
;
purple_request_yes_no
(
guifications
,
_
(
"Delete theme?"
),
NULL
,
_
(
"Are you sure you want to delete this theme?"
),
0
,
NULL
,
NULL
,
NULL
,
filename
,
G_CALLBACK
(
theme_list_delete_yes_cb
),
G_CALLBACK
(
theme_list_delete_no_cb
));
}
static
void
theme_list_copy_cb
(
GtkWidget
*
w
,
gpointer
data
)
{
GfTheme
*
theme
;
GfThemeInfo
*
info
;
GtkTreeSelection
*
sel
;
GtkTreeModel
*
model
;
GtkTreeIter
iter
;
const
gchar
*
oldname
;
gchar
*
filename
,
*
newname
,
*
fullname
,
*
oldpath
,
*
newpath
,
*
dir
;
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
theme_data
.
tree
));
if
(
gtk_tree_selection_get_selected
(
sel
,
&
model
,
&
iter
))
gtk_tree_model_get
(
model
,
&
iter
,
GF_THEME_COL_FILE
,
&
filename
,
-1
);
if
(
!
filename
)
return
;
theme
=
gf_theme_new_from_file
(
filename
);
if
(
!
theme
)
return
;
info
=
gf_theme_get_theme_info
(
theme
);
oldname
=
gf_theme_info_get_name
(
info
);
if
(
oldname
)
newname
=
g_strdup_printf
(
"%s (copy)"
,
oldname
);
else
newname
=
g_strdup
(
"untitled (copy)"
);
gf_theme_info_set_name
(
info
,
newname
);
g_free
(
newname
);
dir
=
gf_theme_info_strip_name
(
info
);
if
(
!
dir
)
{
gf_theme_destory
(
theme
);
return
;
}
newpath
=
g_build_filename
(
purple_user_dir
(),
"guifications"
,
"themes"
,
dir
,
NULL
);
g_free
(
dir
);
purple_build_dir
(
newpath
,
S_IRUSR
|
S_IWUSR
|
S_IXUSR
);
fullname
=
g_build_filename
(
newpath
,
"theme.xml"
,
NULL
);
/* we copy everything first, and then rewrite theme.xml. Yeah it's not ideal but it
* keeps the code simple.
*/
oldpath
=
g_path_get_dirname
(
filename
);
gf_file_copy_directory
(
oldpath
,
newpath
);
g_free
(
oldpath
);
g_free
(
newpath
);
gf_theme_save_to_file
(
theme
,
fullname
);
g_free
(
fullname
);
theme_list_refresh
();
}
static
void
theme_list_get_more_cb
(
GtkWidget
*
w
,
gpointer
data
)
{
purple_notify_uri
(
NULL
,
"http://sourceforge.net/tracker/?atid=676821&group_id=92888&func=browse"
);
}
static
gboolean
theme_list_clicked_cb
(
GtkWidget
*
w
,
GdkEventButton
*
e
,
gpointer
data
)
{
if
(
e
->
button
==
3
)
{
GtkWidget
*
menu
;
GtkTreeSelection
*
sel
;
GtkTreeModel
*
model
;
GtkTreeIter
iter
;
menu
=
gtk_menu_new
();
pidgin_new_item_from_stock
(
menu
,
_
(
"New"
),
GTK_STOCK_NEW
,
G_CALLBACK
(
theme_list_new_cb
),
NULL
,
0
,
0
,
NULL
);
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
theme_data
.
tree
));
if
(
gtk_tree_selection_get_selected
(
sel
,
&
model
,
&
iter
))
{
gchar
*
filename
;
gtk_tree_model_get
(
model
,
&
iter
,
GF_THEME_COL_FILE
,
&
filename
,
-1
);
if
(
!
gf_file_access
(
filename
,
W_OK
))
{
pidgin_new_item_from_stock
(
menu
,
_
(
"Edit"
),
GTK_STOCK_PREFERENCES
,
G_CALLBACK
(
theme_list_edit_cb
),
sel
,
0
,
0
,
NULL
);
pidgin_new_item_from_stock
(
menu
,
_
(
"Delete"
),
GTK_STOCK_DELETE
,
G_CALLBACK
(
theme_list_delete_cb
),
sel
,
0
,
0
,
NULL
);
}
if
(
filename
)
g_free
(
filename
);
}
pidgin_separator
(
menu
);
pidgin_new_item_from_stock
(
menu
,
_
(
"Refresh"
),
GTK_STOCK_REFRESH
,
G_CALLBACK
(
theme_list_refresh_cb
),
NULL
,
0
,
0
,
NULL
);
gtk_widget_show_all
(
menu
);
gtk_menu_popup
(
GTK_MENU
(
menu
),
NULL
,
NULL
,
NULL
,
NULL
,
3
,
gtk_get_current_event_time
());
return
TRUE
;
}
return
FALSE
;
}
static
void
make_theme_list
(
GtkBox
*
parent
)
{
GtkWidget
*
hbox
,
*
sw
;
GtkCellRenderer
*
renderer
;
GtkTreeSelection
*
sel
;
GtkTreeViewColumn
*
col
;
GtkTargetEntry
te
[
3
]
=
{{
"text/plain"
,
0
,
0
},{
"text/uri-list"
,
0
,
1
},{
"STRING"
,
0
,
2
}};
/* scrolled window and tree */
sw
=
gtk_scrolled_window_new
(
NULL
,
NULL
);
gtk_scrolled_window_set_policy
(
GTK_SCROLLED_WINDOW
(
sw
),
GTK_POLICY_AUTOMATIC
,
GTK_POLICY_AUTOMATIC
);
gtk_scrolled_window_set_shadow_type
(
GTK_SCROLLED_WINDOW
(
sw
),
GTK_SHADOW_IN
);
gtk_box_pack_start
(
parent
,
sw
,
TRUE
,
TRUE
,
0
);
theme_data
.
store
=
create_theme_store
();
theme_data
.
tree
=
gtk_tree_view_new_with_model
(
GTK_TREE_MODEL
(
theme_data
.
store
));
gtk_tree_view_set_rules_hint
(
GTK_TREE_VIEW
(
theme_data
.
tree
),
TRUE
);
gtk_widget_set_size_request
(
theme_data
.
tree
,
-1
,
150
);
gtk_container_add
(
GTK_CONTAINER
(
sw
),
theme_data
.
tree
);
g_signal_connect
(
G_OBJECT
(
theme_data
.
tree
),
"button-press-event"
,
G_CALLBACK
(
theme_list_clicked_cb
),
NULL
);
gtk_drag_dest_set
(
theme_data
.
tree
,
GTK_DEST_DEFAULT_MOTION
|
GTK_DEST_DEFAULT_HIGHLIGHT
|
GTK_DEST_DEFAULT_DROP
,
te
,
sizeof
(
te
)
/
sizeof
(
GtkTargetEntry
)
,
GDK_ACTION_COPY
|
GDK_ACTION_MOVE
);
g_signal_connect
(
G_OBJECT
(
theme_data
.
tree
),
"drag_data_received"
,
G_CALLBACK
(
theme_dnd_recv
),
theme_data
.
store
);
renderer
=
gtk_cell_renderer_toggle_new
();
g_signal_connect
(
G_OBJECT
(
renderer
),
"toggled"
,
G_CALLBACK
(
theme_load_cb
),
NULL
);
col
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Loaded"
),
renderer
,
"active"
,
GF_THEME_COL_LOADED
,
NULL
);
gtk_tree_view_column_set_sort_column_id
(
col
,
GF_THEME_COL_LOADED
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
theme_data
.
tree
),
col
);
renderer
=
gtk_cell_renderer_text_new
();
col
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Name"
),
renderer
,
"text"
,
GF_THEME_COL_NAME
,
NULL
);
gtk_tree_view_column_set_sort_column_id
(
col
,
GF_THEME_COL_NAME
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
theme_data
.
tree
),
col
);
renderer
=
gtk_cell_renderer_text_new
();
col
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Summary"
),
renderer
,
"text"
,
GF_THEME_COL_SUMMARY
,
NULL
);
gtk_tree_view_column_set_sort_column_id
(
col
,
GF_THEME_COL_SUMMARY
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
theme_data
.
tree
),
col
);
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
theme_data
.
tree
));
g_signal_connect
(
G_OBJECT
(
sel
),
"changed"
,
G_CALLBACK
(
theme_list_selection_cb
),
NULL
);
/* the new, edit, delete, refresh buttons and get more buttons */
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
parent
),
hbox
,
FALSE
,
FALSE
,
0
);
theme_data
.
theme_new
=
gtk_button_new_from_stock
(
GTK_STOCK_NEW
);
gtk_button_set_relief
(
GTK_BUTTON
(
theme_data
.
theme_new
),
GTK_RELIEF_NONE
);
g_signal_connect
(
G_OBJECT
(
theme_data
.
theme_new
),
"clicked"
,
G_CALLBACK
(
theme_list_new_cb
),
NULL
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_data
.
theme_new
,
FALSE
,
FALSE
,
0
);
theme_data
.
theme_edit
=
pidgin_pixbuf_button_from_stock
(
_
(
"_Edit"
),
GTK_STOCK_PREFERENCES
,
PIDGIN_BUTTON_HORIZONTAL
);
gtk_button_set_relief
(
GTK_BUTTON
(
theme_data
.
theme_edit
),
GTK_RELIEF_NONE
);
gtk_widget_set_sensitive
(
theme_data
.
theme_edit
,
FALSE
);
g_signal_connect
(
G_OBJECT
(
theme_data
.
theme_edit
),
"clicked"
,
G_CALLBACK
(
theme_list_edit_cb
),
NULL
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_data
.
theme_edit
,
FALSE
,
FALSE
,
0
);
theme_data
.
theme_delete
=
gtk_button_new_from_stock
(
GTK_STOCK_DELETE
);
gtk_button_set_relief
(
GTK_BUTTON
(
theme_data
.
theme_delete
),
GTK_RELIEF_NONE
);
gtk_widget_set_sensitive
(
theme_data
.
theme_delete
,
FALSE
);
g_signal_connect
(
G_OBJECT
(
theme_data
.
theme_delete
),
"clicked"
,
G_CALLBACK
(
theme_list_delete_cb
),
NULL
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_data
.
theme_delete
,
FALSE
,
FALSE
,
0
);
theme_data
.
theme_copy
=
gtk_button_new_from_stock
(
GTK_STOCK_COPY
);
gtk_button_set_relief
(
GTK_BUTTON
(
theme_data
.
theme_copy
),
GTK_RELIEF_NONE
);
gtk_widget_set_sensitive
(
theme_data
.
theme_copy
,
FALSE
);
g_signal_connect
(
G_OBJECT
(
theme_data
.
theme_copy
),
"clicked"
,
G_CALLBACK
(
theme_list_copy_cb
),
NULL
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_data
.
theme_copy
,
FALSE
,
FALSE
,
0
);
theme_data
.
theme_refresh
=
gtk_button_new_from_stock
(
GTK_STOCK_REFRESH
);
gtk_button_set_relief
(
GTK_BUTTON
(
theme_data
.
theme_refresh
),
GTK_RELIEF_NONE
);
g_signal_connect
(
G_OBJECT
(
theme_data
.
theme_refresh
),
"clicked"
,
G_CALLBACK
(
theme_list_refresh_cb
),
NULL
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_data
.
theme_refresh
,
FALSE
,
FALSE
,
0
);
theme_data
.
theme_get_more
=
pidgin_pixbuf_button_from_stock
(
_
(
"_Get More"
),
GTK_STOCK_JUMP_TO
,
PIDGIN_BUTTON_HORIZONTAL
);
gtk_button_set_relief
(
GTK_BUTTON
(
theme_data
.
theme_get_more
),
GTK_RELIEF_NONE
);
g_signal_connect
(
G_OBJECT
(
theme_data
.
theme_get_more
),
"clicked"
,
G_CALLBACK
(
theme_list_get_more_cb
),
NULL
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_data
.
theme_get_more
,
FALSE
,
FALSE
,
0
);
gtk_widget_show_all
(
sw
);
}
static
void
make_theme_page
(
GtkWidget
*
notebook
)
{
GtkWidget
*
sw
,
*
vp
,
*
mbox
,
*
vbox
,
*
hbox
,
*
label
;
GtkSizeGroup
*
sg
;
mbox
=
make_notebook_page
(
GTK_NOTEBOOK
(
notebook
),
_
(
"Themes"
),
-1
);
make_theme_list
(
GTK_BOX
(
mbox
));
sw
=
gtk_scrolled_window_new
(
NULL
,
NULL
);
gtk_scrolled_window_set_policy
(
GTK_SCROLLED_WINDOW
(
sw
),
GTK_POLICY_NEVER
,
GTK_POLICY_AUTOMATIC
);
gtk_scrolled_window_set_shadow_type
(
GTK_SCROLLED_WINDOW
(
sw
),
GTK_SHADOW_IN
);
gtk_box_pack_start
(
GTK_BOX
(
mbox
),
sw
,
TRUE
,
TRUE
,
0
);
vp
=
gtk_viewport_new
(
NULL
,
NULL
);
gtk_viewport_set_shadow_type
(
GTK_VIEWPORT
(
vp
),
GTK_SHADOW_NONE
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
vp
),
4
);
gtk_container_add
(
GTK_CONTAINER
(
sw
),
vp
);
vbox
=
gtk_vbox_new
(
FALSE
,
0
);
gtk_container_add
(
GTK_CONTAINER
(
vp
),
vbox
);
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
/* name */
hbox
=
gtk_hbox_new
(
FALSE
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
label
=
make_bold_label
(
_
(
"Name"
),
sg
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
theme_info_pane
.
theme_name
=
make_label
(
NULL
,
NULL
);
gtk_label_set_line_wrap
(
GTK_LABEL
(
theme_info_pane
.
theme_name
),
TRUE
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_info_pane
.
theme_name
,
FALSE
,
FALSE
,
0
);
/* version */
hbox
=
gtk_hbox_new
(
FALSE
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
label
=
make_bold_label
(
_
(
"Version"
),
sg
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
theme_info_pane
.
theme_version
=
make_label
(
NULL
,
NULL
);
gtk_label_set_line_wrap
(
GTK_LABEL
(
theme_info_pane
.
theme_version
),
TRUE
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_info_pane
.
theme_version
,
FALSE
,
FALSE
,
0
);
/* description */
hbox
=
gtk_hbox_new
(
FALSE
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
label
=
make_bold_label
(
_
(
"Description"
),
sg
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
theme_info_pane
.
theme_description
=
make_label
(
NULL
,
NULL
);
gtk_label_set_line_wrap
(
GTK_LABEL
(
theme_info_pane
.
theme_description
),
TRUE
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_info_pane
.
theme_description
,
FALSE
,
FALSE
,
0
);
/* author */
hbox
=
gtk_hbox_new
(
FALSE
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
label
=
make_bold_label
(
_
(
"Author"
),
sg
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
theme_info_pane
.
theme_author
=
make_label
(
NULL
,
NULL
);
gtk_label_set_line_wrap
(
GTK_LABEL
(
theme_info_pane
.
theme_author
),
TRUE
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_info_pane
.
theme_author
,
FALSE
,
FALSE
,
0
);
/* website */
hbox
=
gtk_hbox_new
(
FALSE
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
label
=
make_bold_label
(
_
(
"Website"
),
sg
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
theme_info_pane
.
theme_website
=
make_label
(
NULL
,
NULL
);
gtk_label_set_line_wrap
(
GTK_LABEL
(
theme_info_pane
.
theme_website
),
TRUE
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_info_pane
.
theme_website
,
FALSE
,
FALSE
,
0
);
/* supports */
hbox
=
gtk_hbox_new
(
FALSE
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
label
=
make_bold_label
(
_
(
"Supports"
),
sg
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
theme_info_pane
.
theme_supports
=
make_label
(
NULL
,
NULL
);
gtk_label_set_line_wrap
(
GTK_LABEL
(
theme_info_pane
.
theme_supports
),
TRUE
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_info_pane
.
theme_supports
,
FALSE
,
FALSE
,
0
);
/* filename */
hbox
=
gtk_hbox_new
(
FALSE
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
label
=
make_bold_label
(
_
(
"Filename"
),
sg
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
theme_info_pane
.
theme_filename
=
make_label
(
NULL
,
NULL
);
gtk_label_set_line_wrap
(
GTK_LABEL
(
theme_info_pane
.
theme_filename
),
TRUE
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
theme_info_pane
.
theme_filename
,
FALSE
,
FALSE
,
0
);
/* show it already */
gtk_widget_show_all
(
mbox
);
}
/*******************************************************************************
* Advanced page stuff
******************************************************************************/
static
void
make_advanced_page
(
GtkWidget
*
notebook
)
{
GtkWidget
*
vbox
,
*
frame
;
GtkSizeGroup
*
sg
;
#if GTK_CHECK_VERSION(2,2,0)
gint
screen_count
,
monitor_count
;
#endif
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
vbox
=
make_notebook_page
(
GTK_NOTEBOOK
(
notebook
),
_
(
"Advanced"
),
-1
);
frame
=
pidgin_make_frame
(
vbox
,
_
(
"Display Options"
));
pidgin_prefs_labeled_spin_button
(
frame
,
_
(
"Max _Visible Guifications:"
),
GF_PREF_BEHAVIOR_THROTTLE
,
0
,
255
,
sg
);
#if GTK_CHECK_VERSION(2,2,0)
screen_count
=
gf_display_get_screen_count
();
monitor_count
=
gf_display_get_monitor_count
();
if
(
screen_count
>
0
||
monitor_count
>
0
)
{
frame
=
pidgin_make_frame
(
vbox
,
_
(
"Placement"
));
if
(
screen_count
>
0
)
{
pidgin_prefs_labeled_spin_button
(
frame
,
_
(
"Show notifications on _screen:"
),
GF_PREF_ADVANCED_SCREEN
,
0
,
screen_count
,
sg
);
}
if
(
monitor_count
>
0
)
{
pidgin_prefs_labeled_spin_button
(
frame
,
_
(
"Show notifications on _monitor:"
),
GF_PREF_ADVANCED_MONITOR
,
0
,
monitor_count
,
sg
);
}
}
#endif
/* GTK_CHECK_VERSION(2,2,0) */
gtk_widget_show_all
(
vbox
);
}
/*******************************************************************************
* Callbacks
******************************************************************************/
static
void
gf_preferences_notebook_destroy_cb
(
GtkObject
*
obj
,
gpointer
data
)
{
theme_data
.
tree
=
NULL
;
}
/*******************************************************************************
* exports
******************************************************************************/
GtkWidget
*
gf_preferences_get_frame
(
PurplePlugin
*
plugin
)
{
GtkWidget
*
notebook
;
guifications
=
plugin
;
notebook
=
gtk_notebook_new
();
g_signal_connect
(
GTK_OBJECT
(
notebook
),
"destroy"
,
G_CALLBACK
(
gf_preferences_notebook_destroy_cb
),
NULL
);
gtk_widget_show
(
notebook
);
make_general_page
(
notebook
);
make_notifications_page
(
notebook
);
make_theme_page
(
notebook
);
make_advanced_page
(
notebook
);
return
notebook
;
}
void
gf_preferences_refresh_themes_list
()
{
theme_list_refresh
();
}
void
gf_preferences_add
()
{
GList
*
l
=
NULL
;
gchar
*
def_theme
=
NULL
;
purple_prefs_add_none
(
GF_PREF_ROOT
);
purple_prefs_add_none
(
GF_PREF_PLUGIN_ROOT
);
purple_prefs_add_none
(
GF_PREF_BEHAVIOR_ROOT
);
purple_prefs_add_int
(
GF_PREF_BEHAVIOR_DISPLAY_TIME
,
6
);
purple_prefs_add_int
(
GF_PREF_BEHAVIOR_THROTTLE
,
6
);
purple_prefs_add_bool
(
GF_PREF_BEHAVIOR_SHOW_WHILE_AWAY
,
TRUE
);
purple_prefs_add_none
(
GF_PREF_APPEARANCE_ROOT
);
purple_prefs_add_int
(
GF_PREF_APPEARANCE_POSITION
,
GF_DISPLAY_POSITION_SE
);
purple_prefs_add_bool
(
GF_PREF_APPEARANCE_VERTICAL
,
TRUE
);
purple_prefs_add_bool
(
GF_PREF_APPEARANCE_ANIMATE
,
TRUE
);
purple_prefs_add_none
(
GF_PREF_MOUSE_ROOT
);
purple_prefs_add_string
(
GF_PREF_MOUSE_LEFT
,
"open"
);
purple_prefs_add_string
(
GF_PREF_MOUSE_MIDDLE
,
"close"
);
purple_prefs_add_string
(
GF_PREF_MOUSE_RIGHT
,
"context"
);
def_theme
=
g_build_filename
(
DATADIR
,
"pixmaps"
,
"pidgin"
,
"guifications"
,
"themes"
,
"default"
,
"theme.xml"
,
NULL
);
l
=
g_list_append
(
l
,
def_theme
);
purple_prefs_add_string_list
(
GF_PREF_LOADED_THEMES
,
l
);
g_free
(
def_theme
);
g_list_free
(
l
);
purple_prefs_add_none
(
GF_PREF_ADVANCED_ROOT
);
purple_prefs_add_bool
(
GF_PREF_ADVANCED_RELEASE_NOTIFICATION
,
TRUE
);
purple_prefs_add_int
(
GF_PREF_ADVANCED_RELEASE_LAST_CHECK
,
0
);
#if GTK_CHECK_VERSION(2,2,0)
purple_prefs_add_int
(
GF_PREF_ADVANCED_SCREEN
,
0
);
purple_prefs_add_int
(
GF_PREF_ADVANCED_MONITOR
,
0
);
if
(
purple_prefs_get_int
(
GF_PREF_ADVANCED_SCREEN
)
>
gf_display_get_screen_count
())
{
purple_prefs_set_int
(
GF_PREF_ADVANCED_SCREEN
,
gf_display_get_default_screen
());
}
if
(
purple_prefs_get_int
(
GF_PREF_ADVANCED_MONITOR
)
>
gf_display_get_monitor_count
())
{
purple_prefs_set_int
(
GF_PREF_ADVANCED_MONITOR
,
gf_display_get_default_monitor
());
}
#endif
/* GTK_CHECK_VERSION(2,2,0) */
/* clean up old prefs if they exist */
purple_prefs_remove
(
"/plugins/gtk/amc_grim/guifications2/behavior/show_during_screen_saver"
);
purple_prefs_remove
(
"/plugins/gtk/amc_grim/guifications2/appearance/h_offset"
);
purple_prefs_remove
(
"/plugins/gtk/amc_grim/guifications2/appearance/v_offset"
);
purple_prefs_remove
(
"/plugins/gtk/amc_grim/guifications2/appearance/zoom"
);
purple_prefs_remove
(
"/plugins/gtk/amc_grim/guifications2/appearance/show_contacts"
);
purple_prefs_remove
(
"/plugins/gtk/amc_grim/guifications2/appearance/alias"
);
purple_prefs_remove
(
"/plugins/gtk/amc_grim/guifications2/advanced/sign_on_delay"
);
purple_prefs_remove
(
"/plugins/gtk/amc_grim/guifications2/advanced/hide_joinleave"
);
purple_prefs_remove
(
"/plugins/gtk/amc_grim/guifications2/advanced/hide_conv_focused"
);
}