Hi everyone; as part of the Project Ridley we are trying to get rid of libgnomeui. One of the missing classes left to mark as deprecated is GnomeApp (and its sisters: GnomeAppBar and GnomeAppHelper).
GnomeApp is a simple GtkWindow sub-class, which makes its usage too limited for anything more than a simple, single-window application; also, with the inclusion of GtkUIManager and the future inclusion of GtkBuilder in GTK+, having just a boilerplate code for menus, status bar and tool bar is far less useful than it was before. Taking example from OS X API and from KDE API, GTK+ should have a base, abstract class for application developers to implement; this class should hide away the recent files operations, the desktop-wide events, the session management and the menu/toolbar building objects - while at the same time offering the developer a way to override the default behaviour. Having a base application class also allows us to offer a base class for single instance applications. * API Overview ============== The base cass is GtkApplication - an abstract G_TYPE_OBJECT with a bunch of methods to be overridden: struct _GtkApplicationClass { GObjectClass parent_class; ... We have a document-based API using these five vfuncs: ... gchar * (*new_document) (GtkApplication *application); gboolean (*save_document) (GtkApplication *application, const gchar *document_name, const gchar *document_uri, gboolean save_backup, gboolean overwrite, GError **error); gboolean (*open_document) (GtkApplication *application, const gchar *document_uri, gboolean read_only, GError **error); gboolean (*close_document) (GtkApplication *application, const gchar *document_name, GError **error); GSList * (*list_documents) (GtkApplication *application); ... The vfunc signatures should be self-explanatory. Each document is addressed by a unique id, using a string; newly created documents might have a "document-<timestamp>" id string, or a "document-<monotonic_counter>" id string; opened documents might use the MD5 hash of the document URI. Documents have an unique id because there can be multiple views of the same document and we need to keep a list of documents as well as windows (and windows for documents) of the GtkApplication. Subclasses of GtkApplication *must* override the new_document, save_document and open_document vfuncs; close_document and list_document can offer a default implementation (close_document calls save_document and if successful will remove the document id from the list of known documents, and list_documents returns the list of known document ids). The new_document, save_document and open_document vfuncs may chain up to the parent's class; for instance, open_document default closure will store the document's URI inside the recently used documents list using the default settings - unless you want to override that yourself and *not* chain up to the parent method in your subclass. +++ Each GtkApplication should declare which MIME types it supports: void (*set_mime_types) (GtkApplication *application, const gchar * const mime_types[], gint n_mime_types); GSList *(*get_mime_types) (GtkApplication *application); Since the supported MIME types might change depending on the state of the application at run-time (think of plug-ins) the application implementation might override one or both these vfuncs; instead of using string literals for MIME types maybe we should use something similar to GdkTarget, to know whether the MIME type is supported when saving, when opening or both, like this: typedef enum { GDK_MIME_CAN_OPEN, GDK_MIME_CAN_SAVE } GdkSupportedMimeAction; struct _GtkSupportedMime { const gchar *mime_type; guint id; GdkSupportedMimeAction action; }; ... static const GdkSupportedMime types[] = { { "text/plain", 0, GDK_MIME_CAN_OPEN | GDK_MIME_CAN_SAVE }, { "application/pdf", 0, GDK_MIME_CAN_OPEN }, }; static const gint n_types = G_N_ELEMENTS (types); This might be overkill though. +++ The menus and toolbars are handled by this vfunc: ... GtkUIManager *(*create_ui_manager) (GtkApplication *application, GError **error); ... GtkUIManager does not support the generation of a copy of the widgets to allow the usage of a single GtkUIManager instance with multiple windows; we might as well add this feature, but even then an application might decide to use different menus/toolbars depending on the state of the document, so it makes sense to have the ability to override the GtkUIManager instance creation. The default implementation tries to do the right thing anyway: you can set the UI definition XML using the GtkApplication API and let it create the GtkUIManager instance for you. +++ Now we have the window-related vfuncs: ... void (*add_window) (GtkApplication *application, const gchar *document_name, GtkWindow *window); void (*remove_window) (GtkApplication *application, const gchar *document_name, GtkWindow *window); GSList * (*list_windows) (GtkApplication *application, const gchar *document_name); ... Each window is bound to the document id; these vfuncs can be overridden in case you want to control some data depending on the lifetime of the window, but the default implementation (just add/remove/get the internal list of windows) should just work for most of the cases. * Further Improvements ============== - GtkApplication API can be used to access the GtkSession object, as soon as one is implemented; also it can be used to access the desktop abstraction API (screensaver state, network state, power state), once we have one. - Single instance application can be implemented using a GtkApplication subclass called GtkUniqueApplication, which offers a wrapper around a GdkUniqueApplication class whose implementation depends on the GTK+ target backend (Xlibs/D-Bus on x11, named pipes on win32, Un*x sockets on quartz and direct-fb). I've already done a Xlibs backend for the GtkUnique stand-alone library and merging the code with GTK+ would remove one library developers need to link to. - Once GtkBuilder hits HEAD we could do add a vfunc for it similar to the GtkUIManager vfunc. * Relevant Material =================== I started a page on the wiki[1] about the application class; there's also the Project Ridley page[2], the LibgnomeMustDie[3] page and a bug open about this issue[4]. I'd like to hear from developers using an "application" abstraction in their code (like Gedit, Evince and Epiphany) what they think about this API and what they think an application API should provide for their needs. For instance, this API is designed for document-based applications; non document-based application might have other needs and I'd like to know whether they can be abstracted into a general-purpose class or not. +++ [1] http://live.gnome.org/GTK%2B/ApplicationClass [2] http://live.gnome.org/ProjectRidley [3] http://live.gnome.org/LibgnomeMustDie [3] http://bugzilla.gnome.org/show_bug.cgi?id=127958 Ciao, Emmanuele. -- Emmanuele Bassi, E: [EMAIL PROTECTED] W: http://www.emmanuelebassi.net B: http://log.emmanuelebassi.net _______________________________________________ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list