[Goodies-commits] r6539 - in xfce4-clipman-plugin/branches/xfce-4-6: . panel-plugin tests

Mike Massonnet mmassonnet at xfce.org
Sun Jan 25 12:33:13 CET 2009


Author: mmassonnet
Date: 2009-01-25 11:33:12 +0000 (Sun, 25 Jan 2009)
New Revision: 6539

Added:
   xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/actions.c
   xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/actions.h
   xfce4-clipman-plugin/branches/xfce-4-6/tests/
   xfce4-clipman-plugin/branches/xfce-4-6/tests/Makefile.am
   xfce4-clipman-plugin/branches/xfce-4-6/tests/test_actions.c
Modified:
   xfce4-clipman-plugin/branches/xfce-4-6/ChangeLog
   xfce4-clipman-plugin/branches/xfce-4-6/configure.ac.in
   xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/Makefile.am
   xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/collector.c
   xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/common.h
   xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/menu.c
   xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/panel-plugin.c
   xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/settings-dialog.glade
Log:
Actions are available but hard-coded at this time.

Modified: xfce4-clipman-plugin/branches/xfce-4-6/ChangeLog
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/ChangeLog	2009-01-24 19:05:52 UTC (rev 6538)
+++ xfce4-clipman-plugin/branches/xfce-4-6/ChangeLog	2009-01-25 11:33:12 UTC (rev 6539)
@@ -1,3 +1,20 @@
+2009-01-25	Mike Massonnet
+Actions are available but hard-coded at this time.
+
+	- configure.ac.in, tests/*:
+		Add a test program for the actions.
+	- panel-plugin/actions.c, panel-plugin/actions.h,
+	panel-plugin/Makefile.am:
+		A new GObject ClipmanActions with methods to add and remove
+		commands for a specific regex.  The code to save and load from
+		an XML file still needs to be written.
+	- panel-plugin/collector.c, panel-plugin/panel-plugin.c:
+		Install new property "enable-actions" which will match the
+		clipboard texts for actions.  Bind the property to xfconf
+		inside panel_plugin_register().
+	- panel-plugin/settings-dialog.glade:
+		New dialogs for the actions.
+
 2009-01-15	Mike Massonnet
 Some minor changes.
 

Modified: xfce4-clipman-plugin/branches/xfce-4-6/configure.ac.in
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/configure.ac.in	2009-01-24 19:05:52 UTC (rev 6538)
+++ xfce4-clipman-plugin/branches/xfce-4-6/configure.ac.in	2009-01-25 11:33:12 UTC (rev 6539)
@@ -81,6 +81,7 @@
 AC_OUTPUT([
 Makefile
 panel-plugin/Makefile
+tests/Makefile
 po/Makefile.in
 ])
 

Modified: xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/Makefile.am
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/Makefile.am	2009-01-24 19:05:52 UTC (rev 6538)
+++ xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/Makefile.am	2009-01-25 11:33:12 UTC (rev 6539)
@@ -14,6 +14,7 @@
 xfce4_clipman_plugin_SOURCES =						\
 	panel-plugin.c							\
 	common.h							\
+	actions.c			actions.h			\
 	collector.c			collector.h			\
 	history.c			history.h			\
 	menu.c				menu.h				\

Added: xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/actions.c
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/actions.c	                        (rev 0)
+++ xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/actions.c	2009-01-25 11:33:12 UTC (rev 6539)
@@ -0,0 +1,485 @@
+/*
+ *  Copyright (c) 2009 Mike Massonnet <mmassonnet at xfce.org>
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <exo/exo.h>
+#include <gtk/gtk.h>
+#include <libxfce4util/libxfce4util.h>
+#include <libxfcegui4/libxfcegui4.h>
+
+#include "common.h"
+
+#include "actions.h"
+
+/*
+ * GObject declarations
+ */
+
+G_DEFINE_TYPE (ClipmanActions, clipman_actions, G_TYPE_OBJECT)
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CLIPMAN_TYPE_ACTIONS, ClipmanActionsPrivate))
+
+struct _ClipmanActionsPrivate
+{
+  GSList               *entries;
+  GtkWidget            *menu;
+};
+
+static void             clipman_actions_class_init          (ClipmanActionsClass *klass);
+static void             clipman_actions_init                (ClipmanActions *actions);
+static void             clipman_actions_finalize            (GObject *object);
+
+/*
+ * Misc functions declarations
+ */
+
+static gint           __clipman_actions_entry_compare       (gpointer a,
+                                                             gpointer b);
+static gint           __clipman_actions_entry_compare_name  (gpointer a,
+                                                             gpointer b);
+static void           __clipman_actions_entry_free          (ClipmanActionsEntry *entry);
+#if !GLIB_CHECK_VERSION (2,16,0)
+static void           __g_hash_table_foreach_entry          (gpointer key,
+                                                             gpointer value,
+                                                             gpointer user_data);
+#endif
+
+/*
+ * Callbacks declarations
+ */
+
+static void             cb_entry_activated                  (GtkMenuItem *mi,
+                                                             gpointer user_data);
+
+/*
+ * Callbacks
+ */
+
+static void
+cb_entry_activated (GtkMenuItem *mi,
+                    gpointer user_data)
+{
+  gchar *real_command;
+  const gchar *text;
+  const gchar *command;
+  const GRegex *regex;
+  GError *error = NULL;
+
+  text = g_object_get_data (G_OBJECT (mi), "text");
+  command = g_object_get_data (G_OBJECT (mi), "command");
+  regex = g_object_get_data (G_OBJECT (mi), "regex");
+
+  real_command = g_regex_replace (regex, text, -1, 0, command, 0, NULL);
+  
+  DBG ("Execute command `%s'", real_command);
+
+  xfce_exec (real_command, FALSE, FALSE, &error);
+  if (error != NULL)
+    {
+      xfce_err (_("Unable to execute the command \"%s\"\n\n%s"), real_command, error->message);
+      g_error_free (error);
+    }
+  g_free (real_command);
+}
+
+/*
+ * Misc functions
+ */
+
+static gint
+__clipman_actions_entry_compare (gpointer a,
+                                 gpointer b)
+{
+  const ClipmanActionsEntry *entrya = a;
+  const ClipmanActionsEntry *entryb = b;
+  return g_ascii_strcasecmp (entrya->action_name, entryb->action_name);
+}
+
+static gint
+__clipman_actions_entry_compare_name (gpointer a,
+                                      gpointer b)
+{
+  const ClipmanActionsEntry *entry = a;
+  const char *name = b;
+  return g_ascii_strcasecmp (entry->action_name, name);
+}
+
+static void
+__clipman_actions_entry_free (ClipmanActionsEntry *entry)
+{
+  g_free (entry->action_name);
+  g_regex_unref (entry->regex);
+  g_hash_table_destroy (entry->commands);
+  g_slice_free (ClipmanActionsEntry, entry);
+}
+
+#if !GLIB_CHECK_VERSION (2,16,0)
+static void
+__g_hash_table_foreach_entry (gpointer key,
+                              gpointer value,
+                              gpointer user_data)
+{
+  gchar *command_name = key;
+  gchar *command = value;
+  GtkWidget *menu = user_data;
+  GtkWidget *mi;
+
+  mi = gtk_menu_item_new_with_label (command_name);
+  g_object_set_data (G_OBJECT (mi), "text", g_object_get_data (G_OBJECT (menu), "text"));
+  g_object_set_data (G_OBJECT (mi), "command", command);
+  g_object_set_data (G_OBJECT (mi), "regex", g_object_get_data (G_OBJECT (menu), "regex"));
+  gtk_container_add (GTK_CONTAINER (menu), mi);
+  g_signal_connect (mi, "activate", G_CALLBACK (cb_entry_activated), NULL);
+}
+#endif
+
+/*
+ * Public methods
+ */
+
+/**
+ * clipman_actions_add:
+ * @actions:        a #ClipmanActions
+ * @action_name:    human readable name of @regex
+ * @regex:          a valid regex or NULL if @name already exists in the list
+ * @command_name:   human readable name of @command
+ * @command:        the command to execute
+ *
+ * Adds a new entry to the list of actions.  The same name and regex can be
+ * passed several times for each new command.
+ * If @action_name already exists, the regex is ignored.
+ * If @command_name already exists, the new command will replace the old one.
+ *
+ * The command can contain the parameter '%s' that will be replaced by the
+ * matching regex text.
+ *
+ * Returns: FALSE if the regex was invalid
+ */
+gboolean
+clipman_actions_add (ClipmanActions *actions,
+                     const gchar *action_name,
+                     const gchar *regex,
+                     const gchar *command_name,
+                     const gchar *command)
+{
+  ClipmanActionsEntry *entry;
+  GSList *l;
+  GRegex *_regex;
+
+  g_return_val_if_fail (G_LIKELY (action_name != NULL), FALSE);
+  g_return_val_if_fail (G_LIKELY (command_name != NULL), FALSE);
+  g_return_val_if_fail (G_LIKELY (command != NULL), FALSE);
+
+  l = g_slist_find_custom (actions->priv->entries, action_name, (GCompareFunc)__clipman_actions_entry_compare_name);
+
+  /* Add a new entry to the list */
+  if (l == NULL)
+    {
+      /* Validate the regex */
+      _regex = g_regex_new (regex, 0, 0, NULL);
+      if (_regex == NULL)
+        return FALSE;
+
+      DBG ("New entry `%s' with command `%s'", action_name, command_name);
+
+      entry = g_slice_new0 (ClipmanActionsEntry);
+      entry->action_name = g_strdup (action_name);
+      entry->regex = _regex;
+      entry->commands = g_hash_table_new_full ((GHashFunc)g_str_hash, (GEqualFunc)g_str_equal,
+                                               (GDestroyNotify)g_free, (GDestroyNotify)g_free);
+      g_hash_table_insert (entry->commands, g_strdup (command_name), g_strdup (command));
+
+      actions->priv->entries = g_slist_insert_sorted (actions->priv->entries, entry, (GCompareFunc)__clipman_actions_entry_compare);
+      return TRUE;
+    }
+
+  /* Add command to the existing entry */
+  DBG ("Add to entry `%s' the command `%s'", action_name, command_name);
+
+  entry = l->data;
+  g_hash_table_insert (entry->commands, g_strdup (command_name), g_strdup (command));
+  return TRUE;
+}
+
+/**
+ * clipman_actions_remove:
+ * @actions:        a #ClipmanActions
+ * @action_name:    the human readable name for the regex
+ * @command_name:   the command to remove
+ *
+ * Removes a command from the list of actions.  If the command is the last
+ * command for the corresponding action, than the action will be completely
+ * dropped from the list.
+ *
+ * Returns: FALSE if no command could be removed
+ */
+gboolean
+clipman_actions_remove (ClipmanActions *actions,
+                        const gchar *action_name,
+                        const gchar *command_name)
+{
+  ClipmanActionsEntry *entry;
+  GSList *l;
+  gboolean found;
+
+  l = g_slist_find_custom (actions->priv->entries, action_name, (GCompareFunc)__clipman_actions_entry_compare_name);
+  if (l == NULL)
+    return FALSE;
+
+  entry = l->data;
+  found = g_hash_table_remove (entry->commands, command_name);
+
+  if (!found)
+    g_warning ("No corresponding command `%s' inside entry `%s'", command_name, action_name);
+  else
+    {
+      DBG ("Drop from entry `%s' the command `%s'", action_name, command_name);
+      if (g_hash_table_size (entry->commands) == 0)
+        {
+          DBG ("Clean up the entry");
+          __clipman_actions_entry_free (entry);
+          actions->priv->entries = g_slist_delete_link (actions->priv->entries, l);
+        }
+    }
+
+  return found;
+}
+
+/**
+ * clipman_actions_match:
+ * @actions:    a #ClipmanActions
+ * @text:       the text to match against the existing regex's
+ *
+ * Searches a regex match for @text and returns a newly allocated #GSList which
+ * must be freed with g_slist_free() that contains a list of
+ * #ClipmanActionsEntry for each matched action.
+ * Note that the data inside the list is owned by #ClipmanActions and must not
+ * be modified.
+ *
+ * Returns: a newly allocated #GSList
+ */
+GSList *
+clipman_actions_match (ClipmanActions *actions,
+                       const gchar *text)
+{
+  ClipmanActionsEntry *entry;
+  GSList *l;
+  GSList *entries = NULL;
+
+  for (l = actions->priv->entries; l != NULL; l = l->next)
+    {
+      entry = l->data;
+      if (g_regex_match (entry->regex, text, 0, NULL))
+        entries = g_slist_prepend (entries, entry);
+    }
+
+  return entries;
+}
+
+/**
+ * clipman_actions_match_with_menu:
+ * @actions:    a #ClipmanActions
+ * @text:       the text to match against the existing regex's
+ *
+ * Builds and displays a menu with matching actions for @text.
+ *
+ * Read clipman_actions_match() for more information.
+ */
+void
+clipman_actions_match_with_menu (ClipmanActions *actions,
+                                 const gchar *text)
+{
+  ClipmanActionsEntry *entry;
+  GtkWidget *mi;
+  GSList *l, *entries;
+
+  entries = clipman_actions_match (actions, text);
+
+  if (entries == NULL)
+    return;
+
+  DBG ("Build the menu with actions");
+
+  if (GTK_IS_MENU (actions->priv->menu))
+    {
+      gtk_widget_destroy (actions->priv->menu);
+      actions->priv->menu = NULL;
+    }
+
+  actions->priv->menu = gtk_menu_new ();
+  g_object_set_data_full (G_OBJECT (actions->priv->menu), "text", g_strdup (text), (GDestroyNotify)g_free);
+
+  for (l = entries; l != NULL; l = l->next)
+    {
+      entry = l->data;
+
+      mi = gtk_menu_item_new_with_label (entry->action_name);
+      gtk_widget_set_sensitive (mi, FALSE);
+      gtk_container_add (GTK_CONTAINER (actions->priv->menu), mi);
+
+      mi = gtk_separator_menu_item_new ();
+      gtk_container_add (GTK_CONTAINER (actions->priv->menu), mi);
+
+#if GLIB_CHECK_VERSION (2,16,0)
+      GHashTableIter iter;
+      gpointer key, value;
+      g_hash_table_iter_init (&iter, entry->commands);
+      while (g_hash_table_iter_next (&iter, &key, &value))
+        {
+          mi = gtk_menu_item_new_with_label ((const gchar *)key);
+          g_object_set_data (G_OBJECT (mi), "text", g_object_get_data (G_OBJECT (actions->priv->menu), "text"));
+          g_object_set_data (G_OBJECT (mi), "command", value);
+          g_object_set_data (G_OBJECT (mi), "regex", entry->regex);
+          gtk_container_add (GTK_CONTAINER (actions->priv->menu), mi);
+          g_signal_connect (mi, "activate", G_CALLBACK (cb_entry_activated), NULL);
+        }
+#else
+      g_object_set_data (G_OBJECT (actions->priv->menu), "regex", entry->regex);
+      g_hash_table_foreach (entry->commands, (GHFunc)__g_hash_table_foreach_entry, actions->priv->menu);
+#endif
+
+      mi = gtk_separator_menu_item_new ();
+      gtk_container_add (GTK_CONTAINER (actions->priv->menu), mi);
+    }
+
+  mi = gtk_menu_item_new_with_label ("Cancel");
+  gtk_container_add (GTK_CONTAINER (actions->priv->menu), mi);
+
+  gtk_widget_show_all (actions->priv->menu);
+  gtk_menu_popup (GTK_MENU (actions->priv->menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
+
+  g_slist_free (entries);
+}
+
+/**
+ * clipman_actions_load:
+ * @actions:
+ *
+ */
+void
+clipman_actions_load (ClipmanActions *actions)
+{
+  gchar *filename;
+  gchar *data;
+  gboolean load;
+
+  filename = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "xfce4/panel/xfce4-clipman-plugin-actions.xml", FALSE);
+  load = g_file_get_contents (filename, &data, NULL, NULL);
+
+  if (!load)
+    {
+      g_free (filename);
+      filename = g_strdup (DATADIR"/xfce4/panel-plugins/xfce4-clipman-plugin-actions.xml");
+      load = g_file_get_contents (filename, &data, NULL, NULL);
+    }
+
+  if (load)
+    {
+      /* TODO Add actions from data */
+    }
+  else
+    {
+      /* TODO Move these actions to the system wide XML file */
+      /* Add default actions */
+      clipman_actions_add (actions, _("Web URL"), "^https?://[@:a-zA-Z0-9+.-]+(:[0-9]+)?[/a-zA-Z0-9$-_.+!*'(),?=;%]*$",
+                           _("Open with default application"), "exo-open \\0");
+      clipman_actions_add (actions, _("Web URL"), NULL,
+                           _("Open in Firefox"), "firefox \\0");
+      clipman_actions_add (actions, _("Image"), "^(/|http|ftp).+\\.(jpg|png|gif)$",
+                           _("View in Ristretto"), "ristretto \\0");
+      clipman_actions_add (actions, _("Image"), NULL,
+                           _("Edit in Gimp"), "gimp \\0");
+      clipman_actions_add (actions, _("Bugz"), "(bug #|bug |Bug #|Bug )([0-9]+)",
+                           _("Xfce Bug"), "exo-open http://bugzilla.xfce.org/show_bug.cgi?id=\\2");
+      clipman_actions_add (actions, _("Bugz"), NULL,
+                           _("GNOME Bug"), "exo-open http://bugzilla.gnome.org/show_bug.cgi?id=\\2");
+    }
+
+  g_free (filename);
+  g_free (data);
+}
+
+/**
+ * clipman_actions_save:
+ * @actions:
+ *
+ */
+void
+clipman_actions_save (ClipmanActions *actions)
+{
+}
+
+/**
+ * clipman_actions_get:
+ *
+ */
+ClipmanActions *
+clipman_actions_get ()
+{
+  static ClipmanActions *singleton = NULL;
+
+  if (singleton == NULL)
+    {
+      singleton = g_object_new (CLIPMAN_TYPE_ACTIONS, NULL);
+      g_object_add_weak_pointer (G_OBJECT (singleton), (gpointer)&singleton);
+    }
+  else
+    g_object_ref (G_OBJECT (singleton));
+
+  return singleton;
+}
+
+/*
+ * GObject
+ */
+
+static void
+clipman_actions_class_init (ClipmanActionsClass *klass)
+{
+  GObjectClass *object_class;
+
+  g_type_class_add_private (klass, sizeof (ClipmanActionsPrivate));
+
+  clipman_actions_parent_class = g_type_class_peek_parent (klass);
+
+  object_class = G_OBJECT_CLASS (klass);
+  object_class->finalize = clipman_actions_finalize;
+}
+
+static void
+clipman_actions_init (ClipmanActions *actions)
+{
+  actions->priv = GET_PRIVATE (actions);
+
+  clipman_actions_load (actions);
+}
+
+static void
+clipman_actions_finalize (GObject *object)
+{
+  ClipmanActions *actions = CLIPMAN_ACTIONS (object);
+  GSList *l;
+
+  for (l = actions->priv->entries; l != NULL; l = l->next)
+    __clipman_actions_entry_free (l->data);
+  g_slist_free (actions->priv->entries);
+}
+

Added: xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/actions.h
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/actions.h	                        (rev 0)
+++ xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/actions.h	2009-01-25 11:33:12 UTC (rev 6539)
@@ -0,0 +1,87 @@
+/*
+ *  Copyright (c) 2009 Mike Massonnet <mmassonnet at xfce.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __CLIPMAN_ACTIONS_H__
+#define __CLIPMAN_ACTIONS_H__
+
+#include <glib-object.h>
+
+/*
+ * ClipmanActionsEntry struct declaration
+ */
+
+typedef struct _ClipmanActionsEntry ClipmanActionsEntry;
+struct _ClipmanActionsEntry
+{
+  gchar                *icon_name;
+  gchar                *action_name;
+  GRegex               *regex;
+  GHashTable           *commands;
+};
+
+/*
+ * ClipmanActions GObject declaration
+ */
+
+#define CLIPMAN_TYPE_ACTIONS                  (clipman_actions_get_type())
+
+#define CLIPMAN_ACTIONS(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLIPMAN_TYPE_ACTIONS, ClipmanActions))
+#define CLIPMAN_ACTIONS_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), CLIPMAN_TYPE_ACTIONS, ClipmanActionsClass))
+
+#define CLIPMAN_IS_ACTIONS(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLIPMAN_TYPE_ACTIONS))
+#define CLIPMAN_IS_ACTIONS_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), CLIPMAN_TYPE_ACTIONS))
+
+#define CLIPMAN_ACTIONS_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), CLIPMAN_TYPE_ACTIONS, ClipmanActionsClass))
+
+typedef struct _ClipmanActionsClass           ClipmanActionsClass;
+typedef struct _ClipmanActions                ClipmanActions;
+typedef struct _ClipmanActionsPrivate         ClipmanActionsPrivate;
+
+struct _ClipmanActionsClass
+{
+  GObjectClass              parent_class;
+};
+
+struct _ClipmanActions
+{
+  GObject                   parent;
+
+  /* Private */
+  ClipmanActionsPrivate    *priv;
+};
+
+GType                   clipman_actions_get_type               ();
+
+ClipmanActions *      	clipman_actions_get                    ();
+gboolean                clipman_actions_add                    (ClipmanActions *actions,
+                                                                const gchar *action_name,
+                                                                const gchar *regex,
+                                                                const gchar *command_name,
+                                                                const gchar *command);
+gboolean                clipman_actions_remove                 (ClipmanActions *actions,
+                                                                const gchar *action_name,
+                                                                const gchar *command);
+GSList *                clipman_actions_match                  (ClipmanActions *actions,
+                                                                const gchar *match);
+void                    clipman_actions_match_with_menu        (ClipmanActions *actions,
+                                                                const gchar *match);
+void                    clipman_actions_load                   (ClipmanActions *actions);
+void                    clipman_actions_save                   (ClipmanActions *actions);
+
+#endif /* !__CLIPMAN_ACTIONS_H__ */
+

Modified: xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/collector.c
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/collector.c	2009-01-24 19:05:52 UTC (rev 6538)
+++ xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/collector.c	2009-01-25 11:33:12 UTC (rev 6539)
@@ -25,6 +25,7 @@
 #include <xfconf/xfconf.h>
 
 #include "common.h"
+#include "actions.h"
 #include "history.h"
 
 #include "collector.h"
@@ -39,17 +40,20 @@
 
 struct _ClipmanCollectorPrivate
 {
+  ClipmanActions       *actions;
   ClipmanHistory       *history;
   GtkClipboard         *default_clipboard;
   GtkClipboard         *primary_clipboard;
   guint                 primary_clipboard_timeout;
+  gboolean              restoring;
   gboolean              add_primary_clipboard;
-  gboolean              restoring;
+  gboolean              enable_actions;
 };
 
 enum
 {
   ADD_PRIMARY_CLIPBOARD = 1,
+  ENABLE_ACTIONS,
 };
 
 static void             clipman_collector_class_init        (ClipmanCollectorClass *klass);
@@ -152,11 +156,11 @@
        * actually check inside a delayed timeout if the mouse is still pressed
        * or if the shift key is hold down, and once both are released the
        * content will go to the history. */
-      if (collector->priv->add_primary_clipboard)
+      if (collector->priv->add_primary_clipboard || collector->priv->enable_actions)
         {
           if (collector->priv->primary_clipboard_timeout == 0)
             collector->priv->primary_clipboard_timeout =
-              g_timeout_add (500, (GSourceFunc)cb_check_primary_clipboard, collector);
+              g_timeout_add (250, (GSourceFunc)cb_check_primary_clipboard, collector);
         }
     }
 }
