GList * _filter_out_unshowable_recent_items (PengeEverythingPane *pane, ZeitgeistResultSet *set) { PengeEverythingPanePrivate *priv = GET_PRIVATE (pane); GList *ret = NULL; guint i; /* loop index */ /* probably an error (or an actual empty set, obv), we need to return empty * list anyway */ if (set == NULL) return NULL; while (zeitgeist_result_set_has_next (set)) { ZeitgeistEvent *event = NULL; gchar *thumbnail_path = NULL; /* We have to do this because we edit the list */ event = zeitgeist_result_set_next (set); /* FIXME, so far this is the assumption, then we can use a better data * structure for managing events with multiple subjects */ g_assert (zeitgeist_event_num_subjects (event) == 1); for (i = 0; i < zeitgeist_event_num_subjects (event); ++i) { ZeitgeistSubject *s; GFile *file; const gchar *uri = NULL; s = zeitgeist_event_get_subject (event, i); g_assert (s != NULL); uri = zeitgeist_subject_get_uri (s); g_assert (uri != NULL); /* Just a small debug help :) g_warning ("%s: subj(%d): i=%s m=%s", zeitgeist_subject_get_uri (s), i, zeitgeist_subject_get_interpretation (s), zeitgeist_subject_get_manifestation (s)); */ /* Current detault template look for local files only, if it's not local, * it's probably a template error, log it and move on */ if (!g_str_has_prefix (uri, "file:")) { g_warning ("uri %s for recent event is not local", uri); continue; } file = g_file_new_for_uri (uri); /* if the file does not exist anymore we ignore it and move on */ if (!g_file_query_exists (file, NULL)) break; /* consider the next event */ thumbnail_path = mpl_utils_get_thumbnail_path (uri); /* add to the return list only if it has a valid thumbnail */ if (thumbnail_path && g_file_test (thumbnail_path, G_FILE_TEST_EXISTS)) ret = g_list_prepend (ret, g_object_ref (event)); g_free (thumbnail_path); g_object_unref (file); } } return ret; }
static void _zeitgeist_log_find_received (GObject *source_object, GAsyncResult *res, gpointer user_data) { ZeitgeistLog *log = ZEITGEIST_LOG (source_object); PengeEverythingPane *pane = user_data; PengeEverythingPanePrivate *priv; GList *sw_items, *recent_file_items, *l; ZeitgeistResultSet *set = NULL; GList *old_actors = NULL; ClutterActor *actor; gboolean show_welcome_tile = TRUE; gint recent_files_count, sw_items_count; GError *error = NULL; g_return_if_fail (PENGE_IS_EVERYTHING_PANE (user_data)); priv = GET_PRIVATE (pane); set = zeitgeist_log_find_events_finish (log, res, &error); if (error != NULL) { g_warning (G_STRLOC ": Error obtaining recent files: %s", error->message); g_clear_error (&error); } /* It actually moves the interesting events into a list */ recent_file_items = _filter_out_unshowable_recent_items (pane, set); recent_file_items = g_list_sort (recent_file_items, (GCompareFunc)_recent_files_sort_func); /* Get Sw items */ sw_items = g_hash_table_get_values (priv->uuid_to_sw_items); sw_items = g_list_sort (sw_items, (GCompareFunc)_sw_item_sort_compare_func); recent_files_count = priv->block_count * priv->ratio; if (recent_files_count > g_list_length (recent_file_items)) recent_files_count = g_list_length (recent_file_items); sw_items_count = priv->block_count - recent_files_count; old_actors = g_hash_table_get_values (priv->pointer_to_actor); if (sw_items != NULL || recent_file_items != NULL) { if (priv->welcome_tile) { clutter_container_remove_actor (CLUTTER_CONTAINER (pane), priv->welcome_tile); priv->welcome_tile = NULL; } } while ((sw_items_count && sw_items) || (recent_files_count && recent_file_items)) { SwItem *sw_item = NULL; ZeitgeistEvent *recent_file_event = NULL; /* If no sw items -> force compare to favour recent file */ if (sw_items_count && sw_items) sw_item = (SwItem *)sw_items->data; else sw_item = NULL; /* If no recent files -> force compare to favour sw stuff */ if (recent_files_count && recent_file_items) recent_file_event = recent_file_items->data; else recent_file_event = NULL; if (_compare_item_and_event (sw_item, recent_file_event) < 1) { /* Sw item is newer */ actor = g_hash_table_lookup (priv->pointer_to_actor, sw_item); if (!actor) { actor = _add_from_sw_item (pane, sw_item); g_hash_table_insert (priv->pointer_to_actor, sw_item, actor); /* Needed to remove from hash when we kill the actor */ g_object_set_data (G_OBJECT (actor), "data-pointer", sw_item); } sw_items_count -= _sw_item_weight (sw_item); clutter_container_child_set (CLUTTER_CONTAINER (pane), actor, "col-span", _sw_item_weight (sw_item), NULL); sw_items = g_list_remove (sw_items, sw_item); show_welcome_tile = FALSE; } else { /* Recent file item is newer */ actor = g_hash_table_lookup (priv->pointer_to_actor, recent_file_event); if (!actor) { const gchar *uri = NULL; gchar *thumbnail_path = NULL; ZeitgeistSubject *subj; /* FIXME we assume there is only one subject */ subj = zeitgeist_event_get_subject (recent_file_event, 0); uri = zeitgeist_subject_get_uri (subj); thumbnail_path = mpl_utils_get_thumbnail_path (uri); actor = _add_from_recent_file_event (pane, recent_file_event, thumbnail_path); g_free (thumbnail_path); g_hash_table_insert (priv->pointer_to_actor, recent_file_event, actor); /* Needed to remove from hash when we kill the actor */ g_object_set_data (G_OBJECT (actor), "data-pointer", recent_file_event); show_welcome_tile = FALSE; } recent_files_count--; g_object_unref (recent_file_event); recent_file_items = g_list_remove (recent_file_items, recent_file_event); } clutter_container_lower_child (CLUTTER_CONTAINER (pane), actor, NULL); old_actors = g_list_remove (old_actors, actor); } for (l = old_actors; l; l = l->next) { gpointer p; p = g_object_get_data (G_OBJECT (l->data), "data-pointer"); if (p) { clutter_container_remove_actor (CLUTTER_CONTAINER (pane), CLUTTER_ACTOR (l->data)); g_hash_table_remove (priv->pointer_to_actor, p); } } g_list_free (old_actors); if (show_welcome_tile && !priv->welcome_tile) { priv->welcome_tile = penge_welcome_tile_new (); clutter_container_add_actor (CLUTTER_CONTAINER (pane), priv->welcome_tile); clutter_container_child_set (CLUTTER_CONTAINER (pane), priv->welcome_tile, "col-span", 3, NULL); } g_list_free (sw_items); for (l = recent_file_items; l; l = l->next) { ZeitgeistEvent *recent_file_event = l->data; g_object_unref (recent_file_event); } g_list_free (recent_file_items); }
static void _on_got_events (ZeitgeistResultSet *pEvents, GtkListStore *pModel) { int i, n; ZeitgeistEvent *event; ZeitgeistSubject *subject; gint64 iTimeStamp; const gchar *cEventURI; guint id; gchar *cName = NULL, *cURI = NULL, *cIconName = NULL, *cIconPath, *cPath = NULL; double fOrder; int iVolumeID; gboolean bIsDirectory; GdkPixbuf *pixbuf; GtkTreeIter iter; GHashTable *pHashTable = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); // used to prevent doubles //\_____________ parse all the events. while (zeitgeist_result_set_has_next (pEvents)) { #ifdef ZEITGEIST_1_0 event = zeitgeist_result_set_next (pEvents); #else event = zeitgeist_result_set_next_value (pEvents); #endif iTimeStamp = zeitgeist_event_get_timestamp (event) / 1e3; id = zeitgeist_event_get_id (event); n = zeitgeist_event_num_subjects (event); if (n > 1) cd_debug (" +++ %s, %s, %d", zeitgeist_event_get_interpretation (event), zeitgeist_event_get_manifestation (event), n); for (i = 0; i < n; i++) { subject = zeitgeist_event_get_subject (event, i); //\_____________ prevent doubles. cEventURI = zeitgeist_subject_get_uri (subject); if (g_hash_table_lookup_extended (pHashTable, cEventURI, NULL, NULL)) continue; //g_print (" %s:\n %s, %s\n", cEventURI, zeitgeist_subject_get_interpretation (subject), zeitgeist_subject_get_manifestation (subject)); //\_____________ ignore files that have been deleted cPath = g_filename_from_uri (cEventURI, NULL, NULL); // NULL for anything else than file://* if (strncmp (cEventURI, "file://", 7) == 0 && ! g_file_test (cPath, G_FILE_TEST_EXISTS)) { g_hash_table_insert (pHashTable, (gchar*)cEventURI, NULL); // since we've checked it, insert it, even if we don't display it. g_free (cPath); continue; } //\_____________ get the text to display. const gchar *cText = zeitgeist_subject_get_text (subject); if (cText == NULL) // skip empty texts (they are most of the times web page that redirect to another page, which is probably in the next event anyway). continue; //\_____________ find the icon. if (strncmp (cEventURI, "http", 4) == 0) // gvfs is deadly slow to get info on distant URI... { cIconName = cairo_dock_search_icon_s_path ("text-html", myData.iDesiredIconSize); } else if (strncmp (cEventURI, "application://", 14) == 0) // application URL { gchar *cClass = cairo_dock_register_class (cEventURI+14); cIconName = g_strdup (cairo_dock_get_class_icon (cClass)); cText = cairo_dock_get_class_name (cClass); // use the translated name g_free (cClass); } else { cairo_dock_fm_get_file_info (cEventURI, &cName, &cURI, &cIconName, &bIsDirectory, &iVolumeID, &fOrder, CAIRO_DOCK_FM_SORT_BY_DATE); } if (cIconName != NULL) { cIconPath = cairo_dock_search_icon_s_path (cIconName, myData.iDesiredIconSize); pixbuf = gdk_pixbuf_new_from_file_at_size (cIconPath, myData.iDesiredIconSize, myData.iDesiredIconSize, NULL); g_free (cIconPath); } else pixbuf = NULL; //\_____________ build the path to display. const gchar *cDisplayedPath = (cPath ? cPath : cEventURI); // need to escape the '&' (and ', etc.) because gtk-tooltips use markups by default. gchar *cEscapedPath = g_markup_escape_text (cDisplayedPath, -1); //\_____________ store in the model. memset (&iter, 0, sizeof (GtkTreeIter)); gtk_list_store_append (GTK_LIST_STORE (pModel), &iter); gtk_list_store_set (GTK_LIST_STORE (pModel), &iter, CD_MODEL_NAME, cText, CD_MODEL_URI, cEventURI, CD_MODEL_PATH, cEscapedPath, CD_MODEL_ICON, pixbuf, CD_MODEL_DATE, iTimeStamp, CD_MODEL_ID, id, -1); g_free (cIconName); cIconName = NULL; g_free (cName); cName = NULL; g_free (cURI); cURI = NULL; if (pixbuf) g_object_unref (pixbuf); g_free (cPath); g_free (cEscapedPath); g_hash_table_insert (pHashTable, (gchar*)cEventURI, NULL); // cEventURI stays valid in this function. } } g_hash_table_destroy (pHashTable); }