Пример #1
0
static void
_add_remove_recursive (MexModel *queue_model, MexModel *model, gboolean add)
{
  gint len, i;

  len = mex_model_get_length (model);

  for (i=0; i < len; i++)
    {
      MexContent *content;
      const gchar *mimetype;

      content = mex_model_get_content (model, i);

      mimetype = mex_content_get_metadata (content,
                                           MEX_CONTENT_METADATA_MIMETYPE);

      /* Don't accidentally add a directory or group to the queue */
      if (!g_strcmp0 (mimetype, "x-grl/box")
          || !g_strcmp0 (mimetype, "x-mex/group"))
        continue;

      if (add)
        mex_model_add_content (queue_model, content);
      else
        mex_model_remove_content (queue_model, content);
    }
  g_object_unref (model);
}
Пример #2
0
static void
or_add_to_feed (gpointer key,
                gpointer value,
                gpointer userdata)
{
  MexModel *model = (MexModel *) userdata;

  /* The key and value are the same, doesn't matter which we add */
  mex_model_add_content (model, (MexContent *) key);
}
Пример #3
0
/* This function is synchronous! Blocking once at startup seems pretty
 * reasonable and allows us to avoid any complexity re. races
 */
static void
mex_queue_model_load (MexQueueModel *model)
{
  JsonParser *parser;
  gchar *filename;
  GError *error = NULL;
  JsonNode *root;
  JsonArray *array;
  gint i = 0;

  filename = _queue_file_name ();

  if (!g_file_test (filename, G_FILE_TEST_EXISTS))
    {
      g_free (filename);

      return;
    }

  parser = json_parser_new ();
  if (!json_parser_load_from_file (parser, filename, &error))
    {
      g_warning (G_STRLOC ": error populating from file: %s",
                 error->message);
      g_clear_error (&error);
      goto out;
    }

  root = json_parser_get_root (parser);

  if (!JSON_NODE_HOLDS_ARRAY (root))
    {
      g_warning (G_STRLOC ": JSON data not of expected format!");

      goto out;
    }

  array = json_node_get_array (root);

  for (i = 0; i < json_array_get_length (array); i++)
    {
      MexContent *content;
      JsonNode *node;

      node = json_array_get_element (array, i);
      content = (MexContent *)json_gobject_deserialize (MEX_TYPE_PROGRAM,
                                                        node);

      mex_model_add_content (MEX_MODEL (model), content);
    }

out:
  g_free (filename);
  g_object_unref (parser);
}
Пример #4
0
static void
and_add_to_feed (gpointer key,
                 gpointer value,
                 gpointer userdata)
{
  struct _SearchPayload *payload = (struct _SearchPayload *) userdata;

  /* @value is the number of terms that the program in @key was found
     related to. For AND operations the program needs to have been found
     related to all of the terms */
  if (GPOINTER_TO_INT (value) == payload->term_count) {
    mex_model_add_content (payload->model, (MexContent *) key);
  }
}
Пример #5
0
void
mex_aggregate_model_add_model (MexAggregateModel *aggregate,
                               MexModel          *model)
{
    gint i;
    MexContent *content;
    GController *controller;
    MexAggregateModelPrivate *priv;

    g_return_if_fail (MEX_IS_AGGREGATE_MODEL (aggregate));
    g_return_if_fail (MEX_IS_MODEL (model));

    priv = aggregate->priv;
    if (g_list_find (priv->models, model))
        return;

    /* Add a link back to the model from the controller */
    controller = mex_model_get_controller (model);
    g_hash_table_insert (priv->controller_to_model, controller, model);

    /* Add model to list */
    priv->models = g_list_insert_sorted (priv->models, model,
                                         (GCompareFunc) mex_aggregate_model_sort_func);

    /* Add existing items */
    i = 0;
    while ((content = mex_model_get_content (model, i)))
    {
        g_hash_table_insert (priv->content_to_model, content, model);
        mex_model_add_content (MEX_MODEL (aggregate), content);
        i++;
    }

    /* Connect to the controller changed signal */
    g_signal_connect (controller, "changed",
                      G_CALLBACK (mex_aggregate_model_controller_changed_cb),
                      aggregate);

    /* Emit added signal */
    g_signal_emit (aggregate, signals[MODEL_ADDED], 0, model);
}
Пример #6
0
static void
_queue_button_notify_toggled_cb (MxButton       *button,
                                 GParamSpec     *pspec,
                                 MexQueueButton *q_button)
{
  MexQueueButtonPrivate *priv = q_button->priv;
  const gchar *mimetype;

  gboolean directory;

  mimetype = mex_content_get_metadata (priv->content,
                                       MEX_CONTENT_METADATA_MIMETYPE);
  directory = !g_strcmp0 (mimetype, "x-grl/box")
    || !g_strcmp0 (mimetype, "x-mex/group");

  /* Triggers a train of actions that makes content have it's queued
   * property set which then runs the notify cb which calls
   * mex_queue_button_update so we don't need to run it directly
   */

  if (mx_button_get_toggled (button))
    {
      mex_queue_button_set_animated (q_button, TRUE);

      if (directory)
        _add_from_directory (q_button, TRUE);
      else
        mex_model_add_content (priv->queue_model, priv->content);
    }
  else
    {
      mex_queue_button_set_animated (q_button, FALSE);

      if (directory)
          _add_from_directory (q_button, FALSE);
      else
        mex_model_remove_content (priv->queue_model, priv->content);
    }
}
Пример #7
0
static void
mex_aggregate_model_controller_changed_cb (GController          *controller,
        GControllerAction     action,
        GControllerReference *ref,
        MexAggregateModel    *self)
{
    gint i;

    gint n_indices = 0;
    MexAggregateModelPrivate *priv = self->priv;
    MexModel *model = g_hash_table_lookup (priv->controller_to_model, controller);

    if (!model)
    {
        g_warning (G_STRLOC ": Signal from unknown controller");
        return;
    }

    if (ref)
        n_indices = g_controller_reference_get_n_indices (ref);

    switch (action)
    {
    case G_CONTROLLER_ADD:
        for (i = 0; i < n_indices; i++)
        {
            MexContent *content;

            gint content_index = g_controller_reference_get_index_uint (ref, i);
            content = mex_model_get_content (model, content_index);
            g_hash_table_insert (priv->content_to_model, content, model);

            mex_model_add_content (MEX_MODEL (self), content);
        }
        break;

    case G_CONTROLLER_REMOVE:
        for (i = 0; i < n_indices; i++)
        {
            MexContent *content;

            gint content_index = g_controller_reference_get_index_uint (ref, i);

            content = mex_model_get_content (model, content_index);
            g_hash_table_remove (priv->content_to_model, content);

            mex_model_remove_content (MEX_MODEL (self), content);
        }
        break;

    case G_CONTROLLER_UPDATE:
        break;

    case G_CONTROLLER_CLEAR:
        mex_aggregate_model_clear_model (self, model);
        break;

    case G_CONTROLLER_REPLACE:
    {
        MexContent *content;

        mex_aggregate_model_clear_model (self, model);
        i = 0;
        while ((content = mex_model_get_content (model, i++)))
        {
            g_hash_table_insert (priv->content_to_model, content, model);
            mex_model_add_content (MEX_MODEL (self), content);
        }
    }
    break;

    case G_CONTROLLER_INVALID_ACTION:
        g_warning (G_STRLOC ": Proxy controller has issued an error");
        break;

    default:
        break;
    }
}
Пример #8
0
static void
mex_suggest_complete_cb (MexDownloadQueue *queue,
                         const gchar      *uri,
                         const gchar      *buffer,
                         gsize             count,
                         const GError     *error,
                         gpointer          userdata)
{
  RestXmlNode *root, *n;
  RestXmlParser *parser;
  MexSearchPlugin *self = userdata;
  MexSearchPluginPrivate *priv = self->priv;

  priv->suggest_id = NULL;

  /* hide spinner */
  mx_spinner_set_animating (MX_SPINNER (priv->spinner), FALSE);
  clutter_actor_hide (priv->spinner);

  if (error)
    {
      g_warning ("Error querying Google suggestions: %s",
                 error->message);
      return;
    }

  parser = rest_xml_parser_new ();
  root = rest_xml_parser_parse_from_data (parser, buffer, count);

  if (!root)
    {
      g_warning ("Unknown error parsing Google suggestions XML");
      g_object_unref (parser);
      return;
    }

  /* Clear model */
  mex_model_clear (MEX_MODEL (priv->suggest_model));

  /* Add new suggestions to model */
  n = rest_xml_node_find (root, "CompleteSuggestion");
  for (; n; n = n->next)
    {
      MexContent *content;
      const gchar *suggestion;

      RestXmlNode *node = rest_xml_node_find (n, "suggestion");

      if (!node)
        continue;

      suggestion = rest_xml_node_get_attr (node, "data");

      if (!suggestion)
        continue;

      content = MEX_CONTENT (mex_program_new (priv->suggest_model));
      mex_content_set_metadata (content, MEX_CONTENT_METADATA_TITLE,
                                suggestion);
      mex_content_set_metadata (content, MEX_CONTENT_METADATA_MIMETYPE,
                                "x-mex/search");
      mex_model_add_content (MEX_MODEL (priv->suggest_model), content);
    }

  /* Unref */
  rest_xml_node_unref (root);
  g_object_unref (parser);
}
Пример #9
0
static void
mex_search_plugin_update_history (MexSearchPlugin *self,
                                  const gchar     *term)
{
  gint i;
  gsize length;
  gchar *contents, *current;

  MexSearchPluginPrivate *priv = self->priv;
  const gchar *base_dir =
    mex_settings_get_config_dir (mex_settings_get_default ());
  gchar *history_file = g_build_filename (base_dir, "search", "history", NULL);

  /* Read the history file contents */
  /* TODO: Make this less rubbish? */
  g_file_get_contents (history_file, &contents, &length, NULL);

  /* Prepend new search-term if appropriate */
  if (term)
    {
      gint terms;
      gchar *path;
      gsize new_length;

      gsize term_len = strlen (term);
      gchar *new_contents = g_malloc (length + term_len + 1);

      memcpy (new_contents, term, term_len);
      new_contents[term_len] = '\n';
      new_length = term_len + 1;

      /* Truncate list to 10 terms and remove duplicates */
      if (contents)
        {
          i = 0;
          terms = 1;
          do
            {
              gint cur_len;
              char *eos = strchr (contents + i, '\n');

              if (!eos)
                cur_len = strlen (contents + i);
              else
                cur_len = eos - (contents + i);

              if ((cur_len != term_len) ||
                  (strncmp (contents + i, term, term_len) != 0))
                {
                  memcpy (new_contents + new_length, contents + i, cur_len + 1);
                  new_length += cur_len + 1;

                  if (++terms >= 10)
                    break;
                }

              if (!eos)
                break;

              i += cur_len + 1;
            } while (i < length);
        }

      new_contents[new_length++] = '\0';

      /* Save new list */
      path = g_path_get_dirname (history_file);
      g_mkdir_with_parents (path, 0755);
      g_free (path);

      g_file_set_contents (history_file, new_contents, new_length, NULL);

      /* Replace content with new content */
      g_free (contents);
      contents = new_contents;
      length = new_length;
    }

  /* Empty current list */
  mex_model_clear (MEX_MODEL (priv->history_model));

  /* Populate with search history */
  if (contents)
    {
      current = contents;
      while (current < contents + length)
        {
          MexContent *content =
            MEX_CONTENT (mex_program_new (priv->history_model));
          gchar *end = g_utf8_strchr (current, -1, '\n');

          if (end)
            *end = '\0';

          if (*current)
            {
              mex_content_set_metadata (content,
                                        MEX_CONTENT_METADATA_TITLE,
                                        current);
              mex_content_set_metadata (content,
                                        MEX_CONTENT_METADATA_MIMETYPE,
                                        "x-mex/search");
              mex_model_add_content (MEX_MODEL (priv->history_model),
                                     content);
            }

          if (end)
            current = end + 1;
          else
            break;
        }

      g_free (contents);
    }
  else
    {
      /* Add a default search so the column isn't hidden.
       * TODO: Have a way of inserting 'stock' content rather than doing
       *       this, I suppose.
       */
      MexContent *content = MEX_CONTENT (mex_program_new (priv->history_model));
      mex_content_set_metadata (content, MEX_CONTENT_METADATA_TITLE, "MeeGo");
      mex_content_set_metadata (content, MEX_CONTENT_METADATA_MIMETYPE,
                                "x-mex/search");
      mex_model_add_content (MEX_MODEL (priv->history_model), content);
    }
}