2012-03-12 9 views
10

Sto provando a creare un'estensione Nautilus in C, ma ci sono solo esempi di Python e aiuta.Come creare estensioni Nautilus C

Quasi nessuna documentazione e letteralmente nessun esempio, ma solo alcune estensioni complete che sono lunghe e difficili da comprendere per un principiante.

Ho bisogno solo di un semplice codice di esempio che crei una nuova colonna nella vista elenco di Nautilus. Come scrivere e compilarlo.

Il codice che ho provato è:

#include <libnautilus-extension/nautilus-column-provider.h> 

typedef struct _FooExtension FooExtension; 
typedef struct _FooExtensionClass FooExtensionClass; 

struct _FooExtension 
{ 
    GObject parent_slot; 
}; 

struct _FooExtensionClass 
{ 
    GObjectClass parent_slot; 
}; 

static void foo_extension_class_init (FooExtensionClass *class); 
static void foo_extension_instance_init (FooExtension  *img); 

static void foo_extension_class_init(FooExtensionClass *class) 
{ 
} 

static void foo_extension_instance_init(FooExtension *img) 
{ 
} 

static GType provider_types[1]; 

static GType foo_extension_type; 

static void foo_extension_register_type(GTypeModule *module) 
{ 
    static const GTypeInfo info = { 
       sizeof(FooExtensionClass), 
       (GBaseInitFunc) NULL, 
       (GBaseFinalizeFunc) NULL, 
       (GClassInitFunc) foo_extension_class_init, 
       NULL, 
       NULL, 
       sizeof (FooExtension), 
       0, 
       (GInstanceInitFunc) foo_extension_instance_init, 
       }; 
    foo_extension_type = g_type_module_register_type(module, 
           G_TYPE_OBJECT, 
           "FooExtension", 
           &info, 0); 
     /* ... add interfaces ... */ 
} 

GType foo_extension_get_type(void) 
{ 
    return foo_extension_type; 
} 

static GList *foo_extension_get_columns(NautilusColumnProvider *provider) 
{ 
    NautilusColumn *column; 
    GList *ret; 
    column = nautilus_column_new("FooExtension::foo_data_column", "FooExtension::foo_data", "Foo Data", "Foo Description"); 
/*     _("Foo Data"), 
         _("Information from the Foo Extension"));*/ 
    ret = g_list_append(NULL, column); 
    return ret; 
} 

void nautilus_module_initialize (GTypeModule *module) 
{ 
    foo_extension_register_type(module); 
    provider_types[0] = foo_extension_get_type(); 
} 

void nautilus_module_shutdown(void) 
{ 
    /* Any module-specific shutdown */ 
} 

void nautilus_module_list_types (const GType **types, int *num_types) 
{ 
    *types = provider_types; 
    *num_types = G_N_ELEMENTS (provider_types); 
} 

e ho costruito con:

gcc-c foo_extension.c -o foo_extension.o -fPIC $(pkg-config libnautilus-extension --libs --cflags) 
gcc -shared foo_extension.o -o foo_extension.so $(pkg-config libnautilus-extension --libs --cflags) 

e ho copiato in /usr/lib/nautilus/extensions-2.0/, poi ho provato nautilus -q ma non è così lavoro.

+0

http://pastebin.com/gyCU2sti <- Questo è il codice. L'ho creato con: gcc-c foo_extension.c -o foo_extension.o -fPIC $ (pkg-config libnautilus-extension --libs --cflags) gcc -shared foo_extension.o -o foo_extension.so $ (pkg -config libnautilus-extension --libs --cflags) e lo ha inserito in "/usr/lib/nautilus/extensions-2.0/" quindi "nautilus -q" e non ha funzionato ... –

risposta

8

È inoltre possibile recuperare la documentazione rivolta in Nautilus Extension's wiki da the copy in archive.org. La copia in archive.org ha esempi in C.

MODIFICA: Ho aggiunto un esempio operativo completo, nonché una spiegazione delle parti mancanti nel codice.

