Mercurial > pidgin
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 |