@@ -178,15 +182,22 @@
       text = gtk_clipboard_wait_for_text (collector->priv->primary_clipboard);
       if (text != NULL && text[0] != '\0')
         {
-          clipman_history_add_text (collector->priv->history, text, collector->priv->primary_clipboard);
+          if (collector->priv->add_primary_clipboard)
+            {
+              clipman_history_add_text (collector->priv->history, text, collector->priv->primary_clipboard);
 
-          /* Make a copy inside the default clipboard */
-          collector->priv->restoring = TRUE;
-          gtk_clipboard_set_text (collector->priv->default_clipboard, text, -1);
+              /* Make a copy inside the default clipboard */
+              collector->priv->restoring = TRUE;
+              gtk_clipboard_set_text (collector->priv->default_clipboard, text, -1);
+            }
+
+          /* Match for actions */
+          if (collector->priv->enable_actions)
+            clipman_actions_match_with_menu (collector->priv->actions, text);
         }
       g_free (text);
     }
-  else
+  else if (collector->priv->add_primary_clipboard)
     {
       DBG ("The primary clipboard is empty");
       _clipman_collector_restore_clipboard (collector, collector->priv->primary_clipboard);
@@ -290,6 +301,13 @@
                                                          "Add the primary clipboard to the history",
                                                          DEFAULT_ADD_PRIMARY_CLIPBOARD,
                                                          G_PARAM_CONSTRUCT|G_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, ENABLE_ACTIONS,
+                                   g_param_spec_boolean ("enable-actions",
+                                                         "EnableActions",
+                                                         "Set to TRUE to enable actions (match the clipboard texts against regex's)",
+                                                         DEFAULT_ENABLE_ACTIONS,
+                                                         G_PARAM_CONSTRUCT|G_PARAM_READWRITE));
 }
 
 static void
