/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Engrampa
*
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "file-utils.h"
#include "fr-init.h"
#define FR_SERVICE_NAME "org.mate.Engrampa"
#define FR_SERVICE_PATH "/org/mate/Engrampa"
static const char introspection_xml[] =
""
" "
/**
* GetSupportedTypes:
*
* Returns the supported archive types for a specific action.
*
* Input arguments:
*
* @action:
* Can be one of the following values:
* *) create: create an archive that can contain many files.
* *) create_single_file: create an archive that can contain a single file.
* *) extract: extract the content of an archive.
*
* Output arguments:
*
* @types:
* The supported archive types described as an array of hash tables,
* where each hash table has the following keys:
* *) mime-type: the mime type relative to the archive type.
* *) default-extension: the extension to use for newly created archives.
* *) description: a human readable description of the archive type.
*/
" "
" "
" "
" "
/**
* AddToArchive:
*
* Adds the specified files to an archive. If the archive already
* exists the archive is updated.
*
* Input arguments:
*
* @archive:
* The archive URI.
* @files:
* The files to add to the archive, as an array of URIs.
* @use_progress_dialog:
* Whether to show the progress dialog.
*/
" "
" "
" "
" "
" "
/**
* Compress:
*
* Compresses a series of files in an archive. The user is asked to
* enter an archive name, archive type and other options. In this case
* it's used the same dialog used by the "Compress..." command from the
* Nautilus context menu.
* If the user chooses an existing archive, the archive is updated.
*
* Input arguments:
*
* @files:
* The files to add to the archive, as an array of URIs.
* @destination:
* An optional destination, if not specified the folder of the first
* file in @files is used.
* @use_progress_dialog:
* Whether to show the progress dialog.
*/
" "
" "
" "
" "
" "
/**
* Extract:
*
* Extract an archive in a specified location.
*
* Input arguments:
*
* @archive:
* The archive to extract.
* @destination:
* The location where to extract the archive.
* @use_progress_dialog:
* Whether to show the progress dialog.
*/
" "
" "
" "
" "
" "
/**
* ExtractHere:
*
* Extract an archive in a specified location.
*
* Input arguments:
*
* @archive:
* The archive to extract.
* @use_progress_dialog:
* Whether to show the progress dialog.
*/
" "
" "
" "
" "
/**
* Progress (signal)
*
* Arguments:
*
* @fraction:
* number from 0.0 to 100.0 that indicates the percentage of
* completion of the operation.
* @details:
* text message that describes the current operation.
*/
" "
" "
" "
" "
" "
"";
static GDBusNodeInfo *introspection_data = NULL;
static void
window_ready_cb (GtkWidget *widget,
GError *error,
gpointer user_data)
{
if (error == NULL)
g_dbus_method_invocation_return_value ((GDBusMethodInvocation *) user_data, NULL);
else
g_dbus_method_invocation_return_error ((GDBusMethodInvocation *) user_data,
error->domain,
error->code,
"%s",
error->message);
}
static gboolean
window_progress_cb (FrWindow *window,
double fraction,
char *details,
gpointer user_data)
{
GDBusConnection *connection = user_data;
g_dbus_connection_emit_signal (connection,
NULL,
FR_SERVICE_PATH,
"org.mate.ArchiveManager",
"Progress",
g_variant_new ("(ds)",
fraction,
details),
NULL);
return TRUE;
}
static void
handle_method_call (GDBusConnection *connection,
const char *sender,
const char *object_path,
const char *interface_name,
const char *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
update_registered_commands_capabilities ();
if (g_strcmp0 (method_name, "GetSupportedTypes") == 0) {
char *action;
int *supported_types = NULL;
g_variant_get (parameters, "(s)", &action);
if (g_strcmp0 (action, "create") == 0) {
supported_types = save_type;
}
else if (g_strcmp0 (action, "create_single_file") == 0) {
supported_types = single_file_save_type;
}
else if (g_strcmp0 (action, "extract") == 0) {
supported_types = open_type;
}
if (supported_types == NULL) {
g_dbus_method_invocation_return_error (invocation,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
"Action not valid %s, valid values are: create, create_single_file, extract",
action);
}
else {
GVariantBuilder builder;
int i;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(aa{ss})"));
g_variant_builder_open (&builder, G_VARIANT_TYPE ("aa{ss}"));
for (i = 0; supported_types[i] != -1; i++) {
g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{ss}"));
g_variant_builder_add (&builder, "{ss}",
"mime-type",
mime_type_desc[supported_types[i]].mime_type);
g_variant_builder_add (&builder, "{ss}",
"default-extension",
mime_type_desc[supported_types[i]].default_ext);
g_variant_builder_add (&builder, "{ss}",
"description",
_(mime_type_desc[supported_types[i]].name));
g_variant_builder_close (&builder);
}
g_variant_builder_close (&builder);
g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
}
g_free (action);
}
else if (g_strcmp0 (method_name, "AddToArchive") == 0) {
char *archive;
char **files;
gboolean use_progress_dialog;
int i;
GList *file_list = NULL;
GtkWidget *window;
g_variant_get (parameters, "(s^asb)", &archive, &files, &use_progress_dialog);
for (i = 0; files[i] != NULL; i++)
file_list = g_list_prepend (file_list, files[i]);
file_list = g_list_reverse (file_list);
window = fr_window_new ();
fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
fr_window_new_batch (FR_WINDOW (window), _("Compress"));
fr_window_set_batch__add (FR_WINDOW (window), archive, file_list);
fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
fr_window_start_batch (FR_WINDOW (window));
g_free (archive);
gtk_main ();
}
else if (g_strcmp0 (method_name, "Compress") == 0) {
char **files;
char *destination;
gboolean use_progress_dialog;
int i;
GList *file_list = NULL;
GtkWidget *window;
g_variant_get (parameters, "(^assb)", &files, &destination, &use_progress_dialog);
for (i = 0; files[i] != NULL; i++)
file_list = g_list_prepend (file_list, files[i]);
file_list = g_list_reverse (file_list);
if ((destination == NULL) || (strcmp (destination, "") == 0))
destination = remove_level_from_path (file_list->data);
window = fr_window_new ();
fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
fr_window_set_default_dir (FR_WINDOW (window), destination, TRUE);
g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
fr_window_new_batch (FR_WINDOW (window), _("Extract archive"));
fr_window_set_batch__add (FR_WINDOW (window), NULL, file_list);
fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
fr_window_start_batch (FR_WINDOW (window));
g_free (destination);
gtk_main ();
}
else if (g_strcmp0 (method_name, "Extract") == 0) {
char *archive;
char *destination;
gboolean use_progress_dialog;
GtkWidget *window;
g_variant_get (parameters, "(ssb)", &archive, &destination, &use_progress_dialog);
window = fr_window_new ();
fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
if ((destination != NULL) && (strcmp (destination, "") != 0))
fr_window_set_default_dir (FR_WINDOW (window), destination, TRUE);
g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
fr_window_new_batch (FR_WINDOW (window), _("Extract archive"));
fr_window_set_batch__extract (FR_WINDOW (window), archive, destination);
fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
fr_window_start_batch (FR_WINDOW (window));
g_free (destination);
g_free (archive);
gtk_main ();
}
else if (g_strcmp0 (method_name, "ExtractHere") == 0) {
char *archive;
gboolean use_progress_dialog;
GtkWidget *window;
g_variant_get (parameters, "(sb)", &archive, &use_progress_dialog);
window = fr_window_new ();
fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
fr_window_new_batch (FR_WINDOW (window), _("Extract archive"));
fr_window_set_batch__extract_here (FR_WINDOW (window), archive);
fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
fr_window_start_batch (FR_WINDOW (window));
g_free (archive);
gtk_main ();
}
}
static const GDBusInterfaceVTable interface_vtable = {
handle_method_call,
NULL, /* handle_get_property */
NULL /* handle_set_property */
};
static void
on_bus_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
guint registration_id;
registration_id = g_dbus_connection_register_object (connection,
FR_SERVICE_PATH,
introspection_data->interfaces[0],
&interface_vtable,
NULL,
NULL, /* user_data_free_func */
NULL); /* GError** */
g_assert (registration_id > 0);
initialize_data ();
}
static void
on_name_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
}
static void
on_name_lost (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
gtk_main_quit ();
}
int
main (int argc, char *argv[])
{
GOptionContext *context = NULL;
GError *error = NULL;
guint owner_id;
#ifdef ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
#endif /* ENABLE_NLS */
context = g_option_context_new (N_("- Create and modify an archive"));
#ifdef ENABLE_NLS
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
#endif /* ENABLE_NLS */
g_option_context_add_group (context, gtk_get_option_group (TRUE));
if (! g_option_context_parse (context, &argc, &argv, &error)) {
g_critical ("Failed to parse arguments: %s", error->message);
g_error_free (error);
g_option_context_free (context);
return EXIT_FAILURE;
}
g_option_context_free (context);
g_set_application_name (_("Engrampa"));
gtk_window_set_default_icon_name ("engrampa");
gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
PKG_DATA_DIR G_DIR_SEPARATOR_S "icons");
introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
g_assert (introspection_data != NULL);
owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
FR_SERVICE_NAME,
G_BUS_NAME_OWNER_FLAGS_NONE,
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL,
NULL);
gtk_main ();
g_bus_unown_name (owner_id);
g_dbus_node_info_unref (introspection_data);
return 0;
}