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-2011 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.
*/
#ifdef HAVE_CONFIG_H
#
include
"../gf_config.h"
#endif
#include
<glib.h>
#include
<gtk/gtk.h>
#include
<sys/stat.h>
#include
<sys/types.h>
#include
<string.h>
#include
"gf_internal.h"
#define PURPLE_PLUGINS
#include
<debug.h>
#include
<pidgin.h>
#include
<notify.h>
#include
<plugin.h>
#include
<request.h>
#include
<signals.h>
#include
<util.h>
#include
<gtkplugin.h>
#include
"gf_event.h"
#include
"gf_file.h"
#include
"gf_item.h"
#include
"gf_item_icon.h"
#include
"gf_item_image.h"
#include
"gf_item_offset.h"
#include
"gf_item_text.h"
#include
"gf_menu.h"
#include
"gf_notification.h"
#include
"gf_preferences.h"
#include
"gf_theme.h"
#include
"gf_theme_editor.h"
#include
"gf_theme_info.h"
#include
"gf_theme_ops.h"
#include
"gf_utils.h"
/* Okay, heres the run down of how all of this works.
*
* The theme is loaded and then converted into a GtkTreeStore. The store holds,
* the title of what to display in the tree view, as well as what page to
* display when it's selected, as well as the object itself.
*
* The getters and setters are added as data to the widget at creation time.
* This way when we hit the callback, we grab the item from the store, and pop
* it into the getter or setter function, update accordingly, and go about our
* business.
*
*/
enum
{
GFTE_STORE_TITLE
=
0
,
GFTE_STORE_PAGE
,
GFTE_STORE_OBJECT
,
GFTE_STORE_TOTAL
};
enum
{
GFTE_PAGE_THEME
=
0
,
GFTE_PAGE_INFO
,
GFTE_PAGE_OPS
,
GFTE_PAGE_NOTIFICATION
,
GFTE_PAGE_ICON
,
GFTE_PAGE_IMAGE
,
GFTE_PAGE_TEXT
,
GFTE_PAGE_TOTAL
};
enum
{
GFTE_FLAGS_OBJECT
=
0
,
GFTE_FLAGS_SUB_OBJECT
,
GFTE_FLAGS_H_OFFSET
,
GFTE_FLAGS_V_OFFSET
,
GFTE_FLAGS_TOTAL
};
enum
{
GFTE_MODIFIED_CLOSE
=
0
,
GFTE_MODIFIED_NEW
,
GFTE_MODIFIED_OPEN
,
GFTE_MODIFIED_TOTAL
};
enum
{
GFTE_BUTTON_FILE
=
0
,
GFTE_BUTTON_FONT
,
GFTE_BUTTON_COLOR
,
GFTE_BUTTON_TOTAL
};
struct
GfThemeEditorInfo
{
GtkWidget
*
name
;
GtkWidget
*
version
;
GtkWidget
*
summary
;
GtkWidget
*
description
;
GtkWidget
*
author
;
GtkWidget
*
website
;
};
struct
GfThemeEditorOps
{
GtkWidget
*
time_format
;
GtkWidget
*
date_format
;
GtkWidget
*
warning
;
GtkWidget
*
ellipsis
;
};
struct
GfThemeEditorNotification
{
GtkWidget
*
alias
;
GtkWidget
*
use_gtk
;
GtkWidget
*
filename
;
GtkWidget
*
button
;
GtkWidget
*
width
;
GtkWidget
*
height
;
};
struct
GfThemeEditorItem
{
GtkWidget
*
position
;
GtkWidget
*
h_offset
;
GtkWidget
*
h_offset_p
;
GtkWidget
*
v_offset
;
GtkWidget
*
v_offset_p
;
};
struct
GfThemeEditorIcon
{
struct
GfThemeEditorItem
item
;
GtkWidget
*
type
;
GtkWidget
*
size
;
};
struct
GfThemeEditorImage
{
struct
GfThemeEditorItem
item
;
GtkWidget
*
filename
;
GtkWidget
*
button
;
};
struct
GfThemeEditorText
{
struct
GfThemeEditorItem
item
;
GtkWidget
*
format
;
GtkWidget
*
width
;
GtkWidget
*
clipping
;
GtkWidget
*
font
;
GtkWidget
*
color
;
};
struct
GfThemeEditor
{
GfTheme
*
theme
;
gchar
*
filename
;
gchar
*
path
;
gboolean
changed
;
/* toolbar stuff */
GtkTooltips
*
tooltips
;
GtkWidget
*
tool_notification
;
GtkWidget
*
tool_item
;
GtkWidget
*
tool_copy
;
GtkWidget
*
tool_delete
;
GtkWidget
*
tool_up
;
GtkWidget
*
tool_down
;
/* main stuff */
GtkWidget
*
window
;
GtkWidget
*
vbox
;
GtkWidget
*
hbox
;
GtkWidget
*
tree
;
GtkWidget
*
note
;
GtkTreeStore
*
store
;
/* everything else */
struct
GfThemeEditorInfo
info
;
struct
GfThemeEditorOps
ops
;
struct
GfThemeEditorNotification
notification
;
struct
GfThemeEditorIcon
icon
;
struct
GfThemeEditorImage
image
;
struct
GfThemeEditorText
text
;
};
struct
GfteModified
{
GtkWidget
*
window
;
gint
type
;
gchar
*
filename
;
};
struct
GfteDelete
{
GtkWidget
*
window
;
};
struct
GfteNewNotification
{
GtkWidget
*
window
;
GtkWidget
*
type
;
};
struct
GfteNewItem
{
GtkWidget
*
window
;
GtkWidget
*
type
;
};
typedef
void
(
*
GfteSetFunc
)(
gpointer
obj
,
gconstpointer
val
);
typedef
gconstpointer
(
*
GfteGetFunc
)(
gpointer
obj
);
/*******************************************************************************
* Prototypes ICK!
******************************************************************************/
static
void
gfte_selection_changed_cb
(
GtkTreeSelection
*
sel
,
gpointer
data
);
/*******************************************************************************
* Globals
******************************************************************************/
PurplePlugin
*
plugin_handle
=
NULL
;
gpointer
image_dialog
=
NULL
;
GtkWidget
*
opt_dialog
=
NULL
;
struct
GfThemeEditor
editor
;
struct
GfteModified
modified
;
struct
GfteDelete
del_obj
;
struct
GfteNewNotification
new_notification
;
struct
GfteNewItem
new_item
;
/*******************************************************************************
* Toolbar button stuff
******************************************************************************/
static
void
gfte_toolbar_buttons_update
(
gboolean
item
,
gboolean
copy
,
gboolean
delete
,
gboolean
up
,
gboolean
down
)
{
gtk_widget_set_sensitive
(
editor
.
tool_item
,
item
);
gtk_widget_set_sensitive
(
editor
.
tool_copy
,
copy
);
gtk_widget_set_sensitive
(
editor
.
tool_delete
,
delete
);
gtk_widget_set_sensitive
(
editor
.
tool_up
,
up
);
gtk_widget_set_sensitive
(
editor
.
tool_down
,
down
);
}
/*******************************************************************************
* Main stuff thats used all over the place
******************************************************************************/
static
void
gfte_remove_temp
()
{
gchar
*
name
;
if
(
!
editor
.
path
)
return
;
name
=
g_path_get_basename
(
editor
.
path
);
if
(
name
&&
name
[
0
]
==
'.'
)
gf_file_remove_dir
(
editor
.
path
);
g_free
(
name
);
}
static
void
gfte_save_theme
()
{
gchar
*
path
,
*
oldpath
,
*
dir
;
gboolean
loaded
;
loaded
=
gf_theme_is_loaded
(
editor
.
filename
);
if
(
loaded
)
{
GfTheme
*
theme
=
gf_theme_find_theme_by_filename
(
editor
.
filename
);
if
(
theme
)
gf_theme_unload
(
theme
);
}
gf_theme_save_to_file
(
editor
.
theme
,
editor
.
filename
);
dir
=
gf_theme_strip_name
(
editor
.
theme
);
oldpath
=
g_path_get_dirname
(
editor
.
path
);
/* ok, because windows is retarded, and everyone can edit everything, we get to take
* the editor's path, remove the last part of it, and then attach the new dir name to
* it.
*/
path
=
g_build_filename
(
oldpath
,
dir
,
NULL
);
g_free
(
oldpath
);
g_free
(
dir
);
/* move the dir */
g_rename
(
editor
.
path
,
path
);
/* update the editor's path */
g_free
(
editor
.
path
);
editor
.
path
=
path
;
/* update the editor's file */
g_free
(
editor
.
filename
);
editor
.
filename
=
g_build_filename
(
editor
.
path
,
"theme.xml"
,
NULL
);
/* reprobe the theme and tell the prefs to refresh it.. */
gf_theme_probe
(
editor
.
filename
);
if
(
loaded
)
{
gf_theme_load
(
editor
.
filename
);
gf_themes_save_loaded
();
}
gf_preferences_refresh_themes_list
();
editor
.
changed
=
FALSE
;
}
static
void
gfte_store_add
(
GtkTreeStore
*
store
,
GtkTreeIter
*
child
,
GtkTreeIter
*
parent
,
const
gchar
*
title
,
gint
page
,
gpointer
data
)
{
gtk_tree_store_append
(
store
,
child
,
parent
);
gtk_tree_store_set
(
store
,
child
,
GFTE_STORE_TITLE
,
title
,
GFTE_STORE_PAGE
,
page
,
GFTE_STORE_OBJECT
,
data
,
-1
);
}
static
GtkTreeStore
*
gfte_store_update
()
{
GfThemeInfo
*
info
;
GfThemeOptions
*
ops
;
GfEvent
*
event
;
GfNotification
*
notification
;
GfItem
*
item
;
GtkTreeStore
*
store
;
GtkTreeIter
parent
,
child
,
iter
;
GList
*
n
,
*
i
;
store
=
gtk_tree_store_new
(
GFTE_STORE_TOTAL
,
G_TYPE_STRING
,
G_TYPE_INT
,
G_TYPE_POINTER
);
/* theme */
gfte_store_add
(
store
,
&
parent
,
NULL
,
_
(
"Theme"
),
GFTE_PAGE_THEME
,
editor
.
theme
);
/* info */
info
=
gf_theme_get_theme_info
(
editor
.
theme
);
gfte_store_add
(
store
,
&
child
,
&
parent
,
_
(
"Info"
),
GFTE_PAGE_INFO
,
info
);
/* options */
ops
=
gf_theme_get_theme_options
(
editor
.
theme
);
gfte_store_add
(
store
,
&
child
,
&
parent
,
_
(
"Options"
),
GFTE_PAGE_OPS
,
ops
);
/* notifications */
for
(
n
=
gf_theme_get_notifications
(
editor
.
theme
);
n
;
n
=
n
->
next
)
{
const
gchar
*
alias
=
NULL
,
*
name
=
NULL
;
notification
=
GF_NOTIFICATION
(
n
->
data
);
if
((
alias
=
gf_notification_get_alias
(
notification
)))
name
=
alias
;
else
{
const
gchar
*
type
;
type
=
gf_notification_get_type
(
notification
);
event
=
gf_event_find_for_notification
(
type
);
name
=
gf_event_get_name
(
event
);
}
gfte_store_add
(
store
,
&
child
,
&
parent
,
name
,
GFTE_PAGE_NOTIFICATION
,
notification
);
/* items */
for
(
i
=
gf_notification_get_items
(
notification
);
i
;
i
=
i
->
next
)
{
GfItemType
type
;
gint
page
=
-1
;
item
=
GF_ITEM
(
i
->
data
);
type
=
gf_item_get_type
(
item
);
switch
(
type
)
{
case
GF_ITEM_TYPE_ICON
:
page
=
GFTE_PAGE_ICON
;
break
;
case
GF_ITEM_TYPE_IMAGE
:
page
=
GFTE_PAGE_IMAGE
;
break
;
case
GF_ITEM_TYPE_TEXT
:
page
=
GFTE_PAGE_TEXT
;
break
;
case
GF_ITEM_TYPE_UNKNOWN
:
default
:
break
;
}
if
(
page
==
-1
)
continue
;
gfte_store_add
(
store
,
&
iter
,
&
child
,
gf_item_type_to_string
(
type
,
TRUE
),
page
,
item
);
}
}
return
store
;
}
/* This was yanked from gtk 2.4.x, it's a wrapper to support this function on gtk 2.0 */
static
void
gfte_tree_view_expand_to_path
(
GtkTreeView
*
tree
,
GtkTreePath
*
path
)
{
#if GTK_CHECK_VERSION(2,2,0)
gtk_tree_view_expand_to_path
(
tree
,
path
);
#else
gint
i
,
depth
;
gint
*
indices
;
GtkTreePath
*
tmp
;
g_return_if_fail
(
GTK_IS_TREE_VIEW
(
tree
));
g_return_if_fail
(
path
!=
NULL
);
depth
=
gtk_tree_path_get_depth
(
path
);
indices
=
gtk_tree_path_get_indices
(
path
);
tmp
=
gtk_tree_path_new
();
g_return_if_fail
(
tmp
!=
NULL
);
for
(
i
=
0
;
i
<
depth
;
i
++
)
{
gtk_tree_path_append_index
(
tmp
,
indices
[
i
]);
gtk_tree_view_expand_row
(
tree
,
tmp
,
FALSE
);
}
gtk_tree_path_free
(
tmp
);
#endif
/* GTK 2.0 */
}
static
void
gfte_store_select_iter
(
GtkTreeIter
*
iter
)
{
GtkTreeModel
*
model
;
GtkTreeSelection
*
sel
;
GtkTreePath
*
path
;
model
=
gtk_tree_view_get_model
(
GTK_TREE_VIEW
(
editor
.
tree
));
path
=
gtk_tree_model_get_path
(
model
,
iter
);
gfte_tree_view_expand_to_path
(
GTK_TREE_VIEW
(
editor
.
tree
),
path
);
gtk_tree_path_free
(
path
);
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
editor
.
tree
));
gtk_tree_selection_select_iter
(
sel
,
iter
);
}
static
gchar
*
gfte_make_temp_dir
()
{
gchar
*
path
,
*
dir
;
dir
=
g_strdup_printf
(
".%x"
,
g_random_int
());
path
=
g_build_filename
(
purple_user_dir
(),
"guifications"
,
"themes"
,
dir
,
NULL
);
g_free
(
dir
);
g_mkdir
(
path
,
S_IRUSR
|
S_IWUSR
|
S_IXUSR
);
return
path
;
}
void
gfte_setup
(
const
gchar
*
filename
)
{
GfTheme
*
old
=
editor
.
theme
;
if
(
filename
)
{
GfNotification
*
notification
;
GList
*
l
;
editor
.
theme
=
gf_theme_new_from_file
(
filename
);
for
(
l
=
gf_theme_get_notifications
(
editor
.
theme
);
l
;
l
=
l
->
next
)
{
notification
=
GF_NOTIFICATION
(
l
->
data
);
}
}
else
{
GfNotification
*
master
=
NULL
;
editor
.
theme
=
gf_theme_new
();
gf_theme_set_theme_info
(
editor
.
theme
,
gf_theme_info_new
());
gf_theme_set_theme_options
(
editor
.
theme
,
gf_theme_options_new
());
master
=
gf_notification_new
(
editor
.
theme
);
gf_notification_set_type
(
master
,
GF_NOTIFICATION_MASTER
);
gf_theme_add_notification
(
editor
.
theme
,
master
);
}
if
(
editor
.
theme
)
{
if
(
old
)
gf_theme_unload
(
old
);
old
=
NULL
;
}
else
{
editor
.
theme
=
old
;
return
;
}
gfte_remove_temp
();
if
(
editor
.
filename
)
g_free
(
editor
.
filename
);
if
(
filename
)
{
editor
.
filename
=
g_strdup
(
filename
);
}
else
{
gchar
*
path
=
NULL
;
path
=
gfte_make_temp_dir
();
editor
.
filename
=
g_build_filename
(
path
,
"theme.xml"
,
NULL
);
g_free
(
path
);
}
if
(
editor
.
path
)
g_free
(
editor
.
path
);
editor
.
path
=
g_path_get_dirname
(
editor
.
filename
);
if
(
editor
.
store
)
{
gtk_tree_view_set_model
(
GTK_TREE_VIEW
(
editor
.
tree
),
NULL
);
g_object_unref
(
G_OBJECT
(
editor
.
store
));
}
editor
.
store
=
gfte_store_update
();
if
(
editor
.
window
)
{
GtkTreeIter
iter
;
gtk_tree_view_set_model
(
GTK_TREE_VIEW
(
editor
.
tree
),
GTK_TREE_MODEL
(
editor
.
store
));
gtk_tree_view_expand_all
(
GTK_TREE_VIEW
(
editor
.
tree
));
gtk_tree_model_get_iter_first
(
GTK_TREE_MODEL
(
editor
.
store
),
&
iter
);
gfte_store_select_iter
(
&
iter
);
}
editor
.
changed
=
FALSE
;
}
static
void
gfte_dialog_cleanup
()
{
if
(
del_obj
.
window
)
{
gtk_widget_destroy
(
del_obj
.
window
);
del_obj
.
window
=
NULL
;
}
if
(
new_notification
.
window
)
{
gtk_widget_destroy
(
new_notification
.
window
);
new_notification
.
window
=
NULL
;
}
if
(
new_item
.
window
)
{
gtk_widget_destroy
(
new_item
.
window
);
new_item
.
window
=
NULL
;
}
if
(
modified
.
window
)
{
gtk_widget_destroy
(
modified
.
window
);
modified
.
window
=
NULL
;
if
(
modified
.
filename
)
g_free
(
modified
.
filename
);
modified
.
filename
=
NULL
;
}
if
(
image_dialog
)
{
purple_request_close
(
PURPLE_REQUEST_FILE
,
image_dialog
);
image_dialog
=
NULL
;
}
if
(
opt_dialog
)
{
gtk_widget_destroy
(
opt_dialog
);
opt_dialog
=
NULL
;
}
}
static
void
gfte_cleanup
()
{
gfte_dialog_cleanup
();
editor
.
window
=
NULL
;
if
(
editor
.
theme
)
gf_theme_unload
(
editor
.
theme
);
editor
.
theme
=
NULL
;
if
(
editor
.
filename
)
g_free
(
editor
.
filename
);
editor
.
filename
=
NULL
;
if
(
editor
.
path
)
{
gchar
*
dir
=
NULL
;
dir
=
g_path_get_basename
(
editor
.
path
);
if
(
dir
&&
dir
[
0
]
==
'.'
)
{
gf_file_remove_dir
(
editor
.
path
);
g_free
(
dir
);
}
g_free
(
editor
.
path
);
}
editor
.
path
=
NULL
;
if
(
editor
.
store
)
g_object_unref
(
G_OBJECT
(
editor
.
store
));
editor
.
store
=
NULL
;
if
(
editor
.
tooltips
)
g_object_unref
(
G_OBJECT
(
editor
.
tooltips
));
editor
.
tooltips
=
NULL
;
}
/*******************************************************************************
* new/delete helpers
******************************************************************************/
static
gpointer
gfte_store_get_row
(
GtkTreeIter
*
iter
,
gint
*
page
,
gchar
**
title
)
{
GtkTreeModel
*
model
;
GtkTreeSelection
*
sel
;
gpointer
object
;
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
editor
.
tree
));
if
(
!
gtk_tree_selection_get_selected
(
sel
,
&
model
,
iter
))
return
NULL
;
gtk_tree_model_get
(
model
,
iter
,
GFTE_STORE_OBJECT
,
&
object
,
GFTE_STORE_PAGE
,
page
,
GFTE_STORE_TITLE
,
title
,
-1
);
return
object
;
}
/*******************************************************************************
* modified dialog stuff
******************************************************************************/
static
gboolean
gfte_modified_deleted_cb
(
GtkWidget
*
w
,
GdkEvent
*
e
,
gpointer
data
)
{
modified
.
window
=
NULL
;
if
(
modified
.
filename
)
g_free
(
modified
.
filename
);
modified
.
filename
=
NULL
;
return
FALSE
;
}
static
void
gfte_modified_cancel_cb
(
GtkButton
*
button
,
gpointer
data
)
{
gtk_widget_destroy
(
modified
.
window
);
modified
.
window
=
NULL
;
if
(
modified
.
filename
)
g_free
(
modified
.
filename
);
modified
.
filename
=
NULL
;
}
static
void
gfte_modified_no_cb
(
GtkButton
*
button
,
gpointer
data
)
{
gtk_widget_destroy
(
modified
.
window
);
modified
.
window
=
NULL
;
gfte_remove_temp
();
switch
(
modified
.
type
)
{
case
GFTE_MODIFIED_CLOSE
:
gtk_widget_destroy
(
editor
.
window
);
gfte_cleanup
();
break
;
case
GFTE_MODIFIED_NEW
:
gfte_setup
(
NULL
);
break
;
case
GFTE_MODIFIED_OPEN
:
if
(
modified
.
filename
)
{
gfte_setup
(
modified
.
filename
);
g_free
(
modified
.
filename
);
modified
.
filename
=
NULL
;
}
break
;
case
GFTE_MODIFIED_TOTAL
:
default
:
break
;
}
}
static
void
gfte_modified_yes_cb
(
GtkButton
*
button
,
gpointer
data
)
{
gtk_widget_destroy
(
modified
.
window
);
modified
.
window
=
NULL
;
gfte_save_theme
();
switch
(
modified
.
type
)
{
case
GFTE_MODIFIED_CLOSE
:
gtk_widget_destroy
(
editor
.
window
);
gfte_cleanup
();
break
;
case
GFTE_MODIFIED_NEW
:
gfte_setup
(
NULL
);
break
;
case
GFTE_MODIFIED_OPEN
:
if
(
modified
.
filename
)
{
gfte_setup
(
modified
.
filename
);
g_free
(
modified
.
filename
);
modified
.
filename
=
NULL
;
}
break
;
case
GFTE_MODIFIED_TOTAL
:
default
:
break
;
}
}
static
void
gfte_modified_show
(
gint
type
,
const
gchar
*
filename
)
{
GtkWidget
*
vbox
,
*
hbox
,
*
widget
;
gchar
*
label
=
NULL
;
if
(
modified
.
window
)
{
gtk_widget_show
(
modified
.
window
);
return
;
}
if
(
type
==
GFTE_MODIFIED_CLOSE
)
label
=
g_strdup
(
_
(
"Would you like to save before closing?"
));
else
if
(
type
==
GFTE_MODIFIED_NEW
)
label
=
g_strdup
(
_
(
"Would you like to save before creating a new theme?"
));
else
if
(
type
==
GFTE_MODIFIED_OPEN
)
label
=
g_strdup_printf
(
_
(
"Would you like to save before opening %s?"
),
filename
);
else
return
;
gfte_dialog_cleanup
();
modified
.
type
=
type
;
modified
.
filename
=
g_strdup
(
filename
);
modified
.
window
=
gtk_window_new
(
GTK_WINDOW_TOPLEVEL
);
gtk_window_set_title
(
GTK_WINDOW
(
modified
.
window
),
_
(
"Confirm"
));
gtk_window_set_resizable
(
GTK_WINDOW
(
modified
.
window
),
FALSE
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
modified
.
window
),
12
);
g_signal_connect
(
G_OBJECT
(
modified
.
window
),
"delete-event"
,
G_CALLBACK
(
gfte_modified_deleted_cb
),
NULL
);
vbox
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_add
(
GTK_CONTAINER
(
modified
.
window
),
vbox
);
widget
=
gtk_label_new
(
label
);
g_free
(
label
);
gtk_label_set_line_wrap
(
GTK_LABEL
(
widget
),
TRUE
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
widget
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_hseparator_new
();
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
widget
,
FALSE
,
FALSE
,
0
);
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_button_new_from_stock
(
GTK_STOCK_YES
);
g_signal_connect
(
G_OBJECT
(
widget
),
"clicked"
,
G_CALLBACK
(
gfte_modified_yes_cb
),
NULL
);
gtk_box_pack_end
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_button_new_from_stock
(
GTK_STOCK_NO
);
g_signal_connect
(
G_OBJECT
(
widget
),
"clicked"
,
G_CALLBACK
(
gfte_modified_no_cb
),
NULL
);
gtk_box_pack_end
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_button_new_from_stock
(
GTK_STOCK_CANCEL
);
g_signal_connect
(
G_OBJECT
(
widget
),
"clicked"
,
G_CALLBACK
(
gfte_modified_cancel_cb
),
NULL
);
gtk_box_pack_end
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
gtk_widget_show_all
(
modified
.
window
);
}
/*******************************************************************************
* Delete Item Stuff
******************************************************************************/
static
gboolean
gfte_delete_deleted_cb
(
GtkWidget
*
w
,
GdkEvent
*
e
,
gpointer
data
)
{
del_obj
.
window
=
NULL
;
return
FALSE
;
}
static
void
gfte_delete_no_cb
(
GtkButton
*
button
,
gpointer
data
)
{
gtk_widget_destroy
(
del_obj
.
window
);
del_obj
.
window
=
NULL
;
}
static
void
gfte_delete_yes_cb
(
GtkButton
*
button
,
gpointer
data
)
{
GtkTreeIter
iter
;
gpointer
obj
=
NULL
;
gchar
*
title
=
NULL
;
gint
page
;
obj
=
gfte_store_get_row
(
&
iter
,
&
page
,
&
title
);
if
(
title
)
g_free
(
title
);
if
(
!
obj
)
{
gtk_widget_destroy
(
del_obj
.
window
);
del_obj
.
window
=
NULL
;
return
;
}
if
(
page
==
GFTE_PAGE_NOTIFICATION
)
{
GfTheme
*
theme
=
gf_notification_get_theme
(
GF_NOTIFICATION
(
obj
));
gf_theme_remove_notification
(
theme
,
GF_NOTIFICATION
(
obj
));
gf_notification_destroy
(
GF_NOTIFICATION
(
obj
));
gtk_tree_store_remove
(
editor
.
store
,
&
iter
);
}
else
if
(
page
==
GFTE_PAGE_ICON
||
page
==
GFTE_PAGE_IMAGE
||
page
==
GFTE_PAGE_TEXT
)
{
GfNotification
*
notification
=
gf_item_get_notification
(
GF_ITEM
(
obj
));
gf_notification_remove_item
(
notification
,
GF_ITEM
(
obj
));
gf_item_destroy
(
GF_ITEM
(
obj
));
gtk_tree_store_remove
(
editor
.
store
,
&
iter
);
}
gtk_widget_destroy
(
del_obj
.
window
);
del_obj
.
window
=
NULL
;
gfte_toolbar_buttons_update
(
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
);
editor
.
changed
=
TRUE
;
}
static
void
gfte_delete_show
(
GtkButton
*
button
,
gpointer
data
)
{
GtkWidget
*
vbox
,
*
hbox
,
*
widget
;
GtkTreeIter
iter
;
gchar
*
item
,
*
title
,
*
label
;
gint
page
;
if
(
del_obj
.
window
)
{
gtk_widget_show
(
del_obj
.
window
);
return
;
}
gfte_dialog_cleanup
();
gfte_store_get_row
(
&
iter
,
&
page
,
&
item
);
if
(
page
==
GFTE_PAGE_NOTIFICATION
)
{
label
=
g_strdup_printf
(
_
(
"Are you sure you want to delete this %s notification?"
),
item
);
title
=
g_strdup
(
_
(
"Confirm delete notification"
));
g_free
(
item
);
}
else
if
(
page
==
GFTE_PAGE_ICON
||
page
==
GFTE_PAGE_IMAGE
||
page
==
GFTE_PAGE_TEXT
)
{
label
=
g_strdup_printf
(
_
(
"Are you sure you want to delete this %s item?"
),
item
);
title
=
g_strdup
(
_
(
"Confirm delete item"
));
g_free
(
item
);
}
else
{
g_free
(
item
);
gtk_widget_destroy
(
del_obj
.
window
);
del_obj
.
window
=
NULL
;
return
;
}
del_obj
.
window
=
gtk_window_new
(
GTK_WINDOW_TOPLEVEL
);
gtk_window_set_title
(
GTK_WINDOW
(
del_obj
.
window
),
title
);
g_free
(
title
);
gtk_window_set_resizable
(
GTK_WINDOW
(
del_obj
.
window
),
FALSE
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
del_obj
.
window
),
12
);
g_signal_connect
(
G_OBJECT
(
del_obj
.
window
),
"delete-event"
,
G_CALLBACK
(
gfte_delete_deleted_cb
),
NULL
);
vbox
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_add
(
GTK_CONTAINER
(
del_obj
.
window
),
vbox
);
widget
=
gtk_label_new
(
label
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
widget
,
FALSE
,
FALSE
,
0
);
/* separator */
widget
=
gtk_hseparator_new
();
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
widget
,
FALSE
,
FALSE
,
0
);
/* buttons */
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_button_new_from_stock
(
GTK_STOCK_YES
);
g_signal_connect
(
G_OBJECT
(
widget
),
"clicked"
,
G_CALLBACK
(
gfte_delete_yes_cb
),
NULL
);
gtk_box_pack_end
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_button_new_from_stock
(
GTK_STOCK_NO
);
g_signal_connect
(
G_OBJECT
(
widget
),
"clicked"
,
G_CALLBACK
(
gfte_delete_no_cb
),
NULL
);
gtk_box_pack_end
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
gtk_widget_show_all
(
del_obj
.
window
);
}
/*******************************************************************************
* New Notification Stuff
******************************************************************************/
static
gboolean
gfte_new_notification_deleted_cb
(
GtkWidget
*
w
,
GdkEvent
*
e
,
gpointer
data
)
{
new_notification
.
window
=
NULL
;
return
FALSE
;
}
static
void
gfte_new_notification_cancel_cb
(
GtkButton
*
button
,
gpointer
data
)
{
gtk_widget_destroy
(
new_notification
.
window
);
new_notification
.
window
=
NULL
;
}
static
void
gfte_new_notification_ok_cb
(
GtkButton
*
button
,
gpointer
data
)
{
GfNotification
*
notification
,
*
master
;
GtkTreeIter
parent
,
child
;
gpointer
object
;
const
gchar
*
n_type
;
gint
hist
;
gtk_tree_model_get_iter_first
(
GTK_TREE_MODEL
(
editor
.
store
),
&
parent
);
gtk_tree_model_get
(
GTK_TREE_MODEL
(
editor
.
store
),
&
parent
,
GFTE_STORE_OBJECT
,
&
object
,
-1
);
if
(
object
==
NULL
)
{
purple_debug_misc
(
"guifications"
,
"ouch, I don't know where to put this, aborting
\n
"
);
if
(
new_notification
.
window
)
gtk_widget_destroy
(
new_notification
.
window
);
new_notification
.
window
=
NULL
;
return
;
}
/* find the notification type, this really needs to get cleaned up but works for now
*/
hist
=
gtk_option_menu_get_history
(
GTK_OPTION_MENU
(
new_notification
.
type
));
n_type
=
gf_events_get_nth_notification
(
hist
);
if
(
!
g_utf8_collate
(
n_type
,
GF_NOTIFICATION_MASTER
))
return
;
master
=
gf_theme_get_master
(
editor
.
theme
);
if
(
!
master
)
{
notification
=
gf_notification_new
(
GF_THEME
(
object
));
}
else
{
notification
=
gf_notification_copy
(
master
);
}
/* create the notification */
gf_notification_set_type
(
notification
,
n_type
);
/* add it to the theme */
gf_theme_add_notification
(
GF_THEME
(
object
),
notification
);
/* add it to the store */
gfte_store_add
(
editor
.
store
,
&
child
,
&
parent
,
gf_events_get_nth_name
(
hist
),
GFTE_PAGE_NOTIFICATION
,
notification
);
gfte_store_select_iter
(
&
child
);
if
(
master
)
{
GtkTreeIter
item
;
GList
*
l
;
gboolean
expand
=
FALSE
;
for
(
l
=
gf_notification_get_items
(
notification
);
l
;
l
=
l
->
next
)
{
gint
type
=
gf_item_get_type
(
GF_ITEM
(
l
->
data
));
gfte_store_add
(
editor
.
store
,
&
item
,
&
child
,
gf_item_type_to_string
(
type
,
TRUE
),
type
+
GFTE_PAGE_ICON
,
l
->
data
);
if
(
!
expand
)
expand
=
TRUE
;
}
if
(
expand
)
{
GtkTreePath
*
path
;
path
=
gtk_tree_model_get_path
(
GTK_TREE_MODEL
(
editor
.
store
),
&
child
);
gtk_tree_view_expand_row
(
GTK_TREE_VIEW
(
editor
.
tree
),
path
,
TRUE
);
gtk_tree_path_free
(
path
);
}
}
if
(
new_notification
.
window
)
gtk_widget_destroy
(
new_notification
.
window
);
new_notification
.
window
=
NULL
;
editor
.
changed
=
TRUE
;
}
static
void
gfte_new_notification_show
(
GtkButton
*
button
,
gpointer
data
)
{
GtkWidget
*
vbox
,
*
hbox
,
*
widget
,
*
menu
;
if
(
new_notification
.
window
)
{
gtk_widget_show
(
new_notification
.
window
);
return
;
}
gfte_dialog_cleanup
();
new_notification
.
window
=
gtk_window_new
(
GTK_WINDOW_TOPLEVEL
);
gtk_window_set_title
(
GTK_WINDOW
(
new_notification
.
window
),
_
(
"New Notification"
));
gtk_window_set_resizable
(
GTK_WINDOW
(
new_notification
.
window
),
FALSE
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
new_notification
.
window
),
12
);
g_signal_connect
(
G_OBJECT
(
new_notification
.
window
),
"delete-event"
,
G_CALLBACK
(
gfte_new_notification_deleted_cb
),
NULL
);
vbox
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_add
(
GTK_CONTAINER
(
new_notification
.
window
),
vbox
);
/* option menu */
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_label_new
(
_
(
"New notification type:"
));
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
menu
=
gf_menu_build
(
gf_menu_event
,
editor
.
theme
);
new_notification
.
type
=
gtk_option_menu_new
();
gtk_option_menu_set_menu
(
GTK_OPTION_MENU
(
new_notification
.
type
),
menu
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
new_notification
.
type
,
TRUE
,
TRUE
,
0
);
/* separator */
widget
=
gtk_hseparator_new
();
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
widget
,
FALSE
,
FALSE
,
0
);
/* buttons */
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_button_new_from_stock
(
GTK_STOCK_OK
);
g_signal_connect
(
G_OBJECT
(
widget
),
"clicked"
,
G_CALLBACK
(
gfte_new_notification_ok_cb
),
NULL
);
gtk_box_pack_end
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_button_new_from_stock
(
GTK_STOCK_CANCEL
);
g_signal_connect
(
G_OBJECT
(
widget
),
"clicked"
,
G_CALLBACK
(
gfte_new_notification_cancel_cb
),
NULL
);
gtk_box_pack_end
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
gtk_widget_show_all
(
new_notification
.
window
);
}
/*******************************************************************************
* New Item Stuff
******************************************************************************/
static
gboolean
gfte_new_item_deleted_cb
(
GtkWidget
*
w
,
GdkEvent
*
e
,
gpointer
data
)
{
new_item
.
window
=
NULL
;
return
FALSE
;
}
static
void
gfte_new_item_cancel_cb
(
GtkButton
*
button
,
gpointer
data
)
{
gtk_widget_destroy
(
new_item
.
window
);
new_item
.
window
=
NULL
;
}
static
void
gfte_new_item_ok_cb
(
GtkButton
*
button
,
gpointer
data
)
{
GfItem
*
item
;
GfItemType
type
;
GfItemOffset
*
offset
;
GtkTreeIter
parent
,
child
;
gpointer
object
;
gchar
*
title
=
NULL
;
gint
page
;
object
=
gfte_store_get_row
(
&
parent
,
&
page
,
&
title
);
/* we have to grab this early in case the selected node is an item, and we select the
* notification. If we don't grab this, the selection changes kills all the dialogs
* making this and invalid widget.
*/
type
=
gtk_option_menu_get_history
(
GTK_OPTION_MENU
(
new_item
.
type
));
if
(
page
==
GFTE_PAGE_ICON
||
page
==
GFTE_PAGE_IMAGE
||
page
==
GFTE_PAGE_TEXT
)
{
GtkTreeSelection
*
sel
;
gtk_tree_model_iter_parent
(
GTK_TREE_MODEL
(
editor
.
store
),
&
child
,
&
parent
);
if
(
title
)
g_free
(
title
);
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
editor
.
tree
));
gtk_tree_selection_select_iter
(
sel
,
&
child
);
object
=
gfte_store_get_row
(
&
parent
,
&
page
,
&
title
);
}
if
(
title
)
g_free
(
title
);
if
(
!
object
)
{
purple_debug_misc
(
"guifications"
,
"ouch, I don't know where to put this, aborting
\n
"
);
if
(
new_item
.
window
)
gtk_widget_destroy
(
new_item
.
window
);
new_item
.
window
=
NULL
;
return
;
}
item
=
gf_item_new
(
GF_NOTIFICATION
(
object
));
gf_item_set_type
(
item
,
type
);
if
(
type
==
GF_ITEM_TYPE_ICON
)
{
GfItemIcon
*
icon
=
gf_item_icon_new
(
item
);
gf_item_set_item_icon
(
item
,
icon
);
}
else
if
(
type
==
GF_ITEM_TYPE_IMAGE
)
{
GfItemImage
*
image
=
gf_item_image_new
(
item
);
gf_item_set_item_image
(
item
,
image
);
}
else
if
(
type
==
GF_ITEM_TYPE_TEXT
)
{
GfItemText
*
text
=
gf_item_text_new
(
item
);
gf_item_set_item_text
(
item
,
text
);
}
/* create the offsets for the item */
offset
=
gf_item_offset_new
(
item
);
gf_item_set_horz_offset
(
item
,
offset
);
offset
=
gf_item_offset_new
(
item
);
gf_item_set_vert_offset
(
item
,
offset
);
/* add the item to the notification */
gf_notification_add_item
(
GF_NOTIFICATION
(
object
),
item
);
/* throw it in the tree */
gfte_store_add
(
editor
.
store
,
&
child
,
&
parent
,
gf_item_type_to_string
(
type
,
TRUE
),
/* gross dirty hack.. clean me up later */
type
+
GFTE_PAGE_ICON
,
item
);
gfte_store_select_iter
(
&
child
);
if
(
new_item
.
window
)
gtk_widget_destroy
(
new_item
.
window
);
new_item
.
window
=
NULL
;
editor
.
changed
=
TRUE
;
}
static
void
gfte_new_item_show
(
GtkButton
*
button
,
gpointer
data
)
{
GtkWidget
*
vbox
,
*
hbox
,
*
widget
,
*
menu
;
if
(
new_item
.
window
)
{
gtk_widget_show
(
new_item
.
window
);
return
;
}
gfte_dialog_cleanup
();
new_item
.
window
=
gtk_window_new
(
GTK_WINDOW_TOPLEVEL
);
gtk_window_set_title
(
GTK_WINDOW
(
new_item
.
window
),
_
(
"New Item"
));
gtk_window_set_resizable
(
GTK_WINDOW
(
new_item
.
window
),
FALSE
);
gtk_widget_set_size_request
(
new_item
.
window
,
250
,
-1
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
new_item
.
window
),
12
);
g_signal_connect
(
G_OBJECT
(
new_item
.
window
),
"delete-event"
,
G_CALLBACK
(
gfte_new_item_deleted_cb
),
NULL
);
vbox
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_add
(
GTK_CONTAINER
(
new_item
.
window
),
vbox
);
/* option menu */
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_label_new
(
_
(
"New item type:"
));
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
menu
=
gf_menu_build
(
gf_menu_item_type
,
NULL
);
new_item
.
type
=
gtk_option_menu_new
();
gtk_option_menu_set_menu
(
GTK_OPTION_MENU
(
new_item
.
type
),
menu
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
new_item
.
type
,
TRUE
,
TRUE
,
0
);
/* separator */
widget
=
gtk_hseparator_new
();
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
widget
,
FALSE
,
FALSE
,
0
);
/* buttons */
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_button_new_from_stock
(
GTK_STOCK_OK
);
g_signal_connect
(
G_OBJECT
(
widget
),
"clicked"
,
G_CALLBACK
(
gfte_new_item_ok_cb
),
NULL
);
gtk_box_pack_end
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
widget
=
gtk_button_new_from_stock
(
GTK_STOCK_CANCEL
);
g_signal_connect
(
G_OBJECT
(
widget
),
"clicked"
,
G_CALLBACK
(
gfte_new_item_cancel_cb
),
NULL
);
gtk_box_pack_end
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
gtk_widget_show_all
(
new_item
.
window
);
}
/*******************************************************************************
* Duplicate stuff
******************************************************************************/
static
void
gfte_duplicate_object
(
GtkButton
*
button
,
gpointer
data
)
{
GtkTreeIter
parent
,
child
,
sibling
;
gchar
*
title
;
gint
page
;
gpointer
object
;
object
=
gfte_store_get_row
(
&
sibling
,
&
page
,
&
title
);
gtk_tree_model_iter_parent
(
GTK_TREE_MODEL
(
editor
.
store
),
&
parent
,
&
sibling
);
if
(
page
==
GFTE_PAGE_NOTIFICATION
)
{
GfNotification
*
notification
;
GtkTreeIter
item
;
GList
*
l
;
gboolean
expand
=
FALSE
;
notification
=
gf_notification_copy
(
GF_NOTIFICATION
(
object
));
gfte_store_add
(
editor
.
store
,
&
child
,
&
parent
,
title
,
page
,
notification
);
for
(
l
=
gf_notification_get_items
(
notification
);
l
;
l
=
l
->
next
)
{
gint
type
=
gf_item_get_type
(
GF_ITEM
(
l
->
data
));
gfte_store_add
(
editor
.
store
,
&
item
,
&
child
,
gf_item_type_to_string
(
type
,
TRUE
),
type
+
GFTE_PAGE_ICON
,
l
->
data
);
if
(
!
expand
)
expand
=
TRUE
;
}
gf_theme_add_notification
(
editor
.
theme
,
notification
);
if
(
expand
)
{
GtkTreePath
*
path
;
path
=
gtk_tree_model_get_path
(
GTK_TREE_MODEL
(
editor
.
store
),
&
child
);
gtk_tree_view_expand_row
(
GTK_TREE_VIEW
(
editor
.
tree
),
path
,
TRUE
);
gtk_tree_path_free
(
path
);
}
}
else
if
(
page
==
GFTE_PAGE_ICON
||
page
==
GFTE_PAGE_IMAGE
||
page
==
GFTE_PAGE_TEXT
)
{
GfItem
*
item
;
item
=
gf_item_copy
(
GF_ITEM
(
object
));
gtk_tree_store_append
(
editor
.
store
,
&
child
,
&
parent
);
gtk_tree_store_set
(
editor
.
store
,
&
child
,
GFTE_STORE_OBJECT
,
item
,
GFTE_STORE_PAGE
,
page
,
GFTE_STORE_TITLE
,
title
,
-1
);
gf_notification_add_item
(
gf_item_get_notification
(
GF_ITEM
(
object
)),
item
);
}
else
{
return
;
}
if
(
title
)
g_free
(
title
);
gfte_store_select_iter
(
&
child
);
editor
.
changed
=
TRUE
;
}
/*******************************************************************************
* Moving items
******************************************************************************/
static
gboolean
gfte_is_older_notification
(
GfNotification
*
notification
)
{
GfTheme
*
theme
;
GList
*
l
;
theme
=
gf_notification_get_theme
(
notification
);
if
(
!
theme
)
return
FALSE
;
l
=
gf_theme_get_notifications
(
theme
);
if
(
l
->
data
==
notification
)
return
FALSE
;
else
return
TRUE
;
}
static
gboolean
gfte_is_younger_notification
(
GfNotification
*
notification
)
{
GfTheme
*
theme
;
GList
*
l
;
theme
=
gf_notification_get_theme
(
notification
);
if
(
!
theme
)
return
FALSE
;
/* get the last notification */
for
(
l
=
gf_theme_get_notifications
(
theme
);
l
->
next
;
l
=
l
->
next
);
if
(
l
->
data
==
notification
)
return
FALSE
;
else
return
TRUE
;
}
static
gboolean
gfte_is_older_item
(
GfItem
*
item
)
{
GfNotification
*
notification
;
GList
*
l
;
notification
=
gf_item_get_notification
(
item
);
if
(
!
notification
)
return
FALSE
;
l
=
gf_notification_get_items
(
notification
);
if
(
l
->
data
==
item
)
return
FALSE
;
else
return
TRUE
;
}
static
gboolean
gfte_is_younger_item
(
GfItem
*
item
)
{
GfNotification
*
notification
;
GList
*
l
;
notification
=
gf_item_get_notification
(
item
);
if
(
!
notification
)
return
FALSE
;
/* get the last item */
for
(
l
=
gf_notification_get_items
(
notification
);
l
->
next
;
l
=
l
->
next
);
if
(
l
->
data
==
item
)
return
FALSE
;
else
return
TRUE
;
}
static
void
gfte_store_swap
(
GtkTreeIter
*
a
,
GtkTreeIter
*
b
)
{
GtkTreeSelection
*
sel
;
gchar
*
a_title
,
*
b_title
;
gint
a_page
,
b_page
;
gpointer
a_obj
,
b_obj
;
#if !GTK_CHECK_VERSION(2,2,0)
gchar
*
title
;
gint
page
;
gpointer
obj
;
#endif
/* !GTK_CHECK_VERSION(2,2,0) */
/* get 'em */
gtk_tree_model_get
(
GTK_TREE_MODEL
(
editor
.
store
),
a
,
GFTE_STORE_OBJECT
,
&
a_obj
,
GFTE_STORE_PAGE
,
&
a_page
,
GFTE_STORE_TITLE
,
&
a_title
,
-1
);
gtk_tree_model_get
(
GTK_TREE_MODEL
(
editor
.
store
),
b
,
GFTE_STORE_OBJECT
,
&
b_obj
,
GFTE_STORE_PAGE
,
&
b_page
,
GFTE_STORE_TITLE
,
&
b_title
,
-1
);
if
(
a_page
==
GFTE_PAGE_NOTIFICATION
)
gf_notifications_swap
(
GF_NOTIFICATION
(
a_obj
),
GF_NOTIFICATION
(
b_obj
));
else
{
gf_items_swap
(
GF_ITEM
(
a_obj
),
GF_ITEM
(
b_obj
));
}
#if GTK_CHECK_VERSION(2,2,0)
gtk_tree_store_swap
(
editor
.
store
,
a
,
b
);
#else
/* swap 'em */
title
=
a_title
;
page
=
a_page
;
obj
=
a_obj
;
a_title
=
b_title
;
a_page
=
b_page
;
a_obj
=
b_obj
;
b_title
=
title
;
b_page
=
page
;
b_obj
=
obj
;
/* set 'em */
gtk_tree_store_set
(
editor
.
store
,
a
,
GFTE_STORE_OBJECT
,
a_obj
,
GFTE_STORE_PAGE
,
a_page
,
GFTE_STORE_TITLE
,
a_title
,
-1
);
gtk_tree_store_set
(
editor
.
store
,
b
,
GFTE_STORE_OBJECT
,
b_obj
,
GFTE_STORE_PAGE
,
b_page
,
GFTE_STORE_TITLE
,
b_title
,
-1
);
#endif
/* GTK_CHECK_VERSION(2,2,0) */
/* clean up */
g_free
(
a_title
);
g_free
(
b_title
);
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
editor
.
tree
));
gfte_selection_changed_cb
(
sel
,
NULL
);
}
static
void
gfte_move_up
(
GtkButton
*
button
,
gpointer
data
)
{
GtkTreeIter
child
,
sibling
;
GtkTreePath
*
path
;
gpointer
object
;
gchar
*
title
;
gint
page
;
object
=
gfte_store_get_row
(
&
child
,
&
page
,
&
title
);
if
(
title
)
g_free
(
title
);
path
=
gtk_tree_model_get_path
(
GTK_TREE_MODEL
(
editor
.
store
),
&
child
);
if
(
!
path
)
return
;
if
(
!
gtk_tree_path_prev
(
path
))
{
gtk_tree_path_free
(
path
);
return
;
}
if
(
!
gtk_tree_model_get_iter
(
GTK_TREE_MODEL
(
editor
.
store
),
&
sibling
,
path
))
{
gtk_tree_path_free
(
path
);
return
;
}
gfte_store_swap
(
&
child
,
&
sibling
);
gtk_tree_path_free
(
path
);
}
static
void
gfte_move_down
(
GtkButton
*
button
,
gpointer
data
)
{
GtkTreeIter
child
,
sibling
;
GtkTreePath
*
path
;
gpointer
object
;
gchar
*
title
;
gint
page
;
object
=
gfte_store_get_row
(
&
child
,
&
page
,
&
title
);
if
(
title
)
g_free
(
title
);
path
=
gtk_tree_model_get_path
(
GTK_TREE_MODEL
(
editor
.
store
),
&
child
);
if
(
!
path
)
return
;
/* we just assume this works since it returns void I guess.. */
gtk_tree_path_next
(
path
);
if
(
!
gtk_tree_model_get_iter
(
GTK_TREE_MODEL
(
editor
.
store
),
&
sibling
,
path
))
{
gtk_tree_path_free
(
path
);
return
;
}
gfte_store_swap
(
&
child
,
&
sibling
);
gtk_tree_path_free
(
path
);
}
/*******************************************************************************
* getter/setter helpers
******************************************************************************/
static
gpointer
gfte_store_get_object_and_iter
(
GtkTreeIter
*
iter
)
{
GtkTreeModel
*
model
;
GtkTreeSelection
*
sel
;
gpointer
object
;
g_return_val_if_fail
(
iter
,
NULL
);
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
editor
.
tree
));
gtk_tree_selection_get_selected
(
sel
,
&
model
,
iter
);
gtk_tree_model_get
(
model
,
iter
,
GFTE_STORE_OBJECT
,
&
object
,
-1
);
return
object
;
}
static
gpointer
gfte_store_get_object
()
{
GtkTreeIter
iter
;
return
gfte_store_get_object_and_iter
(
&
iter
);
}
/*******************************************************************************
* Setters
******************************************************************************/
static
void
gfte_set_value
(
GtkWidget
*
widget
,
gint
page
,
gpointer
object
,
gconstpointer
value
)
{
GfteSetFunc
setter
=
g_object_get_data
(
G_OBJECT
(
widget
),
"setter"
);
gint
flags
=
GPOINTER_TO_INT
(
g_object_get_data
(
G_OBJECT
(
widget
),
"flags"
));
switch
(
page
)
{
case
GFTE_PAGE_THEME
:
break
;
case
GFTE_PAGE_INFO
:
setter
(
GF_THEME_INFO
(
object
),
value
);
break
;
case
GFTE_PAGE_OPS
:
setter
(
GF_THEME_OPTIONS
(
object
),
value
);
break
;
case
GFTE_PAGE_NOTIFICATION
:
setter
(
GF_NOTIFICATION
(
object
),
value
);
break
;
case
GFTE_PAGE_ICON
:
switch
(
flags
)
{
case
GFTE_FLAGS_OBJECT
:
setter
(
GF_ITEM
(
object
),
value
);
break
;
case
GFTE_FLAGS_SUB_OBJECT
:
setter
(
gf_item_get_item_icon
(
GF_ITEM
(
object
)),
value
);
break
;
case
GFTE_FLAGS_H_OFFSET
:
setter
(
gf_item_get_horz_offset
(
GF_ITEM
(
object
)),
value
);
break
;
case
GFTE_FLAGS_V_OFFSET
:
setter
(
gf_item_get_vert_offset
(
GF_ITEM
(
object
)),
value
);
break
;
case
GFTE_FLAGS_TOTAL
:
default
:
break
;
}
break
;
case
GFTE_PAGE_IMAGE
:
switch
(
flags
)
{
case
GFTE_FLAGS_OBJECT
:
setter
(
GF_ITEM
(
object
),
value
);
break
;
case
GFTE_FLAGS_SUB_OBJECT
:
setter
(
gf_item_get_item_image
(
GF_ITEM
(
object
)),
value
);
break
;
case
GFTE_FLAGS_H_OFFSET
:
setter
(
gf_item_get_horz_offset
(
GF_ITEM
(
object
)),
value
);
break
;
case
GFTE_FLAGS_V_OFFSET
:
setter
(
gf_item_get_vert_offset
(
GF_ITEM
(
object
)),
value
);
break
;
case
GFTE_FLAGS_TOTAL
:
default
:
break
;
}
break
;
case
GFTE_PAGE_TEXT
:
switch
(
flags
)
{
case
GFTE_FLAGS_OBJECT
:
setter
(
GF_ITEM
(
object
),
value
);
break
;
case
GFTE_FLAGS_SUB_OBJECT
:
setter
(
gf_item_get_item_text
(
GF_ITEM
(
object
)),
value
);
break
;
case
GFTE_FLAGS_H_OFFSET
:
setter
(
gf_item_get_horz_offset
(
GF_ITEM
(
object
)),
value
);
break
;
case
GFTE_FLAGS_V_OFFSET
:
setter
(
gf_item_get_vert_offset
(
GF_ITEM
(
object
)),
value
);
break
;
case
GFTE_FLAGS_TOTAL
:
default
:
break
;
}
break
;
case
GFTE_PAGE_TOTAL
:
default
:
break
;
}
}
static
void
gfte_entry_changed_cb
(
GtkWidget
*
widget
,
gpointer
data
)
{
GtkTreeIter
iter
;
gpointer
object
;
const
gchar
*
value
;
gint
page
;
object
=
gfte_store_get_object_and_iter
(
&
iter
);
value
=
gtk_entry_get_text
(
GTK_ENTRY
(
widget
));
page
=
gtk_notebook_get_current_page
(
GTK_NOTEBOOK
(
editor
.
note
));
editor
.
changed
=
TRUE
;
gfte_set_value
(
widget
,
page
,
object
,
(
gpointer
)
value
);
if
(
page
==
GFTE_PAGE_NOTIFICATION
&&
widget
==
editor
.
notification
.
alias
)
{
GfEvent
*
event
;
GfNotification
*
notification
;
const
gchar
*
alias
=
NULL
,
*
type
=
NULL
;
if
(
!
gf_utils_strcmp
(
value
,
""
))
{
notification
=
GF_NOTIFICATION
(
object
);
type
=
gf_notification_get_type
(
notification
);
event
=
gf_event_find_for_notification
(
type
);
alias
=
gf_event_get_name
(
event
);
}
else
{
alias
=
value
;
}
gtk_tree_store_set
(
editor
.
store
,
&
iter
,
GFTE_STORE_TITLE
,
alias
,
-1
);
}
}
static
void
gfte_check_toggled_cb
(
GtkWidget
*
widget
,
gpointer
data
)
{
gpointer
object
=
gfte_store_get_object
();
gpointer
pvalue
;
gint
page
=
gtk_notebook_get_current_page
(
GTK_NOTEBOOK
(
editor
.
note
));
gboolean
value
;
value
=
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
widget
));
pvalue
=
GINT_TO_POINTER
(
value
);
editor
.
changed
=
TRUE
;
gfte_set_value
(
widget
,
page
,
object
,
pvalue
);
/* adjust the sensitivity according to the use gtk setting */
if
(
widget
==
editor
.
notification
.
use_gtk
)
{
gtk_widget_set_sensitive
(
editor
.
notification
.
button
,
!
value
);
gtk_widget_set_sensitive
(
editor
.
notification
.
width
,
value
);
gtk_widget_set_sensitive
(
editor
.
notification
.
height
,
value
);
}
}
static
void
gfte_spin_changed_cb
(
GtkWidget
*
widget
,
GtkScrollType
arg1
,
gpointer
user_data
)
{
gpointer
object
=
gfte_store_get_object
();
gpointer
value
=
GINT_TO_POINTER
(
gtk_spin_button_get_value_as_int
(
GTK_SPIN_BUTTON
(
widget
)));
gint
page
=
gtk_notebook_get_current_page
(
GTK_NOTEBOOK
(
editor
.
note
));
editor
.
changed
=
TRUE
;
gfte_set_value
(
widget
,
page
,
object
,
value
);
}
static
void
gfte_option_menu_changed_cb
(
GtkWidget
*
widget
,
gpointer
user_data
)
{
gpointer
object
=
gfte_store_get_object
();
gpointer
value
=
GINT_TO_POINTER
(
gtk_option_menu_get_history
(
GTK_OPTION_MENU
(
widget
)));
gint
page
=
gtk_notebook_get_current_page
(
GTK_NOTEBOOK
(
editor
.
note
));
editor
.
changed
=
TRUE
;
gfte_set_value
(
widget
,
page
,
object
,
value
);
}
/*******************************************************************************
* Getters
******************************************************************************/
static
gpointer
gfte_get_value
(
GtkWidget
*
widget
,
gint
page
,
gpointer
object
)
{
GfteGetFunc
getter
=
g_object_get_data
(
G_OBJECT
(
widget
),
"getter"
);
/* The flags decide what item we use in our call to the getter function. This could
* be GfTheme, GfThemeInfo, GfThemeOptions, GfNotification, GfItem, GfItemIcon,
* GfItemImage, GfItemOffset, or GfItemText. Everything besides the item gets called
* as is. Thats why we check it only for the item pages. Since the object we need
* to use for the getter could be GfItem, GfItemIcon, GfItemImage, GfItemOffset, or
* GfItemText. Once we know what it is, we can call it correctly.
*/
gint
flags
=
GPOINTER_TO_INT
(
g_object_get_data
(
G_OBJECT
(
widget
),
"flags"
));
switch
(
page
)
{
case
GFTE_PAGE_THEME
:
return
(
gpointer
)
getter
(
GF_THEME
(
object
));
break
;
case
GFTE_PAGE_INFO
:
return
(
gpointer
)
getter
(
GF_THEME_INFO
(
object
));
break
;
case
GFTE_PAGE_OPS
:
return
(
gpointer
)
getter
(
GF_THEME_OPTIONS
(
object
));
break
;
case
GFTE_PAGE_NOTIFICATION
:
return
(
gpointer
)
getter
(
GF_NOTIFICATION
(
object
));
break
;
case
GFTE_PAGE_ICON
:
switch
(
flags
)
{
case
GFTE_FLAGS_OBJECT
:
return
(
gpointer
)
getter
(
GF_ITEM
(
object
));
break
;
case
GFTE_FLAGS_SUB_OBJECT
:
return
(
gpointer
)
getter
(
gf_item_get_item_icon
(
GF_ITEM
(
object
)));
break
;
case
GFTE_FLAGS_H_OFFSET
:
return
(
gpointer
)
getter
(
gf_item_get_horz_offset
(
GF_ITEM
(
object
)));
break
;
case
GFTE_FLAGS_V_OFFSET
:
return
(
gpointer
)
getter
(
gf_item_get_vert_offset
(
GF_ITEM
(
object
)));
break
;
case
GFTE_FLAGS_TOTAL
:
default
:
return
NULL
;
}
break
;
case
GFTE_PAGE_IMAGE
:
switch
(
flags
)
{
case
GFTE_FLAGS_OBJECT
:
return
(
gpointer
)
getter
(
GF_ITEM
(
object
));
break
;
case
GFTE_FLAGS_SUB_OBJECT
:
return
(
gpointer
)
getter
(
gf_item_get_item_image
(
GF_ITEM
(
object
)));
break
;
case
GFTE_FLAGS_H_OFFSET
:
return
(
gpointer
)
getter
(
gf_item_get_horz_offset
(
GF_ITEM
(
object
)));
break
;
case
GFTE_FLAGS_V_OFFSET
:
return
(
gpointer
)
getter
(
gf_item_get_vert_offset
(
GF_ITEM
(
object
)));
break
;
case
GFTE_FLAGS_TOTAL
:
default
:
return
NULL
;
}
break
;
case
GFTE_PAGE_TEXT
:
switch
(
flags
)
{
case
GFTE_FLAGS_OBJECT
:
return
(
gpointer
)
getter
(
GF_ITEM
(
object
));
break
;
case
GFTE_FLAGS_SUB_OBJECT
:
return
(
gpointer
)
getter
(
gf_item_get_item_text
(
GF_ITEM
(
object
)));
break
;
case
GFTE_FLAGS_H_OFFSET
:
return
(
gpointer
)
getter
(
gf_item_get_horz_offset
(
GF_ITEM
(
object
)));
break
;
case
GFTE_FLAGS_V_OFFSET
:
return
(
gpointer
)
getter
(
gf_item_get_vert_offset
(
GF_ITEM
(
object
)));
break
;
case
GFTE_FLAGS_TOTAL
:
default
:
return
NULL
;
}
break
;
case
GFTE_PAGE_TOTAL
:
default
:
return
NULL
;
break
;
}
}
/*******************************************************************************
* Update Widgets
******************************************************************************/
static
void
gfte_update_entry
(
GtkWidget
*
entry
,
gint
page
,
gpointer
object
)
{
gchar
*
value
=
(
gchar
*
)
gfte_get_value
(
entry
,
page
,
object
);
g_signal_handlers_block_by_func
(
G_OBJECT
(
entry
),
gfte_entry_changed_cb
,
NULL
);
if
(
value
)
gtk_entry_set_text
(
GTK_ENTRY
(
entry
),
value
);
else
gtk_entry_set_text
(
GTK_ENTRY
(
entry
),
""
);
g_signal_handlers_unblock_by_func
(
G_OBJECT
(
entry
),
gfte_entry_changed_cb
,
NULL
);
}
static
void
gfte_update_option_menu
(
GtkWidget
*
opt_menu
,
gint
page
,
gpointer
object
)
{
gint
value
=
GPOINTER_TO_INT
(
gfte_get_value
(
opt_menu
,
page
,
object
));
g_signal_handlers_block_by_func
(
G_OBJECT
(
opt_menu
),
gfte_option_menu_changed_cb
,
NULL
);
gtk_option_menu_set_history
(
GTK_OPTION_MENU
(
opt_menu
),
value
);
g_signal_handlers_unblock_by_func
(
G_OBJECT
(
opt_menu
),
gfte_option_menu_changed_cb
,
NULL
);
}
static
void
gfte_update_spin_button
(
GtkWidget
*
spin
,
gint
page
,
gpointer
object
)
{
gint
value
=
GPOINTER_TO_INT
(
gfte_get_value
(
spin
,
page
,
object
));
g_signal_handlers_block_by_func
(
G_OBJECT
(
spin
),
gfte_spin_changed_cb
,
NULL
);
gtk_spin_button_set_value
(
GTK_SPIN_BUTTON
(
spin
),
value
);
g_signal_handlers_unblock_by_func
(
G_OBJECT
(
spin
),
gfte_spin_changed_cb
,
NULL
);
}
static
void
gfte_update_check
(
GtkWidget
*
check
,
gint
page
,
gpointer
object
)
{
gboolean
value
=
GPOINTER_TO_INT
(
gfte_get_value
(
check
,
page
,
object
));
g_signal_handlers_block_by_func
(
G_OBJECT
(
check
),
gfte_check_toggled_cb
,
NULL
);
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
check
),
value
);
g_signal_handlers_unblock_by_func
(
G_OBJECT
(
check
),
gfte_check_toggled_cb
,
NULL
);
/* adjust the sensitivity according to the use gtk setting */
if
(
check
==
editor
.
notification
.
use_gtk
)
{
gtk_widget_set_sensitive
(
editor
.
notification
.
button
,
!
value
);
gtk_widget_set_sensitive
(
editor
.
notification
.
width
,
value
);
gtk_widget_set_sensitive
(
editor
.
notification
.
height
,
value
);
}
}
/*******************************************************************************
* Button stuff (requires getters and setters thats why it's here...)
******************************************************************************/
static
void
gfte_dialog_file_ok_cb
(
gpointer
data
,
const
gchar
*
filename
)
{
GtkWidget
*
button
;
gpointer
object
;
gchar
*
relative
=
NULL
,
*
target
=
NULL
;
gint
page
;
if
(
!
filename
)
{
image_dialog
=
NULL
;
return
;
}
button
=
GTK_WIDGET
(
data
);
object
=
gfte_store_get_object
();
page
=
gtk_notebook_get_current_page
(
GTK_NOTEBOOK
(
editor
.
note
));
relative
=
g_path_get_basename
(
filename
);
target
=
g_build_filename
(
editor
.
path
,
relative
,
NULL
);
if
(
!
gf_file_copy_file
(
filename
,
target
))
{
g_free
(
target
);
g_free
(
relative
);
return
;
}
g_free
(
target
);
gfte_set_value
(
button
,
page
,
object
,
relative
);
g_free
(
relative
);
if
(
page
==
GFTE_PAGE_NOTIFICATION
)
gfte_update_entry
(
editor
.
notification
.
filename
,
page
,
object
);
else
if
(
page
==
GFTE_PAGE_IMAGE
)
gfte_update_entry
(
editor
.
image
.
filename
,
page
,
object
);
}
static
void
gfte_dialog_file_cancel_cb
(
gpointer
data
,
const
gchar
*
filename
)
{
image_dialog
=
NULL
;
}
static
void
gfte_dialog_font_ok_cb
(
GtkButton
*
b
,
gpointer
data
)
{
GtkWidget
*
button
;
gpointer
object
;
gchar
*
font
;
gint
page
;
button
=
GTK_WIDGET
(
data
);
object
=
gfte_store_get_object
();
page
=
gtk_notebook_get_current_page
(
GTK_NOTEBOOK
(
editor
.
note
));
font
=
gtk_font_selection_dialog_get_font_name
(
GTK_FONT_SELECTION_DIALOG
(
opt_dialog
));
gfte_set_value
(
button
,
page
,
object
,
font
);
if
(
font
)
g_free
(
font
);
gtk_widget_destroy
(
opt_dialog
);
opt_dialog
=
NULL
;
}
static
void
gfte_dialog_font_cancel_cb
(
GtkButton
*
b
,
gpointer
data
)
{
gtk_widget_destroy
(
opt_dialog
);
opt_dialog
=
NULL
;
}
static
void
gfte_dialog_color_ok_cb
(
GtkButton
*
b
,
gpointer
data
)
{
GtkWidget
*
button
;
GdkColor
gcolor
;
gpointer
object
;
gchar
ccolor
[
14
];
gint
page
;
button
=
GTK_WIDGET
(
data
);
object
=
gfte_store_get_object
();
page
=
gtk_notebook_get_current_page
(
GTK_NOTEBOOK
(
editor
.
note
));
gtk_color_selection_get_current_color
(
GTK_COLOR_SELECTION
(
GTK_COLOR_SELECTION_DIALOG
(
opt_dialog
)
->
colorsel
),
&
gcolor
);
g_snprintf
(
ccolor
,
sizeof
(
ccolor
),
"#%04x%04x%04x"
,
gcolor
.
red
,
gcolor
.
green
,
gcolor
.
blue
);
gfte_set_value
(
button
,
page
,
object
,
ccolor
);
gtk_widget_destroy
(
opt_dialog
);
opt_dialog
=
NULL
;
}
static
void
gfte_dialog_color_cancel_cb
(
GtkButton
*
b
,
gpointer
data
)
{
gtk_widget_destroy
(
opt_dialog
);
opt_dialog
=
NULL
;
}
static
void
gfte_button_clicked_cb
(
GtkWidget
*
button
,
gpointer
data
)
{
gpointer
object
,
value
;
gint
page
,
type
;
gfte_dialog_cleanup
();
type
=
GPOINTER_TO_INT
(
g_object_get_data
(
G_OBJECT
(
button
),
"type"
));
object
=
gfte_store_get_object
();
page
=
gtk_notebook_get_current_page
(
GTK_NOTEBOOK
(
editor
.
note
));
value
=
gfte_get_value
(
button
,
page
,
object
);
if
(
type
==
GFTE_BUTTON_FILE
)
{
image_dialog
=
purple_request_file
(
plugin_handle
,
_
(
"Open"
),
""
,
FALSE
,
G_CALLBACK
(
gfte_dialog_file_ok_cb
),
G_CALLBACK
(
gfte_dialog_file_cancel_cb
),
NULL
,
NULL
,
NULL
,
(
gpointer
)
button
);
}
else
if
(
type
==
GFTE_BUTTON_FONT
)
{
opt_dialog
=
gtk_font_selection_dialog_new
(
_
(
"Select font"
));
gtk_font_selection_dialog_set_font_name
(
GTK_FONT_SELECTION_DIALOG
(
opt_dialog
),
(
value
)
?
(
gchar
*
)
value
:
"Arial 12"
);
gtk_font_selection_dialog_set_preview_text
(
GTK_FONT_SELECTION_DIALOG
(
opt_dialog
),
_
(
"Guifications"
));
g_signal_connect
(
G_OBJECT
(
GTK_FONT_SELECTION_DIALOG
(
opt_dialog
)
->
ok_button
),
"clicked"
,
G_CALLBACK
(
gfte_dialog_font_ok_cb
),
(
gpointer
)
button
);
g_signal_connect
(
G_OBJECT
(
GTK_FONT_SELECTION_DIALOG
(
opt_dialog
)
->
cancel_button
),
"clicked"
,
G_CALLBACK
(
gfte_dialog_font_cancel_cb
),
(
gpointer
)
button
);
gtk_widget_show_all
(
opt_dialog
);
}
else
if
(
type
==
GFTE_BUTTON_COLOR
)
{
PangoColor
pcolor
;
GdkColor
gcolor
;
if
(
value
)
{
pango_color_parse
(
&
pcolor
,
(
gchar
*
)
value
);
gcolor
.
red
=
pcolor
.
red
;
gcolor
.
green
=
pcolor
.
green
;
gcolor
.
blue
=
pcolor
.
blue
;
}
else
{
gcolor
.
red
=
gcolor
.
green
=
gcolor
.
blue
=
0
;
}
opt_dialog
=
gtk_color_selection_dialog_new
(
_
(
"Select color"
));
gtk_color_selection_set_current_color
(
GTK_COLOR_SELECTION
(
GTK_COLOR_SELECTION_DIALOG
(
opt_dialog
)
->
colorsel
),
&
gcolor
);
g_signal_connect
(
G_OBJECT
(
GTK_COLOR_SELECTION_DIALOG
(
opt_dialog
)
->
ok_button
),
"clicked"
,
G_CALLBACK
(
gfte_dialog_color_ok_cb
),
(
gpointer
)
button
);
g_signal_connect
(
G_OBJECT
(
GTK_COLOR_SELECTION_DIALOG
(
opt_dialog
)
->
cancel_button
),
"clicked"
,
G_CALLBACK
(
gfte_dialog_color_cancel_cb
),
(
gpointer
)
button
);
gtk_widget_show_all
(
opt_dialog
);
}
}
/*******************************************************************************
* Update pages
******************************************************************************/
static
void
gfte_update_item
(
struct
GfThemeEditorItem
*
te_item
,
gint
page
,
GfItem
*
item
)
{
gfte_update_option_menu
(
te_item
->
position
,
page
,
item
);
gfte_update_spin_button
(
te_item
->
h_offset
,
page
,
item
);
gfte_update_check
(
te_item
->
h_offset_p
,
page
,
item
);
gfte_update_spin_button
(
te_item
->
v_offset
,
page
,
item
);
gfte_update_check
(
te_item
->
v_offset_p
,
page
,
item
);
}
static
void
gfte_update_info_page
()
{
GfThemeInfo
*
info
=
(
GfThemeInfo
*
)
gfte_store_get_object
();
gfte_update_entry
(
editor
.
info
.
name
,
GFTE_PAGE_INFO
,
info
);
gfte_update_entry
(
editor
.
info
.
version
,
GFTE_PAGE_INFO
,
info
);
gfte_update_entry
(
editor
.
info
.
summary
,
GFTE_PAGE_INFO
,
info
);
gfte_update_entry
(
editor
.
info
.
description
,
GFTE_PAGE_INFO
,
info
);
gfte_update_entry
(
editor
.
info
.
author
,
GFTE_PAGE_INFO
,
info
);
gfte_update_entry
(
editor
.
info
.
website
,
GFTE_PAGE_INFO
,
info
);
}
static
void
gfte_update_ops_page
()
{
GfThemeOptions
*
ops
=
(
GfThemeOptions
*
)
gfte_store_get_object
();
gfte_update_entry
(
editor
.
ops
.
date_format
,
GFTE_PAGE_OPS
,
ops
);
gfte_update_entry
(
editor
.
ops
.
time_format
,
GFTE_PAGE_OPS
,
ops
);
gfte_update_entry
(
editor
.
ops
.
warning
,
GFTE_PAGE_OPS
,
ops
);
gfte_update_entry
(
editor
.
ops
.
ellipsis
,
GFTE_PAGE_OPS
,
ops
);
}
static
void
gfte_update_notification_page
()
{
gpointer
obj
;
GfNotification
*
notification
;
obj
=
gfte_store_get_object
();
notification
=
GF_NOTIFICATION
(
obj
);
gfte_update_entry
(
editor
.
notification
.
alias
,
GFTE_PAGE_NOTIFICATION
,
notification
);
gfte_update_check
(
editor
.
notification
.
use_gtk
,
GFTE_PAGE_NOTIFICATION
,
notification
);
gfte_update_entry
(
editor
.
notification
.
filename
,
GFTE_PAGE_NOTIFICATION
,
notification
);
gfte_update_spin_button
(
editor
.
notification
.
width
,
GFTE_PAGE_NOTIFICATION
,
notification
);
gfte_update_spin_button
(
editor
.
notification
.
height
,
GFTE_PAGE_NOTIFICATION
,
notification
);
}
static
void
gfte_update_icon_page
()
{
GfItem
*
item
=
GF_ITEM
(
gfte_store_get_object
());
gfte_update_item
(
&
editor
.
icon
.
item
,
GFTE_PAGE_ICON
,
item
);
gfte_update_option_menu
(
editor
.
icon
.
type
,
GFTE_PAGE_ICON
,
item
);
gfte_update_option_menu
(
editor
.
icon
.
size
,
GFTE_PAGE_ICON
,
item
);
}
static
void
gfte_update_image_page
()
{
GfItem
*
item
=
GF_ITEM
(
gfte_store_get_object
());
gfte_update_item
(
&
editor
.
image
.
item
,
GFTE_PAGE_IMAGE
,
item
);
gfte_update_entry
(
editor
.
image
.
filename
,
GFTE_PAGE_IMAGE
,
item
);
}
static
void
gfte_update_text_page
()
{
GfItem
*
item
=
GF_ITEM
(
gfte_store_get_object
());
gfte_update_item
(
&
editor
.
text
.
item
,
GFTE_PAGE_TEXT
,
item
);
gfte_update_entry
(
editor
.
text
.
format
,
GFTE_PAGE_TEXT
,
item
);
gfte_update_spin_button
(
editor
.
text
.
width
,
GFTE_PAGE_TEXT
,
item
);
gfte_update_option_menu
(
editor
.
text
.
clipping
,
GFTE_PAGE_TEXT
,
item
);
}
/*******************************************************************************
* Callbacks
******************************************************************************/
static
void
gfte_selection_changed_cb
(
GtkTreeSelection
*
sel
,
gpointer
data
)
{
GtkTreeModel
*
model
;
GtkTreeIter
iter
;
gpointer
object
;
gint
page
;
gfte_dialog_cleanup
();
if
(
!
gtk_tree_selection_get_selected
(
sel
,
&
model
,
&
iter
))
{
gtk_notebook_set_current_page
(
GTK_NOTEBOOK
(
editor
.
note
),
GFTE_PAGE_THEME
);
return
;
}
gtk_tree_model_get
(
model
,
&
iter
,
GFTE_STORE_PAGE
,
&
page
,
GFTE_STORE_OBJECT
,
&
object
,
-1
);
gtk_notebook_set_current_page
(
GTK_NOTEBOOK
(
editor
.
note
),
page
);
switch
(
page
)
{
case
GFTE_PAGE_THEME
:
gfte_toolbar_buttons_update
(
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
);
break
;
case
GFTE_PAGE_INFO
:
gfte_toolbar_buttons_update
(
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
);
gfte_update_info_page
();
break
;
case
GFTE_PAGE_OPS
:
gfte_toolbar_buttons_update
(
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
);
gfte_update_ops_page
();
break
;
case
GFTE_PAGE_NOTIFICATION
:
{
GfNotification
*
notification
=
GF_NOTIFICATION
(
object
);
gboolean
master
;
master
=
(
g_ascii_strcasecmp
(
GF_NOTIFICATION_MASTER
,
gf_notification_get_type
(
notification
)));
gfte_toolbar_buttons_update
(
TRUE
,
master
,
master
,
gfte_is_older_notification
(
object
),
gfte_is_younger_notification
(
object
));
gfte_update_notification_page
();
break
;
}
case
GFTE_PAGE_ICON
:
gfte_toolbar_buttons_update
(
TRUE
,
TRUE
,
TRUE
,
gfte_is_older_item
(
object
),
gfte_is_younger_item
(
object
));
gfte_update_icon_page
();
break
;
case
GFTE_PAGE_IMAGE
:
gfte_toolbar_buttons_update
(
TRUE
,
TRUE
,
TRUE
,
gfte_is_older_item
(
object
),
gfte_is_younger_item
(
object
));
gfte_update_image_page
();
break
;
case
GFTE_PAGE_TEXT
:
gfte_toolbar_buttons_update
(
TRUE
,
TRUE
,
TRUE
,
gfte_is_older_item
(
object
),
gfte_is_younger_item
(
object
));
gfte_update_text_page
();
break
;
case
GFTE_PAGE_TOTAL
:
default
:
break
;
}
}
static
void
gfte_new_theme_cb
(
GtkButton
*
button
,
gpointer
data
)
{
if
(
editor
.
changed
)
gfte_modified_show
(
GFTE_MODIFIED_NEW
,
NULL
);
else
gfte_setup
(
NULL
);
}
static
void
gfte_save_theme_cb
(
GtkButton
*
button
,
gpointer
data
)
{
gfte_save_theme
();
}
static
void
gfte_help
(
GtkButton
*
button
,
gpointer
data
)
{
purple_notify_uri
(
NULL
,
GF_WEBSITE
"/themes/theme_howto/"
);
}
/*******************************************************************************
* Helpers
******************************************************************************/
static
void
gfte_build_tree
()
{
GtkWidget
*
sw
;
GtkCellRenderer
*
renderer
;
GtkTreeViewColumn
*
col
;
GtkTreeSelection
*
sel
;
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
(
editor
.
hbox
),
sw
,
FALSE
,
FALSE
,
0
);
editor
.
tree
=
gtk_tree_view_new_with_model
(
GTK_TREE_MODEL
(
editor
.
store
));
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
editor
.
tree
));
g_signal_connect_after
(
G_OBJECT
(
sel
),
"changed"
,
G_CALLBACK
(
gfte_selection_changed_cb
),
NULL
);
gtk_tree_view_set_headers_visible
(
GTK_TREE_VIEW
(
editor
.
tree
),
FALSE
);
gtk_tree_view_set_rules_hint
(
GTK_TREE_VIEW
(
editor
.
tree
),
FALSE
);
gtk_tree_view_expand_all
(
GTK_TREE_VIEW
(
editor
.
tree
));
gtk_container_add
(
GTK_CONTAINER
(
sw
),
editor
.
tree
);
renderer
=
gtk_cell_renderer_text_new
();
col
=
gtk_tree_view_column_new_with_attributes
(
NULL
,
renderer
,
"text"
,
GFTE_STORE_TITLE
,
NULL
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
editor
.
tree
),
col
);
}
static
GtkWidget
*
gfte_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
,
0.5
);
if
(
sg
)
gtk_size_group_add_widget
(
sg
,
label
);
return
label
;
}
static
GtkWidget
*
gfte_add_label
(
GtkWidget
*
widget
,
const
gchar
*
label
,
GtkSizeGroup
*
sg
)
{
GtkWidget
*
hbox
;
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
gfte_make_label
(
label
,
sg
),
FALSE
,
FALSE
,
0
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
widget
,
FALSE
,
FALSE
,
0
);
return
hbox
;
}
static
GtkWidget
*
gfte_add_entry
(
GtkWidget
*
parent
,
GtkSizeGroup
*
sg
,
gint
flags
,
const
gchar
*
label
,
gpointer
getter
,
gpointer
setter
)
{
GtkWidget
*
entry
,
*
hbox
;
entry
=
gtk_entry_new
();
g_object_set_data
(
G_OBJECT
(
entry
),
"getter"
,
getter
);
g_object_set_data
(
G_OBJECT
(
entry
),
"setter"
,
setter
);
g_object_set_data
(
G_OBJECT
(
entry
),
"flags"
,
GINT_TO_POINTER
(
flags
));
g_signal_connect
(
G_OBJECT
(
entry
),
"changed"
,
G_CALLBACK
(
gfte_entry_changed_cb
),
NULL
);
hbox
=
gfte_add_label
(
entry
,
label
,
sg
);
gtk_box_pack_start
(
GTK_BOX
(
parent
),
hbox
,
FALSE
,
FALSE
,
0
);
return
entry
;
}
static
GtkWidget
*
gfte_add_check
(
GtkWidget
*
parent
,
gint
flags
,
const
gchar
*
label
,
gpointer
getter
,
gpointer
setter
)
{
GtkWidget
*
check
;
check
=
gtk_check_button_new_with_mnemonic
(
label
);
g_object_set_data
(
G_OBJECT
(
check
),
"getter"
,
getter
);
g_object_set_data
(
G_OBJECT
(
check
),
"setter"
,
setter
);
g_object_set_data
(
G_OBJECT
(
check
),
"flags"
,
GINT_TO_POINTER
(
flags
));
g_signal_connect
(
G_OBJECT
(
check
),
"toggled"
,
G_CALLBACK
(
gfte_check_toggled_cb
),
NULL
);
gtk_box_pack_start
(
GTK_BOX
(
parent
),
check
,
FALSE
,
FALSE
,
0
);
return
check
;
}
static
GtkWidget
*
gfte_add_spin_button
(
GtkWidget
*
parent
,
GtkSizeGroup
*
sg
,
gint
flags
,
const
gchar
*
label
,
gint
min
,
gint
max
,
gpointer
getter
,
gpointer
setter
)
{
GtkWidget
*
spin
,
*
hbox
;
spin
=
gtk_spin_button_new_with_range
(
min
,
max
,
1
);
gtk_spin_button_set_numeric
(
GTK_SPIN_BUTTON
(
spin
),
TRUE
);
g_object_set_data
(
G_OBJECT
(
spin
),
"getter"
,
getter
);
g_object_set_data
(
G_OBJECT
(
spin
),
"setter"
,
setter
);
g_object_set_data
(
G_OBJECT
(
spin
),
"flags"
,
GINT_TO_POINTER
(
flags
));
g_signal_connect
(
G_OBJECT
(
spin
),
"value-changed"
,
G_CALLBACK
(
gfte_spin_changed_cb
),
NULL
);
hbox
=
gfte_add_label
(
spin
,
label
,
sg
);
gtk_box_pack_start
(
GTK_BOX
(
parent
),
hbox
,
FALSE
,
FALSE
,
0
);
return
spin
;
}
static
GtkWidget
*
gfte_add_option_menu
(
GtkWidget
*
parent
,
GtkSizeGroup
*
sg
,
gint
flags
,
const
gchar
*
label
,
GfMenuItemBuilder
builder
,
gpointer
getter
,
gpointer
setter
)
{
GtkWidget
*
option_menu
,
*
hbox
;
option_menu
=
gtk_option_menu_new
();
gtk_option_menu_set_menu
(
GTK_OPTION_MENU
(
option_menu
),
gf_menu_build
(
builder
,
NULL
));
g_object_set_data
(
G_OBJECT
(
option_menu
),
"getter"
,
getter
);
g_object_set_data
(
G_OBJECT
(
option_menu
),
"setter"
,
setter
);
g_object_set_data
(
G_OBJECT
(
option_menu
),
"flags"
,
GINT_TO_POINTER
(
flags
));
g_signal_connect
(
G_OBJECT
(
option_menu
),
"changed"
,
G_CALLBACK
(
gfte_option_menu_changed_cb
),
NULL
);
hbox
=
gfte_add_label
(
option_menu
,
label
,
sg
);
gtk_box_pack_start
(
GTK_BOX
(
parent
),
hbox
,
FALSE
,
FALSE
,
0
);
return
option_menu
;
}
static
GtkWidget
*
gfte_add_button
(
GtkWidget
*
parent
,
gint
flags
,
gint
type
,
const
gchar
*
stock_id
,
gpointer
getter
,
gpointer
setter
)
{
GtkWidget
*
button
;
button
=
gtk_button_new_from_stock
(
stock_id
);
g_object_set_data
(
G_OBJECT
(
button
),
"getter"
,
getter
);
g_object_set_data
(
G_OBJECT
(
button
),
"setter"
,
setter
);
g_object_set_data
(
G_OBJECT
(
button
),
"flags"
,
GINT_TO_POINTER
(
flags
));
g_object_set_data
(
G_OBJECT
(
button
),
"type"
,
GINT_TO_POINTER
(
type
));
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
gfte_button_clicked_cb
),
NULL
);
if
(
parent
)
gtk_box_pack_start
(
GTK_BOX
(
parent
),
button
,
FALSE
,
FALSE
,
0
);
return
button
;
}
/*******************************************************************************
* Pages
******************************************************************************/
static
GtkWidget
*
gfte_make_theme_page
()
{
GtkWidget
*
page
;
page
=
gtk_vbox_new
(
FALSE
,
0
);
return
page
;
}
static
GtkWidget
*
gfte_make_info_page
()
{
GtkWidget
*
page
;
GtkSizeGroup
*
sg
;
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
page
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
page
),
12
);
editor
.
info
.
name
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Name:"
),
gf_theme_info_get_name
,
gf_theme_info_set_name
);
editor
.
info
.
version
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Version:"
),
gf_theme_info_get_version
,
gf_theme_info_set_version
);
editor
.
info
.
summary
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Summary:"
),
gf_theme_info_get_summary
,
gf_theme_info_set_summary
);
editor
.
info
.
description
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Description:"
),
gf_theme_info_get_description
,
gf_theme_info_set_description
);
editor
.
info
.
author
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Author:"
),
gf_theme_info_get_author
,
gf_theme_info_set_author
);
editor
.
info
.
website
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Website:"
),
gf_theme_info_get_website
,
gf_theme_info_set_website
);
return
page
;
}
static
GtkWidget
*
gfte_make_ops_page
()
{
GtkWidget
*
page
;
GtkSizeGroup
*
sg
;
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
page
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
page
),
12
);
editor
.
ops
.
date_format
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Date Format:"
),
gf_theme_options_get_date_format
,
gf_theme_options_set_date_format
);
editor
.
ops
.
time_format
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Time Format:"
),
gf_theme_options_get_time_format
,
gf_theme_options_set_time_format
);
editor
.
ops
.
warning
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Warning:"
),
gf_theme_options_get_warning
,
gf_theme_options_set_warning
);
editor
.
ops
.
ellipsis
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Ellipsis:"
),
gf_theme_options_get_ellipsis
,
gf_theme_options_set_ellipsis
);
return
page
;
}
static
GtkWidget
*
gfte_make_notification_page
()
{
GtkWidget
*
page
;
GtkSizeGroup
*
sg
;
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
page
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
page
),
12
);
editor
.
notification
.
alias
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Alias:"
),
gf_notification_get_alias
,
gf_notification_set_alias
);
editor
.
notification
.
use_gtk
=
gfte_add_check
(
page
,
GFTE_FLAGS_OBJECT
,
_
(
"Use Gtk theme background"
),
gf_notification_get_use_gtk
,
gf_notification_set_use_gtk
);
editor
.
notification
.
filename
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Background:"
),
gf_notification_get_background
,
gf_notification_set_background
);
gtk_widget_set_sensitive
(
editor
.
notification
.
filename
,
FALSE
);
editor
.
notification
.
button
=
gfte_add_button
(
editor
.
notification
.
filename
->
parent
,
GFTE_FLAGS_OBJECT
,
GFTE_BUTTON_FILE
,
GTK_STOCK_OPEN
,
gf_notification_get_background
,
gf_notification_set_background
);
editor
.
notification
.
width
=
gfte_add_spin_button
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Width:"
),
GF_NOTIFICATION_MIN
,
GF_NOTIFICATION_MAX
,
gf_notification_get_width
,
gf_notification_set_width
);
editor
.
notification
.
height
=
gfte_add_spin_button
(
page
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"Height:"
),
GF_NOTIFICATION_MIN
,
GF_NOTIFICATION_MAX
,
gf_notification_get_height
,
gf_notification_set_height
);
return
page
;
}
static
void
gfte_make_item_widgets
(
GtkWidget
*
parent
,
GtkSizeGroup
*
sg
,
struct
GfThemeEditorItem
*
item
)
{
item
->
position
=
gfte_add_option_menu
(
parent
,
sg
,
GFTE_FLAGS_OBJECT
,
_
(
"_Position:"
),
gf_menu_item_position
,
gf_item_get_position
,
gf_item_set_position
);
item
->
h_offset
=
gfte_add_spin_button
(
parent
,
sg
,
GFTE_FLAGS_H_OFFSET
,
_
(
"_Horizontal Offset:"
),
-1024
,
1023
,
gf_item_offset_get_value
,
gf_item_offset_set_value
);
item
->
h_offset_p
=
gfte_add_check
(
item
->
h_offset
->
parent
,
GFTE_FLAGS_H_OFFSET
,
_
(
"Percentage"
),
gf_item_offset_get_is_percentage
,
gf_item_offset_set_is_percentage
);
item
->
v_offset
=
gfte_add_spin_button
(
parent
,
sg
,
GFTE_FLAGS_V_OFFSET
,
_
(
"_Vertical Offset:"
),
-1024
,
1023
,
gf_item_offset_get_value
,
gf_item_offset_set_value
);
item
->
v_offset_p
=
gfte_add_check
(
item
->
v_offset
->
parent
,
GFTE_FLAGS_V_OFFSET
,
_
(
"Percentage"
),
gf_item_offset_get_is_percentage
,
gf_item_offset_set_is_percentage
);
}
static
GtkWidget
*
gfte_make_icon_page
()
{
GtkWidget
*
page
;
GtkSizeGroup
*
sg
;
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
page
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
page
),
12
);
gfte_make_item_widgets
(
page
,
sg
,
&
editor
.
icon
.
item
);
editor
.
icon
.
type
=
gfte_add_option_menu
(
page
,
sg
,
GFTE_FLAGS_SUB_OBJECT
,
_
(
"_Type:"
),
gf_menu_item_icon_type
,
gf_item_icon_get_type
,
gf_item_icon_set_type
);
editor
.
icon
.
size
=
gfte_add_option_menu
(
page
,
sg
,
GFTE_FLAGS_SUB_OBJECT
,
_
(
"_Size:"
),
gf_menu_item_icon_size
,
gf_item_icon_get_size
,
gf_item_icon_set_size
);
return
page
;
}
static
GtkWidget
*
gfte_make_image_page
()
{
GtkWidget
*
page
;
GtkSizeGroup
*
sg
;
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
page
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
page
),
12
);
gfte_make_item_widgets
(
page
,
sg
,
&
editor
.
image
.
item
);
editor
.
image
.
filename
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_SUB_OBJECT
,
_
(
"Image:"
),
gf_item_image_get_image
,
gf_item_image_set_image
);
gtk_widget_set_sensitive
(
editor
.
image
.
filename
,
FALSE
);
editor
.
image
.
button
=
gfte_add_button
(
editor
.
image
.
filename
->
parent
,
GFTE_FLAGS_SUB_OBJECT
,
GFTE_BUTTON_FILE
,
GTK_STOCK_OPEN
,
gf_item_image_get_image
,
gf_item_image_set_image
);
return
page
;
}
static
GtkWidget
*
gfte_make_text_page
()
{
GtkWidget
*
page
,
*
hbox
;
GtkSizeGroup
*
sg
;
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
page
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
page
),
12
);
gfte_make_item_widgets
(
page
,
sg
,
&
editor
.
text
.
item
);
editor
.
text
.
format
=
gfte_add_entry
(
page
,
sg
,
GFTE_FLAGS_SUB_OBJECT
,
_
(
"Format:"
),
gf_item_text_get_format
,
gf_item_text_set_format
);
editor
.
text
.
width
=
gfte_add_spin_button
(
page
,
sg
,
GFTE_FLAGS_SUB_OBJECT
,
_
(
"Width:"
),
0
,
1023
,
gf_item_text_get_width
,
gf_item_text_set_width
);
editor
.
text
.
clipping
=
gfte_add_option_menu
(
page
,
sg
,
GFTE_FLAGS_SUB_OBJECT
,
_
(
"Clipping:"
),
gf_menu_item_text_clipping
,
gf_item_text_get_clipping
,
gf_item_text_set_clipping
);
editor
.
text
.
font
=
gfte_add_button
(
NULL
,
GFTE_FLAGS_SUB_OBJECT
,
GFTE_BUTTON_FONT
,
GTK_STOCK_SELECT_FONT
,
gf_item_text_get_font
,
gf_item_text_set_font
);
hbox
=
gfte_add_label
(
editor
.
text
.
font
,
NULL
,
sg
);
gtk_box_pack_start
(
GTK_BOX
(
page
),
hbox
,
FALSE
,
FALSE
,
0
);
editor
.
text
.
color
=
gfte_add_button
(
NULL
,
GFTE_FLAGS_SUB_OBJECT
,
GFTE_BUTTON_COLOR
,
GTK_STOCK_SELECT_COLOR
,
gf_item_text_get_color
,
gf_item_text_set_color
);
hbox
=
gfte_add_label
(
editor
.
text
.
color
,
NULL
,
sg
);
gtk_box_pack_start
(
GTK_BOX
(
page
),
hbox
,
FALSE
,
FALSE
,
0
);
return
page
;
}
/*******************************************************************************
* Main stuff
******************************************************************************/
static
GtkWidget
*
gfte_toolbar_button_new
(
GtkWidget
*
parent
,
const
gchar
*
stock_id
,
const
gchar
*
tooltip
,
GCallback
cb
,
gpointer
data
)
{
GtkWidget
*
button
,
*
image
;
button
=
gtk_button_new
();
gtk_button_set_relief
(
GTK_BUTTON
(
button
),
GTK_RELIEF_NONE
);
if
(
cb
)
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
cb
,
data
);
gtk_tooltips_set_tip
(
editor
.
tooltips
,
button
,
tooltip
,
NULL
);
image
=
gtk_image_new_from_stock
(
stock_id
,
GTK_ICON_SIZE_SMALL_TOOLBAR
);
gtk_container_add
(
GTK_CONTAINER
(
button
),
image
);
gtk_box_pack_start
(
GTK_BOX
(
parent
),
button
,
FALSE
,
FALSE
,
0
);
return
button
;
}
static
void
gfte_toolbar_separator_new
(
GtkWidget
*
parent
)
{
GtkWidget
*
sep
;
sep
=
gtk_vseparator_new
();
gtk_box_pack_start
(
GTK_BOX
(
parent
),
sep
,
FALSE
,
FALSE
,
0
);
}
static
void
gfte_build_toolbar
()
{
GtkWidget
*
frame
,
*
hbox
,
*
help
;
frame
=
gtk_frame_new
(
NULL
);
gtk_frame_set_shadow_type
(
GTK_FRAME
(
frame
),
GTK_SHADOW_OUT
);
gtk_box_pack_start
(
GTK_BOX
(
editor
.
vbox
),
frame
,
FALSE
,
FALSE
,
0
);
hbox
=
gtk_hbox_new
(
FALSE
,
0
);
gtk_container_add
(
GTK_CONTAINER
(
frame
),
hbox
);
gfte_toolbar_button_new
(
hbox
,
GTK_STOCK_NEW
,
_
(
"New theme"
),
G_CALLBACK
(
gfte_new_theme_cb
),
NULL
);
gfte_toolbar_button_new
(
hbox
,
GTK_STOCK_SAVE
,
_
(
"Save theme"
),
G_CALLBACK
(
gfte_save_theme_cb
),
NULL
);
gfte_toolbar_separator_new
(
hbox
);
editor
.
tool_notification
=
gfte_toolbar_button_new
(
hbox
,
GTK_STOCK_EXECUTE
,
_
(
"New notification"
),
G_CALLBACK
(
gfte_new_notification_show
),
NULL
);
editor
.
tool_item
=
gfte_toolbar_button_new
(
hbox
,
GTK_STOCK_PROPERTIES
,
_
(
"New item"
),
G_CALLBACK
(
gfte_new_item_show
),
NULL
);
editor
.
tool_copy
=
gfte_toolbar_button_new
(
hbox
,
GTK_STOCK_COPY
,
_
(
"Duplicate"
),
G_CALLBACK
(
gfte_duplicate_object
),
NULL
);
editor
.
tool_delete
=
gfte_toolbar_button_new
(
hbox
,
GTK_STOCK_DELETE
,
_
(
"Delete"
),
G_CALLBACK
(
gfte_delete_show
),
NULL
);
gfte_toolbar_separator_new
(
hbox
);
editor
.
tool_up
=
gfte_toolbar_button_new
(
hbox
,
GTK_STOCK_GO_UP
,
_
(
"Move up"
),
G_CALLBACK
(
gfte_move_up
),
NULL
);
editor
.
tool_down
=
gfte_toolbar_button_new
(
hbox
,
GTK_STOCK_GO_DOWN
,
_
(
"Move down"
),
G_CALLBACK
(
gfte_move_down
),
NULL
);
gfte_toolbar_separator_new
(
hbox
);
help
=
gfte_toolbar_button_new
(
hbox
,
GTK_STOCK_HELP
,
_
(
"Help"
),
G_CALLBACK
(
gfte_help
),
NULL
);
gfte_toolbar_buttons_update
(
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
);
}
static
void
gfte_build_notebook
()
{
editor
.
note
=
gtk_notebook_new
();
gtk_notebook_set_show_tabs
(
GTK_NOTEBOOK
(
editor
.
note
),
FALSE
);
gtk_box_pack_start
(
GTK_BOX
(
editor
.
hbox
),
editor
.
note
,
TRUE
,
TRUE
,
4
);
gtk_notebook_insert_page
(
GTK_NOTEBOOK
(
editor
.
note
),
gfte_make_theme_page
(),
NULL
,
GFTE_PAGE_THEME
);
gtk_notebook_insert_page
(
GTK_NOTEBOOK
(
editor
.
note
),
gfte_make_info_page
(),
NULL
,
GFTE_PAGE_INFO
);
gtk_notebook_insert_page
(
GTK_NOTEBOOK
(
editor
.
note
),
gfte_make_ops_page
(),
NULL
,
GFTE_PAGE_OPS
);
gtk_notebook_insert_page
(
GTK_NOTEBOOK
(
editor
.
note
),
gfte_make_notification_page
(),
NULL
,
GFTE_PAGE_NOTIFICATION
);
gtk_notebook_insert_page
(
GTK_NOTEBOOK
(
editor
.
note
),
gfte_make_icon_page
(),
NULL
,
GFTE_PAGE_ICON
);
gtk_notebook_insert_page
(
GTK_NOTEBOOK
(
editor
.
note
),
gfte_make_image_page
(),
NULL
,
GFTE_PAGE_IMAGE
);
gtk_notebook_insert_page
(
GTK_NOTEBOOK
(
editor
.
note
),
gfte_make_text_page
(),
NULL
,
GFTE_PAGE_TEXT
);
}
static
gboolean
gfte_window_destroyed_cb
(
GtkWidget
*
widget
,
GdkEvent
*
event
,
gpointer
data
)
{
if
(
editor
.
changed
)
{
gfte_modified_show
(
GFTE_MODIFIED_CLOSE
,
NULL
);
return
TRUE
;
}
else
{
gfte_cleanup
();
return
FALSE
;
}
}
static
void
gfte_build_window
()
{
editor
.
tooltips
=
gtk_tooltips_new
();
g_object_ref
(
G_OBJECT
(
editor
.
tooltips
));
gtk_object_sink
(
GTK_OBJECT
(
editor
.
tooltips
));
editor
.
window
=
gtk_window_new
(
GTK_WINDOW_TOPLEVEL
);
gtk_window_set_title
(
GTK_WINDOW
(
editor
.
window
),
_
(
"Guifications Theme Editor"
));
g_signal_connect
(
G_OBJECT
(
editor
.
window
),
"delete-event"
,
G_CALLBACK
(
gfte_window_destroyed_cb
),
NULL
);
editor
.
vbox
=
gtk_vbox_new
(
FALSE
,
4
);
gtk_container_add
(
GTK_CONTAINER
(
editor
.
window
),
editor
.
vbox
);
gfte_build_toolbar
();
editor
.
hbox
=
gtk_hbox_new
(
FALSE
,
4
);
gtk_box_pack_start
(
GTK_BOX
(
editor
.
vbox
),
editor
.
hbox
,
TRUE
,
TRUE
,
0
);
gfte_build_tree
();
gfte_build_notebook
();
}
/*******************************************************************************
* Basic helpers
******************************************************************************/
void
gfte_show
()
{
if
(
editor
.
window
)
{
gtk_window_present
(
GTK_WINDOW
(
editor
.
window
));
return
;
}
gfte_build_window
();
gtk_widget_show_all
(
editor
.
window
);
}
/*******************************************************************************
* Exports
******************************************************************************/
void
gf_theme_editor_init
(
PurplePlugin
*
plugin
)
{
plugin_handle
=
plugin
;
}
void
gf_theme_editor_uninit
()
{
if
(
editor
.
window
)
gtk_widget_destroy
(
editor
.
window
);
gfte_cleanup
();
editor
.
window
=
NULL
;
}
void
gf_theme_editor_show
(
const
gchar
*
filename
)
{
/* if filename is NULL a new theme is being created */
if
(
!
filename
)
{
gfte_setup
(
NULL
);
gfte_show
();
return
;
}
/* theme editor isn't showing so we create it */
if
(
!
editor
.
window
)
{
gfte_setup
(
filename
);
gfte_show
();
return
;
}
/* theme editor is showing, so we check the file names, if they match, we just show
* the editor. If they don't, we check if the theme is modified. If it is, then we
* show the modified dialog, and save it if the user wants it saved, and then open
* the other theme.
*/
if
(
editor
.
filename
)
{
if
(
!
g_ascii_strcasecmp
(
editor
.
filename
,
filename
))
{
gfte_show
();
}
else
{
if
(
editor
.
changed
)
gfte_modified_show
(
GFTE_MODIFIED_OPEN
,
filename
);
else
gfte_setup
(
filename
);
}
}
return
;
}