@@ -301,6 +319,9 @@
    * while avoiding to re-add it to the history. */
   collector->priv->restoring = FALSE;
 
+  /* ClipmanActions */
+  collector->priv->actions = clipman_actions_get ();
+
   /* ClipmanHistory */
   collector->priv->history = clipman_history_get ();
 
@@ -341,6 +362,10 @@
       priv->add_primary_clipboard = g_value_get_boolean (value);
       break;
 
+    case ENABLE_ACTIONS:
+      priv->enable_actions = g_value_get_boolean (value);
+      break;
+
     default:
       break;
     }
@@ -360,6 +385,10 @@
       g_value_set_boolean (value, priv->add_primary_clipboard);
       break;
 
+    case ENABLE_ACTIONS:
+      g_value_set_boolean (value, priv->enable_actions);
+      break;
+
     default:
       break;
     }

Modified: xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/common.h
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/common.h	2009-01-24 19:05:52 UTC (rev 6538)
+++ xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/common.h	2009-01-25 11:33:12 UTC (rev 6539)
@@ -29,4 +29,5 @@
 
 /* Collector */
 #define DEFAULT_ADD_PRIMARY_CLIPBOARD           FALSE
+#define DEFAULT_ENABLE_ACTIONS                  FALSE
 

Modified: xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/menu.c
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/menu.c	2009-01-24 19:05:52 UTC (rev 6538)
+++ xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/menu.c	2009-01-25 11:33:12 UTC (rev 6539)
@@ -132,7 +132,7 @@
   ClipmanHistoryItem *item;
   const ClipmanHistoryItem *item_to_restore;
   GSList *list, *l;
