Mercurial > pidgin
comparison src/gtkrequest.c @ 8294:d5e59ea083be
[gaim-migrate @ 9018]
Added auto-completion for screen names to the New Instant Message and Get
User Info dialogs.
committer: Tailor Script <tailor@pidgin.im>
| author | Christian Hammond <chipx86@chipx86.com> |
|---|---|
| date | Thu, 19 Feb 2004 09:47:44 +0000 |
| parents | e39ea2b4f6cd |
| children | 462ead6fc1a0 |
comparison
equal
deleted
inserted
replaced
| 8293:a1b7c7f3d9a7 | 8294:d5e59ea083be |
|---|---|
| 29 #include "gtkrequest.h" | 29 #include "gtkrequest.h" |
| 30 #include "gtkutils.h" | 30 #include "gtkutils.h" |
| 31 #include "stock.h" | 31 #include "stock.h" |
| 32 #include "ui.h" | 32 #include "ui.h" |
| 33 | 33 |
| 34 #include <gdk/gdkkeysyms.h> | |
| 35 | |
| 36 #if GTK_CHECK_VERSION(2,3,0) | |
| 37 # define NEW_STYLE_COMPLETION | |
| 38 #endif | |
| 39 | |
| 34 typedef struct | 40 typedef struct |
| 35 { | 41 { |
| 36 GaimRequestType type; | 42 GaimRequestType type; |
| 37 | 43 |
| 38 void *user_data; | 44 void *user_data; |
| 60 } multifield; | 66 } multifield; |
| 61 | 67 |
| 62 } u; | 68 } u; |
| 63 | 69 |
| 64 } GaimGtkRequestData; | 70 } GaimGtkRequestData; |
| 71 | |
| 72 #ifndef NEW_STYLE_COMPLETION | |
| 73 typedef struct | |
| 74 { | |
| 75 GCompletion *completion; | |
| 76 | |
| 77 gboolean completion_started; | |
| 78 | |
| 79 } GaimGtkCompletionData; | |
| 80 #endif | |
| 65 | 81 |
| 66 static void | 82 static void |
| 67 input_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) | 83 input_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) |
| 68 { | 84 { |
| 69 const char *value; | 85 const char *value; |
| 458 | 474 |
| 459 gtk_widget_set_sensitive(req_data->ok_button, | 475 gtk_widget_set_sensitive(req_data->ok_button, |
| 460 gaim_request_fields_all_required_filled(field->group->fields_list)); | 476 gaim_request_fields_all_required_filled(field->group->fields_list)); |
| 461 } | 477 } |
| 462 | 478 |
| 479 GList * | |
| 480 get_online_screennames(void) | |
| 481 { | |
| 482 GList *screennames = NULL; | |
| 483 GaimBlistNode *gnode, *cnode, *bnode; | |
| 484 | |
| 485 for (gnode = gaim_get_blist()->root; gnode != NULL; gnode = gnode->next) | |
| 486 { | |
| 487 if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
| 488 continue; | |
| 489 | |
| 490 for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) | |
| 491 { | |
| 492 if (!GAIM_BLIST_NODE_IS_CONTACT(cnode)) | |
| 493 continue; | |
| 494 | |
| 495 for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) | |
| 496 { | |
| 497 GaimBuddy *buddy = (GaimBuddy *)bnode; | |
| 498 | |
| 499 if (!gaim_account_is_connected(buddy->account)) | |
| 500 continue; | |
| 501 | |
| 502 screennames = g_list_append(screennames, g_strdup(buddy->name)); | |
| 503 } | |
| 504 } | |
| 505 } | |
| 506 | |
| 507 return screennames; | |
| 508 } | |
| 509 | |
| 510 #ifndef NEW_STYLE_COMPLETION | |
| 511 static gboolean | |
| 512 completion_entry_event(GtkEditable *entry, GdkEventKey *event, | |
| 513 GaimGtkCompletionData *data) | |
| 514 { | |
| 515 int pos, end_pos; | |
| 516 | |
| 517 if (event->type == GDK_KEY_PRESS && event->keyval == GDK_Tab) | |
| 518 { | |
| 519 gtk_editable_get_selection_bounds(entry, &pos, &end_pos); | |
| 520 | |
| 521 if (data->completion_started && | |
| 522 pos != end_pos && pos > 1 && | |
| 523 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry)))) | |
| 524 { | |
| 525 gtk_editable_select_region(entry, 0, 0); | |
| 526 gtk_editable_set_position(entry, -1); | |
| 527 | |
| 528 return TRUE; | |
| 529 } | |
| 530 } | |
| 531 else if (event->type == GDK_KEY_PRESS && event->length > 0) | |
| 532 { | |
| 533 char *prefix, *nprefix; | |
| 534 | |
| 535 gtk_editable_get_selection_bounds(entry, &pos, &end_pos); | |
| 536 | |
| 537 if (data->completion_started && | |
| 538 pos != end_pos && pos > 1 && | |
| 539 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry)))) | |
| 540 { | |
| 541 char *temp; | |
| 542 | |
| 543 temp = gtk_editable_get_chars(entry, 0, pos); | |
| 544 prefix = g_strconcat(temp, event->string, NULL); | |
| 545 g_free(temp); | |
| 546 } | |
| 547 else if (pos == end_pos && pos > 1 && | |
| 548 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry)))) | |
| 549 { | |
| 550 prefix = g_strconcat(gtk_entry_get_text(GTK_ENTRY(entry)), | |
| 551 event->string, NULL); | |
| 552 } | |
| 553 else | |
| 554 return FALSE; | |
| 555 | |
| 556 pos = strlen(prefix); | |
| 557 nprefix = NULL; | |
| 558 | |
| 559 g_completion_complete(data->completion, prefix, &nprefix); | |
| 560 | |
| 561 if (nprefix != NULL) | |
| 562 { | |
| 563 gtk_entry_set_text(GTK_ENTRY(entry), nprefix); | |
| 564 gtk_editable_set_position(entry, pos); | |
| 565 gtk_editable_select_region(entry, pos, -1); | |
| 566 | |
| 567 data->completion_started = TRUE; | |
| 568 | |
| 569 g_free(nprefix); | |
| 570 g_free(prefix); | |
| 571 | |
| 572 return TRUE; | |
| 573 } | |
| 574 | |
| 575 g_free(prefix); | |
| 576 } | |
| 577 | |
| 578 return FALSE; | |
| 579 } | |
| 580 | |
| 581 static void | |
| 582 destroy_completion_data(GtkWidget *w, GaimGtkCompletionData *data) | |
| 583 { | |
| 584 g_list_foreach(data->completion->items, (GFunc)g_free, NULL); | |
| 585 g_completion_free(data->completion); | |
| 586 | |
| 587 g_free(data); | |
| 588 } | |
| 589 #endif /* !NEW_STYLE_COMPLETION */ | |
| 590 | |
| 591 static void | |
| 592 setup_screenname_autocomplete(GtkWidget *entry, GaimRequestField *field) | |
| 593 { | |
| 594 #ifdef NEW_STYLE_COMPLETION | |
| 595 GtkListStore *store; | |
| 596 GtkTreeIter iter; | |
| 597 GtkEntryCompletion *completion; | |
| 598 GList *screennames, *l; | |
| 599 | |
| 600 store = gtk_list_store_new(1, G_TYPE_STRING); | |
| 601 | |
| 602 screennames = get_online_screennames(); | |
| 603 | |
| 604 for (l = screennames; l != NULL; l = l->next) | |
| 605 { | |
| 606 gtk_list_store_append(store, &iter); | |
| 607 gtk_list_store_set(store, &iter, 0, l->data, -1); | |
| 608 } | |
| 609 | |
| 610 g_list_foreach(screennames, (GFunc)g_free, NULL); | |
| 611 g_list_free(screennames); | |
| 612 | |
| 613 completion = gtk_entry_completion_new(); | |
| 614 gtk_entry_set_completion(GTK_ENTRY(entry), completion); | |
| 615 g_object_unref(completion); | |
| 616 | |
| 617 gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store)); | |
| 618 g_object_unref(store); | |
| 619 | |
| 620 gtk_entry_completion_set_text_column(completion, 0); | |
| 621 | |
| 622 #else /* !NEW_STYLE_COMPLETION */ | |
| 623 GaimGtkCompletionData *data; | |
| 624 GList *screennames; | |
| 625 | |
| 626 data = g_new0(GaimGtkCompletionData, 1); | |
| 627 | |
| 628 data->completion = g_completion_new(NULL); | |
| 629 | |
| 630 g_completion_set_compare(data->completion, g_ascii_strncasecmp); | |
| 631 | |
| 632 screennames = get_online_screennames(); | |
| 633 | |
| 634 g_completion_add_items(data->completion, screennames); | |
| 635 | |
| 636 g_list_free(screennames); | |
| 637 | |
| 638 g_signal_connect(G_OBJECT(entry), "event", | |
| 639 G_CALLBACK(completion_entry_event), data); | |
| 640 g_signal_connect(G_OBJECT(entry), "destroy", | |
| 641 G_CALLBACK(destroy_completion_data), data); | |
| 642 | |
| 643 #endif /* !NEW_STYLE_COMPLETION */ | |
| 644 } | |
| 645 | |
| 463 static void | 646 static void |
| 464 setup_entry_field(GtkWidget *entry, GaimRequestField *field) | 647 setup_entry_field(GtkWidget *entry, GaimRequestField *field) |
| 465 { | 648 { |
| 649 const char *type_hint; | |
| 650 | |
| 466 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); | 651 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); |
| 467 | 652 |
| 468 if (gaim_request_field_is_required(field)) | 653 if (gaim_request_field_is_required(field)) |
| 469 { | 654 { |
| 470 g_signal_connect(G_OBJECT(entry), "changed", | 655 g_signal_connect(G_OBJECT(entry), "changed", |
| 471 G_CALLBACK(req_entry_field_changed_cb), field); | 656 G_CALLBACK(req_entry_field_changed_cb), field); |
| 657 } | |
| 658 | |
| 659 if ((type_hint = gaim_request_field_get_type_hint(field)) != NULL) | |
| 660 { | |
| 661 if (!strcmp(type_hint, "screenname")) | |
| 662 { | |
| 663 setup_screenname_autocomplete(entry, field); | |
| 664 } | |
| 472 } | 665 } |
| 473 } | 666 } |
| 474 | 667 |
| 475 static GtkWidget * | 668 static GtkWidget * |
| 476 create_string_field(GaimRequestField *field) | 669 create_string_field(GaimRequestField *field) |
