comparison src/dialogs.c @ 6340:7a34722b3164

[gaim-migrate @ 6839] DIE old vCard/MultiEntryDlg API! We're better off without you! committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Wed, 30 Jul 2003 08:14:39 +0000
parents 930708df05dd
children 3381f1a85d8f
comparison
equal deleted inserted replaced
6339:cc527f9ba197 6340:7a34722b3164
4142 } 4142 }
4143 4143
4144 gtk_widget_show_all(bbox); 4144 gtk_widget_show_all(bbox);
4145 return button; 4145 return button;
4146 } 4146 }
4147
4148 /*------------------------------------------------------------------------*/
4149 /* The dialog for setting V-Card info */
4150 /*------------------------------------------------------------------------*/
4151 /*
4152 * There are actually two "chunks" of code following: generic "multi-entry dialog"
4153 * support and V-Card dialog specific support.
4154 *
4155 * At first blush, this may seem like an unnecessary duplication of effort given
4156 * that a "set dir info" dialog already exists. However, this is not so because:
4157 *
4158 * 1. V-Cards can have a lot more data in them than what the current
4159 * "set dir" dialog supports.
4160 *
4161 * 2. V-Card data, at least with respect to Jabber, is currently in a
4162 * state of flux. As the data and format changes, all that need be
4163 * changed with the V-Card support I've written is the "template"
4164 * data.
4165 *
4166 * 3. The "multi entry dialog" support itself was originally written
4167 * to support Jabber server user registration (TBD). A "dynamically
4168 * configurable" multi-entry dialog is needed for that, as different
4169 * servers may require different registration information. It just
4170 * turned out to be well-suited to adding V-Card setting support, as
4171 * well :-).
4172 *
4173 * TBD: Add check-box support to the generic multi-entry dialog support so that
4174 * it can be used to "replace" the "set dir info" support?
4175 *
4176 * Multiple-language support. Currently Not In There. I think this should
4177 * be easy. Note that when it's added: if anybody saved their data in
4178 * English, it'll be lost when MLS is added and they'll have to re-enter it.
4179 *
4180 * More "TBDs" noted in the code.
4181 */
4182
4183
4184 /*------------------------------------*/
4185 /* generic multi-entry dialog support */
4186 /*------------------------------------*/
4187
4188 /*
4189 * Print all multi-entry items
4190 *
4191 * Note: Simply a debug helper
4192 */
4193 void multi_entry_item_print_all(const GSList *list) {
4194
4195 int cnt = 0;
4196
4197 /* While there's something to print... */
4198 while(list != NULL) {
4199 fprintf(stderr, "label %2d: \"%s\"", ++cnt, ((MultiEntryData *) (list->data))->label);
4200 if(((MultiEntryData *) (list->data))->text != NULL) {
4201 fprintf(stderr, ", text: \"%s\"", ((MultiEntryData *) (list->data))->text);
4202 }
4203 fputs("\n", stderr);
4204 list = list->next;
4205 }
4206 }
4207
4208 /*
4209 * Print all multi-text items
4210 *
4211 * Note: Simply a debug helper
4212 */
4213 void multi_text_item_print_all(const GSList *list) {
4214
4215 int cnt = 0;
4216
4217 /* While there's something to print... */
4218 while(list != NULL) {
4219 fprintf(stderr, "label %2d: \"%s\"", ++cnt, ((MultiTextData *) (list->data))->label);
4220 if(((MultiTextData *) (list->data))->text != NULL) {
4221 fprintf(stderr, ", text: \"%s\"", ((MultiTextData *) (list->data))->text);
4222 }
4223 fputs("\n", stderr);
4224 list = list->next;
4225 }
4226 }
4227
4228
4229 /*
4230 * Free all multi-entry item allocs and NULL the list pointer
4231 */
4232 void multi_entry_items_free_all(GSList **list)
4233 {
4234
4235 GSList *next = *list;
4236 MultiEntryData *data;
4237
4238 /* While there's something to free() ... */
4239 while(next != NULL) {
4240 data = (MultiEntryData *) next->data;
4241 g_free(data->label);
4242 g_free(data->text);
4243 g_free(data);
4244 next = next->next;
4245 }
4246 g_slist_free(*list);
4247 *list = NULL;
4248 }
4249
4250 /*
4251 * Free all multi-text item allocs and NULL the list pointer
4252 */
4253 void multi_text_items_free_all(GSList **list)
4254 {
4255
4256 GSList *next = *list;
4257 MultiTextData *data;
4258
4259 /* While there's something to free() ... */
4260 while(next != NULL) {
4261 data = (MultiTextData *) next->data;
4262 g_free(data->label);
4263 g_free(data->text);
4264 g_free(data);
4265 next = next->next;
4266 }
4267 g_slist_free(*list);
4268 *list = NULL;
4269 }
4270
4271 /*
4272 * See if a MultiEntryData item contains a given label
4273 *
4274 * See: glib docs for g_slist_compare_custom() for details
4275 */
4276 static gint multi_entry_data_label_compare(gconstpointer data, gconstpointer label)
4277 {
4278 return(strcmp(((MultiEntryData *) (data))->label, (char *) label));
4279 }
4280
4281 /*
4282 * Add a new multi-entry item to list
4283 *
4284 * If adding to existing list: will search the list for existence of
4285 * "label" and change/create "text" entry if necessary.
4286 */
4287
4288 MultiEntryData *multi_entry_list_update(GSList **list, const char *label, const char *text, int add_it)
4289 {
4290 GSList *found;
4291 MultiEntryData *data;
4292
4293 if((found = g_slist_find_custom(*list, (void *)label, multi_entry_data_label_compare)) == NULL) {
4294 if(add_it) {
4295 data = (MultiEntryData *) g_slist_last(*list =
4296 g_slist_append(*list, g_malloc(sizeof(MultiEntryData))))->data;
4297 data->label = strcpy(g_malloc(strlen(label) +1), label);
4298 data->text = NULL;
4299 /*
4300 * default to setting "visible" and editable to TRUE - they can be
4301 * overridden later, of course.
4302 */
4303 data->visible = TRUE;
4304 data->editable = TRUE;
4305 } else {
4306 data = NULL;
4307 }
4308 } else {
4309 data = found->data;
4310 }
4311
4312 if(data != NULL && text != NULL && text[0] != '\0') {
4313 if(data->text == NULL) {
4314 data->text = g_malloc(strlen(text) + 1);
4315 } else {
4316 data->text = g_realloc(data->text, strlen(text) + 1);
4317 }
4318 strcpy(data->text, text);
4319 }
4320
4321 return(data);
4322 }
4323
4324 /*
4325 * See if a MultiTextData item contains a given label
4326 *
4327 * See: glib docs for g_slist_compare_custom() for details
4328 */
4329 static gint multi_text_data_label_compare(gconstpointer data, gconstpointer label)
4330 {
4331 return(strcmp(((MultiTextData *) (data))->label, (char *) label));
4332 }
4333
4334 /*
4335 * Add a new multi-text item to list
4336 *
4337 * If adding to existing list: will search the list for existence of
4338 * "label" and change/create "text" text if necessary.
4339 */
4340
4341 MultiTextData *multi_text_list_update(GSList **list, const char *label, const char *text, int add_it)
4342 {
4343 GSList *found;
4344 MultiTextData *data;
4345
4346 if((found = g_slist_find_custom(*list, (void *)label, multi_text_data_label_compare)) == NULL) {
4347 if(add_it) {
4348 data = (MultiTextData *) g_slist_last(*list =
4349 g_slist_append(*list, g_malloc(sizeof(MultiTextData))))->data;
4350 data->label = strcpy(g_malloc(strlen(label) +1), label);
4351 data->text = NULL;
4352 } else {
4353 data = NULL;
4354 }
4355 } else {
4356 data = found->data;
4357 }
4358
4359 if(data != NULL && text != NULL && text[0] != '\0') {
4360 if(data->text == NULL) {
4361 data->text = g_malloc(strlen(text) + 1);
4362 } else {
4363 data->text = g_realloc(data->text, strlen(text) + 1);
4364 }
4365 strcpy(data->text, text);
4366 }
4367
4368 return(data);
4369 }
4370
4371 /*
4372 * Free-up the multi-entry item list and the MultiEntryDlg
4373 * struct alloc.
4374 */
4375 void multi_entry_free(struct multi_entry_dlg *b)
4376 {
4377 multi_entry_items_free_all(&(b->multi_entry_items));
4378 multi_text_items_free_all(&(b->multi_text_items));
4379 g_free(b->instructions->text);
4380 g_free(b->instructions);
4381 g_free(b->entries_title);
4382 g_free(b);
4383 }
4384
4385 /*
4386 * Multi-Entry dialog "destroyed" catcher
4387 *
4388 * Free-up the multi-entry item list, destroy the dialog widget
4389 * and free the MultiEntryDlg struct alloc.
4390 *
4391 */
4392 void multi_entry_dialog_destroy(GtkWidget *widget, gpointer data)
4393 {
4394 MultiEntryDlg *b = data;
4395
4396 multi_entry_free(b);
4397 }
4398
4399 /*
4400 * Show/Re-show instructions
4401 */
4402 void re_show_multi_entry_instr(MultiInstrData *instructions)
4403 {
4404 if(instructions->label != NULL) {
4405 if(instructions->text == NULL) {
4406 gtk_widget_hide(instructions->label);
4407 } else {
4408 gtk_label_set_text(GTK_LABEL (instructions->label), _(instructions->text));
4409 gtk_widget_show(instructions->label);
4410 }
4411 }
4412 }
4413
4414 /*
4415 * Show/Re-show entry boxes
4416 */
4417 void re_show_multi_entry_entries(GtkWidget **entries_table,
4418 GtkWidget *entries_frame,
4419 GSList *multi_entry_items)
4420 {
4421 GtkWidget *label;
4422 GSList *multi_entry;
4423 MultiEntryData *med;
4424 int rows, row_num, col_num, col_offset;
4425 int cols = 1;
4426
4427 /* Figure-out number of rows needed for table */
4428 if((rows = g_slist_length(multi_entry_items)) > 9) {
4429 rows /= 2;
4430 ++cols;
4431 }
4432
4433 if(*entries_table != NULL) {
4434 gtk_widget_destroy(GTK_WIDGET (*entries_table));
4435 }
4436 *entries_table = gtk_table_new(rows, 3 * cols, FALSE);
4437 gtk_container_add(GTK_CONTAINER (entries_frame), *entries_table);
4438
4439 for(col_num = 0, multi_entry = multi_entry_items; col_num < cols && multi_entry != NULL;
4440 ++col_num) {
4441 col_offset = col_num * 3;
4442 for(row_num = 0; row_num < rows && multi_entry != NULL;
4443 ++row_num, multi_entry = multi_entry->next) {
4444
4445 med = (MultiEntryData *) multi_entry->data;
4446
4447 label = gtk_label_new(_(med->label));
4448 gtk_misc_set_alignment(GTK_MISC(label), (gfloat) 1.0, (gfloat) 0.5);
4449 gtk_table_attach_defaults(GTK_TABLE (*entries_table), label,
4450 col_offset, 1 + col_offset, row_num, row_num +1);
4451 gtk_widget_show(label);
4452
4453 label = gtk_label_new(": ");
4454 gtk_misc_set_alignment(GTK_MISC(label), (gfloat) 0.0, (gfloat) 0.5);
4455 gtk_table_attach_defaults(GTK_TABLE (*entries_table), label,
4456 1 + col_offset, 2 + col_offset, row_num, row_num +1);
4457 gtk_widget_show(label);
4458
4459 med->widget = gtk_entry_new();
4460 gtk_entry_set_max_length(GTK_ENTRY(med->widget), 50);
4461 if(med->text != NULL) {
4462 gtk_entry_set_text(GTK_ENTRY (med->widget), med->text);
4463 }
4464 gtk_entry_set_visibility(GTK_ENTRY (med->widget), med->visible);
4465 gtk_editable_set_editable(GTK_EDITABLE(med->widget), med->editable);
4466 gtk_table_attach(GTK_TABLE (*entries_table), med->widget,
4467 2 + col_offset, 3 + col_offset, row_num, row_num +1,
4468 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 5, 0);
4469 gtk_widget_show(med->widget);
4470 }
4471 }
4472
4473 gtk_widget_show(*entries_table);
4474 }
4475
4476 /*
4477 * Show/Re-show textboxes
4478 */
4479 void re_show_multi_entry_textboxes(GtkWidget **texts_ibox,
4480 GtkWidget *texts_obox,
4481 GSList *multi_text_items)
4482 {
4483 GSList *multi_text;
4484 MultiTextData *mtd;
4485 GtkWidget *frame;
4486 GtkWidget *sw;
4487
4488 if(*texts_ibox != NULL) {
4489 gtk_widget_destroy(GTK_WIDGET (*texts_ibox));
4490 }
4491 *texts_ibox = gtk_vbox_new(FALSE, 5);
4492 gtk_container_add(GTK_CONTAINER (texts_obox), *texts_ibox);
4493
4494 for(multi_text = multi_text_items; multi_text != NULL; multi_text = multi_text->next) {
4495 mtd = (MultiTextData *) multi_text->data;
4496 frame = gtk_frame_new(_(mtd->label));
4497 sw = gtk_scrolled_window_new(NULL, NULL);
4498 gtk_container_set_border_width(GTK_CONTAINER(sw), 5);
4499 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
4500 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
4501 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
4502 GTK_SHADOW_IN);
4503 gtk_widget_set_size_request(sw, 300, 100);
4504 gtk_container_add(GTK_CONTAINER (frame), sw);
4505 gtk_container_add(GTK_CONTAINER (*texts_ibox), frame);
4506 mtd->textbox = gtk_text_view_new();
4507 gtk_text_view_set_editable(GTK_TEXT_VIEW(mtd->textbox), TRUE);
4508 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(mtd->textbox), GTK_WRAP_WORD_CHAR);
4509 gtk_text_buffer_set_text(
4510 gtk_text_view_get_buffer(GTK_TEXT_VIEW(mtd->textbox)),
4511 mtd->text?mtd->text:"", -1);
4512 gtk_container_add(GTK_CONTAINER (sw), mtd->textbox);
4513 gtk_widget_show(mtd->textbox);
4514 gtk_widget_show(sw);
4515 gtk_widget_show(frame);
4516 }
4517
4518 gtk_widget_show(*texts_ibox);
4519 }
4520
4521 /*
4522 * Create and initialize a new Multi-Entry Dialog struct
4523 */
4524 MultiEntryDlg *multi_entry_dialog_new()
4525 {
4526 MultiEntryDlg *b = g_new0(MultiEntryDlg, 1);
4527 b->instructions = g_new0(MultiInstrData, 1);
4528 b->multi_entry_items = NULL;
4529 b->multi_text_items = NULL;
4530 return(b);
4531 }
4532
4533 /*
4534 * Instantiate a new multi-entry dialog
4535 *
4536 * data == pointer to MultiEntryDlg with the following
4537 * initialized:
4538 *
4539 * role
4540 * title
4541 * user
4542 * multi_entry_items - pointers to MultiEntryData list
4543 * and MultiTextData list
4544 * instructions (optional)
4545 * ok function pointer
4546 * cancel function pointer (actually used to set
4547 * window destroy signal--cancel asserts destroy)
4548 *
4549 * sets the following in the MultiEntryDialog struct:
4550 *
4551 * window
4552 */
4553 void show_multi_entry_dialog(gpointer data)
4554 {
4555 GtkWidget *vbox, *hbox;
4556 GtkWidget *button;
4557 MultiEntryDlg *b = data;
4558
4559 GAIM_DIALOG(b->window);
4560 gtk_container_set_border_width(GTK_CONTAINER(b->window), 5);
4561 gtk_window_set_role(GTK_WINDOW(b->window), b->role);
4562 gtk_window_set_title(GTK_WINDOW (b->window), b->title);
4563
4564 /* Clean up if user dismisses window via window manager! */
4565 g_signal_connect(G_OBJECT(b->window), "destroy", G_CALLBACK(b->cancel), (gpointer) b);
4566 gtk_widget_realize(b->window);
4567
4568 vbox = gtk_vbox_new(FALSE, 5);
4569 gtk_container_add(GTK_CONTAINER (b->window), vbox);
4570
4571 b->instructions->label = gtk_label_new(NULL);
4572 gtk_label_set_line_wrap(GTK_LABEL (b->instructions->label), TRUE);
4573 gtk_box_pack_start(GTK_BOX (vbox), b->instructions->label, TRUE, TRUE, 5);
4574 re_show_multi_entry_instr(b->instructions);
4575
4576 b->entries_frame = gtk_frame_new(b->entries_title);
4577 gtk_box_pack_start(GTK_BOX (vbox), b->entries_frame, TRUE, TRUE, 5);
4578 b->entries_table = NULL;
4579 re_show_multi_entry_entries(&(b->entries_table), b->entries_frame, b->multi_entry_items);
4580
4581 b->texts_obox = gtk_vbox_new(FALSE, 0);
4582 gtk_box_pack_start(GTK_BOX (vbox), b->texts_obox, TRUE, TRUE, 5);
4583 b->texts_ibox = NULL;
4584 re_show_multi_entry_textboxes(&(b->texts_ibox), b->texts_obox, b->multi_text_items);
4585
4586 hbox = gtk_hbox_new(FALSE, 0);
4587 gtk_box_pack_start(GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
4588
4589 button = gaim_pixbuf_button_from_stock(_("Save"), GTK_STOCK_SAVE, GAIM_BUTTON_HORIZONTAL);
4590 g_signal_connect(G_OBJECT (button), "clicked",
4591 G_CALLBACK (b->ok), (gpointer) b);
4592 gtk_box_pack_end(GTK_BOX (hbox), button, FALSE, FALSE, 5);
4593
4594 button = gaim_pixbuf_button_from_stock(_("Cancel"), GTK_STOCK_CANCEL, GAIM_BUTTON_HORIZONTAL);
4595
4596 /* Let "destroy handling" (set above) handle cleanup */
4597 g_signal_connect_swapped(G_OBJECT (button), "clicked",
4598 G_CALLBACK (gtk_widget_destroy), G_OBJECT (b->window));
4599 gtk_box_pack_end(GTK_BOX (hbox), button, FALSE, FALSE, 5);
4600
4601 gtk_widget_show_all(b->window);
4602 }
4603
4604
4605 /*------------------------------------*/
4606 /* V-Card dialog specific support */
4607 /*------------------------------------*/
4608
4609 /*
4610 * V-Card "set info" dialog "Save" clicked
4611 *
4612 * Copy data from GTK+ dialogs into GSLists, call protocol-specific
4613 * formatter and save the user info data.
4614 */
4615 void set_vcard_dialog_ok_clicked(GtkWidget *widget, gpointer data)
4616 {
4617 MultiEntryDlg *b = (MultiEntryDlg *) data;
4618 GaimConnection *gc;
4619 gchar *tmp;
4620 GSList *list;
4621
4622 for(list = b->multi_entry_items; list != NULL; list = list->next) {
4623 if(((MultiEntryData *) list->data)->text != NULL) {
4624 g_free(((MultiEntryData *) list->data)->text);
4625 }
4626 ((MultiEntryData *) list->data)->text =
4627 g_strdup(gtk_entry_get_text(GTK_ENTRY(((MultiEntryData *) list->data)->widget)));
4628 }
4629
4630 for(list = b->multi_text_items; list != NULL; list = list->next) {
4631 if(((MultiTextData *) list->data)->text != NULL) {
4632 g_free(((MultiTextData *) list->data)->text);
4633 }
4634 ((MultiTextData *) list->data)->text =
4635 gtk_text_view_get_text(GTK_TEXT_VIEW(((MultiTextData *) list->data)->textbox), FALSE);
4636 }
4637
4638
4639 tmp = b->custom(b);
4640
4641 /*
4642 * Set the user info and (possibly) send to the server
4643 */
4644 if (b->account) {
4645 gaim_account_set_user_info(b->account, tmp);
4646 gc = b->account->gc;
4647
4648 if (gc)
4649 serv_set_info(gc, gaim_account_get_user_info(b->account));
4650 }
4651
4652 g_free(tmp);
4653
4654 /* Let multi-edit dialog window "destroy" event catching handle remaining cleanup */
4655 gtk_widget_destroy(GTK_WIDGET (b->window));
4656 }
4657
4658 /*
4659 * Instantiate a v-card dialog
4660 */
4661 void show_set_vcard(MultiEntryDlg *b)
4662 {
4663 b->ok = set_vcard_dialog_ok_clicked;
4664 b->cancel = multi_entry_dialog_destroy;
4665
4666 show_multi_entry_dialog(b);
4667 }
4668
4669
4670 /*------------------------------------------------------------------------*/
4671 /* End dialog for setting v-card info */
4672 /*------------------------------------------------------------------------*/
4673