3
* gajim plugin for nautilus-sendto
5
* Copyright (C) 2006 Dimitur Kirov
6
* 2006 Roberto Majadas <telemaco@openshine.com>
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License as
10
* published by the Free Software Foundation; either version 2 of the
11
* License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more av.
18
* You should have received a copy of the GNU General Public
19
* License along with this program; if not, write to the
20
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21
* Boston, MA 02110-1301 USA.
26
#include <glib/gi18n-lib.h>
27
#include <dbus/dbus.h>
28
#include <dbus/dbus-glib.h>
29
#include "nautilus-sendto-plugin.h"
31
#define OBJ_PATH "/org/gajim/dbus/RemoteObject"
32
#define INTERFACE "org.gajim.dbus.RemoteInterface"
33
#define SERVICE "org.gajim.dbus"
35
const gchar *COMPLETION_PROPS[] = {"name", "jid"};
36
/* list of contacts, which are not offline */
37
static GHashTable *jid_table = NULL;
38
static gchar *iconset;
41
DBusGProxy *proxy = NULL;
44
* contact cb, gets property from contact dict
45
* and put online contacts to jid_table
48
_foreach_contact(gpointer contact, gpointer user_data)
53
GHashTable *contact_table;
55
/* holds contact props of already exisiting jid/nick */
56
GHashTable *existing_contact;
58
/* name of the contact in completion list
59
it may be jid, nick, jid (account), or nick(account) */
66
if (contact == NULL) {
67
g_warning("Null contact in the list");
70
contact_table = (GHashTable *) contact;
71
account = (gchar *) user_data;
73
value = g_hash_table_lookup(contact_table, "show");
74
if (value == NULL || !G_VALUE_HOLDS_STRING(value)) {
75
g_warning("String expected (contact - show)");
76
g_hash_table_destroy(contact_table);
79
show = g_value_get_string ((GValue *)value);
80
if(g_str_equal(show, "offline") || g_str_equal(show, "error")) {
81
g_hash_table_destroy(contact_table);
84
/* remove unneeded item with key resource and add account
85
to contact properties */
86
g_hash_table_insert(contact_table, "account", account);
87
g_hash_table_remove(contact_table, "resource");
89
/* add nick the same way as jid */
91
value = g_hash_table_lookup(contact_table, COMPLETION_PROPS[i]);
92
if(value == NULL || !G_VALUE_HOLDS_STRING(value)) {
93
g_warning("String expected (contact - name)");
96
jid = g_value_dup_string((GValue *)value);
97
existing_contact = g_hash_table_lookup(jid_table, jid);
98
if(existing_contact) {
99
/* add existing contact as nick (account) */
100
contact_str = g_string_new(jid);
101
g_string_append(contact_str, " (");
102
g_string_append(contact_str,
103
g_hash_table_lookup(existing_contact, "account"));
104
g_string_append(contact_str, ")");
105
g_hash_table_insert(jid_table, contact_str->str,
107
g_string_free(contact_str, FALSE);
109
/* add current contact as nick (account) */
110
contact_str = g_string_new(jid);
111
g_string_append(contact_str, " (");
112
g_string_append(contact_str,
113
g_hash_table_lookup(contact_table, "account"));
114
g_string_append(contact_str, ")");
115
g_hash_table_insert(jid_table, contact_str->str,
117
g_string_free(contact_str, FALSE);
120
g_hash_table_insert(jid_table, jid, contact_table);
127
* connect to session bus, onsuccess return TRUE
132
DBusGConnection *connection;
137
connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
139
g_warning("[Gajim] unable to get session bus, error was:\n %s", error->message);
143
proxy = dbus_g_proxy_new_for_name(connection,
147
dbus_g_connection_unref(connection);
153
if (!dbus_g_proxy_call (proxy, "list_accounts", &error, G_TYPE_INVALID,
154
G_TYPE_STRV, &accounts, G_TYPE_INVALID))
156
g_object_unref(proxy);
160
g_strfreev(accounts);
165
* Print appropriate warnings when dbus raised error
169
_handle_dbus_exception (GError *error, gboolean empty_list_messages)
172
g_warning("[Gajim] unable to parse result");
175
else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
176
g_warning ("[Gajim] caught remote method exception %s: %s",
177
dbus_g_error_get_name (error),
180
else if(empty_list_messages) {
181
/* empty list and error goes here */
182
g_warning ("[Gajim] empty result set: %d %d %s\n", error->domain,
183
error->code, error->message);
185
g_error_free (error);
189
* query object, about the contact list for each account
190
* and fill all available contacts in the contacts table
196
GSList *contacts_list;
197
GHashTable *prefs_map;
199
gchar **account_iter;
201
gpointer iconset_ptr;
206
g_warning("[Gajim] unable to connect to session bus");
209
/* get gajim prefs and lookup for iconset */
210
if (!dbus_g_proxy_call(proxy, "prefs_list", &error, G_TYPE_INVALID,
211
dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING),
212
&prefs_map, G_TYPE_INVALID))
214
_handle_dbus_exception(error, TRUE);
217
iconset_ptr = g_hash_table_lookup(prefs_map, "iconset");
218
if (iconset_ptr != NULL) {
219
iconset = g_strdup((gchar *)iconset_ptr);
221
g_warning("[Gajim] unable to get prefs value for iconset");
224
g_hash_table_destroy(prefs_map);
225
/* END get gajim prefs */
227
if (!dbus_g_proxy_call (proxy, "list_accounts", &error, G_TYPE_INVALID,
229
&accounts, G_TYPE_INVALID))
231
_handle_dbus_exception(error, TRUE);
234
for(account_iter = accounts; *account_iter ; account_iter++) {
235
account = g_strdup(*account_iter);
237
/* query gajim remote object and put results in 'contacts_list' */
238
if (!dbus_g_proxy_call (proxy, "list_contacts", &error,
239
G_TYPE_STRING, account, /* call arguments */
240
G_TYPE_INVALID, /* delimiter */
241
/* return value is collection of maps */
242
dbus_g_type_get_collection ("GSList",
243
dbus_g_type_get_map ("GHashTable",
244
G_TYPE_STRING, G_TYPE_VALUE)),
245
&contacts_list, G_TYPE_INVALID))
247
_handle_dbus_exception(error, FALSE);
251
g_slist_foreach (contacts_list, _foreach_contact, account);
252
g_slist_free(contacts_list);
254
g_strfreev (accounts);
259
init (NstPlugin *plugin)
261
g_print ("Init gajim plugin\n");
263
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
264
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
266
/* connect to gajim dbus service */
267
jid_table = g_hash_table_new (g_str_hash, g_str_equal);
276
_set_pixbuf_from_status (const gchar *show, GdkPixbuf **pixbuf)
278
GString *pixbuf_path;
281
pixbuf_path = g_string_new(GAJIM_SHARE_DIR);
282
g_string_append_c(pixbuf_path, '/');
283
g_string_append(pixbuf_path, "data");
284
g_string_append_c(pixbuf_path, '/');
285
g_string_append(pixbuf_path, "iconsets");
286
g_string_append_c(pixbuf_path, '/');
287
g_string_append(pixbuf_path, iconset);
288
g_string_append_c(pixbuf_path, '/');
289
g_string_append(pixbuf_path, "16x16");
290
g_string_append_c(pixbuf_path, '/');
291
g_string_append(pixbuf_path, show);
292
g_string_append(pixbuf_path, ".png");
293
if(g_file_test(pixbuf_path->str, G_FILE_TEST_EXISTS) &&
294
g_file_test(pixbuf_path->str, G_FILE_TEST_IS_REGULAR)) {
296
*pixbuf = gdk_pixbuf_new_from_file(pixbuf_path->str, &error);
301
g_string_free(pixbuf_path, FALSE);
305
_add_contact_to_model(gpointer key, gpointer value, gpointer user_data)
311
GHashTable *contact_props;
314
contact_props = (GHashTable *) value;
316
val = g_hash_table_lookup(contact_props, "show");
317
if (value == NULL || !G_VALUE_HOLDS_STRING(val)) {
318
g_warning("String expected (contact - show)");
321
show = g_value_get_string ((GValue *)val);
322
_set_pixbuf_from_status(show, &pixbuf);
325
store = (GtkListStore *) user_data;
326
iter = g_malloc (sizeof(GtkTreeIter));
327
gtk_list_store_append (store, iter);
328
gtk_list_store_set (store, iter, 0, pixbuf, 1, key, -1);
333
* put gajim contacts to jid_list
334
* filtering only these which are connected
337
add_gajim_contacts_to_model (GtkListStore *store)
339
if(!_get_contacts()) {
342
if(g_hash_table_size(jid_table) == 0) {
345
g_hash_table_foreach(jid_table, _add_contact_to_model, store);
350
* fill completion model for the entry, using list of
351
* available gajim contacts
354
get_contacts_widget (NstPlugin *plugin)
357
GtkEntryCompletion *completion;
359
GtkCellRenderer *renderer;
360
GtkTreeModel *completion_model;
362
entry = gtk_entry_new ();
363
completion = gtk_entry_completion_new ();
365
renderer = gtk_cell_renderer_pixbuf_new ();
366
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
369
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), renderer,
373
store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
374
if(!add_gajim_contacts_to_model (store)) {
375
gtk_widget_set_sensitive(entry, FALSE);
377
completion_model = GTK_TREE_MODEL (store);
378
gtk_entry_completion_set_model (completion, completion_model);
379
gtk_entry_set_completion (GTK_ENTRY (entry), completion);
380
gtk_entry_completion_set_text_column (completion, 1);
381
g_object_unref (completion_model);
382
g_object_unref (completion);
387
show_error (const gchar *title, const gchar *message)
391
dialog = gtk_message_dialog_new_with_markup(NULL,
392
GTK_DIALOG_DESTROY_WITH_PARENT,
394
GTK_BUTTONS_CLOSE, NULL);
395
gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog),
396
g_markup_printf_escaped("<b>%s</b>\n\n%s", title, message));
397
gtk_dialog_run (GTK_DIALOG (dialog));
398
gtk_widget_destroy (dialog);
403
send_files (NstPlugin *plugin,
404
GtkWidget *contact_widget,
410
GHashTable *contact_props;
418
show_error(_("Unable to send file"),
419
_("There is no connection to gajim remote service."));
422
send_to = (gchar *) gtk_entry_get_text (GTK_ENTRY(contact_widget));
423
g_debug("[Gajim] sending to: %s", send_to);
424
if (strlen (send_to) != 0){
425
contact_props = g_hash_table_lookup (jid_table, send_to);
426
if(contact_props == NULL) {
431
value = g_hash_table_lookup(contact_props, "jid");
432
if(value == NULL || !G_VALUE_HOLDS_STRING(value)) {
433
g_warning("[Gajim] string expected (contact - jid)");
437
jid = g_value_dup_string((GValue *)value);
438
account = g_hash_table_lookup(contact_props, "account");
442
g_warning("[Gajim] missing recipient");
443
show_error(_("Sending file failed"),
444
_("Recipient is missing."));
449
for(file_iter = file_list; file_iter != NULL; file_iter = file_iter->next) {
450
char *uri = file_iter->data;
452
g_debug("[Gajim] file: %s", uri);
454
file_path = g_filename_from_uri(uri, NULL, &error);
456
g_warning("%d Unable to convert URI `%s' to absolute file path",
462
g_debug("[Gajim] file: %s", file_path);
464
dbus_g_proxy_call (proxy, "send_file", &error,
465
G_TYPE_STRING, file_path,
467
G_TYPE_STRING, account,
471
dbus_g_proxy_call (proxy, "send_file", &error,
472
G_TYPE_STRING, file_path,
480
if(error->domain != DBUS_GERROR || error->code != DBUS_GERROR_INVALID_ARGS) {
481
g_warning("[Gajim] sending file %s to %s failed:", uri, send_to);
483
show_error(_("Sending file failed"), _("Unknown recipient."));
493
destroy (NstPlugin *plugin)
496
g_object_unref(proxy);
498
g_hash_table_destroy(jid_table);
503
NstPluginInfo plugin_info = {
506
N_("Instant Message (Gajim)"),
516
NST_INIT_PLUGIN (plugin_info)