From 86b4a15865438fe5c2e247bd526ba661e2d33d74 Mon Sep 17 00:00:00 2001 From: Pierre Wieser Date: Thu, 6 Jan 2011 00:17:16 +0100 Subject: [PATCH] nautilus-actions-gconf2desktop.sh migration tool The script takes care of migrating users and mandatory items to .desktop files. --- ChangeLog | 12 + configure.ac | 15 +- src/utils/.gitignore | 3 + src/utils/Makefile.am | 29 ++ src/utils/nautilus-actions-delete.c | 255 +++++++++++++++ src/utils/nautilus-actions-gconf2desktop.sh.in | 412 +++++++++++++++++++++++++ src/utils/nautilus-actions-print.c | 244 +++++++++++++++ 7 files changed, 959 insertions(+), 11 deletions(-) create mode 100644 src/utils/nautilus-actions-delete.c create mode 100644 src/utils/nautilus-actions-gconf2desktop.sh.in create mode 100644 src/utils/nautilus-actions-print.c diff --git a/ChangeLog b/ChangeLog index 73edcf2b..160f0b1f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -101,6 +101,18 @@ * src/nact/nautilus-actions-config-tool.ui: Apply patch provided by Christian Kirbach. Fix #638548. +2011-01-05 Pierre Wieser + + * src/utils/nautilus-actions-gconf2desktop.sh.in: + * src/utils/nautilus-actions-delete.c: + * src/utils/nautilus-actions-print.c: + New items migration script and programs. + They take care of migrating users and mandatory items to .desktop files. + + * configure.ac: + * src/utils/Makefile.am: + * src/utils/.gitignore: Updated accordingly. + 2011-01-04 Pierre Wieser * src/core/na-tokens.c (na_tokens_new_from_selection): diff --git a/configure.ac b/configure.ac index 8799b35b..25eea6a5 100644 --- a/configure.ac +++ b/configure.ac @@ -28,7 +28,7 @@ AC_PREREQ([2.53]) -AC_INIT([Nautilus-Actions],[3.0.7],[maintainer@nautilus-actions.org],,[http://www.nautilus-actions.org]) +AC_INIT([Nautilus-Actions],[3.1.0],[maintainer@nautilus-actions.org],,[http://www.nautilus-actions.org]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_CANONICAL_TARGET @@ -66,7 +66,10 @@ AC_CONFIG_FILES([ src/test/Makefile src/utils/Makefile tools/Makefile + src/utils/nautilus-actions-gconf2desktop.sh po/Makefile.in +],[ + chmod a+x src/utils/nautilus-actions-gconf2desktop.sh ]) AC_CONFIG_MACRO_DIR([m4]) @@ -152,16 +155,6 @@ NA_CHECK_MODULE([NAUTILUS_EXTENSION],[libnautilus-extension >= 2.8]) AC_SUBST([NAUTILUS_ACTIONS_CFLAGS]) AC_SUBST([NAUTILUS_ACTIONS_LIBS]) -# GSettings migration -AC_MSG_CHECKING([for GSettings]) -PKG_CHECK_EXISTS([glib-2.0 >= 2.26],[have_gsettings="yes"],[have_gsettings="no"]) -AC_MSG_RESULT([${have_gsettings}]) -if test "x${have_gsettings}" = "xyes"; then have_gsettings_b=1; else have_gsettings_b=0; fi -AC_DEFINE_UNQUOTED([HAVE_GSETTINGS],[${have_gsettings_b}],[Whether we compile against a recent enough GIO]) - -# As of N-A 3.0.6, GConf is always enabled -AM_CONDITIONAL([HAVE_GSETTINGS_AND_GCONF], [test "x${have_gsettings}" = "xyes"]) - # check for gtk-doc # Starting with gtk-doc 1.15, multiple source dirs are directly handled # by gtk-doc.make diff --git a/src/utils/.gitignore b/src/utils/.gitignore index d94650ad..b1bb19ab 100644 --- a/src/utils/.gitignore +++ b/src/utils/.gitignore @@ -1,6 +1,9 @@ nautilus-actions-check-actions-change +nautilus-actions-delete +nautilus-actions-gconf2desktop.sh nautilus-actions-new-config nautilus-actions-new +nautilus-actions-print nautilus-actions-run nautilus-actions-run-bindings.h nautilus-actions-schemas diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index b10a3d05..60a6801a 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -27,7 +27,9 @@ # ... and many others (see AUTHORS) bin_PROGRAMS = \ + nautilus-actions-delete \ nautilus-actions-new \ + nautilus-actions-print \ nautilus-actions-run \ nautilus-actions-schemas \ $(NULL) @@ -40,6 +42,17 @@ AM_CPPFLAGS += \ $(NAUTILUS_ACTIONS_CFLAGS) \ $(NULL) +nautilus_actions_delete_SOURCES = \ + nautilus-actions-delete.c \ + console-utils.c \ + console-utils.h \ + $(NULL) + +nautilus_actions_delete_LDADD = \ + $(top_builddir)/src/core/libna-core.la \ + $(NAUTILUS_ACTIONS_LIBS) \ + $(NULL) + nautilus_actions_new_SOURCES = \ nautilus-actions-new.c \ console-utils.c \ @@ -51,6 +64,17 @@ nautilus_actions_new_LDADD = \ $(NAUTILUS_ACTIONS_LIBS) \ $(NULL) +nautilus_actions_print_SOURCES = \ + nautilus-actions-print.c \ + console-utils.c \ + console-utils.h \ + $(NULL) + +nautilus_actions_print_LDADD = \ + $(top_builddir)/src/core/libna-core.la \ + $(NAUTILUS_ACTIONS_LIBS) \ + $(NULL) + BUILT_SOURCES = \ nautilus-actions-run-bindings.h \ $(NULL) @@ -82,4 +106,9 @@ nautilus_actions_schemas_LDADD = \ CLEANFILES = \ $(BUILT_SOURCES) \ + $(bin_SCRIPTS) \ + $(NULL) + +bin_SCRIPTS = \ + nautilus-actions-gconf2desktop.sh \ $(NULL) diff --git a/src/utils/nautilus-actions-delete.c b/src/utils/nautilus-actions-delete.c new file mode 100644 index 00000000..7eddf820 --- /dev/null +++ b/src/utils/nautilus-actions-delete.c @@ -0,0 +1,255 @@ +/* + * Nautilus-Actions + * A Nautilus extension which offers configurable context menu actions. + * + * Copyright (C) 2005 The GNOME Foundation + * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS) + * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS) + * + * 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 Library; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: + * Frederic Ruaudel + * Rodrigo Moya + * Pierre Wieser + * ... and many others (see AUTHORS) + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * This program has been written because I do not have found any reliable + * way of removing a mandatory key (an action or a menu) from the GConf + * XML backend. It is based on http://xmlsoft.org/examples/xpath2.c + */ + +#include + +#include "console-utils.h" + +#if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_OUTPUT_ENABLED) + +static gchar *xpath = ""; +static gchar *xmlfile = ""; +static gboolean version = FALSE; + +static GOptionEntry entries[] = { + + { "path" , 'p', 0, G_OPTION_ARG_STRING , &xpath, + N_( "The XPath to the tree to be deleted" ), N_( "" ) }, + { "xml" , 'x', 0, G_OPTION_ARG_STRING , &xmlfile, + N_( "The filename of the XML backend" ), N_( "" ) }, + { NULL } +}; + +static GOptionEntry misc_entries[] = { + + { "version" , 'v', 0, G_OPTION_ARG_NONE , &version, + N_( "Output the version number" ), NULL }, + { NULL } +}; + +static GOptionContext *init_options( void ); +static void exit_with_usage( void ); + +static void delete_path( const gchar *xmlfile, const xmlChar *xpath ); + +int +main( int argc, char** argv ) +{ + int status = EXIT_SUCCESS; + GOptionContext *context; + GError *error = NULL; + gchar *help; + gint errors; + + g_type_init(); + console_init_log_handler(); + + context = init_options(); + + if( argc == 1 ){ + g_set_prgname( argv[0] ); + help = g_option_context_get_help( context, FALSE, NULL ); + g_print( "\n%s", help ); + g_free( help ); + exit( status ); + } + + if( !g_option_context_parse( context, &argc, &argv, &error )){ + g_printerr( _( "Syntax error: %s\n" ), error->message ); + g_error_free (error); + exit_with_usage(); + } + + g_option_context_free( context ); + + if( version ){ + na_core_utils_print_version(); + exit( status ); + } + + errors = 0; + + if( !xpath || !strlen( xpath )){ + g_printerr( _( "Error: a XPath is mandatory.\n" )); + errors += 1; + } + + if( !xmlfile || !strlen( xmlfile )){ + g_printerr( _( "Error: a XML filename is mandatory.\n" )); + errors += 1; + } + + if( errors ){ + exit_with_usage(); + } + + /* Init libxml */ + xmlInitParser(); + LIBXML_TEST_VERSION + + /* Do the main job */ + delete_path( xmlfile, BAD_CAST( xpath )); + + /* Shutdown libxml */ + xmlCleanupParser(); + + exit( status ); +} + +/* + * init options context + */ +static GOptionContext * +init_options( void ) +{ + GOptionContext *context; + gchar* description; + GOptionGroup *misc_group; + + context = g_option_context_new( _( "Delete a XPath from a XML document." )); + +#ifdef ENABLE_NLS + bindtextdomain( GETTEXT_PACKAGE, GNOMELOCALEDIR ); +# ifdef HAVE_BIND_TEXTDOMAIN_CODESET + bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" ); +# endif + textdomain( GETTEXT_PACKAGE ); + g_option_context_add_main_entries( context, entries, GETTEXT_PACKAGE ); +#else + g_option_context_add_main_entries( context, entries, NULL ); +#endif + + description = console_cmdline_get_description(); + g_option_context_set_description( context, description ); + g_free( description ); + + misc_group = g_option_group_new( + "misc", _( "Miscellaneous options" ), _( "Miscellaneous options" ), NULL, NULL ); + g_option_group_add_entries( misc_group, misc_entries ); + g_option_context_add_group( context, misc_group ); + + return( context ); +} + +/* + * print a help message and exit with failure + */ +static void +exit_with_usage( void ) +{ + g_printerr( _( "Try %s --help for usage.\n" ), g_get_prgname()); + exit( EXIT_FAILURE ); +} + +static void +delete_path( const gchar *xmlfile, const xmlChar *xpathExpr ) +{ + xmlDocPtr doc; + xmlXPathContextPtr xpathCtx; + xmlXPathObjectPtr xpathObj; + xmlNodePtr nodePtr; + int size, i; + + /* Load XML document */ + doc = xmlParseFile( xmlfile ); + if( doc == NULL ){ + g_printerr( _( "Error: unable to parse file '%s'\n" ), xmlfile ); + return; + } + + /* Create xpath evaluation context */ + xpathCtx = xmlXPathNewContext( doc ); + if( xpathCtx == NULL ){ + g_printerr( _( "Error: unable to create new XPath context\n" )); + xmlFreeDoc( doc ); + return; + } + + /* Evaluate xpath expression */ + xpathObj = xmlXPathEvalExpression( xpathExpr, xpathCtx ); + if( xpathObj == NULL ){ + g_printerr( _( "Error: unable to evaluate xpath expression '%s'\n" ), xpathExpr ); + xmlXPathFreeContext( xpathCtx ); + xmlFreeDoc( doc ); + return; + } + + /* update selected nodes */ + /*update_xpath_nodes(xpathObj->nodesetval, value);*/ + size = ( xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0; + /*g_print( "size=%d\n", size );*/ + for( i=0 ; inodesetval->nodeTab[i]; + /*xmlElemDump( stdout, doc, nodePtr );*/ + xmlUnlinkNode( nodePtr ); + } + + /* Cleanup of XPath data */ + xmlXPathFreeObject( xpathObj ); + xmlXPathFreeContext( xpathCtx ); + + /* dump the resulting document */ + xmlDocDump( stdout, doc ); + + /* free the document */ + xmlFreeDoc( doc ); +} + +#else +int +main( void ){ + fprintf( stderr, "XPath support not compiled in\n" ); + exit( 1 ); +} +#endif diff --git a/src/utils/nautilus-actions-gconf2desktop.sh.in b/src/utils/nautilus-actions-gconf2desktop.sh.in new file mode 100644 index 00000000..3cc94d9c --- /dev/null +++ b/src/utils/nautilus-actions-gconf2desktop.sh.in @@ -0,0 +1,412 @@ +#!/bin/ksh +# Nautilus-Actions +# A Nautilus extension which offers configurable context menu actions. +# +# Copyright (C) 2005 The GNOME Foundation +# Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS) +# Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS) +# +# 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 Library; see the file COPYING. If not, +# write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307, USA. +# +# Authors: +# Frederic Ruaudel +# Rodrigo Moya +# Pierre Wieser +# ... and many others (see AUTHORS) + +errs=0 # will be the exit code of the script +my_cmd="${0}" # e.g. "./make-ks.sh" +my_parms="$*" # e.g. "-host toaster" +my_cmdline="${my_cmd} ${my_parms}" +me="$(basename ${my_cmd})" # e.g. "make-ks.sh" + # used in msg and msgerr functions +my_tmproot="/tmp/$(echo ${me} | sed 's?\..*$??').$$" + # e.g. "/tmp/make-ks.1978" + +# These three functions must be defined using the name() syntax in order +# to share traps with the caller process (cf. man (1) ksh). +# +trap_exit() +{ + clear_tmpfiles + [ "${opt_verbose}" = "yes" -o ${errs} -gt 0 ] && msg "exiting with code ${errs}" + exit ${errs} +} + +trap_int() +{ + msg "quitting on keyboard interrupt" + let errs+=1 + exit +} + +trap_term() +{ + [ "${opt_verbose}" = "yes" ] && msg "quitting on TERM signal" + exit +} + +# setup the different trap functions +trap 'trap_term' TERM +trap 'trap_int' INT +trap 'trap_exit' EXIT + +function clear_tmpfiles +{ + \rm -f ${my_tmproot}.* +} + +function msg +{ + typeset _eol="\n" + [ $# -ge 2 ] && _eol="${2}" + printf "[%s] %s${_eol}" ${me} "${1}" + return 0 +} + +function msgerr +{ + msg "error: ${1}" 1>&2 + return $? +} + +function msgwarn +{ + msg "warning: ${1}" 1>&2 + return $? +} + +function msg_help +{ + msg_version + echo " + This program is meant to safely migrate menus and actions from GConf to + .desktop files. + Users menus and actions are automatically migrated when Nautilus-Actions + menu plugin is loaded by Nautilus file-manager. + + Usage: ${my_cmd} [options] + --[no]help print this message, and exit [${opt_help_def}] + --[no]version print script version, and exit [${opt_version_def}] + --[no]dummy dummy execution [${opt_dummy_def}] + --[no]verbose runs verbosely [${opt_verbose_def}] + --print=/filename full pathname of the nautilus-actions-print program [${opt_print_def}] + --dir=/dirname directory where the migrated objects must be stored [${opt_dir_def}] + --[no]force force the rewriting of an already existing item [${opt_force_def}] + --[no]delete delete the item after the migration [${opt_delete_def}]" +} + +function msg_version +{ + echo " + @PACKAGE_NAME@ v @PACKAGE_VERSION@ + Copyright (C) 2011 Pierre Wieser." +} + +function command +{ + typeset _cmd="${1}" + + if [ "${opt_dummy}" = "yes" -o "${opt_verbose}" = "yes" ]; then + typeset _prefix="" + [ "${opt_dummy}" = "yes" ] && _prefix="[dummy] " + echo "${_prefix}${_cmd}" + fi + + if [ "${opt_dummy}" = "no" ]; then + eval ${_cmd} + fi +} + +# initialize common command-line options +nbopt=$# +opt_help= +opt_help_def="no" +opt_dummy= +opt_dummy_def="yes" +opt_version= +opt_version_def="no" +opt_verbose= +opt_verbose_def="no" + +# a first loop over command line arguments to detect verbose mode +while : +do + # break when all arguments have been read + case $# in + 0) + break + ;; + esac + + # get and try to interpret the next argument + _option=$1 + shift + + # make all options have two hyphens + _orig_option=${_option} + case ${_option} in + --*) + ;; + -*) + _option=-${_option} + ;; + esac + + # now process options and their argument + case ${_option} in + --noverb | --noverbo | --noverbos | --noverbose) + opt_verbose="no" + ;; + --verb | --verbo | --verbos | --verbose) + opt_verbose="yes" + ;; + esac +done + +[ "${opt_verbose}" = "yes" ] && msg "setting opt_verbose to 'yes'" + +# script_opt_verb has scanned all command-line arguments +# in order to detect the opt_verbose; +# reset arguments so that they can be scanned again in main script +set -- ${my_parms} + +# interpreting command-line arguments +print_program="nautilus-actions-print" +opt_print= +opt_print_def="$(which ${print_program} 2>/dev/null)" + +opt_dir= +[ $(id -u) -eq 0 ] && opt_dir_def="/usr" || opt_dir_def="${HOME}/.local" +opt_dir_def="${opt_dir_def}/share/file-manager/actions" + +# default is to not force rewriting of already existing items +# instead they are renumbered +opt_force= +opt_force_def="no" + +# default is to not delete the migrated item +opt_delete= +opt_delete_def="no" + +# path of the branch which contains the configurations +na_configurations="/apps/nautilus-actions/configurations" + +# loop over command line arguments +pos=0 +while : +do + # break when all arguments have been read + case $# in + 0) + break + ;; + esac + + # get and try to interpret the next argument + option=$1 + shift + + # make all options have two hyphens + orig_option=${option} + case ${option} in + --*) + ;; + -*) + option=-${option} + ;; + esac + + # split and extract argument for options that take one + case ${option} in + --*=*) + optarg=$(echo ${option} | sed -e 's/^[^=]*=//') + option=$(echo ${option} | sed 's/=.*//') + ;; + # these options take a mandatory argument + # since, we didn't find it in 'option', so it should be + # next word in the command line + --di | --dir | \ + --p | --pr | --pri | --prin | --print) + optarg=$1 + shift + ;; + esac + + # now process options and their argument + case ${option} in + --de | --del | --dele | --delet | --delete) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_delete to 'yes'" + opt_delete="yes" + ;; + --di | --dir) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_dir to '${optarg}'" + opt_dir="${optarg}" + ;; + --du | --dum | --dumm | --dummy) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_dummy to 'yes'" + opt_dummy="yes" + ;; + --f | --fo | --for | --forc | --force) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_force to 'yes'" + opt_force="yes" + ;; + --h | --he | --hel | --help) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_help to 'yes'" + opt_help="yes" + ;; + --node | --nodel | --nodele | --nodelet | --nodelete) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_delete to 'no'" + opt_delete="no" + ;; + --nodu | --nodum | --nodumm | --nodummy) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_dummy to 'no'" + opt_dummy="no" + ;; + --nof | --nofo | --nofor | --noforc | --noforce) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_force to 'no'" + opt_force="no" + ;; + --noh | --nohe | --nohel | --nohelp) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_help to 'no'" + opt_help="no" + ;; + --noverb | --noverbo | --noverbos | --noverbose) + ;; + --novers | --noversi | --noversio | --noversion) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_version to 'no'" + opt_version="no" + ;; + --p | --pr | --pri | --prin | --print) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_print to '${optarg}'" + opt_print="${optarg}" + ;; + --verb | --verbo | --verbos | --verbose) + ;; + --vers | --versi | --versio | --version) + [ "${opt_verbose}" = "yes" ] && msg "setting opt_version to 'yes'" + opt_version="yes" + ;; + --*) + msgerr "unrecognized option: '${orig_option}'" + let errs+=1 + ;; + # positional parameters + *) + let pos+=1 + #if [ ${pos} -eq 1 ]; then + # [ "${opt_verbose}" = "yes" ] && msg "setting opt_output to '${option}'" + # opt_output=${option} + #else + msgerr "unexpected positional parameter #${pos}: '${option}'" + let errs+=1 + #fi + ;; + esac +done + +# set option defaults +set | grep -e '^opt_' | cut -d= -f1 | while read _name; do + if [ "$(echo ${_name} | sed 's/.*\(_orig\)/\1/')" != "_orig" ]; then + if [ "$(echo ${_name} | sed 's/.*\(_def\)/\1/')" != "_def" ]; then + _value="$(eval echo "$"${_name})" + eval ${_name}_orig="$(eval echo "$"${_name})" + if [ ${nbopt} -eq 0 -a "${_name}" = "opt_help" ]; then + opt_help="yes" + _value="yes" + fi + if [ "${_value}" = "" ]; then + eval ${_name}="$(eval echo "$"${_name}_def)" + fi + fi + fi +done + +if [ "${opt_help}" = "yes" ]; then + msg_help + echo "" + exit +fi + +if [ "${opt_version}" = "yes" ]; then + msg_version + echo "" + exit +fi + +if [ "${opt_print}" = "" ]; then + msgerr "${print_program}: not found" + let errs+=1 +elif [ ! -x ${opt_print} ]; then + msgerr "${print_program}: not executable" + let errs+=1 +fi + +if [ ${errs} -gt 0 ]; then + msg "${errs} error(s) have been detected" + msg "try '${my_cmd} --help' for usage" + exit +fi + +# --------------------------------------------------------------------- +# MAIN CODE + +# if we do not have gconftool-2, then exit +which gconftool-2 1>/dev/null 2>&1 || { msg "gconftool-2: not available"; exit 1; } + +# create the destination directory if it does not yet exist +command "mkdir -p ${opt_dir} || exit 1" + +let count=0 + +# list objects in configurations/ subdir +for dir in $(gconftool-2 --all-dirs ${na_configurations}); do + id=$(basename ${dir}) + let count+=1 + [ "${opt_verbose}" = "yes" ] && msg "item=${id}" + if [ -e ${opt_dir}/${id}.desktop -a "${opt_force}" = "no" ]; then + msgwarn "${opt_dir}/${id}.desktop already exists" + i=0 + while [ -e ${opt_dir}/${id}-${i}.desktop ]; do + let i+=1 + done + command "${opt_print} --id ${id} | grep -v ${print_program} > ${opt_dir}/${id}-${i}.desktop" + else + command "${opt_print} --id ${id} | grep -v ${print_program} > ${opt_dir}/${id}.desktop" + fi +done + +# force sync +killall gconfd-2 + +# at the end, we delete the branch +if [ "${opt_delete}" = "yes" -a ${count} -gt 0 ]; then + if [ $(id -u) -eq 0 ]; then + # rather a bad hack to find where mandatory items are stored by GConf + # nautilus-actions-delete directly removes our branch from the XML tree! + xml=$(find /etc -name gconf.xml.mandatory)/%gconf-tree.xml + path='/gconf/dir[@name="apps"]/dir[@name="nautilus-actions"]/dir[@name="configurations"]' + command "$(dirname ${opt_print})/nautilus-actions-delete --path '${path}' --xml ${xml} > ${xml}2" + command "mv ${xml}2 ${xml}" + else + # this does not work for mandatory items + command "gconftool-2 --recursive-unset ${na_configurations}" + fi +fi + +msg "${count} migrated items" + +exit diff --git a/src/utils/nautilus-actions-print.c b/src/utils/nautilus-actions-print.c new file mode 100644 index 00000000..17d1681e --- /dev/null +++ b/src/utils/nautilus-actions-print.c @@ -0,0 +1,244 @@ +/* + * Nautilus-Actions + * A Nautilus extension which offers configurable context menu actions. + * + * Copyright (C) 2005 The GNOME Foundation + * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS) + * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS) + * + * 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 Library; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: + * Frederic Ruaudel + * Rodrigo Moya + * Pierre Wieser + * ... and many others (see AUTHORS) + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "console-utils.h" + +static gchar *id = ""; +static gchar *format = ""; +static gboolean version = FALSE; + +static GOptionEntry entries[] = { + + { "id" , 'i', 0, G_OPTION_ARG_STRING , &id, + N_( "The identifiant of the menu or the action to be printed" ), N_( "" ) }, + { "format" , 'f', 0, G_OPTION_ARG_STRING, &format, + N_( "An export format [Desktop1]" ), N_( "" ) }, + { NULL } +}; + +static GOptionEntry misc_entries[] = { + + { "version" , 'v', 0, G_OPTION_ARG_NONE , &version, + N_( "Output the version number" ), NULL }, + { NULL } +}; + +static NAPivot *pivot = NULL; + +static GOptionContext *init_options( void ); +static NAObjectItem *get_item( const gchar *id ); +static void export_item( const NAObjectItem *item, const gchar *format ); +static void exit_with_usage( void ); + +int +main( int argc, char** argv ) +{ + int status = EXIT_SUCCESS; + GOptionContext *context; + GError *error = NULL; + gchar *help; + gint errors; + NAObjectItem *item; + GList *formats_list, *it; + gboolean format_found; + + g_type_init(); + console_init_log_handler(); + + context = init_options(); + + if( argc == 1 ){ + g_set_prgname( argv[0] ); + help = g_option_context_get_help( context, FALSE, NULL ); + g_print( "\n%s", help ); + g_free( help ); + exit( status ); + } + + if( !g_option_context_parse( context, &argc, &argv, &error )){ + g_printerr( _( "Syntax error: %s\n" ), error->message ); + g_error_free (error); + exit_with_usage(); + } + + g_option_context_free( context ); + + if( version ){ + na_core_utils_print_version(); + exit( status ); + } + + errors = 0; + + if( !id || !strlen( id )){ + g_printerr( _( "Error: a menu or action id is mandatory.\n" )); + errors += 1; + } + + item = get_item( id ); + if( !item ){ + errors += 1; + } + + if( !format || !strlen( format )){ + format = "Desktop1"; + } + + formats_list = na_exporter_get_formats( pivot ); + format_found = FALSE; + + for( it = formats_list ; it && !format_found ; it = it->next ){ + NAExportFormat *export = NA_EXPORT_FORMAT( it->data ); + gchar *export_id = na_export_format_get_id( export ); + format_found = !strcmp( export_id, format ); + g_free( export_id ); + } + + na_exporter_free_formats( formats_list ); + + if( !format_found ){ + /* i18n: %s stands for the id of the export format, and is not translatable */ + g_printerr( _( "Error: %s: unknown export format.\n" ), format ); + errors += 1; + } + + if( errors ){ + exit_with_usage(); + } + + export_item( item, format ); + + exit( status ); +} + +/* + * init options context + */ +static GOptionContext * +init_options( void ) +{ + GOptionContext *context; + gchar* description; + GOptionGroup *misc_group; + + context = g_option_context_new( _( "Print a menu or an action to stdout." )); + +#ifdef ENABLE_NLS + bindtextdomain( GETTEXT_PACKAGE, GNOMELOCALEDIR ); +# ifdef HAVE_BIND_TEXTDOMAIN_CODESET + bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" ); +# endif + textdomain( GETTEXT_PACKAGE ); + g_option_context_add_main_entries( context, entries, GETTEXT_PACKAGE ); +#else + g_option_context_add_main_entries( context, entries, NULL ); +#endif + + description = console_cmdline_get_description(); + g_option_context_set_description( context, description ); + g_free( description ); + + misc_group = g_option_group_new( + "misc", _( "Miscellaneous options" ), _( "Miscellaneous options" ), NULL, NULL ); + g_option_group_add_entries( misc_group, misc_entries ); + g_option_context_add_group( context, misc_group ); + + return( context ); +} + +/* + * search for the action in the repository + */ +static NAObjectItem * +get_item( const gchar *id ) +{ + NAObjectItem *item = NULL; + + pivot = na_pivot_new(); + na_pivot_set_loadable( pivot, PIVOT_LOAD_ALL ); + na_pivot_load_items( pivot ); + + item = na_pivot_get_item( pivot, id ); + + if( !item ){ + g_printerr( _( "Error: item '%s' doesn't exist.\n" ), id ); + } + + return( item ); +} + +/* + * displays the specified item on stdout, in the specified export format + */ +static void +export_item( const NAObjectItem *item, const gchar *format ) +{ + GSList *messages = NULL; + GSList *it; + GQuark q_format = g_quark_from_string( format ); + + gchar *buffer = na_exporter_to_buffer( pivot, item, q_format, &messages ); + + for( it = messages ; it ; it = it->next ){ + g_printerr( "%s\n", ( const gchar * ) it->data ); + } + na_core_utils_slist_free( messages ); + + if( buffer ){ + g_printf( "%s\n", buffer ); + g_free( buffer ); + } +} + +/* + * print a help message and exit with failure + */ +static void +exit_with_usage( void ) +{ + g_printerr( _( "Try %s --help for usage.\n" ), g_get_prgname()); + exit( EXIT_FAILURE ); +} -- 2.11.4.GIT