1 // Copyright (C) 2010-2015 Petr Pavlu <setup@dagobah.cz>
3 // This file is part of CenterIM.
5 // CenterIM is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // CenterIM is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with CenterIM. If not, see <http://www.gnu.org/licenses/>.
24 #include <cppconsui/InputDialog.h>
25 #include <cppconsui/Spacer.h>
28 Request
*Request::my_instance_
= nullptr;
30 Request
*Request::instance()
35 Request::RequestDialog::RequestDialog(const char *title
, const char *primary
,
36 const char *secondary
, const char *ok_text
, GCallback ok_cb
,
37 const char *cancel_text
, GCallback cancel_cb
, void *user_data
)
38 : SplitDialog(title
), ok_cb_(ok_cb
), cancel_cb_(cancel_cb
),
41 setColorScheme(CenterIM::SCHEME_GENERALWINDOW
);
43 lbox_
= new CppConsUI::ListBox(AUTOSIZE
, AUTOSIZE
);
45 lbox_
->appendWidget(*(new CppConsUI::Label(AUTOSIZE
, 1, primary
)));
46 if (primary
&& secondary
)
47 lbox_
->appendWidget(*(new CppConsUI::Spacer(AUTOSIZE
, 1)));
49 lbox_
->appendWidget(*(new CppConsUI::Label(AUTOSIZE
, 1, secondary
)));
50 if (primary
|| secondary
)
51 lbox_
->appendWidget(*(new CppConsUI::HorizontalLine(AUTOSIZE
)));
54 if (ok_text
!= nullptr)
55 addButton(ok_text
, RESPONSE_OK
);
56 if (ok_text
!= nullptr && cancel_text
!= nullptr)
58 if (cancel_text
!= nullptr)
59 addButton(cancel_text
, RESPONSE_CANCEL
);
60 signal_response
.connect(sigc::mem_fun(this, &RequestDialog::responseHandler
));
65 void Request::RequestDialog::onScreenResized()
67 moveResizeRect(CENTERIM
->getScreenArea(CenterIM::CHAT_AREA
));
70 Request::InputTextDialog::InputTextDialog(const char *title
,
71 const char *primary
, const char *secondary
, const char *default_value
,
72 bool /*masked*/, const char *ok_text
, GCallback ok_cb
,
73 const char *cancel_text
, GCallback cancel_cb
, void *user_data
)
74 : RequestDialog(title
, primary
, secondary
, ok_text
, ok_cb
, cancel_text
,
77 entry_
= new CppConsUI::TextEntry(AUTOSIZE
, AUTOSIZE
, default_value
);
78 lbox_
->appendWidget(*entry_
);
82 PurpleRequestType
Request::InputTextDialog::getRequestType()
84 return PURPLE_REQUEST_INPUT
;
87 void Request::InputTextDialog::responseHandler(
88 SplitDialog
& /*activator*/, ResponseType response
)
91 case AbstractDialog::RESPONSE_OK
:
92 if (ok_cb_
!= nullptr)
93 reinterpret_cast<PurpleRequestInputCb
>(ok_cb_
)(
94 user_data_
, entry_
->getText());
96 case AbstractDialog::RESPONSE_CANCEL
:
97 if (cancel_cb_
!= nullptr)
98 reinterpret_cast<PurpleRequestInputCb
>(cancel_cb_
)(
99 user_data_
, entry_
->getText());
102 g_assert_not_reached();
107 Request::ChoiceDialog::ChoiceDialog(const char *title
, const char *primary
,
108 const char *secondary
, int default_value
, const char *ok_text
,
109 GCallback ok_cb
, const char *cancel_text
, GCallback cancel_cb
,
110 void *user_data
, va_list choices
)
111 : RequestDialog(title
, primary
, secondary
, ok_text
, ok_cb
, cancel_text
,
112 cancel_cb
, user_data
)
114 combo_
= new CppConsUI::ComboBox(AUTOSIZE
, 1, _("Selected value"));
115 lbox_
->appendWidget(*combo_
);
119 while ((text
= va_arg(choices
, const char *)) != nullptr) {
120 int resp
= va_arg(choices
, int);
121 combo_
->addOption(text
, resp
);
123 combo_
->setSelectedByData(default_value
);
126 PurpleRequestType
Request::ChoiceDialog::getRequestType()
128 return PURPLE_REQUEST_CHOICE
;
131 void Request::ChoiceDialog::responseHandler(
132 SplitDialog
& /*activator*/, ResponseType response
)
135 case AbstractDialog::RESPONSE_OK
:
136 if (ok_cb_
!= nullptr)
137 reinterpret_cast<PurpleRequestChoiceCb
>(ok_cb_
)(
138 user_data_
, combo_
->getSelectedData());
140 case AbstractDialog::RESPONSE_CANCEL
:
141 if (cancel_cb_
!= nullptr)
142 reinterpret_cast<PurpleRequestChoiceCb
>(cancel_cb_
)(
143 user_data_
, combo_
->getSelectedData());
146 g_assert_not_reached();
151 Request::ActionDialog::ActionDialog(const char *title
, const char *primary
,
152 const char *secondary
, int default_value
, void *user_data
,
153 std::size_t action_count
, va_list actions
)
155 title
, primary
, secondary
, nullptr, nullptr, nullptr, nullptr, user_data
)
157 for (std::size_t i
= 0; i
< action_count
; ++i
) {
158 const char *title
= va_arg(actions
, const char *);
159 GCallback cb
= va_arg(actions
, GCallback
);
161 CppConsUI::Button
*b
= buttons_
->appendItem(title
,
162 sigc::bind(sigc::mem_fun(this, &ActionDialog::onActionChoice
), i
, cb
));
163 if (static_cast<int>(i
) == default_value
)
166 if (i
< action_count
- 1)
167 buttons_
->appendSeparator();
171 PurpleRequestType
Request::ActionDialog::getRequestType()
173 return PURPLE_REQUEST_ACTION
;
176 void Request::ActionDialog::responseHandler(
177 SplitDialog
& /*activator*/, ResponseType
/*response*/)
181 void Request::ActionDialog::onActionChoice(
182 CppConsUI::Button
& /*activator*/, std::size_t i
, GCallback cb
)
185 reinterpret_cast<PurpleRequestActionCb
>(cb
)(user_data_
, i
);
187 // It is possible that the callback action already called
188 // purple_request_destroy() in which case 'this' object is already deleted and
189 // calling close() in such a case leads to an error.
190 Requests
*requests
= &REQUEST
->requests_
;
191 if (requests
->find(this) != requests
->end())
195 Request::FieldsDialog::FieldsDialog(const char *title
, const char *primary
,
196 const char *secondary
, PurpleRequestFields
*request_fields
,
197 const char *ok_text
, GCallback ok_cb
, const char *cancel_text
,
198 GCallback cancel_cb
, void *user_data
)
199 : RequestDialog(title
, primary
, secondary
, ok_text
, ok_cb
, cancel_text
,
200 cancel_cb
, user_data
),
201 fields_(request_fields
)
203 treeview_
= new CppConsUI::TreeView(AUTOSIZE
, AUTOSIZE
);
204 lbox_
->appendWidget(*treeview_
);
206 bool grouping
= true;
207 GList
*groups
= purple_request_fields_get_groups(fields_
);
208 if (groups
== nullptr)
210 if (purple_request_field_group_get_title(
211 static_cast<PurpleRequestFieldGroup
*>(groups
->data
)) == nullptr &&
212 groups
->next
== nullptr)
214 for (; groups
!= nullptr; groups
= groups
->next
) {
215 PurpleRequestFieldGroup
*group
=
216 static_cast<PurpleRequestFieldGroup
*>(groups
->data
);
218 CppConsUI::TreeView::NodeReference parent
= treeview_
->getRootNode();
220 const char *title
= purple_request_field_group_get_title(group
);
221 if (title
== nullptr)
222 title
= _("Settings group");
224 auto button
= new CppConsUI::TreeView::ToggleCollapseButton(title
);
225 parent
= treeview_
->appendNode(treeview_
->getRootNode(), *button
);
228 for (GList
*gfields
= purple_request_field_group_get_fields(group
);
229 gfields
!= nullptr; gfields
= gfields
->next
) {
230 PurpleRequestField
*field
=
231 static_cast<PurpleRequestField
*>(gfields
->data
);
233 if (!purple_request_field_is_visible(field
))
236 PurpleRequestFieldType type
= purple_request_field_get_type(field
);
239 case PURPLE_REQUEST_FIELD_STRING
:
240 treeview_
->appendNode(parent
, *(new StringField(field
)));
242 case PURPLE_REQUEST_FIELD_INTEGER
:
243 treeview_
->appendNode(parent
, *(new IntegerField(field
)));
245 case PURPLE_REQUEST_FIELD_BOOLEAN
:
246 treeview_
->appendNode(parent
, *(new BooleanField(field
)));
248 case PURPLE_REQUEST_FIELD_CHOICE
:
249 treeview_
->appendNode(parent
, *(new ChoiceField(field
)));
251 case PURPLE_REQUEST_FIELD_LIST
:
252 if (purple_request_field_list_get_multi_select(field
))
253 treeview_
->appendNode(parent
, *(new ListFieldMultiple(field
)));
255 treeview_
->appendNode(parent
, *(new ListFieldSingle(field
)));
257 case PURPLE_REQUEST_FIELD_LABEL
:
258 treeview_
->appendNode(parent
, *(new LabelField(field
)));
260 case PURPLE_REQUEST_FIELD_IMAGE
:
261 treeview_
->appendNode(parent
, *(new ImageField(field
)));
263 case PURPLE_REQUEST_FIELD_ACCOUNT
:
264 treeview_
->appendNode(parent
, *(new AccountField(field
)));
267 LOG
->error(_("Unhandled request field type '%d'."), type
);
273 treeview_
->grabFocus();
276 PurpleRequestType
Request::FieldsDialog::getRequestType()
278 return PURPLE_REQUEST_FIELDS
;
281 Request::FieldsDialog::StringField::StringField(PurpleRequestField
*field
)
282 : Button(FLAG_VALUE
), field_(field
)
284 g_assert(field_
!= nullptr);
286 if (purple_request_field_string_is_masked(field_
))
290 g_strdup_printf("%s%s", purple_request_field_is_required(field_
) ? "*" : "",
291 purple_request_field_get_label(field_
));
295 setValue(purple_request_field_string_get_value(field_
));
296 signal_activate
.connect(sigc::mem_fun(this, &StringField::onActivate
));
299 void Request::FieldsDialog::StringField::onActivate(
300 CppConsUI::Button
& /*activator*/)
303 new CppConsUI::InputDialog(purple_request_field_get_label(field_
),
304 purple_request_field_string_get_value(field_
));
305 dialog
->setMasked(isMasked());
306 dialog
->signal_response
.connect(
307 sigc::mem_fun(this, &StringField::responseHandler
));
311 void Request::FieldsDialog::StringField::responseHandler(
312 CppConsUI::InputDialog
&activator
,
313 CppConsUI::AbstractDialog::ResponseType response
)
315 if (response
!= AbstractDialog::RESPONSE_OK
)
318 purple_request_field_string_set_value(field_
, activator
.getText());
319 setValue(purple_request_field_string_get_value(field_
));
322 Request::FieldsDialog::IntegerField::IntegerField(PurpleRequestField
*field
)
323 : Button(FLAG_VALUE
), field_(field
)
325 g_assert(field_
!= nullptr);
328 g_strdup_printf("%s%s", purple_request_field_is_required(field_
) ? "*" : "",
329 purple_request_field_get_label(field_
));
333 setValue(purple_request_field_int_get_value(field_
));
334 signal_activate
.connect(sigc::mem_fun(this, &IntegerField::onActivate
));
337 void Request::FieldsDialog::IntegerField::onActivate(
338 CppConsUI::Button
& /*activator*/)
341 g_strdup_printf("%d", purple_request_field_int_get_value(field_
));
343 new CppConsUI::InputDialog(purple_request_field_get_label(field_
), value
);
345 dialog
->setFlags(CppConsUI::TextEntry::FLAG_NUMERIC
);
346 dialog
->signal_response
.connect(
347 sigc::mem_fun(this, &IntegerField::responseHandler
));
351 void Request::FieldsDialog::IntegerField::responseHandler(
352 CppConsUI::InputDialog
&activator
,
353 CppConsUI::AbstractDialog::ResponseType response
)
355 if (response
!= AbstractDialog::RESPONSE_OK
)
359 if (!Utils::stringToNumber(activator
.getText(), INT_MIN
, INT_MAX
, &num
))
361 purple_request_field_int_set_value(field_
, num
);
362 setValue(purple_request_field_int_get_value(field_
));
365 Request::FieldsDialog::BooleanField::BooleanField(PurpleRequestField
*field
)
368 g_assert(field_
!= nullptr);
371 g_strdup_printf("%s%s", purple_request_field_is_required(field_
) ? "*" : "",
372 purple_request_field_get_label(field_
));
376 setChecked(purple_request_field_bool_get_value(field_
));
377 signal_toggle
.connect(sigc::mem_fun(this, &BooleanField::onToggle
));
380 void Request::FieldsDialog::BooleanField::onToggle(
381 CheckBox
& /*activator*/, bool new_state
)
383 purple_request_field_bool_set_value(field_
, new_state
);
386 Request::FieldsDialog::ChoiceField::ChoiceField(PurpleRequestField
*field
)
389 g_assert(field_
!= nullptr);
392 g_strdup_printf("%s%s", purple_request_field_is_required(field_
) ? "*" : "",
393 purple_request_field_get_label(field_
));
397 for (GList
*list
= purple_request_field_choice_get_labels(field_
);
398 list
!= nullptr; list
= list
->next
)
399 addOption(static_cast<const char *>(list
->data
));
400 setSelected(purple_request_field_choice_get_default_value(field_
));
402 signal_selection_changed
.connect(
403 sigc::mem_fun(this, &ChoiceField::onSelectionChanged
));
406 void Request::FieldsDialog::ChoiceField::onSelectionChanged(
407 ComboBox
& /*activator*/, int new_entry
, const char * /*title*/,
410 purple_request_field_choice_set_value(field_
, new_entry
);
413 Request::FieldsDialog::ListFieldMultiple::ListFieldMultiple(
414 PurpleRequestField
*field
)
415 : ListBox(AUTOSIZE
, 1), field_(field
)
417 g_assert(field_
!= nullptr);
419 // TODO Display label of the field somewhere.
422 for (GList
*list
= purple_request_field_list_get_items(field_
);
423 list
!= nullptr; list
= list
->next
, ++height
)
425 *(new ListFieldItem(field_
, static_cast<const char *>(list
->data
))));
429 Request::FieldsDialog::ListFieldMultiple::ListFieldItem::ListFieldItem(
430 PurpleRequestField
*field
, const char *text
)
433 g_assert(field_
!= nullptr);
436 setChecked(purple_request_field_list_is_selected(field_
, text
));
437 signal_toggle
.connect(sigc::mem_fun(this, &ListFieldItem::onToggle
));
440 void Request::FieldsDialog::ListFieldMultiple::ListFieldItem::onToggle(
441 CheckBox
& /*activator*/, bool new_state
)
444 purple_request_field_list_add_selected(field_
, getText());
446 // XXX This chunk is very slow, libpurple should provide
447 // purple_request_field_list_remove_selected() function.
448 GList
*new_selected
= nullptr;
449 for (GList
*selected
= purple_request_field_list_get_selected(field_
);
450 selected
!= nullptr; selected
= selected
->next
) {
451 const char *data
= static_cast<const char *>(selected
->data
);
452 if (std::strcmp(getText(), data
) != 0)
453 new_selected
= g_list_append(new_selected
, g_strdup(data
));
456 if (new_selected
!= nullptr) {
457 purple_request_field_list_set_selected(field_
, new_selected
);
458 g_list_foreach(new_selected
, reinterpret_cast<GFunc
>(g_free
), nullptr);
459 g_list_free(new_selected
);
462 purple_request_field_list_clear_selected(field_
);
466 Request::FieldsDialog::ListFieldSingle::ListFieldSingle(
467 PurpleRequestField
*field
)
470 g_assert(field_
!= nullptr);
473 g_strdup_printf("%s%s", purple_request_field_is_required(field_
) ? "*" : "",
474 purple_request_field_get_label(field_
));
478 GList
*list
= purple_request_field_list_get_items(field_
);
479 for (int i
= 0; list
!= nullptr; ++i
, list
= list
->next
) {
480 const char *text
= static_cast<const char *>(list
->data
);
482 if (purple_request_field_list_is_selected(field_
, text
))
486 signal_selection_changed
.connect(
487 sigc::mem_fun(this, &ListFieldSingle::onSelectionChanged
));
490 void Request::FieldsDialog::ListFieldSingle::onSelectionChanged(
491 ComboBox
& /*activator*/, int /*new_entry*/, const char *title
,
494 purple_request_field_list_clear_selected(field_
);
495 purple_request_field_list_add_selected(field_
, title
);
498 Request::FieldsDialog::LabelField::LabelField(PurpleRequestField
*field
)
501 g_assert(field_
!= nullptr);
503 setText(purple_request_field_get_label(field_
));
506 Request::FieldsDialog::ImageField::ImageField(PurpleRequestField
*field
)
509 g_assert(field_
!= nullptr);
512 g_strdup_printf("%s%s", purple_request_field_is_required(field_
) ? "*" : "",
513 purple_request_field_get_label(field_
));
519 signal_activate
.connect(sigc::mem_fun(this, &ImageField::onActivate
));
522 void Request::FieldsDialog::ImageField::onActivate(Button
& /*activator*/)
526 Request::FieldsDialog::AccountField::AccountField(PurpleRequestField
*field
)
529 g_assert(field_
!= nullptr);
531 // TODO filter (purple_request_field_account_get_filter())
532 // TODO signals (signed-on, signed-off, account-added, account-removed)
535 g_strdup_printf("%s%s", purple_request_field_is_required(field_
) ? "*" : "",
536 purple_request_field_get_label(field_
));
540 gboolean show_all
= purple_request_field_account_get_show_all(field_
);
541 for (GList
*list
= purple_accounts_get_all(); list
!= nullptr;
543 PurpleAccount
*account
= static_cast<PurpleAccount
*>(list
->data
);
544 if (!show_all
&& !purple_account_is_connected(account
))
548 g_strdup_printf("[%s] %s", purple_account_get_protocol_name(account
),
549 purple_account_get_username(account
));
550 addOptionPtr(label
, account
);
553 setSelectedByDataPtr(purple_request_field_account_get_default_value(field_
));
555 signal_selection_changed
.connect(
556 sigc::mem_fun(this, &AccountField::onAccountChanged
));
559 void Request::FieldsDialog::AccountField::onAccountChanged(
560 Button
& /*activator*/, std::size_t /*new_entry*/, const char * /*title*/,
563 purple_request_field_account_set_value(
564 field_
, reinterpret_cast<PurpleAccount
*>(data
));
567 void Request::FieldsDialog::responseHandler(
568 SplitDialog
& /*activator*/, ResponseType response
)
571 case AbstractDialog::RESPONSE_OK
:
572 if (ok_cb_
!= nullptr)
573 reinterpret_cast<PurpleRequestFieldsCb
>(ok_cb_
)(user_data_
, fields_
);
575 case AbstractDialog::RESPONSE_CANCEL
:
576 if (cancel_cb_
!= nullptr)
577 reinterpret_cast<PurpleRequestFieldsCb
>(cancel_cb_
)(user_data_
, fields_
);
580 g_assert_not_reached();
584 purple_request_fields_destroy(fields_
);
589 std::memset(¢erim_request_ui_ops_
, 0, sizeof(centerim_request_ui_ops_
));
591 // Set the purple request callbacks.
592 centerim_request_ui_ops_
.request_input
= request_input_
;
593 centerim_request_ui_ops_
.request_choice
= request_choice_
;
594 centerim_request_ui_ops_
.request_action
= request_action_
;
595 centerim_request_ui_ops_
.request_fields
= request_fields_
;
596 centerim_request_ui_ops_
.request_file
= request_file_
;
597 centerim_request_ui_ops_
.close_request
= close_request_
;
598 centerim_request_ui_ops_
.request_folder
= request_folder_
;
599 centerim_request_ui_ops_
.request_action_with_icon
= request_action_with_icon_
;
600 purple_request_set_ui_ops(¢erim_request_ui_ops_
);
605 // Close all opened requests.
606 while (!requests_
.empty()) {
607 RequestDialog
*dialog
= *(requests_
.begin());
608 purple_request_close(dialog
->getRequestType(), dialog
);
611 purple_request_set_ui_ops(nullptr);
616 g_assert(my_instance_
== nullptr);
618 my_instance_
= new Request
;
621 void Request::finalize()
623 g_assert(my_instance_
!= nullptr);
626 my_instance_
= nullptr;
629 void Request::onDialogResponse(CppConsUI::SplitDialog
&dialog
,
630 CppConsUI::AbstractDialog::ResponseType
/*response*/)
632 RequestDialog
*rdialog
= dynamic_cast<RequestDialog
*>(&dialog
);
633 g_assert(rdialog
!= nullptr);
635 if (requests_
.find(rdialog
) == requests_
.end())
638 requests_
.erase(rdialog
);
639 purple_request_close(rdialog
->getRequestType(), rdialog
);
642 void *Request::request_input(const char *title
, const char *primary
,
643 const char *secondary
, const char *default_value
, gboolean
/*multiline*/,
644 gboolean masked
, char * /*hint*/, const char *ok_text
, GCallback ok_cb
,
645 const char *cancel_text
, GCallback cancel_cb
, PurpleAccount
* /*account*/,
646 const char * /*who*/, PurpleConversation
* /*conv*/, void *user_data
)
648 LOG
->debug("request_input");
650 auto dialog
= new InputTextDialog(title
, primary
, secondary
, default_value
,
651 masked
, ok_text
, ok_cb
, cancel_text
, cancel_cb
, user_data
);
652 dialog
->signal_response
.connect(
653 sigc::mem_fun(this, &Request::onDialogResponse
));
656 requests_
.insert(dialog
);
660 void *Request::request_choice(const char *title
, const char *primary
,
661 const char *secondary
, int default_value
, const char *ok_text
,
662 GCallback ok_cb
, const char *cancel_text
, GCallback cancel_cb
,
663 PurpleAccount
* /*account*/, const char * /*who*/,
664 PurpleConversation
* /*conv*/, void *user_data
, va_list choices
)
666 LOG
->debug("request_choice");
668 auto dialog
= new ChoiceDialog(title
, primary
, secondary
, default_value
,
669 ok_text
, ok_cb
, cancel_text
, cancel_cb
, user_data
, choices
);
670 dialog
->signal_response
.connect(
671 sigc::mem_fun(this, &Request::onDialogResponse
));
674 requests_
.insert(dialog
);
678 void *Request::request_action(const char *title
, const char *primary
,
679 const char *secondary
, int default_action
, PurpleAccount
* /*account*/,
680 const char * /*who*/, PurpleConversation
* /*conv*/, void *user_data
,
681 std::size_t action_count
, va_list actions
)
683 LOG
->debug("request_action");
685 auto dialog
= new ActionDialog(title
, primary
, secondary
, default_action
,
686 user_data
, action_count
, actions
);
687 dialog
->signal_response
.connect(
688 sigc::mem_fun(this, &Request::onDialogResponse
));
691 requests_
.insert(dialog
);
695 void *Request::request_fields(const char *title
, const char *primary
,
696 const char *secondary
, PurpleRequestFields
*fields
, const char *ok_text
,
697 GCallback ok_cb
, const char *cancel_text
, GCallback cancel_cb
,
698 PurpleAccount
* /*account*/, const char * /*who*/,
699 PurpleConversation
* /*conv*/, void *user_data
)
701 LOG
->debug("request_fields");
703 auto dialog
= new FieldsDialog(title
, primary
, secondary
, fields
, ok_text
,
704 ok_cb
, cancel_text
, cancel_cb
, user_data
);
705 dialog
->signal_response
.connect(
706 sigc::mem_fun(this, &Request::onDialogResponse
));
709 requests_
.insert(dialog
);
713 void *Request::request_file(const char * /*title*/, const char * /*filename*/,
714 gboolean
/*savedialog*/, GCallback
/*ok_cb*/, GCallback
/*cancel_cb*/,
715 PurpleAccount
* /*account*/, const char * /*who*/,
716 PurpleConversation
* /*conv*/, void * /*user_data*/)
721 void Request::close_request(PurpleRequestType
/*type*/, void *ui_handle
)
723 LOG
->debug("close_request");
725 g_assert(ui_handle
!= nullptr);
727 RequestDialog
*dialog
= static_cast<RequestDialog
*>(ui_handle
);
728 if (requests_
.find(dialog
) == requests_
.end())
731 requests_
.erase(dialog
);
735 void *Request::request_folder(const char * /*title*/, const char * /*dirname*/,
736 GCallback
/*ok_cb*/, GCallback
/*cancel_cb*/, PurpleAccount
* /*account*/,
737 const char * /*who*/, PurpleConversation
* /*conv*/, void * /*user_data*/)
742 void *Request::request_action_with_icon(const char * /*title*/,
743 const char * /*primary*/, const char * /*secondary*/, int /*default_action*/,
744 PurpleAccount
* /*account*/, const char * /*who*/,
745 PurpleConversation
* /*conv*/, gconstpointer
/*icon_data*/,
746 gsize
/*icon_size*/, void * /*user_data*/, std::size_t /*action_count*/,
752 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: