pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Update to libadwaita 1.2
20 months ago, Gary Kramlich
cde17b22217f
Update to libadwaita 1.2
Fedora 36 updates finally has it and all of our build agents have it as well,
so it's time to move to it, so we can update a bunch of stuff.
Testing Done:
compiled
Reviewed at https://reviews.imfreedom.org/r/1988/
/*
* finch
*
* Finch is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include
<glib/gi18n-lib.h>
#include
<purple.h>
#include
<gnt.h>
#include
"gntrequest.h"
typedef
struct
{
void
*
user_data
;
GntWidget
*
dialog
;
GCallback
*
cbs
;
gboolean
save
;
}
FinchFileRequest
;
static
GntWidget
*
setup_request_window
(
const
char
*
title
,
const
char
*
primary
,
const
char
*
secondary
,
PurpleRequestType
type
)
{
GntWidget
*
window
;
window
=
gnt_vbox_new
(
FALSE
);
gnt_box_set_toplevel
(
GNT_BOX
(
window
),
TRUE
);
gnt_box_set_title
(
GNT_BOX
(
window
),
title
);
gnt_box_set_alignment
(
GNT_BOX
(
window
),
GNT_ALIGN_MID
);
if
(
primary
)
gnt_box_add_widget
(
GNT_BOX
(
window
),
gnt_label_new_with_format
(
primary
,
GNT_TEXT_FLAG_BOLD
));
if
(
secondary
)
gnt_box_add_widget
(
GNT_BOX
(
window
),
gnt_label_new
(
secondary
));
g_signal_connect_swapped
(
G_OBJECT
(
window
),
"destroy"
,
G_CALLBACK
(
purple_request_close
),
GINT_TO_POINTER
(
type
));
return
window
;
}
/*
* If the window is closed by the wm (ie, without triggering any of
* the buttons, then do some default callback.
*/
static
void
setup_default_callback
(
GntWidget
*
window
,
gpointer
default_cb
,
gpointer
data
)
{
if
(
default_cb
==
NULL
)
return
;
g_object_set_data
(
G_OBJECT
(
window
),
"default-callback"
,
default_cb
);
g_signal_connect_swapped
(
G_OBJECT
(
window
),
"destroy"
,
G_CALLBACK
(
default_cb
),
data
);
}
static
void
action_performed
(
GntWidget
*
button
,
gpointer
data
)
{
g_signal_handlers_disconnect_matched
(
data
,
G_SIGNAL_MATCH_FUNC
,
0
,
0
,
NULL
,
g_object_get_data
(
data
,
"default-callback"
),
NULL
);
}
/*
* setup_button_box:
* @win: this is the window
* @userdata: the userdata to pass to the primary callbacks
* @cb: the callback
* @data: data for the callback
* @...: (text, primary-callback) pairs, ended by a NULL
*
* The cancellation callback should be the last callback sent.
*/
static
GntWidget
*
setup_button_box
(
GntWidget
*
win
,
gpointer
userdata
,
gpointer
cb
,
gpointer
data
,
...)
{
GntWidget
*
box
;
GntWidget
*
button
=
NULL
;
va_list
list
;
const
char
*
text
;
gpointer
callback
;
box
=
gnt_hbox_new
(
FALSE
);
va_start
(
list
,
data
);
while
((
text
=
va_arg
(
list
,
const
char
*
)))
{
callback
=
va_arg
(
list
,
gpointer
);
button
=
gnt_button_new
(
text
);
gnt_box_add_widget
(
GNT_BOX
(
box
),
button
);
g_object_set_data
(
G_OBJECT
(
button
),
"activate-callback"
,
callback
);
g_object_set_data
(
G_OBJECT
(
button
),
"activate-userdata"
,
userdata
);
g_signal_connect
(
G_OBJECT
(
button
),
"activate"
,
G_CALLBACK
(
action_performed
),
win
);
g_signal_connect
(
G_OBJECT
(
button
),
"activate"
,
G_CALLBACK
(
cb
),
data
);
}
if
(
button
)
g_object_set_data
(
G_OBJECT
(
button
),
"cancellation-function"
,
GINT_TO_POINTER
(
TRUE
));
va_end
(
list
);
return
box
;
}
static
void
notify_input_cb
(
GntWidget
*
button
,
GntWidget
*
entry
)
{
PurpleRequestInputCb
callback
=
g_object_get_data
(
G_OBJECT
(
button
),
"activate-callback"
);
gpointer
data
=
g_object_get_data
(
G_OBJECT
(
button
),
"activate-userdata"
);
const
char
*
text
=
gnt_entry_get_text
(
GNT_ENTRY
(
entry
));
GntWidget
*
window
;
if
(
callback
)
callback
(
data
,
text
);
window
=
gnt_widget_get_toplevel
(
button
);
purple_request_close
(
PURPLE_REQUEST_INPUT
,
window
);
}
static
void
*
finch_request_input
(
const
char
*
title
,
const
char
*
primary
,
const
char
*
secondary
,
const
char
*
default_value
,
gboolean
multiline
,
gboolean
masked
,
gchar
*
hint
,
const
char
*
ok_text
,
GCallback
ok_cb
,
const
char
*
cancel_text
,
GCallback
cancel_cb
,
PurpleRequestCommonParameters
*
cpar
,
void
*
user_data
)
{
GntWidget
*
window
,
*
box
,
*
entry
;
window
=
setup_request_window
(
title
,
primary
,
secondary
,
PURPLE_REQUEST_INPUT
);
entry
=
gnt_entry_new
(
default_value
);
if
(
masked
)
gnt_entry_set_masked
(
GNT_ENTRY
(
entry
),
TRUE
);
gnt_box_add_widget
(
GNT_BOX
(
window
),
entry
);
box
=
setup_button_box
(
window
,
user_data
,
notify_input_cb
,
entry
,
ok_text
,
ok_cb
,
cancel_text
,
cancel_cb
,
NULL
);
gnt_box_add_widget
(
GNT_BOX
(
window
),
box
);
setup_default_callback
(
window
,
cancel_cb
,
user_data
);
gnt_widget_show
(
window
);
return
window
;
}
static
void
finch_close_request
(
PurpleRequestType
type
,
gpointer
ui_handle
)
{
GntWidget
*
widget
=
GNT_WIDGET
(
ui_handle
);
if
(
type
==
PURPLE_REQUEST_FIELDS
)
{
PurpleRequestFields
*
fields
=
g_object_get_data
(
G_OBJECT
(
widget
),
"fields"
);
purple_request_fields_destroy
(
fields
);
}
widget
=
gnt_widget_get_toplevel
(
widget
);
gnt_widget_destroy
(
widget
);
}
static
void
request_choice_cb
(
GntWidget
*
button
,
GntComboBox
*
combo
)
{
PurpleRequestChoiceCb
callback
=
g_object_get_data
(
G_OBJECT
(
button
),
"activate-callback"
);
gpointer
data
=
g_object_get_data
(
G_OBJECT
(
button
),
"activate-userdata"
);
gpointer
choice
=
gnt_combo_box_get_selected_data
(
GNT_COMBO_BOX
(
combo
));
GntWidget
*
window
;
if
(
callback
)
callback
(
data
,
choice
);
window
=
gnt_widget_get_toplevel
(
button
);
purple_request_close
(
PURPLE_REQUEST_INPUT
,
window
);
}
static
void
*
finch_request_choice
(
const
char
*
title
,
const
char
*
primary
,
const
char
*
secondary
,
gpointer
default_value
,
const
char
*
ok_text
,
GCallback
ok_cb
,
const
char
*
cancel_text
,
GCallback
cancel_cb
,
PurpleRequestCommonParameters
*
cpar
,
void
*
user_data
,
va_list
choices
)
{
GntWidget
*
window
,
*
combo
,
*
box
;
const
char
*
text
;
int
val
;
window
=
setup_request_window
(
title
,
primary
,
secondary
,
PURPLE_REQUEST_CHOICE
);
combo
=
gnt_combo_box_new
();
gnt_box_add_widget
(
GNT_BOX
(
window
),
combo
);
while
((
text
=
va_arg
(
choices
,
const
char
*
)))
{
val
=
va_arg
(
choices
,
int
);
gnt_combo_box_add_data
(
GNT_COMBO_BOX
(
combo
),
GINT_TO_POINTER
(
val
+
1
),
text
);
}
gnt_combo_box_set_selected
(
GNT_COMBO_BOX
(
combo
),
default_value
);
box
=
setup_button_box
(
window
,
user_data
,
request_choice_cb
,
combo
,
ok_text
,
ok_cb
,
cancel_text
,
cancel_cb
,
NULL
);
gnt_box_add_widget
(
GNT_BOX
(
window
),
box
);
setup_default_callback
(
window
,
cancel_cb
,
user_data
);
gnt_widget_show
(
window
);
return
window
;
}
static
void
request_action_cb
(
GntWidget
*
button
,
GntWidget
*
window
)
{
PurpleRequestActionCb
callback
=
g_object_get_data
(
G_OBJECT
(
button
),
"activate-callback"
);
gpointer
data
=
g_object_get_data
(
G_OBJECT
(
button
),
"activate-userdata"
);
int
id
=
GPOINTER_TO_INT
(
g_object_get_data
(
G_OBJECT
(
button
),
"activate-id"
));
if
(
callback
)
callback
(
data
,
id
);
purple_request_close
(
PURPLE_REQUEST_ACTION
,
window
);
}
static
void
*
finch_request_action
(
const
char
*
title
,
const
char
*
primary
,
const
char
*
secondary
,
int
default_value
,
PurpleRequestCommonParameters
*
cpar
,
void
*
user_data
,
size_t
actioncount
,
va_list
actions
)
{
GntWidget
*
window
,
*
box
,
*
button
,
*
focus
=
NULL
;
gsize
i
;
window
=
setup_request_window
(
title
,
primary
,
secondary
,
PURPLE_REQUEST_ACTION
);
box
=
gnt_hbox_new
(
FALSE
);
gnt_box_add_widget
(
GNT_BOX
(
window
),
box
);
for
(
i
=
0
;
i
<
actioncount
;
i
++
)
{
const
char
*
text
=
va_arg
(
actions
,
const
char
*
);
PurpleRequestActionCb
callback
=
va_arg
(
actions
,
PurpleRequestActionCb
);
button
=
gnt_button_new
(
text
);
gnt_box_add_widget
(
GNT_BOX
(
box
),
button
);
g_object_set_data
(
G_OBJECT
(
button
),
"activate-callback"
,
callback
);
g_object_set_data
(
G_OBJECT
(
button
),
"activate-userdata"
,
user_data
);
g_object_set_data
(
G_OBJECT
(
button
),
"activate-id"
,
GINT_TO_POINTER
(
i
));
g_signal_connect
(
G_OBJECT
(
button
),
"activate"
,
G_CALLBACK
(
request_action_cb
),
window
);
if
(
default_value
>=
0
&&
i
==
(
gsize
)
default_value
)
focus
=
button
;
}
gnt_widget_show
(
window
);
if
(
focus
)
gnt_box_give_focus_to_child
(
GNT_BOX
(
window
),
focus
);
return
window
;
}
static
void
request_fields_cb
(
GntWidget
*
button
,
PurpleRequestFields
*
fields
)
{
PurpleRequestFieldsCb
callback
=
g_object_get_data
(
G_OBJECT
(
button
),
"activate-callback"
);
gpointer
data
=
g_object_get_data
(
G_OBJECT
(
button
),
"activate-userdata"
);
GList
*
list
;
GntWidget
*
window
;
/* Update the data of the fields. Pidgin does this differently. Instead of
* updating the fields at the end like here, it updates the appropriate field
* instantly whenever a change is made. That allows it to make sure the
* 'required' fields are entered before the user can hit OK. It's not the case
* here, although it can be done. */
for
(
list
=
purple_request_fields_get_groups
(
fields
);
list
;
list
=
list
->
next
)
{
PurpleRequestFieldGroup
*
group
=
list
->
data
;
GList
*
fields
=
purple_request_field_group_get_fields
(
group
);
for
(;
fields
;
fields
=
fields
->
next
)
{
PurpleRequestField
*
field
=
fields
->
data
;
PurpleRequestFieldType
type
=
purple_request_field_get_field_type
(
field
);
if
(
!
purple_request_field_is_visible
(
field
))
continue
;
if
(
type
==
PURPLE_REQUEST_FIELD_BOOLEAN
)
{
GntWidget
*
check
=
purple_request_field_get_ui_data
(
field
);
gboolean
value
=
gnt_check_box_get_checked
(
GNT_CHECK_BOX
(
check
));
purple_request_field_bool_set_value
(
field
,
value
);
}
else
if
(
type
==
PURPLE_REQUEST_FIELD_STRING
)
{
GntWidget
*
entry
=
purple_request_field_get_ui_data
(
field
);
const
char
*
text
=
gnt_entry_get_text
(
GNT_ENTRY
(
entry
));
purple_request_field_string_set_value
(
field
,
(
text
&&
*
text
)
?
text
:
NULL
);
}
else
if
(
type
==
PURPLE_REQUEST_FIELD_INTEGER
)
{
GntWidget
*
entry
=
purple_request_field_get_ui_data
(
field
);
const
char
*
text
=
gnt_entry_get_text
(
GNT_ENTRY
(
entry
));
int
value
=
(
text
&&
*
text
)
?
atoi
(
text
)
:
0
;
purple_request_field_int_set_value
(
field
,
value
);
}
else
if
(
type
==
PURPLE_REQUEST_FIELD_CHOICE
)
{
GntWidget
*
combo
=
purple_request_field_get_ui_data
(
field
);
gpointer
value
=
gnt_combo_box_get_selected_data
(
GNT_COMBO_BOX
(
combo
));
purple_request_field_choice_set_value
(
field
,
value
);
}
else
if
(
type
==
PURPLE_REQUEST_FIELD_LIST
)
{
GList
*
selected
=
NULL
;
GList
*
list
=
purple_request_field_list_get_items
(
field
);
if
(
purple_request_field_list_get_multi_select
(
field
))
{
GntWidget
*
tree
=
purple_request_field_get_ui_data
(
field
);
for
(;
list
;
list
=
list
->
next
)
{
PurpleKeyValuePair
*
item
=
list
->
data
;
const
char
*
text
=
item
->
key
;
gpointer
key
=
purple_request_field_list_get_data
(
field
,
text
);
if
(
gnt_tree_get_choice
(
GNT_TREE
(
tree
),
key
))
{
selected
=
g_list_prepend
(
selected
,
(
gpointer
)
text
);
}
}
}
else
{
GntWidget
*
combo
=
purple_request_field_get_ui_data
(
field
);
gpointer
data
=
gnt_combo_box_get_selected_data
(
GNT_COMBO_BOX
(
combo
));
for
(;
list
;
list
=
list
->
next
)
{
PurpleKeyValuePair
*
item
=
list
->
data
;
const
char
*
text
=
item
->
key
;
gpointer
key
=
purple_request_field_list_get_data
(
field
,
text
);
if
(
key
==
data
)
{
selected
=
g_list_prepend
(
selected
,
(
gpointer
)
text
);
break
;
}
}
}
purple_request_field_list_set_selected
(
field
,
selected
);
g_list_free
(
selected
);
}
else
if
(
type
==
PURPLE_REQUEST_FIELD_ACCOUNT
)
{
GntWidget
*
combo
=
purple_request_field_get_ui_data
(
field
);
PurpleAccount
*
acc
=
gnt_combo_box_get_selected_data
(
GNT_COMBO_BOX
(
combo
));
purple_request_field_account_set_value
(
field
,
acc
);
}
}
}
purple_notify_close_with_handle
(
button
);
if
(
!
g_object_get_data
(
G_OBJECT
(
button
),
"cancellation-function"
)
&&
(
!
purple_request_fields_all_required_filled
(
fields
)
||
!
purple_request_fields_all_valid
(
fields
)))
{
purple_notify_error
(
button
,
_
(
"Error"
),
_
(
"You must properly fill all the required fields."
),
_
(
"The required fields are underlined."
),
NULL
);
return
;
}
if
(
callback
)
callback
(
data
,
fields
);
window
=
gnt_widget_get_toplevel
(
button
);
purple_request_close
(
PURPLE_REQUEST_FIELDS
,
window
);
}
static
void
update_selected_account
(
GntEntry
*
username
,
const
char
*
start
,
const
char
*
end
,
GntComboBox
*
accountlist
)
{
GList
*
accounts
=
gnt_tree_get_rows
(
GNT_TREE
(
gnt_combo_box_get_dropdown
(
accountlist
)));
const
char
*
name
=
gnt_entry_get_text
(
username
);
while
(
accounts
)
{
if
(
purple_blist_find_buddy
(
accounts
->
data
,
name
))
{
gnt_combo_box_set_selected
(
accountlist
,
accounts
->
data
);
gnt_widget_draw
(
GNT_WIDGET
(
accountlist
));
break
;
}
accounts
=
accounts
->
next
;
}
}
static
GntWidget
*
create_boolean_field
(
PurpleRequestField
*
field
)
{
const
char
*
label
=
purple_request_field_get_label
(
field
);
GntWidget
*
check
=
gnt_check_box_new
(
label
);
gnt_check_box_set_checked
(
GNT_CHECK_BOX
(
check
),
purple_request_field_bool_get_default_value
(
field
));
return
check
;
}
static
GntWidget
*
create_string_field
(
PurpleRequestField
*
field
,
GntWidget
**
username
)
{
const
char
*
hint
=
purple_request_field_get_field_type_hint
(
field
);
GntWidget
*
entry
=
gnt_entry_new
(
purple_request_field_string_get_default_value
(
field
));
gnt_entry_set_masked
(
GNT_ENTRY
(
entry
),
purple_request_field_string_is_masked
(
field
));
if
(
hint
&&
g_str_has_prefix
(
hint
,
"screenname"
))
{
PurpleBlistNode
*
node
=
purple_blist_get_default_root
();
gboolean
offline
=
g_str_has_suffix
(
hint
,
"all"
);
for
(;
node
;
node
=
purple_blist_node_next
(
node
,
offline
))
{
if
(
!
PURPLE_IS_BUDDY
(
node
))
continue
;
gnt_entry_add_suggest
(
GNT_ENTRY
(
entry
),
purple_buddy_get_name
((
PurpleBuddy
*
)
node
));
}
gnt_entry_set_always_suggest
(
GNT_ENTRY
(
entry
),
TRUE
);
if
(
username
)
*
username
=
entry
;
}
else
if
(
purple_strequal
(
hint
,
"group"
))
{
PurpleBlistNode
*
node
;
for
(
node
=
purple_blist_get_default_root
();
node
;
node
=
purple_blist_node_get_sibling_next
(
node
))
{
if
(
PURPLE_IS_GROUP
(
node
))
gnt_entry_add_suggest
(
GNT_ENTRY
(
entry
),
purple_group_get_name
((
PurpleGroup
*
)
node
));
}
}
return
entry
;
}
static
GntWidget
*
create_integer_field
(
PurpleRequestField
*
field
)
{
char
str
[
256
];
int
val
=
purple_request_field_int_get_default_value
(
field
);
GntWidget
*
entry
;
g_snprintf
(
str
,
sizeof
(
str
),
"%d"
,
val
);
entry
=
gnt_entry_new
(
str
);
gnt_entry_set_flag
(
GNT_ENTRY
(
entry
),
GNT_ENTRY_FLAG_INT
);
return
entry
;
}
static
GntWidget
*
create_choice_field
(
PurpleRequestField
*
field
)
{
GntWidget
*
combo
=
gnt_combo_box_new
();
for
(
GList
*
it
=
purple_request_field_choice_get_elements
(
field
);
it
!=
NULL
;
it
=
g_list_next
(
it
))
{
PurpleKeyValuePair
*
choice
=
it
->
data
;
gnt_combo_box_add_data
(
GNT_COMBO_BOX
(
combo
),
choice
->
value
,
choice
->
key
);
}
gnt_combo_box_set_selected
(
GNT_COMBO_BOX
(
combo
),
purple_request_field_choice_get_default_value
(
field
));
return
combo
;
}
static
GntWidget
*
create_list_field
(
PurpleRequestField
*
field
)
{
GntWidget
*
ret
=
NULL
;
GList
*
list
=
purple_request_field_list_get_items
(
field
);
if
(
purple_request_field_list_get_multi_select
(
field
))
{
GntWidget
*
tree
=
gnt_tree_new
();
for
(;
list
;
list
=
list
->
next
)
{
PurpleKeyValuePair
*
item
=
list
->
data
;
const
char
*
text
=
item
->
key
;
gpointer
key
=
purple_request_field_list_get_data
(
field
,
text
);
gnt_tree_add_choice
(
GNT_TREE
(
tree
),
key
,
gnt_tree_create_row
(
GNT_TREE
(
tree
),
text
),
NULL
,
NULL
);
if
(
purple_request_field_list_is_selected
(
field
,
text
))
gnt_tree_set_choice
(
GNT_TREE
(
tree
),
key
,
TRUE
);
}
ret
=
tree
;
}
else
{
GntWidget
*
combo
=
gnt_combo_box_new
();
for
(;
list
;
list
=
list
->
next
)
{
PurpleKeyValuePair
*
item
=
list
->
data
;
const
char
*
text
=
item
->
key
;
gpointer
key
=
purple_request_field_list_get_data
(
field
,
text
);
gnt_combo_box_add_data
(
GNT_COMBO_BOX
(
combo
),
key
,
text
);
if
(
purple_request_field_list_is_selected
(
field
,
text
))
gnt_combo_box_set_selected
(
GNT_COMBO_BOX
(
combo
),
key
);
}
ret
=
combo
;
}
return
ret
;
}
static
void
add_account_to_combo
(
GntWidget
*
combo
,
PurpleAccount
*
account
)
{
char
*
text
=
NULL
;
text
=
g_strdup_printf
(
"%s (%s)"
,
purple_account_get_username
(
account
),
purple_account_get_protocol_name
(
account
));
gnt_combo_box_add_data
(
GNT_COMBO_BOX
(
combo
),
account
,
text
);
g_free
(
text
);
}
static
GntWidget
*
create_account_field
(
PurpleRequestField
*
field
)
{
gboolean
all
;
PurpleAccount
*
def
;
GntWidget
*
combo
=
gnt_combo_box_new
();
all
=
purple_request_field_account_get_show_all
(
field
);
def
=
purple_request_field_account_get_value
(
field
);
if
(
!
def
)
{
def
=
purple_request_field_account_get_default_value
(
field
);
}
if
(
all
)
{
GListModel
*
manager_model
=
NULL
;
guint
n_items
=
0
;
manager_model
=
purple_account_manager_get_default_as_model
();
n_items
=
g_list_model_get_n_items
(
manager_model
);
for
(
guint
index
=
0
;
index
<
n_items
;
index
++
)
{
PurpleAccount
*
account
;
account
=
g_list_model_get_item
(
manager_model
,
index
);
add_account_to_combo
(
combo
,
account
);
if
(
account
==
def
)
{
gnt_combo_box_set_selected
(
GNT_COMBO_BOX
(
combo
),
account
);
}
g_object_unref
(
account
);
}
}
else
{
GList
*
list
=
purple_connections_get_all
();
for
(;
list
;
list
=
list
->
next
)
{
PurpleAccount
*
account
=
NULL
;
account
=
purple_connection_get_account
(
list
->
data
);
add_account_to_combo
(
combo
,
account
);
if
(
account
==
def
)
{
gnt_combo_box_set_selected
(
GNT_COMBO_BOX
(
combo
),
account
);
}
}
}
gnt_widget_set_size
(
combo
,
20
,
3
);
/* ew */
return
combo
;
}
static
void
multifield_extra_cb
(
GntWidget
*
button
,
PurpleRequestFields
*
allfields
)
{
PurpleRequestFieldsCb
cb
;
gpointer
cb_data
;
gpointer
handle
;
handle
=
g_object_get_data
(
G_OBJECT
(
button
),
"ui-handle"
);
cb
=
g_object_get_data
(
G_OBJECT
(
button
),
"extra-cb"
);
cb_data
=
g_object_get_data
(
G_OBJECT
(
button
),
"extra-cb-data"
);
if
(
cb
!=
NULL
)
cb
(
cb_data
,
allfields
);
action_performed
(
button
,
handle
);
purple_request_close
(
PURPLE_REQUEST_FIELDS
,
handle
);
}
static
void
*
finch_request_fields
(
const
char
*
title
,
const
char
*
primary
,
const
char
*
secondary
,
PurpleRequestFields
*
allfields
,
const
char
*
ok
,
GCallback
ok_cb
,
const
char
*
cancel
,
GCallback
cancel_cb
,
PurpleRequestCommonParameters
*
cpar
,
void
*
userdata
)
{
GntWidget
*
window
,
*
box
;
GList
*
grlist
;
GntWidget
*
username
=
NULL
,
*
accountlist
=
NULL
;
PurpleRequestHelpCb
help_cb
;
gpointer
help_data
;
GSList
*
extra_actions
;
window
=
setup_request_window
(
title
,
primary
,
secondary
,
PURPLE_REQUEST_FIELDS
);
/* This is how it's going to work: the request-groups are going to be
* stacked vertically one after the other. A GntLine will be separating
* the groups. */
box
=
gnt_vbox_new
(
FALSE
);
gnt_box_set_pad
(
GNT_BOX
(
box
),
0
);
gnt_box_set_fill
(
GNT_BOX
(
box
),
TRUE
);
for
(
grlist
=
purple_request_fields_get_groups
(
allfields
);
grlist
;
grlist
=
grlist
->
next
)
{
PurpleRequestFieldGroup
*
group
=
grlist
->
data
;
GList
*
fields
=
purple_request_field_group_get_fields
(
group
);
GntWidget
*
hbox
;
const
char
*
title
=
purple_request_field_group_get_title
(
group
);
if
(
title
)
gnt_box_add_widget
(
GNT_BOX
(
box
),
gnt_label_new_with_format
(
title
,
GNT_TEXT_FLAG_BOLD
));
for
(;
fields
;
fields
=
fields
->
next
)
{
PurpleRequestField
*
field
=
fields
->
data
;
PurpleRequestFieldType
type
=
purple_request_field_get_field_type
(
field
);
const
char
*
label
=
purple_request_field_get_label
(
field
);
if
(
!
purple_request_field_is_visible
(
field
))
continue
;
hbox
=
gnt_hbox_new
(
TRUE
);
/* hrm */
gnt_box_add_widget
(
GNT_BOX
(
box
),
hbox
);
if
(
type
!=
PURPLE_REQUEST_FIELD_BOOLEAN
&&
label
)
{
GntWidget
*
l
;
if
(
purple_request_field_is_required
(
field
))
l
=
gnt_label_new_with_format
(
label
,
GNT_TEXT_FLAG_UNDERLINE
);
else
l
=
gnt_label_new
(
label
);
gnt_widget_set_size
(
l
,
0
,
1
);
gnt_box_add_widget
(
GNT_BOX
(
hbox
),
l
);
}
if
(
type
==
PURPLE_REQUEST_FIELD_BOOLEAN
)
{
purple_request_field_set_ui_data
(
field
,
create_boolean_field
(
field
));
}
else
if
(
type
==
PURPLE_REQUEST_FIELD_STRING
)
{
purple_request_field_set_ui_data
(
field
,
create_string_field
(
field
,
&
username
));
}
else
if
(
type
==
PURPLE_REQUEST_FIELD_INTEGER
)
{
purple_request_field_set_ui_data
(
field
,
create_integer_field
(
field
));
}
else
if
(
type
==
PURPLE_REQUEST_FIELD_CHOICE
)
{
purple_request_field_set_ui_data
(
field
,
create_choice_field
(
field
));
}
else
if
(
type
==
PURPLE_REQUEST_FIELD_LIST
)
{
purple_request_field_set_ui_data
(
field
,
create_list_field
(
field
));
}
else
if
(
type
==
PURPLE_REQUEST_FIELD_ACCOUNT
)
{
accountlist
=
create_account_field
(
field
);
purple_request_field_set_ui_data
(
field
,
accountlist
);
}
else
{
purple_request_field_set_ui_data
(
field
,
gnt_label_new_with_format
(
_
(
"Not implemented yet."
),
GNT_TEXT_FLAG_BOLD
));
}
gnt_box_set_alignment
(
GNT_BOX
(
hbox
),
GNT_ALIGN_MID
);
gnt_box_add_widget
(
GNT_BOX
(
hbox
),
GNT_WIDGET
(
purple_request_field_get_ui_data
(
field
)));
}
if
(
grlist
->
next
)
gnt_box_add_widget
(
GNT_BOX
(
box
),
gnt_hline_new
());
}
gnt_box_add_widget
(
GNT_BOX
(
window
),
box
);
box
=
setup_button_box
(
window
,
userdata
,
request_fields_cb
,
allfields
,
ok
,
ok_cb
,
cancel
,
cancel_cb
,
NULL
);
extra_actions
=
purple_request_cpar_get_extra_actions
(
cpar
);
for
(
GSList
*
it
=
extra_actions
;
it
;
it
=
it
->
next
)
{
PurpleKeyValuePair
*
extra_action
=
it
->
data
;
GntWidget
*
button
=
gnt_button_new
(
extra_action
->
key
);
gnt_box_add_widget_in_front
(
GNT_BOX
(
box
),
button
);
g_object_set_data
(
G_OBJECT
(
button
),
"ui-handle"
,
window
);
g_object_set_data
(
G_OBJECT
(
button
),
"extra-cb"
,
extra_action
->
value
);
g_object_set_data
(
G_OBJECT
(
button
),
"extra-cb-data"
,
userdata
);
g_signal_connect
(
G_OBJECT
(
button
),
"activate"
,
G_CALLBACK
(
multifield_extra_cb
),
allfields
);
}
help_cb
=
purple_request_cpar_get_help_cb
(
cpar
,
&
help_data
);
if
(
help_cb
)
{
GntWidget
*
button
=
gnt_button_new
(
_
(
"Help"
));
gnt_box_add_widget_in_front
(
GNT_BOX
(
box
),
button
);
g_signal_connect_swapped
(
G_OBJECT
(
button
),
"activate"
,
G_CALLBACK
(
help_cb
),
help_data
);
}
gnt_box_add_widget
(
GNT_BOX
(
window
),
box
);
setup_default_callback
(
window
,
cancel_cb
,
userdata
);
gnt_widget_show
(
window
);
if
(
username
&&
accountlist
)
{
g_signal_connect
(
username
,
"completion"
,
G_CALLBACK
(
update_selected_account
),
accountlist
);
}
g_object_set_data
(
G_OBJECT
(
window
),
"fields"
,
allfields
);
return
window
;
}
static
void
file_cancel_cb
(
GntWidget
*
wid
,
gpointer
fq
)
{
FinchFileRequest
*
data
=
fq
;
if
(
data
->
dialog
==
NULL
)
{
/* We've already handled this request, and are in the destroy handler. */
return
;
}
if
(
data
->
cbs
[
1
]
!=
NULL
)
((
PurpleRequestFileCb
)
data
->
cbs
[
1
])(
data
->
user_data
,
NULL
);
purple_request_close
(
PURPLE_REQUEST_FILE
,
data
->
dialog
);
data
->
dialog
=
NULL
;
}
static
void
file_ok_cb
(
GntWidget
*
widget
,
const
char
*
path
,
const
char
*
file
,
gpointer
fq
)
{
FinchFileRequest
*
data
=
fq
;
char
*
dir
=
g_path_get_dirname
(
path
);
if
(
data
->
cbs
[
0
]
!=
NULL
)
((
PurpleRequestFileCb
)
data
->
cbs
[
0
])(
data
->
user_data
,
file
);
purple_prefs_set_path
(
data
->
save
?
"/finch/filelocations/last_save_folder"
:
"/finch/filelocations/last_open_folder"
,
dir
);
g_free
(
dir
);
purple_request_close
(
PURPLE_REQUEST_FILE
,
data
->
dialog
);
data
->
dialog
=
NULL
;
}
static
void
file_request_destroy
(
FinchFileRequest
*
data
)
{
g_free
(
data
->
cbs
);
g_free
(
data
);
}
static
FinchFileRequest
*
finch_file_request_window
(
const
char
*
title
,
const
char
*
path
,
GCallback
ok_cb
,
GCallback
cancel_cb
,
void
*
user_data
)
{
GntWidget
*
window
=
gnt_file_sel_new
();
GntFileSel
*
sel
=
GNT_FILE_SEL
(
window
);
FinchFileRequest
*
data
=
g_new0
(
FinchFileRequest
,
1
);
data
->
user_data
=
user_data
;
data
->
cbs
=
g_new0
(
GCallback
,
2
);
data
->
cbs
[
0
]
=
ok_cb
;
data
->
cbs
[
1
]
=
cancel_cb
;
data
->
dialog
=
window
;
gnt_box_set_title
(
GNT_BOX
(
window
),
title
);
gnt_file_sel_set_current_location
(
sel
,
(
path
&&
*
path
)
?
path
:
purple_home_dir
());
g_signal_connect
(
G_OBJECT
(
sel
),
"destroy"
,
G_CALLBACK
(
file_cancel_cb
),
data
);
g_signal_connect
(
G_OBJECT
(
sel
),
"cancelled"
,
G_CALLBACK
(
file_cancel_cb
),
data
);
g_signal_connect
(
G_OBJECT
(
sel
),
"file_selected"
,
G_CALLBACK
(
file_ok_cb
),
data
);
g_object_set_data_full
(
G_OBJECT
(
window
),
"filerequestdata"
,
data
,
(
GDestroyNotify
)
file_request_destroy
);
return
data
;
}
static
void
*
finch_request_file
(
const
char
*
title
,
const
char
*
filename
,
gboolean
savedialog
,
GCallback
ok_cb
,
GCallback
cancel_cb
,
PurpleRequestCommonParameters
*
cpar
,
void
*
user_data
)
{
FinchFileRequest
*
data
;
const
char
*
path
;
path
=
purple_prefs_get_path
(
savedialog
?
"/finch/filelocations/last_save_folder"
:
"/finch/filelocations/last_open_folder"
);
data
=
finch_file_request_window
(
title
?
title
:
(
savedialog
?
_
(
"Save File..."
)
:
_
(
"Open File..."
)),
path
,
ok_cb
,
cancel_cb
,
user_data
);
data
->
save
=
savedialog
;
if
(
savedialog
)
gnt_file_sel_set_suggested_filename
(
GNT_FILE_SEL
(
data
->
dialog
),
filename
);
gnt_widget_show
(
data
->
dialog
);
return
data
->
dialog
;
}
static
void
*
finch_request_folder
(
const
char
*
title
,
const
char
*
dirname
,
GCallback
ok_cb
,
GCallback
cancel_cb
,
PurpleRequestCommonParameters
*
cpar
,
void
*
user_data
)
{
FinchFileRequest
*
data
;
data
=
finch_file_request_window
(
title
?
title
:
_
(
"Choose Location..."
),
dirname
,
ok_cb
,
cancel_cb
,
user_data
);
data
->
save
=
TRUE
;
gnt_file_sel_set_dirs_only
(
GNT_FILE_SEL
(
data
->
dialog
),
TRUE
);
gnt_widget_show
(
data
->
dialog
);
return
data
->
dialog
;
}
static
PurpleRequestUiOps
uiops
=
{
.
request_input
=
finch_request_input
,
.
request_choice
=
finch_request_choice
,
.
request_action
=
finch_request_action
,
.
request_fields
=
finch_request_fields
,
.
request_file
=
finch_request_file
,
.
request_folder
=
finch_request_folder
,
.
close_request
=
finch_close_request
,
};
PurpleRequestUiOps
*
finch_request_get_ui_ops
(
void
)
{
return
&
uiops
;
}
void
finch_request_init
(
void
)
{
}
void
finch_request_uninit
(
void
)
{
}
void
finch_request_save_in_prefs
(
gpointer
data
,
PurpleRequestFields
*
allfields
)
{
GList
*
list
;
for
(
list
=
purple_request_fields_get_groups
(
allfields
);
list
;
list
=
list
->
next
)
{
PurpleRequestFieldGroup
*
group
=
list
->
data
;
GList
*
fields
=
purple_request_field_group_get_fields
(
group
);
for
(;
fields
;
fields
=
fields
->
next
)
{
PurpleRequestField
*
field
=
fields
->
data
;
PurpleRequestFieldType
type
=
purple_request_field_get_field_type
(
field
);
PurplePrefType
pt
;
gpointer
val
=
NULL
;
const
char
*
id
=
purple_request_field_get_id
(
field
);
switch
(
type
)
{
case
PURPLE_REQUEST_FIELD_LIST
:
val
=
purple_request_field_list_get_selected
(
field
)
->
data
;
val
=
purple_request_field_list_get_data
(
field
,
val
);
break
;
case
PURPLE_REQUEST_FIELD_BOOLEAN
:
val
=
GINT_TO_POINTER
(
purple_request_field_bool_get_value
(
field
));
break
;
case
PURPLE_REQUEST_FIELD_INTEGER
:
val
=
GINT_TO_POINTER
(
purple_request_field_int_get_value
(
field
));
break
;
case
PURPLE_REQUEST_FIELD_STRING
:
val
=
(
gpointer
)
purple_request_field_string_get_value
(
field
);
break
;
default
:
break
;
}
pt
=
purple_prefs_get_pref_type
(
id
);
switch
(
pt
)
{
case
PURPLE_PREF_INT
:
{
long
int
tmp
=
GPOINTER_TO_INT
(
val
);
if
(
type
==
PURPLE_REQUEST_FIELD_LIST
)
{
/* Lists always return string */
if
(
sscanf
(
val
,
"%ld"
,
&
tmp
)
!=
1
)
tmp
=
0
;
}
purple_prefs_set_int
(
id
,
(
gint
)
tmp
);
break
;
}
case
PURPLE_PREF_BOOLEAN
:
purple_prefs_set_bool
(
id
,
GPOINTER_TO_INT
(
val
));
break
;
case
PURPLE_PREF_STRING
:
purple_prefs_set_string
(
id
,
val
);
break
;
default
:
break
;
}
}
}
}
GntWidget
*
finch_request_field_get_widget
(
PurpleRequestField
*
field
)
{
GntWidget
*
ret
=
NULL
;
switch
(
purple_request_field_get_field_type
(
field
))
{
case
PURPLE_REQUEST_FIELD_BOOLEAN
:
ret
=
create_boolean_field
(
field
);
break
;
case
PURPLE_REQUEST_FIELD_STRING
:
ret
=
create_string_field
(
field
,
NULL
);
break
;
case
PURPLE_REQUEST_FIELD_INTEGER
:
ret
=
create_integer_field
(
field
);
break
;
case
PURPLE_REQUEST_FIELD_CHOICE
:
ret
=
create_choice_field
(
field
);
break
;
case
PURPLE_REQUEST_FIELD_LIST
:
ret
=
create_list_field
(
field
);
break
;
case
PURPLE_REQUEST_FIELD_ACCOUNT
:
ret
=
create_account_field
(
field
);
break
;
default
:
purple_debug_error
(
"GntRequest"
,
"Unimplemented request-field %d
\n
"
,
purple_request_field_get_field_type
(
field
));
break
;
}
return
ret
;
}