Logo Search packages:      
Sourcecode: netbook-launcher version File versions

launcher-util.c

/*
 * Copyright (C) 2008 Canonical Ltd
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as 
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authored by Neil Jagdish Patel <neil.patel@canonical.com>
 *
 */


#include <string.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <gdk/gdkx.h>

#include <clutter-gtk/gtk-clutter-util.h>

#include "launcher-config.h"
#include "launcher-defines.h"
#include "launcher-util.h"

#include <libgnome/gnome-desktop-item.h>

/* Convert command line to argv array, stripping % conversions on the way */
#define MAX_ARGS 255

/*
 * Convert a desktop file exec string to an array of strings suitable for
 * passing to gdk_spawn_on_screen. Code from libtaku (matchbox-desktop-2).
 */
gchar**
launcher_util_exec_to_argv (const gchar *exec)
{
  const char *p;
  char *buf, *bufp, **argv;
  int nargs;
  gboolean escape, single_quote, double_quote;
  
  argv = g_new (char *, MAX_ARGS + 1);
  buf = g_alloca (strlen (exec) + 1);
  bufp = buf;
  nargs = 0;
  escape = single_quote = double_quote = FALSE;
  
  for (p = exec; *p; p++) {
    if (escape) {
      *bufp++ = *p;
      
      escape = FALSE;
    } else {
      switch (*p) {
      case '\\':
        escape = TRUE;

        break;
      case '%':
        /* Strip '%' conversions */
        if (p[1] && p[1] == '%')
          *bufp++ = *p;
        else if (p[1] && p[1] == 'c')
        {
          *bufp++ = *p;
        }
        
        p++;

        break;
      case '\'':
        if (double_quote)
          *bufp++ = *p;
        else
          single_quote = !single_quote;
        
        break;
      case '\"':
        if (single_quote)
          *bufp++ = *p;
        else
          double_quote = !double_quote;
        
        break;
      case ' ':
        if (single_quote || double_quote)
          *bufp++ = *p;
        else {
          *bufp = 0;
          
          if (nargs < MAX_ARGS)
            argv[nargs++] = g_strdup (buf);
          
          bufp = buf;
        }
        
        break;
      default:
        *bufp++ = *p;
        break;
      }
    }
  }
  
  if (bufp != buf) {
    *bufp = 0;
    
    if (nargs < MAX_ARGS)
      argv[nargs++] = g_strdup (buf);
  }
  
  argv[nargs] = NULL;
  
  return argv;
}


ClutterActor * 
launcher_util_texture_new_from_file (const gchar *filename)
{
  ClutterActor *texture;
  GdkPixbuf *pixbuf;
  GError *error = NULL;

  texture = clutter_texture_new ();

  pixbuf = gdk_pixbuf_new_from_file (filename, &error);
  if (error)
  {
    g_warning ("Unable to load %s: %s", filename, error->message);
    g_error_free (error);
  }
  else
    launcher_util_texture_set_from_pixbuf (CLUTTER_TEXTURE (texture), pixbuf);
  
  if (G_IS_OBJECT (pixbuf)) 
    g_object_unref (pixbuf);

  return texture;
}

/* From matchbox-desktop */
static char *
strip_extension (const char *file)
{
        char *stripped, *p;

        stripped = g_strdup (file);

        p = strrchr (stripped, '.');
        if (p &&
            (!strcmp (p, ".png") ||
             !strcmp (p, ".svg") ||
             !strcmp (p, ".xpm")))
              *p = 0;

        return stripped;
}

/* Gets the pixbuf from a desktop file's icon name. Based on the same function
 * from matchbox-desktop
 */
static GdkPixbuf *
get_icon (const gchar *name, guint size)
{
  static GtkIconTheme *theme = NULL;
  GdkPixbuf *pixbuf = NULL;
  GError *error = NULL;
  gchar *stripped = NULL;

  gint width, height;

  if (theme == NULL)
    theme = gtk_icon_theme_get_default ();

  if (name == NULL)
  {
    pixbuf = gtk_icon_theme_load_icon (theme, "application-x-executable",
                                       size, 0, NULL);
    return pixbuf;
  }

  if (g_path_is_absolute (name))
  {
    if (g_file_test (name, G_FILE_TEST_EXISTS))
    {
      pixbuf = gdk_pixbuf_new_from_file_at_scale (name, size, size, 
                                                  TRUE, &error);
      if (error)
      {
        /*g_warning ("Error loading icon: %s\n", error->message);*/
        g_error_free (error);
        error = NULL;
     }
      return pixbuf;
    } 
  }

  stripped = strip_extension (name);
  
  pixbuf = gtk_icon_theme_load_icon (theme,
                                     stripped,
                                     size,
                                     GTK_ICON_LOOKUP_FORCE_SVG, &error);
  if (error)
  {   
    /*g_warning ("Error loading icon: %s\n", error->message);*/
    g_error_free (error);
    error = NULL;
  }
  
  /* Always try and send back something */
  if (pixbuf == NULL)
    pixbuf = gtk_icon_theme_load_icon (theme, "stock_folder",
                                       size, 0, NULL);
  
  width = gdk_pixbuf_get_width (pixbuf);
  height = gdk_pixbuf_get_height (pixbuf);

  if (width != size || height != size)
  {
    GdkPixbuf *temp = pixbuf;
    pixbuf = gdk_pixbuf_scale_simple (temp, 
                                      size,
                                      size,
                                      GDK_INTERP_HYPER);
    g_object_unref (temp);
  }

  g_free (stripped);

 return pixbuf;
}



