Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions data/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ dbusFiles = [
output: 'nemo.FileManager1.service',
configuration: dataConf,
),

configure_file(
input : 'org.Nemo.FileChooser.service.in',
output: 'org.Nemo.FileChooser.service',
configuration: dataConf,
),
]

install_data(dbusFiles,
Expand Down
3 changes: 3 additions & 0 deletions data/org.Nemo.FileChooser.service.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[D-BUS Service]
Name=org.Nemo.FileChooser
Exec=@bindir@/nemo --no-default-window
20 changes: 20 additions & 0 deletions data/org.Nemo.FileChooser.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<interface name="org.Nemo.FileChooser">
<method name="OpenFile">
<arg type="s" name="title" direction="in"/>
<arg type="as" name="filters" direction="in"/>
<arg type="b" name="multiselect" direction="in"/>
<arg type="b" name="directory" direction="in"/>
<arg type="s" name="initial_folder" direction="in"/>
<arg type="as" name="results" direction="out"/>
</method>
<method name="SaveFile">
<arg type="s" name="title" direction="in"/>
<arg type="s" name="initial_folder" direction="in"/>
<arg type="s" name="suggested_name" direction="in"/>
<arg type="s" name="result" direction="out"/>
</method>
</interface>
</node>
427 changes: 427 additions & 0 deletions gresources/nemo-file-chooser-dialog.glade

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions gresources/nemo.gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<file>nemo-desktop-preferences.glade</file>
<file>nemo-file-management-properties.glade</file>
<file>nemo-search-bar.glade</file>
<file>nemo-file-chooser-dialog.glade</file>

<file>nemo-shortcuts.ui</file>

Expand Down
11 changes: 11 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,18 @@ nemoBuiltSources = gnome.gdbus_codegen(
object_manager: true
)

nemoFileChooserBuiltSources = gnome.gdbus_codegen(
'nemo-file-chooser-generated',
join_paths(meson.project_source_root(), 'data', 'org.Nemo.FileChooser.xml'),
interface_prefix: 'org.Nemo.',
namespace: 'Nemo',
object_manager: false
)

nemoCommon_sources = [
dbusBuiltSources,
nemoBuiltSources,
nemoFileChooserBuiltSources,
'nemo-action-config-widget.c',
'nemo-application.c',
'nemo-blank-desktop-window.c',
Expand All @@ -36,6 +45,8 @@ nemoCommon_sources = [
'nemo-file-management-properties.c',
'nemo-filter-bar.c',
'nemo-floating-bar.c',
'nemo-file-chooser-dbus.c',
'nemo-file-chooser-dialog.c',
'nemo-freedesktop-dbus.c',
'nemo-icon-view-container.c',
'nemo-icon-view-grid-container.c',
Expand Down
234 changes: 234 additions & 0 deletions src/nemo-file-chooser-dbus.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/*
* nemo-file-chooser-dbus: D-Bus service provider for org.Nemo.FileChooser
*/

#include <config.h>
#include <gio/gio.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>

#include "nemo-application.h"
#include "nemo-file-chooser-dbus.h"
#include "nemo-file-chooser-dialog.h"
#include "nemo-file-chooser-generated.h"

struct _NemoFileChooserDBus {
GObject parent;
guint owner_id;
NemoFileChooser *skeleton;
};

struct _NemoFileChooserDBusClass {
GObjectClass parent_class;
};

G_DEFINE_TYPE (NemoFileChooserDBus, nemo_file_chooser_dbus, G_TYPE_OBJECT);

typedef struct {
GDBusMethodInvocation *invocation;
GtkWidget *dialog;
NemoFileChooser *skeleton;
} ResponseData;

static void
on_open_dialog_response (GtkDialog *dialog, gint response_id, gpointer user_data)
{
ResponseData *data = user_data;
GPtrArray *results = g_ptr_array_new_with_free_func (g_free);

g_message ("Nemo Open Dialog Response ID: %d", response_id);

if (response_id == GTK_RESPONSE_ACCEPT || response_id == GTK_RESPONSE_OK) {
GSList *uris = nemo_file_chooser_dialog_get_selected_uris (dialog);
GSList *l;
for (l = uris; l != NULL; l = l->next) {
g_message ("Nemo Dialog selected URI: %s", (const gchar *)l->data);
g_ptr_array_add (results, g_strdup (l->data));
}
g_slist_free_full (uris, g_free);
}

g_ptr_array_add (results, NULL); // NULL terminator for const gchar *const * parameter

nemo_file_chooser_complete_open_file (data->skeleton, data->invocation, (const gchar *const *)results->pdata);

g_ptr_array_unref (results);
gtk_widget_destroy (GTK_WIDGET (dialog));
g_application_release (g_application_get_default ());
g_free (data);
}

static gboolean
handle_open_file_cb (NemoFileChooser *object,
GDBusMethodInvocation *invocation,
const gchar *title,
const gchar *const *filters,
gboolean multiselect,
gboolean directory,
const gchar *initial_folder,
gpointer user_data)
{
GtkWidget *dialog;

g_message ("handle_open_file_cb: title='%s', multiselect=%d, directory=%d, initial_folder='%s'",
title ? title : "", multiselect, directory, initial_folder ? initial_folder : "");

dialog = nemo_file_chooser_dialog_new (title,
directory ? GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER : GTK_FILE_CHOOSER_ACTION_OPEN,
multiselect,
initial_folder,
NULL);

ResponseData *data = g_new0 (ResponseData, 1);
data->invocation = invocation;
data->dialog = dialog;
data->skeleton = object;

g_signal_connect (dialog, "response", G_CALLBACK (on_open_dialog_response), data);
gtk_widget_show_all (dialog);
g_application_hold (g_application_get_default ());

return TRUE;
}

static void
on_save_dialog_response (GtkDialog *dialog, gint response_id, gpointer user_data)
{
ResponseData *data = user_data;
gchar *result = NULL;

if (response_id == GTK_RESPONSE_ACCEPT || response_id == GTK_RESPONSE_OK) {
result = nemo_file_chooser_dialog_get_selected_uri (dialog);
if (result && *result) {
g_autoptr(GFile) file = g_file_new_for_uri (result);
if (g_file_query_exists (file, NULL)) {
g_autofree gchar *basename = g_file_get_basename (file);
GtkWidget *msg_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
_("A file named \"%s\" already exists. Do you want to replace it?"),
basename);
gtk_window_set_title (GTK_WINDOW (msg_dialog), _("Replace File"));
gint res = gtk_dialog_run (GTK_DIALOG (msg_dialog));
gtk_widget_destroy (msg_dialog);

if (res != GTK_RESPONSE_YES) {
g_free (result);
return;
}
}
}
}

nemo_file_chooser_complete_save_file (data->skeleton, data->invocation, result ? result : "");

g_free (result);
gtk_widget_destroy (GTK_WIDGET (dialog));
g_application_release (g_application_get_default ());
g_free (data);
}

static gboolean
handle_save_file_cb (NemoFileChooser *object,
GDBusMethodInvocation *invocation,
const gchar *title,
const gchar *initial_folder,
const gchar *suggested_name,
gpointer user_data)
{
GtkWidget *dialog;

dialog = nemo_file_chooser_dialog_new (title,
GTK_FILE_CHOOSER_ACTION_SAVE,
FALSE,
initial_folder,
suggested_name);

ResponseData *data = g_new0 (ResponseData, 1);
data->invocation = invocation;
data->dialog = dialog;
data->skeleton = object;

g_signal_connect (dialog, "response", G_CALLBACK (on_save_dialog_response), data);
gtk_widget_show_all (dialog);
g_application_hold (g_application_get_default ());

return TRUE;
}

static void
bus_acquired_cb (GDBusConnection *conn,
const gchar *name,
gpointer user_data)
{
NemoFileChooserDBus *self = user_data;

self->skeleton = nemo_file_chooser_skeleton_new ();

g_signal_connect (self->skeleton, "handle-open-file",
G_CALLBACK (handle_open_file_cb), self);
g_signal_connect (self->skeleton, "handle-save-file",
G_CALLBACK (handle_save_file_cb), self);

g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->skeleton), conn, "/org/Nemo/FileChooser", NULL);
}