-  gint pos = 0, i;
+  gint pos = 0;
 
   /* Get the most recent item in the history */
   item_to_restore = clipman_history_get_item_to_restore (menu->priv->history);

Modified: xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/panel-plugin.c
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/panel-plugin.c	2009-01-24 19:05:52 UTC (rev 6538)
+++ xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/panel-plugin.c	2009-01-25 11:33:12 UTC (rev 6539)
@@ -20,6 +20,7 @@
 #include <config.h>
 #endif
 
+#include <glib/gstdio.h>
 #include <gtk/gtk.h>
 #include <libxfce4util/libxfce4util.h>
 #include <libxfcegui4/libxfcegui4.h>
@@ -30,6 +31,7 @@
 
 #include "common.h"
 #include "settings-dialog_glade.h"
+#include "actions.h"
 #include "collector.h"
 #include "history.h"
 #include "menu.h"
@@ -45,6 +47,7 @@
 {
   XfcePanelPlugin      *panel_plugin;
   XfconfChannel        *channel;
+  ClipmanActions       *actions;
   ClipmanCollector     *collector;
   ClipmanHistory       *history;
   GtkWidget            *button;
@@ -112,6 +115,9 @@
   /* XfconfChannel */
   plugin->channel = xfconf_channel_new_with_property_base ("xfce4-panel", "/plugins/clipman");
 
+  /* ClipmanActions */
+  plugin->actions = clipman_actions_get ();
+
   /* ClipmanHistory */
   plugin->history = clipman_history_get ();
   xfconf_g_property_bind (plugin->channel, "/settings/max-texts-in-history",
@@ -125,6 +131,8 @@
   plugin->collector = clipman_collector_get ();
   xfconf_g_property_bind (plugin->channel, "/settings/add-primary-clipboard",
                           G_TYPE_BOOLEAN, plugin->collector, "add-primary-clipboard");
+  xfconf_g_property_bind (plugin->channel, "/settings/enable-actions",
+                          G_TYPE_BOOLEAN, plugin->collector, "enable-actions");
 
   /* Panel Button */
   plugin->button = xfce_create_panel_toggle_button ();
@@ -351,6 +359,7 @@
   gtk_widget_destroy (plugin->menu);
   gtk_widget_destroy (plugin->button);
   g_object_unref (plugin->channel);
+  g_object_unref (plugin->actions);
   g_object_unref (plugin->collector);
   g_object_unref (plugin->history);
   g_slice_free (MyPlugin, plugin);

Modified: xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/settings-dialog.glade
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/settings-dialog.glade	2009-01-24 19:05:52 UTC (rev 6538)
+++ xfce4-clipman-plugin/branches/xfce-4-6/panel-plugin/settings-dialog.glade	2009-01-25 11:33:12 UTC (rev 6539)
@@ -1,14 +1,17 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.5 on Thu Jan 15 09:34:53 2009 -->
+<?xml version="1.0"?>
 <glade-interface>
+  <!-- interface-requires gtk+ 2.16 -->
   <requires lib="xfce4"/>
+  <!-- interface-requires xfce4 2335.53032 -->
+  <!-- interface-naming-policy toplevel-contextual -->
   <widget class="XfceTitledDialog" id="settings-dialog">
     <property name="title">Clipman</property>
-    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <property name="window_position">center</property>
+    <property name="default_width">300</property>
+    <property name="default_height">380</property>
     <property name="destroy_with_parent">True</property>
     <property name="icon_name">gtk-paste</property>
-    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="type_hint">dialog</property>
     <property name="has_separator">False</property>
     <property name="subtitle" translatable="yes">Configure the plugin</property>
     <child internal-child="vbox">
@@ -20,7 +23,6 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="border_width">6</property>
-            <property name="show_tabs">False</property>
             <child>
               <widget class="GtkVBox" id="vbox1">
                 <property name="visible">True</property>
@@ -30,7 +32,7 @@
                   <widget class="GtkFrame" id="frame1">
                     <property name="visible">True</property>
                     <property name="label_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
+                    <property name="shadow_type">none</property>
                     <child>
                       <widget class="GtkAlignment" id="alignment1">
                         <property name="visible">True</property>
@@ -42,23 +44,26 @@
                             <property name="spacing">6</property>
                             <child>
                               <widget class="GtkCheckButton" id="save-on-quit">
+                                <property name="label" translatable="yes">Save on _quit</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
                                 <property name="tooltip" translatable="yes">If checked, this option will restore the history on every new Xfce session</property>
-                                <property name="label" translatable="yes">Save on _quit</property>
                                 <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
                                 <property name="draw_indicator">True</property>
                               </widget>
+                              <packing>
+                                <property name="position">0</property>
+                              </packing>
                             </child>
                             <child>
                               <widget class="GtkCheckButton" id="add-selections">
+                                <property name="label" translatable="yes">Add _selections</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
                                 <property name="tooltip" translatable="yes">If checked, the selections will go into the history. This behavior can be very verbose and make the whole history unusable. However it can be useful if you wish to always copy the selections to the default clipboard, in a way that you can paste what you select.</property>
-                                <property name="label" translatable="yes">Add _selections</property>
                                 <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
                                 <property name="draw_indicator">True</property>
                               </widget>
                               <packing>
@@ -67,12 +72,12 @@
                             </child>
                             <child>
                               <widget class="GtkCheckButton" id="store-an-image">
+                                <property name="label" translatable="yes">Store an _image</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
                                 <property name="tooltip" translatable="yes">If checked, this option allows to store one image inside the history</property>
-                                <property name="label" translatable="yes">Store an _image</property>
                                 <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
                                 <property name="draw_indicator">True</property>
                               </widget>
                               <packing>
@@ -82,6 +87,7 @@
                             <child>
                               <widget class="GtkHBox" id="hbox1">
                                 <property name="visible">True</property>
+                                <property name="spacing">6</property>
                                 <child>
                                   <widget class="GtkLabel" id="label5">
                                     <property name="visible">True</property>
@@ -90,12 +96,17 @@
                                     <property name="use_underline">True</property>
                                     <property name="mnemonic_widget">max-texts-in-history</property>
                                   </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
                                 </child>
                                 <child>
                                   <widget class="GtkSpinButton" id="max-texts-in-history">
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
-                                    <property name="adjustment">6 5 100 1 10 10</property>
+                                    <property name="adjustment">6 5 100 1 10 0</property>
                                   </widget>
                                   <packing>
                                     <property name="expand">False</property>
@@ -126,6 +137,7 @@
                   <packing>
                     <property name="expand">False</property>
                     <property name="fill">False</property>
+                    <property name="position">0</property>
                   </packing>
                 </child>
               </widget>
@@ -136,8 +148,8 @@
                 <property name="label" translatable="yes">General</property>
               </widget>
               <packing>
+                <property name="tab_fill">False</property>
                 <property name="type">tab</property>
-                <property name="tab_fill">False</property>
               </packing>
             </child>
             <child>
@@ -145,55 +157,117 @@
                 <property name="visible">True</property>
                 <property name="sensitive">False</property>
                 <property name="border_width">6</property>
+                <property name="spacing">6</property>
                 <child>
-                  <widget class="GtkScrolledWindow" id="scrolledwindow1">
+                  <widget class="GtkCheckButton" id="enable-actions">
+                    <property name="label" translatable="yes">Enable _actions</property>
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                    <property name="shadow_type">GTK_SHADOW_IN</property>
-                    <child>
-                      <widget class="GtkTreeView" id="actions">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="rules_hint">True</property>
-                      </widget>
-                    </child>
+                    <property name="receives_default">False</property>
+                    <property name="tooltip" translatable="yes">Enable the actions to match the clipboard texts against regular expressions</property>
+                    <property name="use_underline">True</property>
+                    <property name="draw_indicator">True</property>
                   </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
                 </child>
                 <child>
-                  <widget class="GtkHButtonBox" id="hbuttonbox1">
+                  <widget class="GtkHBox" id="hbox2">
                     <property name="visible">True</property>
-                    <property name="border_width">6</property>
-                    <property name="homogeneous">True</property>
-                    <property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
+                    <property name="spacing">6</property>
                     <child>
-                      <widget class="GtkButton" id="button2">
+                      <widget class="GtkScrolledWindow" id="scrolledwindow1">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="label" translatable="yes">gtk-add</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
+                        <property name="hscrollbar_policy">automatic</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <widget class="GtkTreeView" id="actions">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="headers_visible">False</property>
+                            <property name="rules_hint">True</property>
+                          </widget>
+                        </child>
                       </widget>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
                     </child>
                     <child>
-                      <widget class="GtkButton" id="button3">
+                      <widget class="GtkVBox" id="vbox4">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="label" translatable="yes">gtk-remove</property>
-                        <property name="use_stock">True</property>
-                        <property name="response_id">0</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <widget class="GtkButton" id="add-action2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child>
+                              <widget class="GtkImage" id="image1">
+                                <property name="visible">True</property>
+                                <property name="stock">gtk-add</property>
+                                <property name="icon-size">4</property>
+                              </widget>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkButton" id="button3">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child>
+                              <widget class="GtkImage" id="image2">
+                                <property name="visible">True</property>
+                                <property name="stock">gtk-edit</property>
+                                <property name="icon-size">1</property>
+                              </widget>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkButton" id="remove-action2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child>
+                              <widget class="GtkImage" id="image3">
+                                <property name="visible">True</property>
+                                <property name="stock">gtk-delete</property>
+                                <property name="icon-size">1</property>
+                              </widget>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
                       </widget>
                       <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
                         <property name="position">1</property>
                       </packing>
                     </child>
                   </widget>
                   <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
                     <property name="position">1</property>
                   </packing>
                 </child>
@@ -208,9 +282,9 @@
                 <property name="label" translatable="yes">Actions</property>
               </widget>
               <packing>
-                <property name="type">tab</property>
                 <property name="position">1</property>
                 <property name="tab_fill">False</property>
+                <property name="type">tab</property>
               </packing>
             </child>
           </widget>
@@ -221,24 +295,415 @@
         <child internal-child="action_area">
           <widget class="GtkHButtonBox" id="dialog-action_area1">
             <property name="visible">True</property>
-            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <property name="layout_style">edge</property>
             <child>
+              <widget class="GtkButton" id="button2">
+                <property name="label" translatable="yes">gtk-help</property>
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </widget>
+              <packing>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
               <widget class="GtkButton" id="button1">
+                <property name="label" translatable="yes">gtk-close</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
-                <property name="label" translatable="yes">gtk-close</property>
                 <property name="use_stock">True</property>
-                <property name="response_id">0</property>
               </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
             </child>
           </widget>
           <packing>
             <property name="expand">False</property>
-            <property name="pack_type">GTK_PACK_END</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
           </packing>
         </child>
       </widget>
     </child>
   </widget>
+  <widget class="GtkDialog" id="action-entry-dialog">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Edit Action</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="type_hint">normal</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox2">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkFrame" id="frame-action">
+            <property name="visible">True</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">none</property>
+            <child>
+              <widget class="GtkAlignment" id="alignment1">
+                <property name="visible">True</property>
+                <property name="top_padding">6</property>
+                <property name="bottom_padding">6</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkTable" id="table1">
+                    <property name="visible">True</property>
+                    <property name="n_rows">2</property>
+                    <property name="n_columns">2</property>
+                    <property name="column_spacing">6</property>
+                    <property name="row_spacing">6</property>
+                    <child>
+                      <widget class="GtkEntry" id="regex">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label4">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Name:</property>
+                      </widget>
+                      <packing>
+                        <property name="x_options">GTK_FILL</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label5">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Regex:</property>
+                      </widget>
+                      <packing>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                        <property name="x_options">GTK_FILL</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkEntry" id="action-nam">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes"><b>Action</b></property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="type">label_item</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkFrame" id="frame-commands">
+            <property name="visible">True</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">none</property>
+            <child>
+              <widget class="GtkAlignment" id="alignment2">
+                <property name="visible">True</property>
+                <property name="top_padding">6</property>
+                <property name="bottom_padding">6</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkHBox" id="hbox1">
+                    <property name="visible">True</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <widget class="GtkScrolledWindow" id="scrolledwindow1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hscrollbar_policy">automatic</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <widget class="GtkTreeView" id="commands">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                          </widget>
+                        </child>
+                      </widget>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkVBox" id="vbox4">
+                        <property name="visible">True</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <widget class="GtkButton" id="add-command">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child>
+                              <widget class="GtkImage" id="image1">
+                                <property name="visible">True</property>
+                                <property name="stock">gtk-add</property>
+                                <property name="icon-size">1</property>
+                              </widget>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkButton" id="remove-command">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child>
+                              <widget class="GtkImage" id="image3">
+                                <property name="visible">True</property>
+                                <property name="stock">gtk-delete</property>
+                                <property name="icon-size">1</property>
+                              </widget>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes"><b>Commands</b></property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="type">label_item</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area2">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <widget class="GtkButton" id="button1">
+                <property name="label" translatable="yes">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </widget>
+              <packing>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button2">
+                <property name="label" translatable="yes">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkDialog" id="command-dialog">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Edit Command</property>
+    <property name="resizable">False</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="icon_name">system-run</property>
+    <property name="type_hint">normal</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox3">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="spacing">6</property>
+            <child>
+              <widget class="GtkImage" id="image1">
+                <property name="visible">True</property>
+                <property name="stock">gtk-dialog-info</property>
+                <property name="icon-size">5</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">You can use the matching regex parameters "\1", "\2", and so on in the command to replace it against the matched sub-texts. The parameter "\0" represents the complete text.</property>
+                <property name="wrap">True</property>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkTable" id="table1">
+            <property name="visible">True</property>
+            <property name="border_width">6</property>
+            <property name="n_rows">2</property>
+            <property name="n_columns">2</property>
+            <property name="column_spacing">6</property>
+            <property name="row_spacing">6</property>
+            <child>
+              <widget class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Name:</property>
+              </widget>
+              <packing>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Command:</property>
+              </widget>
+              <packing>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkEntry" id="entry1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkEntry" id="entry2">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area3">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <widget class="GtkButton" id="button1">
+                <property name="label" translatable="yes">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </widget>
+              <packing>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button2">
+                <property name="label" translatable="yes">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
 </glade-interface>

Added: xfce4-clipman-plugin/branches/xfce-4-6/tests/Makefile.am
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/tests/Makefile.am	                        (rev 0)
+++ xfce4-clipman-plugin/branches/xfce-4-6/tests/Makefile.am	2009-01-25 11:33:12 UTC (rev 6539)
@@ -0,0 +1,14 @@
+NULL = 
+
+INCLUDES =								\
+	-I${top_srcdir}							\
+	-DDATADIR=\"$(datadir)\"					\
+	-DSRCDIR=\"$(top_srcdir)\"					\
+	-DPACKAGE_LOCALE_DIR=\"$(localedir)\"				\
+	-DLOCALEDIR=\"$(localedir)\"					\
+	$(NULL)
+
+noinst_PROGRAMS = test-actions
+test_actions_SOURCES = test_actions.c ../panel-plugin/actions.c ../panel-plugin/actions.h ../panel-plugin/common.h
+test_actions_CFLAGS = @GTK_CFLAGS@ @EXO_CFLAGS@ @LIBXFCE4UTIL_CFLAGS@ @LIBXFCEGUI4_CFLAGS@
+test_actions_LDADD = @GTK_LIBS@ @EXO_LIBS@ @LIBXFCE4UTIL_LIBS@ @LIBXFCEGUI4_LIBS@ 

Added: xfce4-clipman-plugin/branches/xfce-4-6/tests/test_actions.c
===================================================================
--- xfce4-clipman-plugin/branches/xfce-4-6/tests/test_actions.c	                        (rev 0)
+++ xfce4-clipman-plugin/branches/xfce-4-6/tests/test_actions.c	2009-01-25 11:33:12 UTC (rev 6539)
@@ -0,0 +1,31 @@
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <panel-plugin/actions.h>
+
+int main (int argc, char *argv[])
+{
+  ClipmanActions *actions;
+
+  gtk_init (&argc, &argv);
+
+  actions = clipman_actions_get ();
+  clipman_actions_add (actions, "Image", ".*\\.(gif|jpg|png)", "GPicView", "gpicview \\0");
+  clipman_actions_add (actions, "Image", NULL, "Gimp", "gimp \\0");
+  clipman_actions_add (actions, "Image", NULL, "Ristretto", "ristretto \\0");
+  clipman_actions_add (actions, "Image", NULL, "Gimp (remote)", "gimp-remote \\0");
+  clipman_actions_add (actions, "Image", NULL, "GPicView", "gpicview2 \\0");
+  clipman_actions_add (actions, "Print", ".*\\.png", "Print with GTK+", "gtk-print \\0");
+  clipman_actions_match_with_menu (actions, "imagE.png");
+  clipman_actions_add (actions, "Text", "(txt)", "Mousepad", "mousepad \\0");
+
+  gtk_main ();
+
+  clipman_actions_remove (actions, "Image", "GPicView");
+  clipman_actions_remove (actions, "Image", "GPicView");
+  clipman_actions_remove (actions, "Image", "view");
+  clipman_actions_remove (actions, "Image", "Ristretto");
+  clipman_actions_remove (actions, "Text", "Mousepad");
+
+  return 0;
+}
+




More information about the Goodies-commits mailing list