Back to index

indicator-appmenu  12.10.0
hudquery.c
Go to the documentation of this file.
00001 /*
00002  * Copyright © 2012 Canonical Ltd.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU General Public License version 3, as
00006  * published by the Free Software Foundation.
00007  *
00008  * This program is distributed in the hope that it will be useful, but
00009  * WITHOUT ANY WARRANTY; without even the implied warranties of
00010  * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
00011  * PURPOSE.  See the GNU General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU General Public License along
00014  * with this program.  If not, see <http://www.gnu.org/licenses/>.
00015  *
00016  * Author: Ryan Lortie <desrt@desrt.ca>
00017  */
00018 
00019 #define G_LOG_DOMAIN "hudquery"
00020 
00021 #include "hudquery.h"
00022 
00023 #include "hudresult.h"
00024 
00048 struct _HudQuery
00049 {
00050   GObject parent_instance;
00051 
00052   HudSource *source;
00053   gchar *search_string;
00054   HudTokenList *token_list;
00055   gint num_results;
00056   guint refresh_id;
00057 
00058   GPtrArray *results;
00059 };
00060 
00061 typedef GObjectClass HudQueryClass;
00062 
00063 G_DEFINE_TYPE (HudQuery, hud_query, G_TYPE_OBJECT)
00064 static guint hud_query_changed_signal;
00065 
00066 static HudQuery *last_created_query;
00067 
00068 static void
00069 hud_query_find_max_usage (gpointer data,
00070                           gpointer user_data)
00071 {
00072   guint *max_usage = user_data;
00073   HudResult *result = data;
00074   HudItem *item;
00075   guint usage;
00076 
00077   item = hud_result_get_item (result);
00078   usage = hud_item_get_usage (item);
00079 
00080   *max_usage = MAX (*max_usage, usage);
00081 }
00082 
00083 static gint
00084 hud_query_compare_results (gconstpointer a,
00085                            gconstpointer b,
00086                            gpointer      user_data)
00087 {
00088   HudResult *result_a = *(HudResult * const *) a;
00089   HudResult *result_b = *(HudResult * const *) b;
00090   gint max_usage = GPOINTER_TO_INT (user_data);
00091   guint distance_a;
00092   guint distance_b;
00093 
00094   distance_a = hud_result_get_distance (result_a, max_usage);
00095   distance_b = hud_result_get_distance (result_b, max_usage);
00096 
00097   return distance_a - distance_b;
00098 }
00099 
00100 static void
00101 hud_query_refresh (HudQuery *query)
00102 {
00103   guint max_usage = 0;
00104   guint64 start_time;
00105 
00106   start_time = g_get_monotonic_time ();
00107 
00108   g_ptr_array_set_size (query->results, 0);
00109 
00110   if (hud_token_list_get_length (query->token_list) != 0)
00111     hud_source_search (query->source, query->results, query->token_list);
00112 
00113   g_ptr_array_foreach (query->results, hud_query_find_max_usage, &max_usage);
00114   g_ptr_array_sort_with_data (query->results, hud_query_compare_results, GINT_TO_POINTER (max_usage));
00115   if (query->results->len > query->num_results)
00116     g_ptr_array_set_size (query->results, query->num_results);
00117 
00118   g_debug ("query took %dus\n", (int) (g_get_monotonic_time () - start_time));
00119 }
00120 
00121 static gboolean
00122 hud_query_dispatch_refresh (gpointer user_data)
00123 {
00124   HudQuery *query = user_data;
00125 
00126   hud_query_refresh (query);
00127 
00128   g_signal_emit (query, hud_query_changed_signal, 0);
00129 
00130   query->refresh_id = 0;
00131 
00132   return G_SOURCE_REMOVE;
00133 }
00134 static void
00135 hud_query_source_changed (HudSource *source,
00136                           gpointer   user_data)
00137 {
00138   HudQuery *query = user_data;
00139 
00140   if (!query->refresh_id)
00141     query->refresh_id = g_idle_add (hud_query_dispatch_refresh, query);
00142 }
00143 
00144 static void
00145 hud_query_finalize (GObject *object)
00146 {
00147   HudQuery *query = HUD_QUERY (object);
00148 
00149   g_debug ("Destroyed query '%s'", query->search_string);
00150 
00151   if (query->refresh_id)
00152     g_source_remove (query->refresh_id);
00153 
00154   hud_source_unuse (query->source);
00155 
00156   g_object_unref (query->source);
00157   hud_token_list_free (query->token_list);
00158   g_free (query->search_string);
00159   g_ptr_array_unref (query->results);
00160 
00161   G_OBJECT_CLASS (hud_query_parent_class)
00162     ->finalize (object);
00163 }
00164 
00165 static void
00166 hud_query_init (HudQuery *query)
00167 {
00168 }
00169 
00170 static void
00171 hud_query_class_init (HudQueryClass *class)
00172 {
00179   hud_query_changed_signal = g_signal_new ("changed", HUD_TYPE_QUERY, G_SIGNAL_RUN_LAST, 0, NULL,
00180                                            NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
00181 
00182   class->finalize = hud_query_finalize;
00183 }
00184 
00203 HudQuery *
00204 hud_query_new (HudSource   *source,
00205                const gchar *search_string,
00206                gint         num_results)
00207 {
00208   HudQuery *query;
00209 
00210   g_debug ("Created query '%s'", search_string);
00211 
00212   query = g_object_new (HUD_TYPE_QUERY, NULL);
00213   query->source = g_object_ref (source);
00214   query->results = g_ptr_array_new_with_free_func (g_object_unref);
00215   query->search_string = g_strdup (search_string);
00216   query->token_list = hud_token_list_new_from_string (query->search_string);
00217   query->num_results = num_results;
00218 
00219   hud_source_use (query->source);
00220 
00221   hud_query_refresh (query);
00222 
00223   g_signal_connect_object (source, "changed", G_CALLBACK (hud_query_source_changed), query, 0);
00224 
00225   g_clear_object (&last_created_query);
00226   last_created_query = g_object_ref (query);
00227 
00228   return query;
00229 }
00230 
00244 GVariant *
00245 hud_query_get_query_key (HudQuery *query)
00246 {
00247   static GVariant *query_key;
00248 
00249   if (query_key == NULL)
00250     query_key = g_variant_ref_sink (g_variant_new_string ("query key"));
00251 
00252   return query_key;
00253 }
00254 
00263 HudQuery *
00264 hud_query_lookup (GVariant *query_key)
00265 {
00266   return last_created_query;
00267 }
00268 
00281 void
00282 hud_query_close (HudQuery *query)
00283 {
00284   if (query == last_created_query)
00285     g_clear_object (&last_created_query);
00286 }
00287 
00296 guint
00297 hud_query_get_n_results (HudQuery *query)
00298 {
00299   return query->results->len;
00300 }
00301 
00314 HudResult *
00315 hud_query_get_result_by_index (HudQuery *query,
00316                                guint     i)
00317 {
00318   return query->results->pdata[i];
00319 }