static void
name_acquired_cb (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
}

static void
name_lost_cb (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
}

static void
nemo_file_chooser_dbus_dispose (GObject *object)
{
NemoFileChooserDBus *self = (NemoFileChooserDBus *) object;

if (self->owner_id != 0) {
g_bus_unown_name (self->owner_id);
self->owner_id = 0;
}

if (self->skeleton != NULL) {
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self->skeleton));
g_object_unref (self->skeleton);
self->skeleton = NULL;
}

G_OBJECT_CLASS (nemo_file_chooser_dbus_parent_class)->dispose (object);
}

static void
nemo_file_chooser_dbus_class_init (NemoFileChooserDBusClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = nemo_file_chooser_dbus_dispose;
}

static void
nemo_file_chooser_dbus_init (NemoFileChooserDBus *self)
{
self->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
"org.Nemo.FileChooser",
G_BUS_NAME_OWNER_FLAGS_NONE,
bus_acquired_cb,
name_acquired_cb,
name_lost_cb,
self,
NULL);
}

NemoFileChooserDBus *
nemo_file_chooser_dbus_new (void)
{
return g_object_new (nemo_file_chooser_dbus_get_type (), NULL);
}
28 changes: 28 additions & 0 deletions src/nemo-file-chooser-dbus.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* nemo-file-chooser-dbus: Implementation for the org.Nemo FileChooser D-Bus interface
*/

#ifndef __NEMO_FILE_CHOOSER_DBUS_H__
#define __NEMO_FILE_CHOOSER_DBUS_H__

#include <glib-object.h>

#define NEMO_TYPE_FILE_CHOOSER_DBUS nemo_file_chooser_dbus_get_type()
#define NEMO_FILE_CHOOSER_DBUS(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_FILE_CHOOSER_DBUS, NemoFileChooserDBus))
#define NEMO_FILE_CHOOSER_DBUS_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_FILE_CHOOSER_DBUS, NemoFileChooserDBusClass))
#define NEMO_IS_FILE_CHOOSER_DBUS(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_FILE_CHOOSER_DBUS))
#define NEMO_IS_FILE_CHOOSER_DBUS_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_FILE_CHOOSER_DBUS))
#define NEMO_FILE_CHOOSER_DBUS_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_FILE_CHOOSER_DBUS, NemoFileChooserDBusClass))

typedef struct _NemoFileChooserDBus NemoFileChooserDBus;
typedef struct _NemoFileChooserDBusClass NemoFileChooserDBusClass;

GType nemo_file_chooser_dbus_get_type (void);
NemoFileChooserDBus * nemo_file_chooser_dbus_new (void);

#endif /* __NEMO_FILE_CHOOSER_DBUS_H__ */
Loading