ClutterActor * 
launcher_util_texture_new_from_named_icon (const gchar *name)
{
  GdkPixbuf *pixbuf;
  ClutterActor *texture;
  LauncherConfig *cfg = launcher_config_get_default ();

  pixbuf = get_icon (name, cfg->shortcut_height *2);
  
  texture = launcher_util_texture_new_from_pixbuf (pixbuf);

  g_object_unref (pixbuf);

  return texture;
}

static void
_normalize (char *str)
{
      size_t len;
      int i;

      len = strlen(str);

      for (i = 0; i < len; i++) 
  {
            switch (str[i]) 
    {
                  case ' ':
                        str[i] = '-';
        break;
      case '/':
        str[i] = '-';

      default:
                        break;
            }
      }

}

void           
launcher_util_create_favorite (LauncherMenuApplication *app)
{
  GError *error = NULL;
  GnomeDesktopItem *item = NULL;
  GnomeDesktopItem *fav = NULL;
  const gchar *item_file;
  gchar *appdir, *filename, *favfile;

  g_return_if_fail (app);

  item_file = launcher_menu_application_get_desktop_filename (app);
  item = gnome_desktop_item_new_from_file (item_file,
                                         GNOME_DESKTOP_ITEM_LOAD_ONLY_IF_EXISTS,
                                           NULL);
  if (item == NULL)
    return;

  fav = gnome_desktop_item_copy (item);
  gnome_desktop_item_set_string (fav, 
                                 GNOME_DESKTOP_ITEM_CATEGORIES,
                                 "Favorites");

  appdir = g_strdup_printf ("file://%s/.local/share/applications", 
                            g_get_home_dir ());
  filename = g_strdup_printf ("%s-favorite-%ld.desktop",
                              launcher_menu_application_get_name (app),
                              time (NULL));
  _normalize (filename);

  favfile = g_build_filename (appdir, filename, NULL);
                               
  gnome_desktop_item_save (fav, favfile, TRUE, &error);
  
  if (error)
  {
    g_warning ("Unable to create favorite: %s", error->message);
    g_error_free (error);
  }

  g_free (appdir);
  g_free (filename);
  g_free (favfile);

  gnome_desktop_item_unref (item);
  gnome_desktop_item_unref (fav);
}

void
launcher_util_remove_favorite (LauncherMenuApplication *app)
{
  GnomeDesktopItem *item;
  const gchar *path;
  gchar *filename;
  gchar *basename;
  GError *error = NULL;

  g_return_if_fail (app);

  path = launcher_menu_application_get_desktop_filename (app);

  if ((g_remove (path) == 0))
  {
    return;
  }
  
  item = gnome_desktop_item_new_from_file (path,
                                        GNOME_DESKTOP_ITEM_LOAD_ONLY_IF_EXISTS, 
                                        NULL);
  if (!item)
  {
    g_debug ("Unable to remove : %s, cannot open desktop file", path);
    return;
  }

  gnome_desktop_item_set_string (item, 
                                 GNOME_DESKTOP_ITEM_NO_DISPLAY, 
                                 "true");
  basename = g_path_get_basename (path);
  filename = g_build_filename ("file://",
                               g_get_home_dir (), 
                               ".local/share/applications",
                               basename,
                               NULL);
  gnome_desktop_item_save (item, filename, TRUE, &error);

  if (error)
  {
    g_warning ("Unable to remove favorite: %s", error->message);
    g_error_free (error);
  }
  g_free (basename);
  g_free (filename);

  gnome_desktop_item_unref (item);
}