non trovi due cose:

  1. Aggiungere le interfacce. Per il provider di colonne sarebbe foo_extension_column_provider_iface_init e sarà necessario associare il collegamento alle interfacce previste con la propria implementazione. In questo caso specifico get_columns.
  2. Con il precedente, si otterrebbe solo una colonna ma con valore sconosciuto per ogni file. Pertanto, è necessario utilizzare anche lo InfoProvider . In particolare, l'interfaccia update_file_info. In questa interfaccia è possibile associare l'attributo della colonna a ciascun file tramite nautilus_file_info_add_string_attribute.

Di seguito è riportato un esempio funzionante. Attenzione NautilusFileInfoProvider fa parte del sistema IO asincrono di Nautilus. Quindi, se le operazioni sono lente, bloccherai Nautilus. Nell'esempio seguente ho appena impostato una stringa fissa per file ("Foo"). Tuttavia, se è necessario raccogliere altre informazioni, è necessario implementare anche gli argomenti update_complete e handle e l'interfaccia cancel_update. Controllare il documentation whose copy is available in archive.org

#include <libnautilus-extension/nautilus-column-provider.h> 
#include <libnautilus-extension/nautilus-info-provider.h> 

typedef struct _FooExtension FooExtension; 
typedef struct _FooExtensionClass FooExtensionClass; 

typedef struct { 
    GClosure *update_complete; 
    NautilusInfoProvider *provider; 
    NautilusFileInfo *file; 
    int operation_handle; 
    gboolean cancelled; 
} UpdateHandle; 

struct _FooExtension 
{ 
    GObject parent_slot; 
}; 

struct _FooExtensionClass 
{ 
    GObjectClass parent_slot; 
}; 

static void foo_extension_class_init (FooExtensionClass *class); 
static void foo_extension_instance_init (FooExtension  *img); 
static GList *foo_extension_get_columns (NautilusColumnProvider *provider); 
static NautilusOperationResult foo_extension_update_file_info (
             NautilusInfoProvider *provider, 
             NautilusFileInfo *file, 
             GClosure *update_complete, 
             NautilusOperationHandle **handle); 

/* Interfaces */ 
static void 
foo_extension_column_provider_iface_init (NautilusColumnProviderIface *iface) { 
    iface->get_columns = foo_extension_get_columns; 
    return; 
} 

static void 
foo_extension_info_provider_iface_init (NautilusInfoProviderIface *iface) { 
    iface->update_file_info = foo_extension_update_file_info; 
    return; 
} 

/* Extension */ 
static void foo_extension_class_init(FooExtensionClass *class) 
{ 
} 

static void foo_extension_instance_init(FooExtension *img) 
{ 
} 

static GType provider_types[1]; 

static GType foo_extension_type; 

static void foo_extension_register_type(GTypeModule *module) 
{ 
    static const GTypeInfo info = { 
       sizeof(FooExtensionClass), 
       (GBaseInitFunc) NULL, 
       (GBaseFinalizeFunc) NULL, 
       (GClassInitFunc) foo_extension_class_init, 
       NULL, 
       NULL, 
       sizeof (FooExtension), 
       0, 
       (GInstanceInitFunc) foo_extension_instance_init, 
       }; 

    static const GInterfaceInfo column_provider_iface_info = { 
     (GInterfaceInitFunc) foo_extension_column_provider_iface_init, 
     NULL, 
     NULL 
    }; 

    static const GInterfaceInfo info_provider_iface_info = { 
     (GInterfaceInitFunc) foo_extension_info_provider_iface_init, 
     NULL, 
     NULL 
    }; 

    foo_extension_type = g_type_module_register_type(module, 
           G_TYPE_OBJECT, 
           "FooExtension", 
           &info, 0); 

    /* ... add interfaces ... */ 
    g_type_module_add_interface (module, 
           foo_extension_type, 
           NAUTILUS_TYPE_COLUMN_PROVIDER, 
           &column_provider_iface_info); 

    g_type_module_add_interface (module, 
           foo_extension_type, 
           NAUTILUS_TYPE_INFO_PROVIDER, 
           &info_provider_iface_info); 
} 

