From 3291a47e988c8074aa1d7dfa54a98f7ab8930175 Mon Sep 17 00:00:00 2001 From: Benedikt Meurer <benny@xfce.org> Date: Fri, 24 Mar 2006 14:46:35 +0000 Subject: [PATCH] 2006-03-24 Benedikt Meurer <benny@xfce.org> * plugins/thunar-sbr/thunar-sbr-case-renamer.h, plugins/thunar-sbr/thunar-sbr-insert-renamer.h, plugins/thunar-sbr/thunar-sbr-remove-renamer.h, plugins/thunar-sbr/thunar-sbr-replace-renamer.h: Fix typos. * docs/reference/thunarx/tmpl/thunarx-file-info.sgml, thunarx/thunarx-file-info.c: Register the "changed" and "renamed" signals right after the type is registered. This way gtk-doc will properly display the signals (gtk-doc doesn't invoke base_init() for interfaces). Bug #1418. * docs/reference/thunarx/tmpl/thunarx-property-page-provider.sgml, docs/reference/thunarx/tmpl/thunarx-property-page.sgml, thunarx/thunarx-property-page-provider.c: Properly document ThunarxPropertyPage and ThunarxPropertyPageProvider. Bug #1456. (Old svn revision: 20531) --- ChangeLog | 16 ++ .../thunarx/tmpl/thunarx-file-info.sgml | 14 + .../tmpl/thunarx-property-page-provider.sgml | 4 +- .../thunarx/tmpl/thunarx-property-page.sgml | 246 +++++++++++++++++- plugins/thunar-sbr/thunar-sbr-case-renamer.h | 2 +- .../thunar-sbr/thunar-sbr-insert-renamer.h | 2 +- .../thunar-sbr/thunar-sbr-remove-renamer.h | 2 +- .../thunar-sbr/thunar-sbr-replace-renamer.h | 2 +- thunarx/thunarx-file-info.c | 31 +-- thunarx/thunarx-property-page-provider.c | 24 +- 10 files changed, 312 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index bca688358..c54ba74f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2006-03-24 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-sbr/thunar-sbr-case-renamer.h, + plugins/thunar-sbr/thunar-sbr-insert-renamer.h, + plugins/thunar-sbr/thunar-sbr-remove-renamer.h, + plugins/thunar-sbr/thunar-sbr-replace-renamer.h: Fix typos. + * docs/reference/thunarx/tmpl/thunarx-file-info.sgml, + thunarx/thunarx-file-info.c: Register the "changed" and "renamed" + signals right after the type is registered. This way gtk-doc will + properly display the signals (gtk-doc doesn't invoke base_init() for + interfaces). Bug #1418. + * docs/reference/thunarx/tmpl/thunarx-property-page-provider.sgml, + docs/reference/thunarx/tmpl/thunarx-property-page.sgml, + thunarx/thunarx-property-page-provider.c: Properly document + ThunarxPropertyPage and ThunarxPropertyPageProvider. Bug #1456. + 2006-03-24 Benedikt Meurer <benny@xfce.org> * thunar/thunar-renamer-progress.{c,h}: Add new helper method diff --git a/docs/reference/thunarx/tmpl/thunarx-file-info.sgml b/docs/reference/thunarx/tmpl/thunarx-file-info.sgml index c97bb77fb..e912baf8e 100644 --- a/docs/reference/thunarx/tmpl/thunarx-file-info.sgml +++ b/docs/reference/thunarx/tmpl/thunarx-file-info.sgml @@ -42,6 +42,20 @@ Stable </para> +<!-- ##### SIGNAL ThunarxFileInfo::changed ##### --> +<para> + +</para> + +@thunarxfileinfo: the object which received the signal. + +<!-- ##### SIGNAL ThunarxFileInfo::renamed ##### --> +<para> + +</para> + +@thunarxfileinfo: the object which received the signal. + <!-- ##### FUNCTION thunarx_file_info_get_name ##### --> <para> diff --git a/docs/reference/thunarx/tmpl/thunarx-property-page-provider.sgml b/docs/reference/thunarx/tmpl/thunarx-property-page-provider.sgml index 82efbf010..80c65139c 100644 --- a/docs/reference/thunarx/tmpl/thunarx-property-page-provider.sgml +++ b/docs/reference/thunarx/tmpl/thunarx-property-page-provider.sgml @@ -29,8 +29,8 @@ Stable <!-- ##### STRUCT ThunarxPropertyPageProviderIface ##### --> <para> - Interface with virtual methods implemented by extensions that provide - additional pages for the file properties dialog. + Interface with virtual methods implemented by extensions that provide + additional pages for the file properties dialog. </para> @get_pages: see thunarx_property_page_provider_get_pages(). diff --git a/docs/reference/thunarx/tmpl/thunarx-property-page.sgml b/docs/reference/thunarx/tmpl/thunarx-property-page.sgml index 932f077e7..3c11f0ff8 100644 --- a/docs/reference/thunarx/tmpl/thunarx-property-page.sgml +++ b/docs/reference/thunarx/tmpl/thunarx-property-page.sgml @@ -7,7 +7,251 @@ The base class for pages added to the properties dialog <!-- ##### SECTION Long_Description ##### --> <para> The class for pages that can be added to Thunar's file properties dialog - by extensions implementing the #ThunarxPropertyPageProvider interface. + by extensions implementing the #ThunarxPropertyPageProvider interface. The + pages returned by extensions from thunarx_property_page_provider_get_pages() + method are instances of this class or a derived class. Note that extensions + do not need to subclass #ThunarxPropertyPage, but may also instantiate it + directly and add widgets to it, but I strongly suggest to create a subclass + as it usually leads to better modularization and thereby better maintainability + in the code. +</para> + +<para> + To pick up the #TagPage example from the thunarx_property_page_provider_get_pages() + description again, you'd create a new class #TagPage, that inherits #ThunarxPropertyPage + (using the #THUNARX_DEFINE_TYPE macro), which provides several user interface elements + in the property, and defines atleast one property named <literal>"file"</literal>, which + is the #ThunarxFileInfo whose tags are displayed in the property page. For example, the + <filename>tag-page.h</filename> header file would look like this (this is really just + an example of the suggested way to implement property pages, you may of course choose + a different way): +</para> + +<informalexample><programlisting> +##ifndef __TAG_PAGE_H__ +##define __TAG_PAGE_H__ + +##include <thunarx/thunarx.h> + +G_BEGIN_DECLS; + +typedef struct _TagPageClass TagPageClass; +typedef struct _TagPage TagPage; + +#define TAG_TYPE_PAGE (tag_page_get_type ()) +#define TAG_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TAG_TYPE_PAGE, TagPage)) +#define TAG_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TAG_TYPE_PAGE, TagPageClass)) +#define TAG_IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TAG_TYPE_PAGE)) +#define TAG_IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TAG_TYPE_PAGE)) +#define TAG_PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TAG_TYPE_PAGE, TagPageClass)) + +/* these two functions are implemented automatically by the THUNARX_DEFINE_TYPE macro */ +GType tag_page_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; +void tag_page_register_type (ThunarxProviderPlugin *plugin) G_GNUC_INTERNAL; + +GtkWidget *tag_page_new (ThunarxFileInfo *file) G_GNUC_INTERNAL G_GNUC_MALLOC; + +ThunarxFileInfo *tag_page_get_file (TagPage *tag_page) G_GNUC_INTERNAL; +void tag_page_set_file (TagPage *tag_page, + ThunarxFileInfo *file) G_GNUC_INTERNAL; + +G_END_DECLS; + +##endif /* !__TAG_PAGE_H__ */ +</programlisting></informalexample> + +<para> + And the <filename>tag-page.c</filename> source file could look like this: +</para> + +<informalexample><programlisting> +##include "tag-page.h" + +/* Property identifiers */ +enum +{ + PROP_0, + PROP_FILE, +}; + +static void tag_page_class_init (TagPageClass *klass); +static void tag_page_init (TagPage *tag_page); +static void tag_page_finalize (GObject *object); +static void tag_page_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void tag_page_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void tag_page_file_changed (ThunarxFileInfo *file, + TagPage *tag_page); + +struct _TagPageClass +{ + ThunarxPropertyPageClass __parent__; +}; + +struct _TagPage +{ + ThunarxPropertyPage __parent__; + ThunarxFileInfo *file; + + /* your widgets... */ +}; + +/* implements the tag_page_get_type() and tag_page_register_type() functions */ +THUNARX_DEFINE_TYPE (TagPage, tag_page, THUNARX_TYPE_PROPERTY_PAGE); + +static void +tag_page_class_init (TagPageClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = tag_page_finalize; + gobject_class->get_property = tag_page_get_property; + gobject_class->set_property = tag_page_set_property; + + /** + * TagPage:file: + * + * The #ThunarxFileInfo displayed by this #TagPage. + **/ + g_object_class_install_property (gobject_class, + PROP_FILE, + g_param_spec_object ("file", "file", "file, + THUNARX_TYPE_FILE_INFO, + G_PARAM_READWRITE)); +} + +static void +tag_page_init (TagPage *tag_page) +{ + GtkWidget *table; + + /* you can of course also use a GtkVBox here, or whatever */ + table = gtk_table_new (2, 2, FALSE); + gtk_container_add (GTK_CONTAINER (tag_page), table); + gtk_widget_show (table); + + /* add your widgets to the table... */ +} + +static void +tag_page_finalize (GObject *object) +{ + TagPage *tag_page = TAG_PAGE (object); + + /* disconnect from the file */ + tag_page_set_file (tag_page, NULL); + + /* release any additional resources... */ + + (*G_OBJECT_CLASS (tag_page_parent_class)->finalize) (object); +} + +static void +tag_page_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + TagPage *tag_page = TAG_PAGE (object); + + switch (prop_id) + { + case PROP_FILE: + g_value_set_object (value, tag_page_get_file (tag_page)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +tag_page_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + TagPage *tag_page = TAG_PAGE (object); + + switch (prop_id) + { + case PROP_FILE: + tag_page_set_file (tag_page, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +tag_page_file_changed (ThunarxFileInfo *file, + TagPage *tag_page) +{ + /* update your user interface elements in the tag_page + * to display the new state of the file... + */ +} + +GtkWidget* +tag_page_new (ThunarxFileInfo *file) +{ + return g_object_new (TAG_TYPE_PAGE, "file", file, NULL); +} + +ThunarxFileInfo* +tag_page_get_file (TagPage *tag_page) +{ + g_return_val_if_fail (TAG_IS_PAGE (tag_page), NULL); + return tag_page->file; +} + +void +tag_page_set_file (TagPage *tag_page, + ThunarxFileInfo *file) +{ + g_return_if_fail (TAG_IS_PAGE (tag_page)); + g_return_if_fail (file == NULL || THUNARX_IS_FILE_INFO (file)); + + if (tag_page->file != NULL) + { + g_signal_handlers_disconnect_by_func (tag_page->file, tag_page_file_changed, tag_page); + g_object_unref (G_OBJECT (tag_page->file)); + } + + tag_page->file = file; + + if (file != NULL) + { + g_object_ref (file); + tag_page_file_changed (file, tag_page); + g_signal_connect (file, "changed", G_CALLBACK (tag_page_file_changed), tag_page); + } + + g_object_notify (G_OBJECT (tag_page), "file"); +} +</programlisting></informalexample> + +<para> + If this seems to be too complicated to you, just don't follow the suggestion. But keep in mind, that + while the above solution is a little longer than a less structured solution, it yields great flexbility + and maintainability. For example the #TagPage class described above, once filled with user interface + elements, may be used for a standalone MP3-Tag editor out of the box (i.e. as an action returned from + the thunarx_renamer_get_actions() method). +</para> + +<para> + What is important to remember is that you should connect to the <literal>"changed"</literal> signal + of the #ThunarxFileInfo<!---->s you are displaying, and update the user interface whenever the file + changes. </para> <!-- ##### SECTION See_Also ##### --> diff --git a/plugins/thunar-sbr/thunar-sbr-case-renamer.h b/plugins/thunar-sbr/thunar-sbr-case-renamer.h index f1939bf0d..700497145 100644 --- a/plugins/thunar-sbr/thunar-sbr-case-renamer.h +++ b/plugins/thunar-sbr/thunar-sbr-case-renamer.h @@ -38,7 +38,7 @@ typedef struct _ThunarSbrCaseRenamer ThunarSbrCaseRenamer; GType thunar_sbr_case_renamer_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; void thunar_sbr_case_renamer_register_type (ThunarxProviderPlugin *plugin) G_GNUC_INTERNAL; -ThunarSbrCaseRenamer *thunar_sbr_case_renamer_new (void) G_GNUC_CONST G_GNUC_INTERNAL G_GNUC_MALLOC; +ThunarSbrCaseRenamer *thunar_sbr_case_renamer_new (void) G_GNUC_INTERNAL G_GNUC_MALLOC; ThunarSbrCaseRenamerMode thunar_sbr_case_renamer_get_mode (ThunarSbrCaseRenamer *case_renamer) G_GNUC_INTERNAL; void thunar_sbr_case_renamer_set_mode (ThunarSbrCaseRenamer *case_renamer, diff --git a/plugins/thunar-sbr/thunar-sbr-insert-renamer.h b/plugins/thunar-sbr/thunar-sbr-insert-renamer.h index 473d602e6..b55030ca8 100644 --- a/plugins/thunar-sbr/thunar-sbr-insert-renamer.h +++ b/plugins/thunar-sbr/thunar-sbr-insert-renamer.h @@ -38,7 +38,7 @@ typedef struct _ThunarSbrInsertRenamer ThunarSbrInsertRenamer; GType thunar_sbr_insert_renamer_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; void thunar_sbr_insert_renamer_register_type (ThunarxProviderPlugin *plugin) G_GNUC_INTERNAL; -ThunarSbrInsertRenamer *thunar_sbr_insert_renamer_new (void) G_GNUC_CONST G_GNUC_INTERNAL G_GNUC_MALLOC; +ThunarSbrInsertRenamer *thunar_sbr_insert_renamer_new (void) G_GNUC_INTERNAL G_GNUC_MALLOC; ThunarSbrInsertMode thunar_sbr_insert_renamer_get_mode (ThunarSbrInsertRenamer *insert_renamer) G_GNUC_INTERNAL; void thunar_sbr_insert_renamer_set_mode (ThunarSbrInsertRenamer *insert_renamer, diff --git a/plugins/thunar-sbr/thunar-sbr-remove-renamer.h b/plugins/thunar-sbr/thunar-sbr-remove-renamer.h index 59ce722c1..2aa56e53f 100644 --- a/plugins/thunar-sbr/thunar-sbr-remove-renamer.h +++ b/plugins/thunar-sbr/thunar-sbr-remove-renamer.h @@ -38,7 +38,7 @@ typedef struct _ThunarSbrRemoveRenamer ThunarSbrRemoveRenamer; GType thunar_sbr_remove_renamer_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; void thunar_sbr_remove_renamer_register_type (ThunarxProviderPlugin *plugin) G_GNUC_INTERNAL; -ThunarSbrRemoveRenamer *thunar_sbr_remove_renamer_new (void) G_GNUC_CONST G_GNUC_INTERNAL G_GNUC_MALLOC; +ThunarSbrRemoveRenamer *thunar_sbr_remove_renamer_new (void) G_GNUC_INTERNAL G_GNUC_MALLOC; guint thunar_sbr_remove_renamer_get_end_offset (ThunarSbrRemoveRenamer *remove_renamer) G_GNUC_INTERNAL; void thunar_sbr_remove_renamer_set_end_offset (ThunarSbrRemoveRenamer *remove_renamer, diff --git a/plugins/thunar-sbr/thunar-sbr-replace-renamer.h b/plugins/thunar-sbr/thunar-sbr-replace-renamer.h index c01f7bd21..ed0d4f005 100644 --- a/plugins/thunar-sbr/thunar-sbr-replace-renamer.h +++ b/plugins/thunar-sbr/thunar-sbr-replace-renamer.h @@ -38,7 +38,7 @@ typedef struct _ThunarSbrReplaceRenamer ThunarSbrReplaceRenamer; GType thunar_sbr_replace_renamer_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; void thunar_sbr_replace_renamer_register_type (ThunarxProviderPlugin *plugin) G_GNUC_INTERNAL; -ThunarSbrReplaceRenamer *thunar_sbr_replace_renamer_new (void) G_GNUC_CONST G_GNUC_INTERNAL G_GNUC_MALLOC; +ThunarSbrReplaceRenamer *thunar_sbr_replace_renamer_new (void) G_GNUC_INTERNAL G_GNUC_MALLOC; gboolean thunar_sbr_replace_renamer_get_case_sensitive (ThunarSbrReplaceRenamer *replace_renamer) G_GNUC_INTERNAL; void thunar_sbr_replace_renamer_set_case_sensitive (ThunarSbrReplaceRenamer *replace_renamer, diff --git a/thunarx/thunarx-file-info.c b/thunarx/thunarx-file-info.c index 5c555797f..d4340f4f9 100644 --- a/thunarx/thunarx-file-info.c +++ b/thunarx/thunarx-file-info.c @@ -38,10 +38,6 @@ enum -static void thunarx_file_info_base_init (gpointer klass); - - - static guint file_info_signals[LAST_SIGNAL]; @@ -56,7 +52,7 @@ thunarx_file_info_get_type (void) static const GTypeInfo info = { sizeof (ThunarxFileInfoIface), - (GBaseInitFunc) thunarx_file_info_base_init, + NULL, NULL, NULL, NULL, @@ -67,22 +63,12 @@ thunarx_file_info_get_type (void) NULL, }; + /* register the interface type */ type = g_type_register_static (G_TYPE_INTERFACE, I_("ThunarxFileInfo"), &info, 0); - g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); - } - - return type; -} + /* implementations must inherit GObject */ + g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); - -static void -thunarx_file_info_base_init (gpointer klass) -{ - static gboolean initialized = FALSE; - - if (G_UNLIKELY (!initialized)) - { /** * ThunarxFileInfo::changed: * @file_info : a #ThunarxFileInfo. @@ -96,7 +82,7 @@ thunarx_file_info_base_init (gpointer klass) **/ file_info_signals[CHANGED] = g_signal_new (I_("changed"), - G_TYPE_FROM_CLASS (klass), + type, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (ThunarxFileInfoIface, changed), NULL, NULL, @@ -116,16 +102,15 @@ thunarx_file_info_base_init (gpointer klass) **/ file_info_signals[RENAMED] = g_signal_new (I_("renamed"), - G_TYPE_FROM_CLASS (klass), + type, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (ThunarxFileInfoIface, renamed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - /* yep, we're initialized now */ - initialized = TRUE; } + + return type; } diff --git a/thunarx/thunarx-property-page-provider.c b/thunarx/thunarx-property-page-provider.c index d45f3caf8..0cb9fd87d 100644 --- a/thunarx/thunarx-property-page-provider.c +++ b/thunarx/thunarx-property-page-provider.c @@ -1,6 +1,6 @@ /* $Id$ */ /*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -66,6 +66,28 @@ thunarx_property_page_provider_get_type (void) * * Returns the list of #ThunarxPropertyPage<!---->s that @provider has to offer for @files. * + * Extensions that implement this interface, must first check whether they support all the + * #ThunarxFileInfo<!---->s in the list of @files. Most extensions will probably only support + * #ThunarxPropertyPage<!---->s for exactly one file of a certain type. For example an MP3-Tag + * editor property page will most probably support only a single audio file, and so the method + * would be implemented like this + * <informalexample><programlisting> + * GList* + * tag_provider_get_pages (ThunarxPropertyPageProvider *property_page_provider, + * GList *files) + * { + * if (g_list_length (files) != 1) + * return NULL; + * else if (!thunarx_file_info_has_mime_type (files->data, "audio/mp3")) + * return NULL; + * else + * return g_list_append (NULL, tag_page_new (files->data)); + * } + * </programlisting></informalexample> + * where tag_page_new() allocates a new #TagPage instance for a #ThunarxFileInfo object + * passed to it. See the description of the #ThunarxPropertyPage class for additional + * information about the #TagPage example class. + * * As a special note, this method automatically takes a reference on the * @provider for every #ThunarxPropertyPage object returned from the real implementation * of this method in @provider. This is to make sure that the extension stays -- GitLab