# HG changeset patch # User Mark Doliner # Date 1136251506 0 # Node ID 473c23442a36a44cbb4274555716952c3b6d613f # Parent 88ccc36031635a0b44a40e2e011b05354c2e1050 [gaim-migrate @ 15031] Add the notion of "popular" saved statuses. This lets us show 6 recently used/popular statuses in the context menu for the docklet. Eventually I'll add the same list to the status box--but that's a little more work. If someone else wants to tackle it before I have a chance to feel free (and let me know!) Does this look ok to everyone (the docklet menu changes)? Would it be better if it was a submenu? Or if it was labeled? It'd be cool if the icons reflected the status. Oh, and I just remembered that the menu items don't actually work yet... but that's not too hard, I think I can get to that tonight committer: Tailor Script diff -r 88ccc3603163 -r 473c23442a36 plugins/docklet/docklet.c --- a/plugins/docklet/docklet.c Tue Jan 03 01:19:32 2006 +0000 +++ b/plugins/docklet/docklet.c Tue Jan 03 01:25:06 2006 +0000 @@ -367,6 +367,7 @@ docklet_menu() { static GtkWidget *menu = NULL; GtkWidget *menuitem; + GList *popular_statuses, *cur; if (menu) { gtk_widget_destroy(menu); @@ -409,6 +410,18 @@ gaim_separator(menu); + popular_statuses = gaim_savedstatuses_get_popular(6); + for (cur = popular_statuses; cur != NULL; cur = cur->next) + { + GaimSavedStatus *saved_status = cur->data; + gaim_new_item_from_stock(menu, + gaim_savedstatus_get_title(saved_status), + GAIM_STOCK_ICON_AWAY, NULL /* TODO */, NULL, 0, 0, NULL); + } + g_list_free(popular_statuses); + + gaim_separator(menu); + gaim_new_item_from_stock(menu, _("Accounts"), GAIM_STOCK_ACCOUNTS, G_CALLBACK(gaim_gtk_accounts_window_show), NULL, 0, 0, NULL); gaim_new_item_from_stock(menu, _("Plugins"), GAIM_STOCK_PLUGIN, G_CALLBACK(gaim_gtk_plugin_dialog_show), NULL, 0, 0, NULL); gaim_new_item_from_stock(menu, _("Preferences"), GTK_STOCK_PREFERENCES, G_CALLBACK(gaim_gtk_prefs_show), NULL, 0, 0, NULL); diff -r 88ccc3603163 -r 473c23442a36 src/savedstatuses.c --- a/src/savedstatuses.c Tue Jan 03 01:19:32 2006 +0000 +++ b/src/savedstatuses.c Tue Jan 03 01:25:06 2006 +0000 @@ -60,6 +60,8 @@ time_t lastused; + unsigned int usage_count; + GList *substatuses; /**< A list of GaimSavedStatusSub's. */ }; @@ -75,6 +77,7 @@ }; static GList *saved_statuses = NULL; +static GList *popular_statuses = NULL; static guint save_timer = 0; static gboolean statuses_loaded = FALSE; @@ -272,6 +275,9 @@ snprintf(buf, sizeof(buf), "%lu", status->lastused); xmlnode_set_attrib(node, "lastused", buf); + snprintf(buf, sizeof(buf), "%u", status->usage_count); + xmlnode_set_attrib(node, "usage_count", buf); + child = xmlnode_new_child(node, "state"); xmlnode_insert_data(child, gaim_primitive_get_id_from_type(status->type), -1); @@ -458,6 +464,10 @@ attrib = xmlnode_get_attrib(status, "lastused"); ret->lastused = (attrib != NULL ? atol(attrib) : 0); + /* Read the usage count */ + attrib = xmlnode_get_attrib(status, "usage_count"); + ret->usage_count = (attrib != NULL ? atol(attrib) : 0); + /* Read the primitive status type */ node = xmlnode_get_child(status, "state"); if ((node != NULL) && ((data = xmlnode_get_data(node)) != NULL)) @@ -665,6 +675,50 @@ return saved_statuses; } +/** + * A magic number is calcuated for each status, and then the + * statuses are ordered by the magic number. The magic number + * is the date the status was last used offset by one day for + * each time the status has been used (but only by 10 days at + * the most). + * + * The goal is to have recently used statuses at the top of + * the list, but to also keep frequently used statuses near + * the top. + */ +static gint +popular_statuses_compare_func(gconstpointer a, gconstpointer b) +{ + const GaimSavedStatus *saved_status_a = a; + const GaimSavedStatus *saved_status_b = b; + time_t time_a = saved_status_a->lastused + + (MIN(saved_status_a->usage_count, 10) * 86400); + time_t time_b = saved_status_b->lastused + + (MIN(saved_status_b->usage_count, 10) * 86400); + if (time_a > time_b) + return -1; + if (time_a < time_b) + return 1; + return 0; +} + +GList * +gaim_savedstatuses_get_popular(unsigned int how_many) +{ + GList *truncated = NULL; + GList *cur; + int i; + + /* Copy 'how_many' elements to a new list */ + for (i = 0, cur = popular_statuses; (i < how_many) && (cur != NULL); i++) + { + truncated = g_list_append(truncated, cur->data); + cur = cur->next; + } + + return truncated; +} + GaimSavedStatus * gaim_savedstatus_get_current() { @@ -747,6 +801,32 @@ { g_return_val_if_fail(saved_status != NULL, NULL); + /* If transient then make up a title on the fly */ + if (saved_status->title == NULL) + { + const char *message = gaim_savedstatus_get_message(saved_status); + + if (message == NULL) + { + GaimStatusPrimitive primitive; + primitive = gaim_savedstatus_get_type(saved_status); + return gaim_primitive_get_id_from_type(primitive); + } + else + { + static char buf[64]; + strncpy(buf, message, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + if ((strlen(message) + 1) > sizeof(buf)) + { + /* Truncate and ellipsize */ + char *tmp = g_utf8_find_prev_char(buf, &buf[sizeof(buf) - 4]); + strcpy(tmp, "..."); + } + return buf; + } + } + return saved_status->title; } @@ -840,6 +920,14 @@ saved_status->lastused = time(NULL); gaim_prefs_set_int("/core/savedstatus/current", gaim_savedstatus_get_creation_time(saved_status)); + + /* Update our list of popular statuses */ + saved_status->usage_count++; + g_list_free(popular_statuses); + popular_statuses = g_list_copy(saved_statuses); + popular_statuses = g_list_sort(popular_statuses, + popular_statuses_compare_func); + } void diff -r 88ccc3603163 -r 473c23442a36 src/savedstatuses.h --- a/src/savedstatuses.h Tue Jan 03 01:19:32 2006 +0000 +++ b/src/savedstatuses.h Tue Jan 03 01:25:06 2006 +0000 @@ -152,6 +152,21 @@ const GList *gaim_savedstatuses_get_all(void); /** + * Returns the n most popular saved statuses. "Popularity" is + * determined by when the last time a saved_status was used and + * how many times it has been used. + * + * @param how_many The maximum number of saved statuses + * to return, or '0' to get all saved + * statuses sorted by popularity. + * @return A linked list containing at most how_many + * GaimSavedStatuses. This list should be + * g_list_free'd by the caller (but the + * GaimSavedStatuses must not be free'd). + */ +GList *gaim_savedstatuses_get_popular(unsigned int how_many); + +/** * Returns the currently selected saved status. * * @return A pointer to the in-use GaimSavedStatus.