GType foo_extension_get_type(void) 
{ 
    return foo_extension_type; 
} 

/* Column interfaces */ 
static GList *foo_extension_get_columns(NautilusColumnProvider *provider) 
{ 
    NautilusColumn *column; 
    GList *ret; 
    column = nautilus_column_new ("FooExtension::foo_data_column", 
            "FooExtension::foo_data", 
            "Foo Data", 
            "Foo Description"); 
    ret = g_list_append(NULL, column); 

    return ret; 
} 

/* Info interfaces */ 
static NautilusOperationResult 
foo_extension_update_file_info (NautilusInfoProvider *provider, 
           NautilusFileInfo *file, 
           GClosure *update_complete, 
           NautilusOperationHandle **handle) 
{ 
    char *data; 

    /* Check if we've previously cached the file info */ 
    data = g_object_get_data (G_OBJECT (file), "foo_extension_data"); 

    /* get and provide the information associated with the column. 
     If the operation is not fast enough, we should use the arguments 
     update_complete and handle for asyncrhnous operation. */ 
    if (!data) { 
     data = g_strdup ("Foo"); 
    } 

    nautilus_file_info_add_string_attribute (file, 
          "FooExtension::foo_data", 
          data); 
    return NAUTILUS_OPERATION_COMPLETE; 
} 

/* Extension initialization */ 
void nautilus_module_initialize (GTypeModule *module) 
{ 
    foo_extension_register_type(module); 
    provider_types[0] = foo_extension_get_type(); 
} 

void nautilus_module_shutdown(void) 
{ 
    /* Any module-specific shutdown */ 
} 

void nautilus_module_list_types (const GType **types, int *num_types) 
{ 
    *types = provider_types; 
    *num_types = G_N_ELEMENTS (provider_types); 
} 

compilarlo:

$ gcc -c foo-extension.c -o foo-extension.o -fPIC $(pkg-config libnautilus-extension --cflags) 
$ gcc -shared foo-extension.o -o foo-extension.so $(pkg-config libnautilus-extension --libs) 

Per testare l'estensione, in primo luogo è necessario fermare ogni istanza in esecuzione di nautilus e rilancio nautilus.Cioè:

$ nautilus -q 
$ nautilus 

Si noti che è senza l'opzione -q si è utilizzato, che è per smettere.

Se si desidera controllare se Nautilus sta caricando il proprio interno, è possibile utilizzare strace come segue:

$ strace -e trace=open nautilus 

e vedere cosa librerie e file Nautilus sta caricando/apertura.

Mentre si lavora nel proprio interno, invece di copiare il file di estensione in [libdir] /nautilus/extensions-3.0, è possibile creare un link simbolico nella directory di lavoro. Se si utilizza Nautilus 2.x, utilizzare invece [libdir] /nautilus/extensions-2,0.

+0

Il primo collegamento ha solo esempi di Python, il secondo è quello che ho usato per il mio codice ma senza successo. nautilus-sendto non è per ColumnView, solo per il menu contestuale, quindi anche se imparo leggendo il codice probabilmente sarà inutile. –

+0

Hai chiesto di scrivere e compilare. nautilus-sendto ha già impostato la toolchain, quindi puoi usarlo come modello per il tuo progetto. Inizia con qualcosa che sai funziona e puoi controllare. Una volta ottenuto il set, inizia ad applicare le modifiche. – gpoo

+0

Proverò a dare un'occhiata, ma probabilmente (anche se si tratta di un semplice plug-in) sarà troppo complesso avere un "feedback rapido" sulle estensioni e sarà inutile. Tempo fa ho già provato con un altro semplice progetto ed era troppo lungo per leggere e capire solo quello di cui avevo bisogno. –