From 847c92e99b3d2f80e989dc1809ced62e3f6540b8 Mon Sep 17 00:00:00 2001 From: Rodrigo Moya Date: Thu, 1 Sep 2005 11:16:11 +0000 Subject: [PATCH] Nautilus Actions 0.4 --- AUTHORS | 7 +- ChangeLog | 23 ++- Makefile | 38 +++-- nact/nautilus-actions-config.py.template | 285 +++++++++++++++++++------------ nact/nautilus-actions-config_dev.glade | 216 ++++++++++++++++++++--- nautilus-actions-config.c | 132 ++++++++++---- nautilus-actions-config.h | 5 + nautilus-actions-test.c | 28 +-- nautilus-actions-utils.c | 14 +- nautilus-actions.c | 10 +- 10 files changed, 552 insertions(+), 206 deletions(-) diff --git a/AUTHORS b/AUTHORS index bd7f857d..c054b790 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,8 @@ -Frederic Ruaudel +Frederic Ruaudel based on nautilus-sendto module from Roberto Majadas + +== Contributors == + +Ed Catmur : NACT .desktop file and Makefile patch for packaging on gentoo +Kasys : Makefile patch to build on 64bits arch diff --git a/ChangeLog b/ChangeLog index 2da4bbf1..fab8c474 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,26 @@ -* Fri Aug 19 2005 Frederic Ruaudel 0.3 +* Fri Aug 28 2005 Frederic Ruaudel 0.4 +- Add -fPIC option in the Makefile to make nautilus-actions compile on 64bits arch +- Apply patch from Ed Catmur that add DESTDIR var in Makefile for gentoo ebuild +- Add the desktop file for nact submited by Ed Catmur +- Add per user config possibility. Per user config are saved by default in ~/.nautilus-actions +- NACT has been updated to manage per user config. If launch as normal user, it edit the user +config and if launched as root, it manage system wide config. +- add LICENSE file of the GNU GPL License +- Update authors and contributors list +- Add more user friendly description of schemes in Nact. +- Add %M pattern for the parameters field which give the list of the files like %m but with full path +- Modify NACT to add the %M option in the legend dialog and to take care of it in the example string +- In NACT, replace the buggy FileChooserButton with an Entry and a Browse Button. +- Add an action for launching nact from nautilus in the config folder and add it in install part of Makefile +- Add installation of nact desktop file in the Makefile +- Add some customization to the desktop file to insert value (version, icon) from the Makefile + +* Fri Aug 19 2005 Frederic Ruaudel 0.3 - Fix a bug in NACT when parsing 'accept-multiple-files' tags - Remove a unused function -* Fri Aug 19 2005 Frederic Ruaudel 0.2 +* Fri Aug 19 2005 Frederic Ruaudel 0.2 - Add NACT the configuration GUI -* Thu Aug 12 2005 Frederic Ruaudel 0.1 +* Thu Aug 12 2005 Frederic Ruaudel 0.1 - First version diff --git a/Makefile b/Makefile index 84b61fc6..c606a6b0 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,24 @@ prefix=/usr +libdir=$(prefix)/lib +bindir=${prefix}/bin +DESTDIR= +GNOME_MENU_DIR=$(prefix)/share/applications DEFAULT_CONFIG_PATH=$(prefix)/share/nautilus-actions +DEFAULT_PER_USER_PATH=.nautilus-actions DEFAULT_NACT_DATA_PATH=$(DEFAULT_CONFIG_PATH)/nact -EXTDIR=$(prefix)/lib/nautilus/extensions-1.0 +EXTDIR=$(libdir)/nautilus/extensions-1.0 EXT_NAME=nautilus-action.so SOURCES=nautilus-actions.c nautilus-actions-config.c nautilus-actions-module.c nautilus-actions-test.c nautilus-actions-utils.c HEADERS=nautilus-actions-config.h nautilus-actions.h nautilus-actions-test.h nautilus-actions-utils.h -VERSION=0.3 -bindir=${prefix}/bin +VERSION=0.4 -all: $(EXT_NAME) nact/nautilus-actions-config.py nact/nact nact/nautilus-actions-config.glade +all: $(EXT_NAME) nact/nautilus-actions-config.py nact/nact nact/nautilus-actions-config.glade nact/nact.desktop $(EXT_NAME): $(SOURCES) $(HEADERS) - gcc -o $(EXT_NAME) -shared -DDEFAULT_CONFIG_PATH="\"$(DEFAULT_CONFIG_PATH)\"" -I. `pkg-config --libs --cflags libnautilus-extension libxml-2.0 gobject-2.0` $(SOURCES) + gcc -o $(EXT_NAME) -shared -fPIC -DDEFAULT_CONFIG_PATH="\"$(DEFAULT_CONFIG_PATH)\"" -DDEFAULT_PER_USER_PATH="\"$(DEFAULT_PER_USER_PATH)\"" -I. `pkg-config --libs --cflags libnautilus-extension libxml-2.0 gobject-2.0` $(SOURCES) nact/nautilus-actions-config.py: nact/nautilus-actions-config.py.template - sed -e 's#%%%DEFAULT_CONFIG_PATH%%%#$(DEFAULT_CONFIG_PATH)#' -e 's#%%%DATA_DIR%%%#$(DEFAULT_NACT_DATA_PATH)#' -e 's#%%%VERSION%%%#$(VERSION)#' nact/nautilus-actions-config.py.template > nact/nautilus-actions-config.py + sed -e 's#%%%DEFAULT_CONFIG_PATH%%%#$(DEFAULT_CONFIG_PATH)#' -e 's#%%%DATA_DIR%%%#$(DEFAULT_NACT_DATA_PATH)#' -e 's#%%%VERSION%%%#$(VERSION)#' -e 's#%%%DEFAULT_PER_USER_PATH%%%#$(DEFAULT_PER_USER_PATH)#' nact/nautilus-actions-config.py.template > nact/nautilus-actions-config.py nact/nact: nact/nact.template sed 's#%%%DATA_DIR%%%#$(DEFAULT_NACT_DATA_PATH)#' nact/nact.template > nact/nact @@ -22,14 +26,20 @@ nact/nact: nact/nact.template nact/nautilus-actions-config.glade: nact/nautilus-actions-config_dev.glade sed -e 's#nautilus-launch-icon.png#$(DEFAULT_NACT_DATA_PATH)/nautilus-launch-icon.png#' nact/nautilus-actions-config_dev.glade > nact/nautilus-actions-config.glade +nact/nact.desktop: nact/nact.desktop.template + sed -e 's#%%%DATA_DIR%%%#$(DEFAULT_NACT_DATA_PATH)#' -e 's#%%%VERSION%%%#$(VERSION)#' nact/nact.desktop.template > nact/nact.desktop + install: - /usr/bin/install -d -m 755 $(DEFAULT_NACT_DATA_PATH) - /usr/bin/install -d -m 755 $(EXTDIR) - /usr/bin/install -d -m 755 $(bindir) - /usr/bin/install -m 755 $(EXT_NAME) $(EXTDIR) - /usr/bin/install -m 755 nact/nact $(bindir) - /usr/bin/install -m 644 nact/nautilus-actions-config.glade nact/nautilus-launch-icon.png $(DEFAULT_NACT_DATA_PATH) - /usr/bin/install -m 755 nact/nautilus-actions-config.py $(DEFAULT_NACT_DATA_PATH) + /usr/bin/install -d -m 755 $(DESTDIR)$(DEFAULT_NACT_DATA_PATH) + /usr/bin/install -d -m 755 $(DESTDIR)$(EXTDIR) + /usr/bin/install -d -m 755 $(DESTDIR)$(bindir) + /usr/bin/install -d -m 755 $(DESTDIR)$(GNOME_MENU_DIR) + /usr/bin/install -m 755 $(EXT_NAME) $(DESTDIR)$(EXTDIR) + /usr/bin/install -m 755 nact/nact $(DESTDIR)$(bindir) + /usr/bin/install -m 644 nact/nautilus-actions-config.glade nact/nautilus-launch-icon.png $(DESTDIR)$(DEFAULT_NACT_DATA_PATH) + /usr/bin/install -m 755 nact/nautilus-actions-config.py $(DESTDIR)$(DEFAULT_NACT_DATA_PATH) + /usr/bin/install -m 644 config/config_newaction.xml $(DESTDIR)$(DEFAULT_CONFIG_PATH) + /usr/bin/install -m 644 nact/nact.desktop $(DESTDIR)$(GNOME_MENU_DIR) clean: - rm -f $(EXT_NAME) nact/nautilus-actions-config.py nact/nact nact/nautilus-actions-config.glade *~ *.o nact/*.bak nact/*~ + rm -f $(EXT_NAME) nact/nautilus-actions-config.py nact/nact nact/nact.desktop nact/nautilus-actions-config.glade *~ *.o nact/*.bak nact/*~ diff --git a/nact/nautilus-actions-config.py.template b/nact/nautilus-actions-config.py.template index 87b2e24e..da4c2494 100755 --- a/nact/nautilus-actions-config.py.template +++ b/nact/nautilus-actions-config.py.template @@ -3,6 +3,7 @@ import sys import os.path +import pwd import popen2 import string import commands @@ -146,7 +147,12 @@ class Config: class ConfigParser: def __init__ (self): - self.config_dir = ["%%%DEFAULT_CONFIG_PATH%%%"] + uid = os.getuid () + if uid == 0: + self.config_dir = ["%%%DEFAULT_CONFIG_PATH%%%"] + else: + home_dir = pwd.getpwuid (uid)[5] + self.config_dir = [home_dir + "/%%%DEFAULT_PER_USER_PATH%%%"] class ConfigReader (ConfigParser): def __init__ (self): @@ -367,10 +373,23 @@ class ConfigWriter (ConfigParser): # # + class NACTGui (gtk.glade.XML): def __init__ (self, windowname): gladefile = "%%%DATA_DIR%%%/nautilus-actions-config.glade" gtk.glade.XML.__init__ (self, gladefile, windowname) + self.widget = self.get_widget (windowname) + + def Show (self): + self.widget.show () + + def ActionDialogCloseHandler (self, widget, event): + self.widget.hide () + return True + + def ActionCloseHandler (self, widget): + self.widget.hide () + class NACTAboutDialog (NACTGui): def __init__ (self): @@ -380,14 +399,8 @@ class NACTAboutDialog (NACTGui): } self.signal_autoconnect (dic) - self.get_widget ("AboutDialog").set_version ("%%%VERSION%%%") + self.widget.set_version ("%%%VERSION%%%") - def Show (self): - self.get_widget ("AboutDialog").show () - - def ActionDialogCloseHandler (self, widget, event): - self.get_widget ("AboutDialog").hide () - return True class NACTLegendDialog (NACTGui): def __init__ (self): @@ -399,21 +412,39 @@ class NACTLegendDialog (NACTGui): self.signal_autoconnect (dic) - def Show (self): - self.get_widget ("DialogLegend").show () - def ActionDialogCloseHandler (self, widget, event): - self.get_widget ("DialogLegend").hide () - return True +class NACTFileChooserDialog (NACTGui): + def __init__ (self, entry_path): + NACTGui.__init__ (self, "FileChooserDialogPath") + + dic = { "ActionFileDialogClose" : self.ActionDialogCloseHandler, + "ActionFileDialogCancel" : self.ActionCloseHandler, + "ActionFileChoose" : self.ActionFileChooseHandler + } + + self.signal_autoconnect (dic) + self.entry_path = entry_path + + def SetCurrentFile (self, filename): + self.widget.set_filename (filename) + + def GetCurrentFile (self): + return self.widget.get_filename () + + def ActionFileChooseHandler (self, widget): + self.widget.hide () + self.entry_path.set_text (self.GetCurrentFile ()) - def ActionCloseHandler (self, widget): - self.get_widget ("DialogLegend").hide () class NACTMainWindow (NACTGui): def __init__ (self): NACTGui.__init__ (self, "WindowMain") - self.scheme_list = ["file", "sftp", "smb", "ftp", "dav"] + self.scheme_list = [["file" , "Local files"], + ["sftp" , "SSH files"], + ["smb" , "Windows files"], + ["ftp" , "FTP files"], + ["dav" , "Webdav files"] ] self.new_config_name = "New Config" @@ -423,6 +454,7 @@ class NACTMainWindow (NACTGui): "ActionDeleteConfig" : self.ActionDeleteConfigHandler, "ActionConfigSelect" : self.ActionConfigSelectHandler, "ActionShowLegend" : self.ActionShowLegendHandler, + "ActionBrowse" : self.ActionBrowseHandler, "ActionLabelChange" : self.ActionLabelChangeHandler, "ActionTooltipChange" : self.ActionTooltipChangeHandler, "ActionPathChange" : self.ActionPathChangeHandler, @@ -446,6 +478,7 @@ class NACTMainWindow (NACTGui): self.example_text = self.get_widget ("LabelExampleCmd").get_label () self.config_title_text = self.get_widget ("LabelConfigTitle").get_label () self.legenddialog = NACTLegendDialog () + self.filedialog = NACTFileChooserDialog (self.get_widget ("EntryPath")) self.aboutdialog = NACTAboutDialog () self.config_selection_change = False self.config_modified = False @@ -479,9 +512,9 @@ class NACTMainWindow (NACTGui): treeview.append_column (column) def CreateSchemeListStore (self): - dist_store = gtk.ListStore (gobject.TYPE_BOOLEAN, str) + dist_store = gtk.ListStore (gobject.TYPE_BOOLEAN, str, str) for scheme in self.scheme_list: - dist_store.append([False, scheme]) + dist_store.append([False, scheme[0], scheme[1]]) treeview = self.get_widget("TreeViewSelectScheme") treeview.set_model (dist_store) @@ -498,6 +531,16 @@ class NACTMainWindow (NACTGui): text_renderer = gtk.CellRendererText () column.pack_end (text_renderer, True) column.add_attribute (text_renderer, "text", 1) + + column.set_min_width (100) + treeview.append_column(column) + + column = gtk.TreeViewColumn () + column.set_title ("Description") + + text_renderer = gtk.CellRendererText () + column.pack_start (text_renderer, False) + column.add_attribute (text_renderer, "text", 2) treeview.append_column(column) def ManageWidgetSensitivity (self): @@ -528,13 +571,15 @@ class NACTMainWindow (NACTGui): # def SetCurrentFilename (self, path): - filechooser = self.get_widget ("FileChooserButtonPath") - dir = os.path.dirname (path) - if filechooser.get_current_folder () != dir: - filechooser.set_current_folder (dir) - filechooser.set_filename (path) - while gtk.events_pending(): - gtk.main_iteration(False) +# filechooser = self.get_widget ("FileChooserDialogPath") +# dir = os.path.dirname (path) +# if filechooser.get_current_folder () != dir: +# filechooser.set_current_folder (dir) +# filechooser.set_filename (path) +# while gtk.events_pending(): +# gtk.main_iteration(False) + self.filedialog.SetCurrentFile (path) + self.get_widget ("EntryPath").set_text (path) def FillConfigPanelFromConfigName (self, config_name): if config_name != self.new_config_name: @@ -577,7 +622,7 @@ class NACTMainWindow (NACTGui): def ActionNewConfigNameEditHandler (self, cellrenderer, path, new_text, model): treeview = self.get_widget("TreeViewConfigList") - if new_text != self.new_config_name and not self.config_list.has_key (new_text): + if new_text != self.new_config_name and not self.config_list.has_key (new_text) and len (new_text) > 0: # iter = model.get_iter_from_string (path) model.set (iter, 0, new_text) @@ -630,116 +675,134 @@ class NACTMainWindow (NACTGui): def ActionShowLegendHandler (self, widget): self.legenddialog.Show () + def ActionBrowseHandler (self, widget): + self.filedialog.Show () + def ParseParameters (self, parameters, config_name): - ex_path = "/path/to" - ex_files = [ "file1.txt", "file2.txt" ] - ex_dirs = [ "dir1", "dir2"] - ex_mixed = ["file1.txt", "dir1" ] - ex_scheme = "file" - ex_one = "file.txt" - ex_list = [ ex_one ] - config = self.config_list[config_name] - if config.get_test_accept_multiple_file (): - # - if config.get_test_isfile () and config.get_test_isdir (): - # - ex_one = ex_files[0] - ex_list = ex_mixed - # - elif config.get_test_isfile (): - # - ex_one = ex_files[0] - ex_list = ex_files - # - elif config.get_test_isdir (): - # - ex_one = ex_dirs[0] - ex_list = ex_dirs - # - # - else: + retv = "" + if config_name != self.new_config_name: # - if config.get_test_isdir () and not config.get_test_isfile (): - # - ex_one = "dir" + ex_path = "/path/to" + ex_files = [ "file1.txt", "file2.txt" ] + ex_dirs = [ "dir1", "dir2"] + ex_mixed = ["file1.txt", "dir1" ] + ex_scheme = "file" + ex_one = "file.txt" + ex_list = [ ex_one ] + ex_path_list = [ ex_path + "/" + ex_one ] + config = self.config_list[config_name] + if config.get_test_accept_multiple_file (): # - # - schemes = config.get_test_schemes () - if len (schemes) != 0: - # - ex_scheme = schemes[0] - # - if ex_scheme == "file": - # - if len (schemes) > 1: - ex_scheme = schemes[1] - ex_host = "test.example.net" - else: - ex_host = "" - # - else: - # - ex_host = "test.example.net" - # + if config.get_test_isfile () and config.get_test_isdir (): + # + ex_one = ex_files[0] + ex_list = ex_mixed + # + elif config.get_test_isfile (): + # + ex_one = ex_files[0] + ex_list = ex_files + # + elif config.get_test_isdir (): + # + ex_one = ex_dirs[0] + ex_list = ex_dirs + # - tmp = parameters - pos = string.find (tmp, "%") - retv = tmp[:pos] - while pos != -1 and len (tmp) >= pos + 2: - # - ex_str = "" - if tmp[pos+1] == 'u': - # - ex_str = ex_scheme + "://" + ex_path + ex_one - # - elif tmp[pos+1] == 'd': - # - ex_str = ex_path - # - elif tmp[pos+1] == 'p': - # - ex_str = os.path.dirname (ex_path) - # - elif tmp[pos+1] == 'f': - # - ex_str = ex_one + ex_path_list = [] + for value in ex_list: + # + ex_path_list.append ( ex_path + "/" + value) + # # - elif tmp[pos+1] == 'm': + else: # - ex_str = string.join (ex_list, " ") + if config.get_test_isdir () and not config.get_test_isfile (): + # + ex_one = "dir" + # # - elif tmp[pos+1] == 's': + schemes = config.get_test_schemes () + if len (schemes) != 0: # - ex_str = ex_scheme + ex_scheme = schemes[0] # - elif tmp[pos+1] == 'h': + if ex_scheme == "file": # - ex_str = ex_host + if len (schemes) > 1: + ex_scheme = schemes[1] + ex_host = "test.example.net" + else: + ex_host = "" # - elif tmp[pos+1] == 'U': + else: # - ex_str = "root" + ex_host = "test.example.net" # - elif tmp[pos+1] == '%': + + tmp = parameters + pos = string.find (tmp, "%") + retv = tmp[:pos] + while pos != -1 and len (tmp) >= pos + 2: # - ex_str = "%" + ex_str = "" + if tmp[pos+1] == 'u': + # + ex_str = ex_scheme + "://" + ex_path + ex_one + # + elif tmp[pos+1] == 'd': + # + ex_str = ex_path + # + elif tmp[pos+1] == 'p': + # + ex_str = os.path.dirname (ex_path) + # + elif tmp[pos+1] == 'f': + # + ex_str = ex_one + # + elif tmp[pos+1] == 'm': + # + ex_str = string.join (ex_list, " ") + # + elif tmp[pos+1] == 'M': + # + ex_str = string.join (ex_path_list, " ") + # + elif tmp[pos+1] == 's': + # + ex_str = ex_scheme + # + elif tmp[pos+1] == 'h': + # + ex_str = ex_host + # + elif tmp[pos+1] == 'U': + # + ex_str = "root" + # + elif tmp[pos+1] == '%': + # + ex_str = "%" + # + retv += ex_str + tmp = tmp[pos+2:] + pos = string.find (tmp, "%") + retv += tmp[:pos] # - retv += ex_str - tmp = tmp[pos+2:] - pos = string.find (tmp, "%") - retv += tmp[:pos] # return retv def UpdateCommandExample (self): - path = self.get_widget ("FileChooserButtonPath").get_filename () + path = self.get_widget ("EntryPath").get_text () parameters = self.ParseParameters (self.get_widget ("EntryParameters").get_text (), self.GetCurrentEditedConfig ()) self.get_widget ("LabelExampleCmd").set_label (self.example_text % (path, parameters)) def ActionPathChangeHandler (self, widget): if not self.config_selection_change: # - path = self.get_widget ("FileChooserButtonPath").get_filename () + path = self.get_widget ("EntryPath").get_text () config_name = self.GetCurrentEditedConfig () if config_name != None and self.config_list[config_name].get_command_path () != path : # diff --git a/nact/nautilus-actions-config_dev.glade b/nact/nautilus-actions-config_dev.glade index 752f0357..c402026b 100644 --- a/nact/nautilus-actions-config_dev.glade +++ b/nact/nautilus-actions-config_dev.glade @@ -756,14 +756,111 @@ - + True - Select A File - GTK_FILE_CHOOSER_ACTION_OPEN - True - False - -1 - + False + 6 + + + + True + parameters that will be send to the program. Click the 'Legend' button to see the different replacement options + True + True + True + 0 + + True + * + False + + + + 0 + True + True + + + + + + 88 + True + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-open + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Browse... + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + 0 @@ -846,6 +943,7 @@ + 88 True True GTK_RELIEF_NORMAL @@ -1412,10 +1510,10 @@ False NACT - (C) 2005 Frederic Ruaudel <ruaudel@embl.fr> + (C) 2005 Frederic Ruaudel <grumz@grumz.net> Nautilus Action Configuration Tool Application to configure Nautilus Action extension - Frederic Ruaudel <ruaudel@embl.fr> + Frederic Ruaudel <grumz@grumz.net> translator-credits nautilus-launch-icon.png @@ -1763,10 +1861,10 @@ Application to configure Nautilus Action extension 0 - 1 - 2 - 3 - 4 + 0 + 1 + 4 + 5 @@ -1774,7 +1872,7 @@ Application to configure Nautilus Action extension True True - <b>%m</b> : list of the basename of the selected files/directories separated by space. + <b>%M</b> : list of the selected files/directories with their full path separated by space. False True GTK_JUSTIFY_LEFT @@ -1790,22 +1888,23 @@ Application to configure Nautilus Action extension 0 - 0 - 1 + 1 + 2 4 5 - + True - + True + <b>%m</b> : list of the basename of the selected files/directories separated by space. False - False + True GTK_JUSTIFY_LEFT - False - False + True + True 0 0 0 @@ -1818,8 +1917,8 @@ Application to configure Nautilus Action extension 1 2 - 4 - 5 + 3 + 4 @@ -1840,4 +1939,75 @@ Application to configure Nautilus Action extension + + GTK_FILE_CHOOSER_ACTION_OPEN + True + False + False + Select a command + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + nautilus-launch-icon.png + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + True + False + 24 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + + True + True + True + True + gtk-open + True + GTK_RELIEF_NORMAL + True + -5 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + diff --git a/nautilus-actions-config.c b/nautilus-actions-config.c index 1e5ec81c..db8bed9f 100644 --- a/nautilus-actions-config.c +++ b/nautilus-actions-config.c @@ -10,25 +10,55 @@ static GList *nautilus_actions_config_get_config_files (void) GDir* config_dir = NULL; gchar* filename; gchar* path; + gchar* per_user_dir = g_build_path ("/", g_get_home_dir (), DEFAULT_PER_USER_PATH, NULL); - /* First get system-wide config files */ - config_dir = g_dir_open (DEFAULT_CONFIG_PATH, 0, NULL); - if (config_dir != NULL) + /* First get the per user files so they have priority because there are first parsed */ + + if (g_file_test (per_user_dir, G_FILE_TEST_IS_DIR)) { - filename = g_dir_read_name (config_dir); - while (filename != NULL) + config_dir = g_dir_open (per_user_dir, 0, NULL); + if (config_dir != NULL) { - path = g_build_path ("/", DEFAULT_CONFIG_PATH, filename, NULL); - if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) + filename = g_dir_read_name (config_dir); + while (filename != NULL) { - /* This is a regular file, we can add it */ - config_files = g_list_append (config_files, g_strdup (path)); + path = g_build_path ("/", per_user_dir, filename, NULL); + if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) + { + // This is a regular file, we can add it + config_files = g_list_append (config_files, g_strdup (path)); + } + g_free (path); + filename = g_dir_read_name (config_dir); } - g_free (path); - filename = g_dir_read_name (config_dir); + + g_dir_close (config_dir); } + } + + g_free (per_user_dir); + + /* Then get system-wide config files, if there are duplicate of above, they will be skipped during parsing */ + if (g_file_test (DEFAULT_CONFIG_PATH, G_FILE_TEST_IS_DIR)) + { + config_dir = g_dir_open (DEFAULT_CONFIG_PATH, 0, NULL); + if (config_dir != NULL) + { + filename = g_dir_read_name (config_dir); + while (filename != NULL) + { + path = g_build_path ("/", DEFAULT_CONFIG_PATH, filename, NULL); + if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) + { + /* This is a regular file, we can add it */ + config_files = g_list_append (config_files, g_strdup (path)); + } + g_free (path); + filename = g_dir_read_name (config_dir); + } - g_dir_close (config_dir); + g_dir_close (config_dir); + } } return config_files; @@ -47,13 +77,14 @@ static void nautilus_actions_config_free_config_files (GList* config_files) config_files = NULL; } -static ConfigAction *nautilus_actions_config_action_new (gchar* name) +static ConfigAction *nautilus_actions_config_action_new (gchar* name, gchar* version) { ConfigAction* action = NULL; action = g_new (ConfigAction, 1); - action->name = g_strdup (name); // FIXME: must check that this name is uniq + action->name = g_strdup (name); + action->version = g_strdup (version); action->test = g_new (ConfigActionTest, 1); action->test->basename = NULL; @@ -97,7 +128,7 @@ static gboolean nautilus_actions_config_action_fill_test_scheme (GList** test_sc return retv; } -static gboolean nautilus_actions_config_action_fill_test (ConfigActionTest *test_action, xmlNode* config_test_node) +static gboolean nautilus_actions_config_action_fill_test (ConfigAction *action, xmlNode* config_test_node) { xmlNode *iter; gboolean retv = FALSE; @@ -106,6 +137,8 @@ static gboolean nautilus_actions_config_action_fill_test (ConfigActionTest *test gboolean isdir_ok = FALSE; gboolean scheme_ok = FALSE; gboolean accept_multiple_file_ok = FALSE; + ConfigActionTest* test_action = action->test; + for (iter = config_test_node->children; iter; iter = iter->next) { @@ -148,6 +181,15 @@ static gboolean nautilus_actions_config_action_fill_test (ConfigActionTest *test accept_multiple_file_ok = nautilus_actions_utils_parse_boolean (text, &test_action->accept_multiple_file); xmlFree (text); } + else if (!accept_multiple_file_ok && iter->type == XML_ELEMENT_NODE && + g_ascii_strncasecmp (iter->name, + "accept-multiple-files", + strlen ("accept-multiple-files")) == 0) + { + text = xmlNodeGetContent (iter); + accept_multiple_file_ok = nautilus_actions_utils_parse_boolean (text, &test_action->accept_multiple_file); + xmlFree (text); + } else if (!scheme_ok && iter->type == XML_ELEMENT_NODE && g_ascii_strncasecmp (iter->name, "scheme", @@ -156,7 +198,8 @@ static gboolean nautilus_actions_config_action_fill_test (ConfigActionTest *test scheme_ok = nautilus_actions_config_action_fill_test_scheme (&(test_action->schemes), iter); } } - + + if (basename_ok && isfile_ok && isdir_ok && accept_multiple_file_ok && scheme_ok) { retv = TRUE; @@ -165,12 +208,13 @@ static gboolean nautilus_actions_config_action_fill_test (ConfigActionTest *test return retv; } -static gboolean nautilus_actions_config_action_fill_command (ConfigActionCommand *command_action, xmlNode* config_command_node) +static gboolean nautilus_actions_config_action_fill_command (ConfigAction *action, xmlNode* config_command_node) { xmlNode *iter; gboolean retv = FALSE; gboolean path_ok = FALSE; gboolean parameters_ok = FALSE; + ConfigActionCommand* command_action = action->command; for (iter = config_command_node->children; iter; iter = iter->next) { @@ -206,12 +250,13 @@ static gboolean nautilus_actions_config_action_fill_command (ConfigActionCommand return retv; } -static gboolean nautilus_actions_config_action_fill_menu_item (ConfigActionMenuItem *menu_item_action, xmlNode* config_menu_item_node) +static gboolean nautilus_actions_config_action_fill_menu_item (ConfigAction *action, xmlNode* config_menu_item_node) { xmlNode *iter; gboolean retv = FALSE; gboolean label_ok = FALSE; gboolean tootip_ok = FALSE; + ConfigActionMenuItem* menu_item_action = action->menu_item; for (iter = config_menu_item_node->children; iter; iter = iter->next) { @@ -262,21 +307,21 @@ static gboolean nautilus_actions_config_action_fill (ConfigAction* action, xmlNo "test", strlen ("test")) == 0) { - test_ok = nautilus_actions_config_action_fill_test (action->test, iter); + test_ok = nautilus_actions_config_action_fill_test (action, iter); } else if (!command_ok && iter->type == XML_ELEMENT_NODE && g_ascii_strncasecmp (iter->name, "command", strlen ("command")) == 0) { - command_ok = nautilus_actions_config_action_fill_command (action->command, iter); + command_ok = nautilus_actions_config_action_fill_command (action, iter); } else if (!menu_item_ok && iter->type == XML_ELEMENT_NODE && g_ascii_strncasecmp (iter->name, "menu-item", strlen ("menu-item")) == 0) { - menu_item_ok = nautilus_actions_config_action_fill_menu_item (action->menu_item, iter); + menu_item_ok = nautilus_actions_config_action_fill_menu_item (action, iter); } } @@ -298,7 +343,7 @@ GList *nautilus_actions_config_get_fake_list (char* filename, int level) GList* iter; gchar* base = g_path_get_basename (filename); - action = nautilus_actions_config_action_new (base); + action = nautilus_actions_config_action_new (base, 0.1); g_free (base); action->test->basename = g_strdup ("*"); action->test->isfile = TRUE; @@ -315,12 +360,18 @@ GList *nautilus_actions_config_get_fake_list (char* filename, int level) return config_actions; } */ -static GList *nautilus_actions_config_parse_file (const gchar* filename) + +static gint nautilus_actions_compare_actions (const ConfigAction* action1, const gchar* action_name) +{ + return g_ascii_strcasecmp (action1->name, action_name); +} + +static GList *nautilus_actions_config_parse_file (const gchar* filename, GList* config_actions) { - GList* config_actions = NULL; xmlDoc *doc = NULL; xmlNode *root_node; xmlNode *iter; + xmlChar* version; ConfigAction *action; doc = xmlParseFile (filename); @@ -331,6 +382,8 @@ static GList *nautilus_actions_config_parse_file (const gchar* filename) "nautilus-actions-config", strlen ("nautilus-actions-config")) == 0) { + version = xmlGetProp (root_node, "version"); + for (iter = root_node->children; iter; iter = iter->next) { xmlChar *config_name; @@ -343,19 +396,24 @@ static GList *nautilus_actions_config_parse_file (const gchar* filename) config_name = xmlGetProp (iter, "name"); if (config_name != NULL) { - action = nautilus_actions_config_action_new ((gchar*)config_name); - if (nautilus_actions_config_action_fill (action, iter)) + if (g_list_find_custom (config_actions, config_name, nautilus_actions_compare_actions) == NULL) { - config_actions = g_list_append (config_actions, action); - } - else - { - nautilus_actions_config_free_action (action); + // We skip this file because per user config have priority and there are in the beginning of the file list + action = nautilus_actions_config_action_new ((gchar*)config_name, version); + if (nautilus_actions_config_action_fill (action, iter)) + { + config_actions = g_list_append (config_actions, action); + } + else + { + nautilus_actions_config_free_action (action); + } } xmlFree (config_name); } } } + xmlFree (version); } xmlFreeDoc(doc); @@ -374,7 +432,7 @@ GList *nautilus_actions_config_get_list (void) ConfigAction* action; GList* iter; - action = nautilus_actions_config_action_new ("test"); + action = nautilus_actions_config_action_new ("test", 0.1); action->test->basename = g_strdup ("**"); action->test->isfile = TRUE; action->test->isdir = TRUE; @@ -414,7 +472,8 @@ GList *nautilus_actions_config_get_list (void) for (iter = config_files; iter; iter = iter->next) { gchar* filename = (gchar*)iter->data; - config_actions = g_list_concat (config_actions, nautilus_actions_config_parse_file (filename)); + //config_actions = g_list_concat (config_actions, nautilus_actions_config_parse_file (filename)); + config_actions = nautilus_actions_config_parse_file (filename, config_actions); } nautilus_actions_config_free_config_files (config_files); @@ -429,7 +488,7 @@ ConfigAction *nautilus_actions_config_action_dup (ConfigAction* action) if (action != NULL) { - new_action = nautilus_actions_config_action_new (action->name); + new_action = nautilus_actions_config_action_new (action->name, action->version); if (action->test != NULL) @@ -543,6 +602,11 @@ void nautilus_actions_config_free_action (ConfigAction* action) g_free (action->name); action->name = NULL; } + if (action->version != NULL) + { + g_free (action->version); + action->version = NULL; + } g_free (action); action = NULL; } diff --git a/nautilus-actions-config.h b/nautilus-actions-config.h index 4814e7af..a51beca8 100644 --- a/nautilus-actions-config.h +++ b/nautilus-actions-config.h @@ -10,6 +10,10 @@ G_BEGIN_DECLS #define DEFAULT_CONFIG_PATH "/usr/share/nautilus-actions" #endif +#ifndef DEFAULT_PER_USER_PATH +#define DEFAULT_PER_USER_PATH ".nautilus-actions" +#endif + typedef enum _IsFileEnumType IsFileType; /* not used */ typedef struct _ConfigAction ConfigAction; typedef struct _ConfigActionTest ConfigActionTest; @@ -27,6 +31,7 @@ enum _IsFileEnumType /* not used */ struct _ConfigAction { gchar* name; /* name must be uniq */ + gchar* version; ConfigActionTest *test; ConfigActionCommand *command; ConfigActionMenuItem *menu_item; diff --git a/nautilus-actions-test.c b/nautilus-actions-test.c index 485d72c8..cce1dadd 100644 --- a/nautilus-actions-test.c +++ b/nautilus-actions-test.c @@ -35,20 +35,11 @@ gboolean nautilus_actions_test_validate (ConfigActionTest *action_test, GList* f gboolean test_basename = FALSE; GPatternSpec* glob_pattern = g_pattern_spec_new (action_test->basename); GList* iter; - int dir_count = 0; - int file_count = 0; - int total_count = 0; - int scheme_ok_count = 0; - int glob_ok_count = 0; - - if ((files != NULL) && (files->next == NULL) && (!action_test->accept_multiple_file)) - { - test_multiple_file = TRUE; - } - else if (action_test->accept_multiple_file) - { - test_multiple_file = TRUE; - } + guint dir_count = 0; + guint file_count = 0; + guint total_count = 0; + guint scheme_ok_count = 0; + guint glob_ok_count = 0; for (iter = files; iter; iter = iter->next) { @@ -77,6 +68,15 @@ gboolean nautilus_actions_test_validate (ConfigActionTest *action_test, GList* f total_count++; } + if ((files != NULL) && (files->next == NULL) && (!action_test->accept_multiple_file)) + { + test_multiple_file = TRUE; + } + else if (action_test->accept_multiple_file) + { + test_multiple_file = TRUE; + } + if (action_test->isdir && action_test->isfile) { if (dir_count > 0 || file_count > 0) diff --git a/nautilus-actions-utils.c b/nautilus-actions-utils.c index 372ce432..7ff51ed9 100644 --- a/nautilus-actions-utils.c +++ b/nautilus-actions-utils.c @@ -14,6 +14,7 @@ gchar* nautilus_actions_utils_parse_parameter (const gchar* param_template, GLis * %p : parent directory of the selected directory(ies) of basedir of the file(s) * %f : the name of the selected file or the 1st one if many are selected * %m : list of the basename of the selected files/directories separated by space. + * %M : list of the selected files/directories with their complete path separated by space. * %s : scheme of the gnome-vfs URI * %h : hostname of the gnome-vfs URI * %U : username of the gnome-vfs URI @@ -39,8 +40,12 @@ gchar* nautilus_actions_utils_parse_parameter (const gchar* param_template, GLis gchar* username = g_strdup (gnome_vfs_uri_get_user_name (gvfs_uri)); gchar* parent_dir; gchar* file_list; + gchar* path_file_list; GList* file_iter = NULL; GString* tmp_file_list = g_string_new (filename); + GString* tmp_path_file_list = g_string_new (""); + + g_string_printf (tmp_path_file_list, "%s/%s", dirname, filename); if (gnome_vfs_uri_has_parent (gvfs_uri)) { @@ -60,14 +65,15 @@ gchar* nautilus_actions_utils_parse_parameter (const gchar* param_template, GLis GnomeVFSURI* tmp_gvfs_uri = gnome_vfs_uri_new (tmp_uri); gchar* tmp_filename = g_path_get_basename (gnome_vfs_uri_get_path (tmp_gvfs_uri)); - tmp_file_list = g_string_append (tmp_file_list, " "); - tmp_file_list = g_string_append (tmp_file_list, tmp_filename); + g_string_append_printf (tmp_file_list, " %s", tmp_filename); + g_string_append_printf (tmp_path_file_list, " %s/%s", dirname, tmp_filename); g_free (tmp_filename); gnome_vfs_uri_unref (tmp_gvfs_uri); g_free (tmp_uri); } file_list = g_string_free (tmp_file_list, FALSE); + path_file_list = g_string_free (tmp_path_file_list, FALSE); while (iter = g_strstr_len (iter, strlen (iter), "%")) @@ -91,6 +97,9 @@ gchar* nautilus_actions_utils_parse_parameter (const gchar* param_template, GLis case 'm': // list of the basename of the selected files/directories separated by space tmp_string = g_string_append (tmp_string, file_list); break; + case 'M': // list of the selected files/directories with their complete path separated by space. + tmp_string = g_string_append (tmp_string, path_file_list); + break; case 's': // scheme of the gnome-vfs URI tmp_string = g_string_append (tmp_string, scheme); break; @@ -118,6 +127,7 @@ gchar* nautilus_actions_utils_parse_parameter (const gchar* param_template, GLis g_free (dirname); g_free (filename); g_free (file_list); + g_free (path_file_list); g_free (scheme); g_free (hostname); g_free (username); diff --git a/nautilus-actions.c b/nautilus-actions.c index 2ea6630c..6bcf9e28 100644 --- a/nautilus-actions.c +++ b/nautilus-actions.c @@ -28,14 +28,15 @@ static void nautilus_actions_execute (NautilusMenuItem *item, ConfigAction *acti cmd = g_string_new (action->command->path); + param = nautilus_actions_utils_parse_parameter (action->command->parameters, files); - + if (param != NULL) { g_string_append_printf (cmd, " %s", param); g_free (param); } - + g_spawn_command_line_async (cmd->str, NULL); g_string_free (cmd, TRUE); @@ -52,19 +53,20 @@ static NautilusMenuItem *nautilus_actions_create_menu_item (ConfigAction *action action->menu_item->label, action->menu_item->tooltip, NULL); - + g_signal_connect_data (item, "activate", G_CALLBACK (nautilus_actions_execute), action, (GClosureNotify)nautilus_actions_config_free_action, 0); - + g_object_set_data_full (G_OBJECT (item), "files", nautilus_file_info_list_copy (files), (GDestroyNotify) nautilus_file_info_list_free); + g_free (name); return item; -- 2.11.4.GIT