void    
launcher_util_add_favorite    (const gchar *name,
                               const gchar *category,
                               const gchar *exec,
                               const gchar *icon)
{
  GError *error = NULL;
  GnomeDesktopItem *item = NULL;
  gchar *uri, *leaf;

  leaf = g_strdup_printf ("%s-fav-%ld.desktop", name, time (NULL));
  _normalize (leaf);
  uri = g_strdup_printf ("file://%s/.local/share/applications/%s",
                         g_get_home_dir (),
                         leaf);

  item = gnome_desktop_item_new ();

  gnome_desktop_item_set_string (item, 
                                 GNOME_DESKTOP_ITEM_NAME,
                                 name); 
  gnome_desktop_item_set_string (item, 
                                 GNOME_DESKTOP_ITEM_CATEGORIES,
                                 category);
  gnome_desktop_item_set_string (item, 
                                 GNOME_DESKTOP_ITEM_EXEC,
                                 exec);
  gnome_desktop_item_set_string (item, 
                                 GNOME_DESKTOP_ITEM_ICON,
                                 icon);
  gnome_desktop_item_set_string (item, 
                                 GNOME_DESKTOP_ITEM_TYPE,
                                 "Application");
  gnome_desktop_item_set_string (item, 
                                 GNOME_DESKTOP_ITEM_VERSION,
                                 "1.0");
                        
  g_debug ("Creating new favourite: %s", uri);

  gnome_desktop_item_save (item, uri, TRUE, &error);
  if (error)
  {
    g_warning ("Unable to create favorite: %s", error->message);
    g_error_free (error);
  }

  gnome_desktop_item_unref (item);

  g_free (leaf);
  g_free (uri);
}

/*
 * Taken from libtomboy, (C) 2008 Novell, LGPL v2 or later
 */

static void
tomboy_window_override_user_time (GtkWindow *window)
{
      guint32 ev_time = gtk_get_current_event_time();

      if (ev_time == 0) {
            /* 
             * FIXME: Global keypresses use an event filter on the root
             * window, which processes events before GDK sees them.
             */
            //ev_time = tomboy_keybinder_get_current_event_time ();
    ev_time = CLUTTER_CURRENT_TIME;
      }
      if (ev_time == 0) {
            gint ev_mask = gtk_widget_get_events (GTK_WIDGET(window));
            if (!(ev_mask & GDK_PROPERTY_CHANGE_MASK)) {
                  gtk_widget_add_events (GTK_WIDGET (window),
                                     GDK_PROPERTY_CHANGE_MASK);
            }

            /* 
             * NOTE: Last resort for D-BUS or other non-interactive
             *       openings.  Causes roundtrip to server.  Lame. 
             */
            ev_time = gdk_x11_get_server_time (GTK_WIDGET(window)->window);
      }

      gdk_x11_window_set_user_time (GTK_WIDGET(window)->window, ev_time);
}



void 
launcher_util_present_window (GtkWindow *window)
{
      if (!GTK_WIDGET_REALIZED (window))
            gtk_widget_realize (GTK_WIDGET (window));

      tomboy_window_override_user_time (window);

      gtk_window_present (window);
}

/*
 * Fixes bug in gtk_clutter_texture_set_from_pixbuf
 * Remove this when clutter-gtk-0.8.2 releases 
 */
void     
launcher_util_texture_set_from_pixbuf (ClutterTexture *texture,
                                       GdkPixbuf      *pixbuf)
{
  GError *error;

  g_return_if_fail (CLUTTER_IS_TEXTURE (texture));
  g_return_if_fail (GDK_IS_PIXBUF (pixbuf));

  error = NULL;
  clutter_texture_set_from_rgb_data (texture,
                                     gdk_pixbuf_get_pixels (pixbuf),
                                     gdk_pixbuf_get_has_alpha (pixbuf),
                                     gdk_pixbuf_get_width (pixbuf),
                                     gdk_pixbuf_get_height (pixbuf),
                                     gdk_pixbuf_get_rowstride (pixbuf),
                                     gdk_pixbuf_get_has_alpha (pixbuf) ? 4 : 3,
                                     0,
                                     &error);
  if (error)
  {
    g_warning ("Unable to set the pixbuf: %s", error->message);
    g_error_free (error);
  }
}

/*
 * Fixes bug in gtk_clutter_new_from_pixbuf 
 * Remove this when clutter-gtk-0.8.2 releaes
 */
ClutterActor *
launcher_util_texture_new_from_pixbuf (GdkPixbuf *pixbuf)
{
  ClutterActor *retval;
  GError *error;

  g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);

  retval = clutter_texture_new ();

  error = NULL;
  clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (retval),
                                     gdk_pixbuf_get_pixels (pixbuf),
                                     gdk_pixbuf_get_has_alpha (pixbuf),
                                     gdk_pixbuf_get_width (pixbuf),
                                     gdk_pixbuf_get_height (pixbuf),
                                     gdk_pixbuf_get_rowstride (pixbuf),
                                     gdk_pixbuf_get_has_alpha (pixbuf) ? 4 : 3,
                                     0,
                                     &error);
  if (error)
    {
      g_warning ("Unable to set the pixbuf: %s", error->message);
      g_error_free (error);
    }

  return retval; 

}


Generated by  Doxygen 1.6.0   Back to index