Compare commits

...

30 Commits

Author SHA1 Message Date
Dan Winship
6b6d4bb140 reviewed by: Maciej Stachowiak <mjs@eazel.com>
* mime-type-capplet/libuuid/Makefile.am (NULL): Remove "SUBDIRS="
	line, which causes automake (1.4 at least) to generate a Makefile
	containing invalid sh script that bash (2.03.0(1) at least) won't
	parse.
2001-03-05 14:38:10 +00:00
Gene Z. Ragan
d423110faa reviewed by: Pavel Cisler <pavel@eazel.com>
2001-03-01  Gene Z. Ragan  <gzr@eazel.com>

	reviewed by: Pavel Cisler  <pavel@eazel.com>

	* mime-type-capplet/Makefile.am:
	The capplet .desktop should be copied to the Documents
	directory of the control-center .desktop files directory,
	not the root level.
2001-03-01 21:31:42 +00:00
Maciej Stachowiak
d97f432f33 another unreviewed change to fix tinderox
* mime-type-capplet/Makefile.am: Install .desktop file in both the
	places the .spec file expects it. Not sure if it was removed
	intentionally or not.
2001-02-27 16:01:15 +00:00
Maciej Stachowiak
9e7e24a991 unreviewed change to fix tinderox
* mime-type-capplet/Makefile.am: Add .desktop.in file to
	EXTRA_DIST.
2001-02-27 15:21:53 +00:00
Rebecca Schulman
9662231641 Fixed bugzilla.eazel.com bug 7010, that the file types capplet should use
2001-02-26  Rebecca Schulman  <rebecka@eazel.com>
	Fixed bugzilla.eazel.com bug 7010, that the
	file types capplet should use .desktop.in
	xml-i18-tools stuff.

	reviewed by: Maciej Stachowiak <mjs@eazel.com>

	* libgnomevfs/gnome-vfs-mime.c:
	* libgnomevfs/gnome-vfs-mime.h:
	Add a FIXME and a comment about functions
	in this file; no code changes

	* mime-type-capplet/.cvsignore:
	Add file-types-capplet.desktop
	* mime-type-capplet/file-types-capplet.desktop.in:
	Add this with new nifty xml-18n technology
	* mime-type-capplet/file-types-capplet.desktop:
	Remove the old file

	* mime-type-capplet/Makefile.am:
	Fix the build to build and install the new desktop file
	instead of the old one
2001-02-27 08:03:44 +00:00
jjranta
808b6df4de Updated Finnish translation by Pauli Virtanen. 2001-02-27 06:30:18 +00:00
Gene Z. Ragan
ba220ebdc3 reviewed by: Pavel Cisler <pavel@eazel.com>
2001-02-26  Gene Z. Ragan  <gzr@eazel.com>

	reviewed by: Pavel Cisler <pavel@eazel.com>

	Fixed bug 7039, User-entered application that matches
	built-in application can't be deleted

	Fixed bug 7040, User-entered application that matches built-in
	application doesn't go away when "all user changes" reverted

	Fixed bug 7064, New mime types added by user using the capplet
	do not appear when capplet is launched again.

	* mime-type-capplet/Makefile.am:
	Add libuuid to build.

	* mime-type-capplet/libuuid/Makefile.am:
	* mime-type-capplet/libuuid/clear.c: (uuid_clear):
	* mime-type-capplet/libuuid/compare.c: (uuid_compare):
	* mime-type-capplet/libuuid/copy.c: (uuid_copy):
	* mime-type-capplet/libuuid/gen_uuid.c: (get_random_bytes),
	(get_node_id), (get_clock), (uuid_generate_time),
	(uuid_generate_random), (uuid_generate):
	* mime-type-capplet/libuuid/gen_uuid_nt.c: (Nt5), (uuid_generate):
	* mime-type-capplet/libuuid/isnull.c: (uuid_is_null):
	* mime-type-capplet/libuuid/pack.c: (uuid_pack):
	* mime-type-capplet/libuuid/parse.c: (uuid_parse):
	* mime-type-capplet/libuuid/tst_uuid.c: (main):
	* mime-type-capplet/libuuid/unpack.c: (uuid_unpack):
	* mime-type-capplet/libuuid/unparse.c: (uuid_unparse):
	* mime-type-capplet/libuuid/uuid.h:
	* mime-type-capplet/libuuid/uuidP.h:
	* mime-type-capplet/libuuid/uuid_time.c: (uuid_time), (uuid_type),
	(uuid_variant), (variant_string), (main):
	Add libuuid to capplet and link statically. This is sort of sad. It would
	be nice if gnome had a uuid library, but at this time it does not.

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(nautilus_mime_type_capplet_show_new_mime_window):
	Call proper API to ensure that new mime type is added to the database.

	(add_or_update_application), (add_item_to_application_list),
	(run_edit_or_new_application_dialog):
	Create and assign a uuid to user defined application so that we never
	conflict with system defined types that use the application name
	as the application id.
2001-02-27 05:15:46 +00:00
John Sullivan
730e168518 reviewed by: Gene Ragan <gzr@eazel.com>
Fixed bug 6675 (Capplet allows user to add application for
	non-existent program (or not in path).

	* libgnomevfs/gnome-vfs-utils.h:
	* libgnomevfs/gnome-vfs-utils.c: (strdup_to), (is_executable_file),
	(executable_in_path), (get_executable_name_from_command_string),
	(gnome_vfs_is_executable_command_string): Moved code that tests
	for executable commands from -mime-handlers.c to here. Made
	gnome_vfs_is_executable_command_string public. Added FIXMEs
	and tweaked full-path handling code to work in more cases.

	* libgnomevfs/gnome-vfs-mime-handlers.c:
	(application_known_to_be_nonexistent): Replaced the code testing
	for executable commands with call to
	gnome_vfs_is_executable_command_string.

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(initialize_edit_applications_dialog): Added FIXME.
	(handle_invalid_application_input): New function, handles bad
	name or command string with explanatory error message.
	(run_edit_or_new_application_dialog): New function, guts of both
	show_ and edit_new_application_window, which formerly had nearly
	identical copy/pasted code. Now doesn't close dialog if input
	is bad and user clicks OK; other minor cleanup.
	(show_new_application_window), (show_edit_application_window):
	Each of these now calls run_edit_or_new_application_dialog.

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	(add_mime_clicked), (update_mime_list_action),
	(populate_mime_list): Added tests for missing icon files to
	avoid zillions of GTK-CRITICALs from gdk_pixbuf if you run
	the capplet without installing Nautilus firt (discovered during
	clean rebuild); fixed a couple of leaking strings.
2001-02-26 03:43:23 +00:00
Christian Rose
d5e862145a Added sv description. 2001-02-24 23:53:47 +00:00
John Sullivan
d8fabf0557 reviewed by: Gene Ragan <gzr@eazel.com>
Fixed bug 6524 (No default icons for MIME types)

	Fixed bug 6525 (capplet will only let you pick icons
	from a single directory)

	Fixed bug 6596 ("We need a good explanation here"
	isn't a good explanation)

	I didn't fix all the fundamental brokenness about Nautilus
	themes vs. the MIME database, but I fixed the most obvious
	problems and added some FIXMEs to help clarify some of the
	remaining issues. I also did a tiny fraction of the cleanup
	that could be done in this code. Users can now browse around
	to choose icons from anywhere, and they will all work in
	Nautilus (no change required in Nautilus).

	* mime-type-capplet/files-types-capplet.desktop:
	Replaced placeholder description string with Vera's.

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	Removed bogus but relatively harmless initial slashes
	from two DEFAULT_REGULAR_ICON and DEFAULT_ACTION_ICON.
	(really_change_icon): Handle full as well as relative
	filenames; update displayed info here instead of relying
	on the icon_entry widget doing it.
	(icon_chosen_callback): Renamed from gil_icon_selected_cb;
	hide the dialog here so we can eliminate the almost-identical
	code in nautilus-mime-type-icon-entry.c that did that one
	extra thing.
	(change_icon_clicked_cb_real): use GNOME_OK instead of 0
	(change_icon_clicked): Update for name change.
	(is_full_path): Little bitty helper function that checks for
	initial slash, mainly separated for clarity.
	(capplet_get_icon_path): New function used to get a full icon
	path from a file name, icon name, relative path, or
	possibly non-existent full path.
	(nautilus_mime_type_capplet_update_info): Simplify logic,
	use capplet_get_icon_path.
	(add_mime_clicked), (update_mime_list_action),
	(populate_mime_list):
	Use capplet_get_icon_path; use generic
	executable icon for app instead of repeating MIME-type icon.
	(capplet_get_icon_pixbuf): Simplify logic; use capplet_get_icon_path;
	Add FIXME about future code cleanup

	* mime-type-capplet/nautilus-mime-type-icon-entry.h:
	* mime-type-capplet/nautilus-mime-type-icon-entry.c:
	(nautilus_mime_type_icon_entry_get_full_filename): Renamed from
	_get_filename for clarity
	(entry_activated): Made behavior match comment (act like OK
	button was hit)
	(icon_selected_cb): Removed this function; this was redundant with
	code in nautilus-mime-type-capplet.c.
	(gil_icon_selected_cb): Removed this function; it was redundant
	with a function in nautilus-mime-type-capplet.c except that this one
	hid the dialog and that one didn't (now that one does).
	(nautilus_mime_type_show_icon_selection): Remove commented-out
	line that implemented the Browse button that let the user choose
	from different directories; removed redundant signal handlers;
	added FIXME.
	(nautilus_mime_type_icon_entry_get_relative_filename): Simplify
	logic; made it return NULL instead of "" and a g_warning when
	it can't create a relative path from the full path.

	* libgnomevfs/gnome-vfs-utils.c: Added FIXME
2001-02-23 01:18:52 +00:00
Gene Z. Ragan
6981fe9144 reviewed by: John Sullivan <sullivan@eazel.com>
2001-02-22  Gene Z. Ragan  <gzr@eazel.com>

	reviewed by: John Sullivan <sullivan@eazel.com>

	Fixed bug 6568, Closing capplet right away warns
	about uncommitted changes

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	(init_mime_capplet):
	Use new interface that I added to control-center
	that informs the control center that changes are immediate.
	The control center now behaves properly.
2001-02-22 23:14:20 +00:00
Seth Nickell
b2ee2fa5bd reviewed by: Pavel Cisler <pavel@eazel.com>
2001-02-22  Seth Nickell  <seth@eazel.com>

	reviewed by: Pavel Cisler <pavel@eazel.com>

	* libgnomevfs/gnome-vfs-application-registry.c:
	(strip_trailing_whitespace):
	* libgnomevfs/gnome-vfs-uri.c: (split_toplevel_uri):
	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(nautilus_mime_type_capplet_show_new_mime_window):

	Add casts to is* functions as necessary when chars are
	used to fix Solaris warnings.
2001-02-22 11:41:42 +00:00
Gene Z. Ragan
388af8aa64 reviewed by: John Sullivan<sullivan@eazel.com>
2001-02-21  Gene Z. Ragan  <gzr@eazel.com>

	reviewed by: John Sullivan<sullivan@eazel.com>

	Fixed bug 6626, Applications deleted from the
	short list reappear (unchecked)

	The original intent of this dialog button was to allow the user to
	delete their custom added applications.  The logic has been
	added to handle this and update the control properly.
	There is a larger issue that if the user wants to delete system
	level applications, the current API makes it impossible to do
	so.

	* libgnomevfs/gnome-vfs-application-registry.c:
	* libgnomevfs/gnome-vfs-application-registry.h:
	(application_lookup_or_create), (application_lookup),
	(application_remove), (gnome_vfs_application_registry_init),
	(gnome_vfs_application_registry_clear),
	(gnome_vfs_application_registry_shutdown),
	(gnome_vfs_application_registry_sync),
	(gnome_vfs_application_registry_save_mime_application):
	Renamed a potentially confusing global variable.


	(gnome_vfs_application_is_user_owned_application):
	New function that returns a value indicating if this
	is a user owned or system owned application.

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(create_application_list_item),
	(populate_default_applications_list),
	(initialize_edit_applications_dialog),
	(show_new_application_window), (delete_selected_application),
	(add_or_update_application), (add_item_to_application_list):
	Determine if application data is user owned and act accordingly.

	(check_button_status):
	Remove delete button handling in certain cases and use new
	update_delete_button function instead.

	(update_delete_button):
	New function to that sensitizes the delete button
	based on user ownership of the selected application item.
2001-02-21 19:47:05 +00:00
Darin Adler
82c493b6fb reviewed by: Mike Fleming <mfleming@eazel.com>
* libgnomevfs/gnome-vfs-process.c: (sigchld_handler): Fix
	uninitialized variable problem (reported by danw I think).
	* libgnomevfs/gnome-vfs-utils.c:
	(gnome_vfs_get_local_path_from_uri): Simplify function and make it
	return NULL with # characters.

	* test/test-uri.c: (main): Update tests to match the change to
	gnome_vfs_get_local_path_from_uri.

	* libgnomevfs-pthread/gnome-vfs-job.c: Improve a variable name.

	* mime-type-capplet/.cvsignore: Ignore the executable under its
	new name, not its old name.
2001-02-21 02:23:04 +00:00
John Sullivan
e1c8837b0b Changed "Delete this MIME type..." to "Delete This MIME Type" because that
* mime-type-capplet/nautilus-mime-type-capplet.c:
	(init_mime_capplet): Changed "Delete this MIME type..."
	to "Delete This MIME Type" because that follows the
	capitalization rules, and because there's no dialog
	involved so the "..." is a lie.
2001-02-21 02:09:41 +00:00
John Sullivan
94fe6d69d0 reviewed by: Seth Nickell <seth@eazel.com>
Fixed various small capplet bugs while pondering the
	big scary icon-related ones, including:

	Fixed bug 4768 (hardcoded icon file name in
	nautilus-mime-type-capplet.c)

	Fixed bug 6636 (Text descenders clipped for selected item in mime list)

	Fixed bug 6641 (Icons clipped in mime list)

	Fixed bug 6647 ("Change Icon" dialog has silly title)

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(nautilus_mime_type_capplet_show_new_mime_window): Simplified
	widgetry, tweaked layout and wording to look halfway decent and
	be clear.

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	Added constants for icon height/width in list. Added FIXME for
	huge hunks of copy/pasted code.
	(init_mime_capplet): Removed two set_usize calls; replaced one
	with a gtk_misc_set_padding call so "Edit List" button isn't
	too cramped.
	(add_mime_clicked),
	(nautilus_mime_type_capplet_update_mime_list_icon_and_description):
	Use icon size constants instead of magic numbers.
	(update_mime_list_action), (populate_mime_list):
	 Use icon size constants; use
	 gnome_vfs_icon_path_from_filename to avoid hard-coded path.
	(mime_list_reset_row_height): New function, sets the row height
	based on font size and image height.
	(create_mime_list_and_scroller): Reset row height at the right time.

	* mime-type-capplet/nautilus-mime-type-icon-entry.c:
	(nautilus_mime_type_show_icon_selection): Set icon selection window
	title; add FIXME for (at long last discovered) code that prevents
	user from choosing icons in arbitrary directories.
2001-02-21 01:53:58 +00:00
Gene Z. Ragan
6d3177ec51 Fix bug 6384, Nautilus program chooser uses "nautilus-mime-type-capplet"
2001-02-20  Gene Z. Ragan  <gzr@eazel.com>

	Fix bug 6384, Nautilus program chooser uses
	"nautilus-mime-type-capplet" to launch capplet

	* mime-type-capplet/Makefile.am:
	* mime-type-capplet/files-types-capplet.desktop:
	* mime-type-capplet/nautilus-mime-type.desktop:
	Rename the capplet binary and change the name and
	contents of the .desktop file to reflect the new name.
2001-02-20 20:10:46 +00:00
Gene Z. Ragan
a5b9b55591 reviewed by: Mike Enger <engber@eazel.com>
2001-02-16  Gene Z. Ragan  <gzr@eazel.com>

	reviewed by: Mike Enger <engber@eazel.com>

	Fixed bug 6624, Selected mime type/description displayed
	below the list is incorrect after reverting to system defaults.

	Fixed bug 6644, List sorting after using "revert to system defaults"
	is inconsistent.

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	(revert_real_cb):
	Sort the list using current sort column and select the
	first item to force an update of the dialog contents.
	Also freeze and thaw list to avoid annoying flicker while
	list is being repopulated.
2001-02-16 20:46:02 +00:00
John Sullivan
059b37012d reviewed by: Gene Z. Ragan <gzr@eazel.com>
Fixed bug 6635 (in MIME capplet, descriptions can't be
	edited though they look editable)

	* libgnomevfs/gnome-vfs-mime-handlers.c:
	* libgnomevfs/gnome-vfs-mime-handlers.h:
	(gnome_vfs_mime_set_description): New function,
	just like existing _set_icon.

	* mime-type-capplet/nautilus-mime-type-capplet.h:
	* mime-type-capplet/nautilus-mime-type-capplet.c:
	(nautilus_mime_type_capplet_update_mime_list_icon_and_description):
	Changed name to add the _and_description part. It already handled
	the description properly but the name was misleading.
	(really_change_icon): Updated for name change.
	(update_description_from_input): New function, sets the description
	in database and UI (list) from what's in the field.
	(description_entry_changed): Set dirty flag.
	(description_entry_activate), (description_entry_lost_focus):
	If dirty flag set, update.
	(init_mime_capplet): Hook up text field signal handlers, make
	field editable, remove "No Description" case since putting status
	text in editable field is wrong.
	(nautilus_mime_type_capplet_update_info): Clear dirty flag
	when description is updated due to selection change.

	* mime-type-capplet/nautilus-mime-type-icon-entry.c:
	(icon_selected_cb): Updated for name change.
2001-02-16 19:15:15 +00:00
Gene Z. Ragan
b28b2644a1 reviewed by: John Sullivan <sullivan@eazel.com>
2001-02-16  Gene Z. Ragan  <gzr@eazel.com>

	reviewed by: John Sullivan <sullivan@eazel.com>

	Fixed bug 6648, Able to add mime type even if "mime type"
	and description fields are blank.

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(validate_text_and_update_button),
	(nautilus_mime_type_capplet_show_new_mime_window):
	Set sensitive state of OK button based on content of
	text entry item in dialog box.

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	(nautilus_mime_type_capplet_add_extension), (init_mime_capplet),
	(add_mime_clicked):
	Check for '\0' instead of ' ' to avoid empty strings
2001-02-16 19:03:10 +00:00
John Sullivan
fdd551dbad reviewed by: Gene Ragan <gzr@eazel.com>
Fixed some problems and cleaned up some code
	that I ran into while investigating bug 5777 (Nautilus
	does not pick up MIME preferences right away)

	* libgnomevfs/gnome-vfs-mime-handlers.c:
	(gnome_vfs_mime_get_short_list_applications):
	Prune user's short list additions of nonexistent
	applications (already pruned other lists); removed
	mysteriously incorrect FIXME; deployed
	gnome_vfs_mime_type_is_supertype() one more place.

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(insert_item), (create_application_list_item):
	New helper functions used for dialogs showing lists
	of applications, extracted and simplified from existing
	code.
	(populate_default_applications_list): Use helper functions
	instead of repeating all the code here.
	(initialize_edit_applications_dialog): Swapped order of two
	lines for clarity & slight efficiency gain.
	(add_item_to_application_list): Use helper functions instead
	of repeating all the code here; select newly-added item.
	(show_new_application_window): Removed two initialized but
	never used variables.
	(show_edit_applications_dialog), (show_edit_components_dialog),
	(nautilus_mime_type_capplet_show_new_mime_window),
	(nautilus_mime_type_capplet_show_change_extension_window),
	(nautilus_mime_type_capplet_show_new_extension_window),
	(show_new_application_window), (show_edit_application_window):
	Cleaned up all callers of gnome_dialog_run; some were not
	handling the close box properly; others were just using more
	lines of code than needed; none were using GNOME_OK for clarity.

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	(revert_mime_clicked): Improved some error message text a little.
2001-02-16 00:49:38 +00:00
Darin Adler
cf03cbeff9 Rolled change back out that John checked in by accident. 2001-02-15 20:06:36 +00:00
John Sullivan
36656755c3 reviewed by: Darin Adler <darin@eazel.com>
Fixed bug 6660 (list of all apps for text/xml
	doesn't include text/* handlers)

	* libgnomevfs/gnome-vfs-mime.h:
	* libgnomevfs/gnome-vfs-mime.c:
	(gnome_vfs_mime_type_is_supertype): New public function.
	(extract_prefix_add_suffix): Utility function used
	by _get_supertype_from_mime_type, moved from another file.
	(gnome_vfs_get_supertype_from_mime_type): New public
	function (formerly private in mime-handlers.c under
	the name "mime_type_from_supertype".

	* libgnomevfs/gnome-vfs-mime-handlers.c:
	(gnome_vfs_mime_get_default_component),
	(gnome_vfs_mime_get_short_list_applications),
	(gnome_vfs_mime_get_short_list_components),
	(gnome_vfs_mime_get_all_components),
	(gnome_vfs_mime_component_list_free):
	Update for renaming; remove mime_type_from_supertype.

	* libgnomevfs/gnome-vfs-application-registry.c:
	(gnome_vfs_application_registry_get_applications):
	Use new functions to fix completely broken code to
	get supertype's	list of apps.

	(add_application_to_mime_type_table),
	(remove_application_from_mime_type_table): Use
	new is_supertype function instead of using strstr.
2001-02-15 19:50:26 +00:00
Gene Z. Ragan
694815ad59 Fixed bug 6629, Default action icon disappears when switching from
2001-02-14  Gene Z. Ragan  <gzr@eazel.com>

	Fixed bug 6629, Default action icon disappears when switching
	from application->viewer->application

	Fixed bug 6630, Default action icon not drawn when changing
	the default application

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	(init_mime_capplet), (update_mime_list_action):
	Call handy utility function to get custom or default
	action icon based on mime tpye and type of action.

	(column_clicked):
	Remove some debugging cruft.
2001-02-15 02:09:16 +00:00
Gene Z. Ragan
ccfe3a4abf Fixed bug 6570, Initial tab order in "Add application" dialog is broken.
2001-02-14  Gene Z. Ragan  <gzr@eazel.com>

	Fixed bug 6570, Initial tab order in "Add application"
	dialog is broken.

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(nautilus_mime_type_capplet_show_new_mime_window),
	(add_extension_clicked),
	(nautilus_mime_type_capplet_show_new_extension_window),
	(show_new_application_window), (show_edit_application_window):
	Set focus to proper widget in all of these functions.
2001-02-14 08:15:45 +00:00
Gene Z. Ragan
cdae99d075 Fixed bug 6579, Clicking on a column for sorting performs descending sort
2001-02-13  Gene Z. Ragan  <gzr@eazel.com>

	Fixed bug 6579, Clicking on a column for sorting performs
	descending sort first.

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	(init_mime_capplet):
	Create a global array that tracks the initial first time click
	state of the columns.

	(column_clicked):
	Check click state of column and decide initial sort mode based
	on value.
2001-02-14 07:44:36 +00:00
Gene Z. Ragan
8deb8274bf Fixed bug 6577, New mime type isn't highlighted after creation.
2001-02-13  Gene Z. Ragan  <gzr@eazel.com>

	Fixed bug 6577, New mime type isn't highlighted after creation.

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	(find_row_for_mime_type):
	Return index of row if mime type is found in list
	or -1 if it is not.

	(init_mime_capplet):
	Call find_row_for_mime_type()

	(nautilus_mime_type_capplet_update_info), (add_mime_clicked):
	Sort, select and scroll to new mime type.
2001-02-14 04:27:20 +00:00
Gene Z. Ragan
62c1eec01b Fixed bug 6447, "Change file extensions" erases all extensions
2001-02-12  Gene Z. Ragan  <gzr@eazel.com>

	Fixed bug 6447, "Change file extensions" erases all extensions

	* mime-type-capplet/nautilus-mime-type-capplet.c:
	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.h:
	(nautilus_mime_type_capplet_show_change_extension_window):
	Add a variable to function that tells if returned list
	is to be used to replace existing extension mapping for
	mime type.

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(add_extension_clicked), (change_file_extensions_clicked):
	Do some sanity checking for empty or NULL new extensions
2001-02-13 00:53:05 +00:00
Gene Z. Ragan
c65cc26463 Fixed bug 6471, wrong text in "add extension" dialog
2001-02-12  Gene Z. Ragan  <gzr@eazel.com>

	Fixed bug 6471, wrong text in "add extension" dialog

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(nautilus_mime_type_capplet_show_new_extension_window):
	Update text using new language from Vera.
2001-02-13 00:26:23 +00:00
John Sullivan
85d7761573 reviewed by: Gene Z. Ragan <gzr@eazel.com> (under protest,
since Gene hates the use of "MIME")

	Changed all uses of "Mime" or "mime" in the UI to be
	"MIME". Also improved the wording for the "revert"
	dialog, though it still could use Verafication. Also,
	using "MIME" in the UI at all rather sucks. It would
	be nice if we could avoid this nerd terminology someday.

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(initialize_edit_applications_dialog),
	(initialize_edit_components_dialog),
	(nautilus_mime_type_capplet_show_new_mime_window):
	* mime-type-capplet/nautilus-mime-type-capplet.c:
	(init_mime_capplet), (revert_mime_clicked),
	(create_mime_list_and_scroller):
2001-02-12 19:04:45 +00:00
486 changed files with 1782 additions and 122384 deletions

View File

@@ -1,30 +0,0 @@
ABOUT-NLS
.new.ltmain.sh
Makefile
Makefile.in
aclocal.m4
config.cache
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
configure.scan
intl
libtool
ltconfig
ltmain.sh
missing
mkinstalldirs
COPYING
install-sh
stamp-h
stamp-h.in
version.h
intl
macros
INSTALL
control-center.spec
my_control_center_idl

View File

@@ -1 +0,0 @@
Jonathan Blandford <jrb@redhat.com>

1934
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +0,0 @@
Email: hovinen@ximian.com
Email: jacob@ximian.com

View File

@@ -1,8 +0,0 @@
SUBDIRS = intl po capplets root-manager new-control-center
EXTRA_DIST = control-center.spec.in
dist-hook: control-center.spec
cp control-center.spec $(distdir)

1
NEWS
View File

@@ -1 +0,0 @@
First split version of this package

8
README
View File

@@ -1,8 +0,0 @@
Control-Center
--------------
To install this package, you need to install (at minimum):
ORBit
gnome-libs
esd

View File

@@ -1,19 +0,0 @@
<todo>
<title>GNOME Control Center TODO list</title>
<section>
<title>Capplets</title>
<entry size="big" status="10%" target="1.4">
<title>Screensaver XML descriptions</title>
<description>
<p>
Create XML descriptions to allow dialog configuration of the various
screensavers that come with XScreensaver. See
capplets/new-screensaver-properties/screensavers/README for
documentaiton.
</p>
</description>
<contact>hovinen@helixcode.com</contact>
</entry>
</section> <!--Capplets-->
</todo>

View File

@@ -1,25 +0,0 @@
#undef ENABLE_NLS
#undef HAVE_CATGETS
#undef HAVE_DEVGTK
#undef HAVE_GETTEXT
#undef HAVE_LC_MESSAGES
#undef HAVE_STPCPY
#undef HAVE_LIBSM
#undef HAVE_PROGRAM_INVOCATION_SHORT_NAME
#undef HAVE_PROGRAM_INVOCATION_NAME
#undef PACKAGE
#undef VERSION
#undef HAVE_ESD
#undef HAVE_LIBESD
/* Define if there is no `u_int64_t' and `int64_t'. */
#undef u_int64_t
#undef int64_t
#undef HAVE_DEVGTK
#undef WITH_SYMBOL_UNDERSCORE
#undef HAVE_PUTENV
#undef HAVE_SETENV

View File

@@ -1,164 +0,0 @@
# Configure paths for ESD
# Manish Singh 98-9-30
# stolen back from Frank Belew
# stolen from Manish Singh
# Shamelessly stolen from Owen Taylor
dnl AM_PATH_ESD([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
dnl Test for ESD, and define ESD_CFLAGS and ESD_LIBS
dnl
AC_DEFUN(AM_PATH_ESD,
[dnl
dnl Get the cflags and libraries from the esd-config script
dnl
AC_ARG_WITH(esd-prefix,[ --with-esd-prefix=PFX Prefix where ESD is installed (optional)],
esd_prefix="$withval", esd_prefix="")
AC_ARG_WITH(esd-exec-prefix,[ --with-esd-exec-prefix=PFX Exec prefix where ESD is installed (optional)],
esd_exec_prefix="$withval", esd_exec_prefix="")
AC_ARG_ENABLE(esdtest, [ --disable-esdtest Do not try to compile and run a test ESD program],
, enable_esdtest=yes)
if test x$esd_exec_prefix != x ; then
esd_args="$esd_args --exec-prefix=$esd_exec_prefix"
if test x${ESD_CONFIG+set} != xset ; then
ESD_CONFIG=$esd_exec_prefix/bin/esd-config
fi
fi
if test x$esd_prefix != x ; then
esd_args="$esd_args --prefix=$esd_prefix"
if test x${ESD_CONFIG+set} != xset ; then
ESD_CONFIG=$esd_prefix/bin/esd-config
fi
fi
AC_PATH_PROG(ESD_CONFIG, esd-config, no)
min_esd_version=ifelse([$1], ,0.2.5,$1)
AC_MSG_CHECKING(for ESD - version >= $min_esd_version)
no_esd=""
if test "$ESD_CONFIG" = "no" ; then
no_esd=yes
else
ESD_CFLAGS=`$ESD_CONFIG $esdconf_args --cflags`
ESD_LIBS=`$ESD_CONFIG $esdconf_args --libs`
esd_major_version=`$ESD_CONFIG $esd_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
esd_minor_version=`$ESD_CONFIG $esd_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
esd_micro_version=`$ESD_CONFIG $esd_config_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
if test "x$enable_esdtest" = "xyes" ; then
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $ESD_CFLAGS"
LIBS="$LIBS $ESD_LIBS"
dnl
dnl Now check if the installed ESD is sufficiently new. (Also sanity
dnl checks the results of esd-config to some extent
dnl
rm -f conf.esdtest
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <esd.h>
char*
my_strdup (char *str)
{
char *new_str;
if (str)
{
new_str = malloc ((strlen (str) + 1) * sizeof(char));
strcpy (new_str, str);
}
else
new_str = NULL;
return new_str;
}
int main ()
{
int major, minor, micro;
char *tmp_version;
system ("touch conf.esdtest");
/* HP/UX 9 (%@#!) writes to sscanf strings */
tmp_version = my_strdup("$min_esd_version");
if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
printf("%s, bad version string\n", "$min_esd_version");
exit(1);
}
if (($esd_major_version > major) ||
(($esd_major_version == major) && ($esd_minor_version > minor)) ||
(($esd_major_version == major) && ($esd_minor_version == minor) && ($esd_micro_version >= micro)))
{
return 0;
}
else
{
printf("\n*** 'esd-config --version' returned %d.%d.%d, but the minimum version\n", $esd_major_version, $esd_minor_version, $esd_micro_version);
printf("*** of ESD required is %d.%d.%d. If esd-config is correct, then it is\n", major, minor, micro);
printf("*** best to upgrade to the required version.\n");
printf("*** If esd-config was wrong, set the environment variable ESD_CONFIG\n");
printf("*** to point to the correct copy of esd-config, and remove the file\n");
printf("*** config.cache before re-running configure\n");
return 1;
}
}
],, no_esd=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
if test "x$no_esd" = x ; then
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
AC_MSG_RESULT(no)
if test "$ESD_CONFIG" = "no" ; then
echo "*** The esd-config script installed by ESD could not be found"
echo "*** If ESD was installed in PREFIX, make sure PREFIX/bin is in"
echo "*** your path, or set the ESD_CONFIG environment variable to the"
echo "*** full path to esd-config."
else
if test -f conf.esdtest ; then
:
else
echo "*** Could not run ESD test program, checking why..."
CFLAGS="$CFLAGS $ESD_CFLAGS"
LIBS="$LIBS $ESD_LIBS"
AC_TRY_LINK([
#include <stdio.h>
#include <esd.h>
], [ return 0; ],
[ echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding ESD or finding the wrong"
echo "*** version of ESD. If it is not finding ESD, you'll need to set your"
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
echo "*** to the installed location Also, make sure you have run ldconfig if that"
echo "*** is required on your system"
echo "***"
echo "*** If you have an old version installed, it is best to remove it, although"
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
[ echo "*** The test program failed to compile or link. See the file config.log for the"
echo "*** exact error that occured. This usually means ESD was incorrectly installed"
echo "*** or that you have moved ESD since it was installed. In the latter case, you"
echo "*** may want to edit the esd-config script: $ESD_CONFIG" ])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
ESD_CFLAGS=""
ESD_LIBS=""
ifelse([$3], , :, [$3])
fi
AC_SUBST(ESD_CFLAGS)
AC_SUBST(ESD_LIBS)
rm -f conf.esdtest
])

View File

@@ -1,10 +0,0 @@
.deps
.libs
*.lo
*.la
Makefile
ximia-archiver
Makefile.in
ximian-config-manager
ximian_archiverConf.sh
ximian-archiver

View File

@@ -1,210 +0,0 @@
2001-01-25 Bradford Hovinen <hovinen@ximian.com>
* config-log.c (get_current_date): Use local time rather than
Greenwich Mean Time
* location.c (location_store_xml): Implement; copy from
location_store
(location_store): Free filename after use
* archive.c (archive_load): Free prefix only if not global
* location.c (location_rollback_all_to): Increment array
* util.c (parse_date): Normalize values
2001-01-24 Bradford Hovinen <hovinen@ximian.com>
* config-log.c (do_load): Disabled locking for now
* archiver-spec: Added fine-grained location management description
2001-01-15 Bradford Hovinen <hovinen@ximian.com>
* Makefile.am: Added rule for ximian_archiverConf.sh; add
installation target for Conf.sh
2001-01-13 Bradford Hovinen <hovinen@ximian.com>
* Makefile.am: Replaced occurrences of helix with ximian
Removed references to ximian_config_manager
2000-12-22 Bradford Hovinen <hovinen@helixcode.com>
* archive.c (foreach_cb):
(archive_foreach_child_location): Use auxillary structure to pass
data to traversal callback
(archive_get_location):
(archive_register_location): strdup() location ids
(free_location_cb): free() key
2000-12-20 Bradford Hovinen <hovinen@helixcode.com>
* location.c (location_get_parent): Implement
* archive.c (load_all_locations): Implement
(foreach_cb):
(archive_foreach_child_location): Implement
2000-12-19 Bradford Hovinen <hovinen@helixcode.com>
* Makefile.am (bin_PROGRAMS): Changed name of archiver to
helix-archiver
(lib_LIBRARIES): Added libhelix_archiver.a
(helix_archiver_SOURCES): Moved archiver core to
libhelix_archiver_a_SOURCES
(helix_archiver_LDADD): Added libhelix_archiver.a
(INCLUDES): Changed XML_CFLAGS to GNOME_XML_CFLAGS
(include_HEADERS): Create and include headers for
libhelix_archiver.a
(includedir): Set includedire to include/helix-archiver
2000-12-18 Bradford Hovinen <hovinen@helixcode.com>
* main.c (do_rollback): Support rolling back by steps
* location.c (location_rollback_backend_by): Implement
(location_dump_rollback_data): Support passing steps as well as
date
* config-log.c (config_log_get_rollback_id_by_steps): Implement
* location.c (write_metadata_file): Don't support writing out the
master list any more
(save_metadata): Ditto
(load_metadata_file): Get backends list from BackendList object
(rather than finding it out oneself) if location is toplevel
(do_create): Ditto
(get_backends_cb): Implement
(location_add_backend): Add return values for error conditions
2000-10-15 Bradford Hovinen <hovinen@helixcode.com>
* location.c (location_rollback_backends_to): Free id_array when done
* config-log.c (config_log_reset_filenames): Implement
* archive.c (archive_set_current_location_id): Move gnome_config_
code from set_current_location
* location.c (location_set_id): Implement
* main.c (do_rename_location): Implement
* archive.c (free_location_cb): Don't free locid
(archive_get_location):
(archive_register_location): Don't strdup the location id
(archive_set_current_location_id): Implement
* main.c: Add options for renaming locations and specifying that
backends should be added to or removed from the master list
* location.c (run_backend_proc): Close all descriptors other than
0, 1, 2
(location_set_id): Implement
(location_set_arg): Free previous locid if exists
* archive.c (add_location_cb): Implement
(archive_set_current_location): Add location change algorithm
* location.c (location_find_path_from_common_parent): Implement
(location_foreach_backend): Implement
* archive.c (archive_set_current_location): Set
archive->current_location_id
* main.c (do_add_location): Check parent_str for NULL before
loading location
(do_change_location): Implement
(main): Support changing location
* archive.c (archive_register_location): Implement
* location.c (do_create):
(do_load): Use archive_get_prefix
(do_create): Load global location metadata if this location does
not inherit from anything
(location_get_id): Implement
* archive.c (archive_get_prefix): Implement
* location.c (location_get_path): Implement
(load_metadata_file): Use archive_is_global
(location_set_arg): Set label when setting locid
* location.[ch]: Make all data members private
* main.c (main): Get current location name properly, create
location iff location id is "default"; bail out with error otherwise
(do_remove_location):
(do_add_location): Implement
* config-log.c: Include ctype.h to fix implicit declarations
* location.c (location_rollback_backends_to): Property initialize i
(location_contains): Fix precondition checks
(do_create): Remove unused variables
* archive.c (archive_get_location): Make a copy of locid before
working with it
(do_load): Fix precondition checks
* location.c (location_open):
(location_new): Make locid const
* archive.c (archive_get_location): Make locid const
* location.c (data_delete_cb):
(location_delete): Implement
* config-log.c (config_log_iterate): Implement
(config_log_destroy): Make private, pass GtkObject
(config_log_delete): Implement
2000-10-14 Bradford Hovinen <hovinen@helixcode.com>
* location.c (location_close): Add precondition checks
* archive.c (archive_destroy): Make private; pass GtkObject
* location.c (location_add_backend):
(location_remove_backend): Add precondition checks
(location_destroy): Make private
(location_destroy): Pass GtkObject pointer rather than Location
pointer; this cleans up assignment in _class_init
* archive.c (archive_get_current_location_id): Implement
(archive_get_current_location): Implement
2000-09-03 Bradford Hovinen <hovinen@helixcode.com>
* location.c (location_new): Set is_new
(save_metadata): Don't write file unless necessary
(save_metadata):
(write_metadata_file): Split out file writing into
write_metadata_file; write default data file as necessary
(location_add_backend):
(location_remove_backend): Implement
* main.c: Add command line arguments for adding/removing locations
and backends; move backend id argument into global options
* location.c (do_load):
(load_metadata_file): Split out file parsing logic into
load_metadata_file; call load_metadata_file on default file to get
contains list if current location doesn't inherit anything
(load_metadata_file): g_strdup backend string
(load_metadata_file): Warn if top-level location has contains clauses
(location_store): Check if the location contains the given backend
and try the location it inherits if it doesn't
* archive.c (archive_load): Set is_global in archive object
* Makefile.am (Locationmeta{dir|_DATA}): Added commands to install
data files
(INCLUDES): Added define for LOCATION_DIR
2000-09-03 Bradford Hovinen <hovinen@helixcode.com>
* location.c (save_metadata): Write attributes when saving

View File

@@ -1,61 +0,0 @@
confexecdir = $(libdir)
confexec_DATA = ximian_archiverConf.sh
Locationmetadir = $(datadir)/hcm/default
Locationmeta_DATA = default-user.xml default-global.xml
gladedir = $(prefix)/share/hcm/glade
glade_DATA = rollback-location-management.glade
includedir = $(prefix)/include/ximian-archiver
INCLUDES = \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-I$(includedir) $(GNOME_INCLUDEDIR) \
-DVERSION=\""$(VERSION)"\" \
-DCONFIGDIR=\""/etc"\" \
-DLOCATION_DIR=\""$(datadir)/hcm/default"\" \
-DGLADE_DIR=\""$(datadir)/hcm/glade"\" \
$(GNOME_XML_CFLAGS) \
$(LIBGLADE_CFLAGS)
bin_PROGRAMS = ximian-archiver
lib_LTLIBRARIES = libximian_archiver.la
libximian_archiver_la_SOURCES = \
archive.c archive.h \
location.c location.h \
config-log.c config-log.h \
backend-list.c backend-list.h \
util.c util.h
include_HEADERS = \
archive.h location.h config-log.h backend-list.h util.h
ximian_archiver_SOURCES = \
main.c
ximian_archiver_LDADD = \
$(GNOME_LIBDIR) \
$(GNOMEUI_LIBS) \
$(INTLLIBS) \
$(GNOME_XML_LIB) \
libximian_archiver.la
EXTRA_DIST = \
$(Locationmeta_DATA) \
$(glade_DATA) \
ximian_archiverConf.sh.in
#
# Create the ximian_archiverConf.sh file from the sh.in file
#
ximian_archiverConf.sh: ximian_archiverConf.sh.in Makefile
sed -e 's?\@GNOME_LIBDIR\@?$(GNOME_LIBDIR) -L$(prefix)/lib?' \
-e 's?\@GNOMEUI_LIBS\@?$(GNOMEUI_LIBS)?g' \
-e 's?\@GNOME_INCLUDEDIR\@?$(GNOME_INCLUDEDIR) -I$(prefix)/include?g' \
-e 's?\@ORB_LIBS\@?$(ORB_LIBS)?g' \
< $(srcdir)/ximian_archiverConf.sh.in > ximian_archiverConf.tmp \
&& mv ximian_archiverConf.tmp ximian_archiverConf.sh

View File

@@ -1,40 +0,0 @@
* Add per-user master list
* Archiving changes in location metadata
* Fix race in lock handling and add timeout support (look in gnome-mime)
* Support multiple backends from CLI
* Add translateable backend description support
* Some way to store the rollback time for each backend, for GUI purposes
* Have defaults stored somewhere, to be restored when the user goes
back before the first configuration edit
Long-term
* Add clustering support:
- Add Cluster class inheriting Archive class and overriding path
semantics
- Change location rollback functionality to send data through to
clients if the archive is a cluster
* Allow backend specs to identify an order in which they should be applied
- Specify this in the master list; have each location look up that
information before invoking multiple backends
Questions
Done
* Global list of configs for a given archive
* Location should store backend data in the location where it is valid
* Add support for dumping XML to stdout rather than running the backend
* Fix bug where EOF not sent through pipe
* Changing the name of a location
* Adding per-user/global backends
- Don't try to write out contains list on toplevel locations
- Give error if the user tries to add a backend to a toplevel location
* Consistency check on adding and removing backends
- Make sure the backend is included in the global metadata list before
adding
- When removing global and per-user backends, mark the backend
"invalid" and exclude from location_foreach_backend,
location_rollback_all_to, and location_contains.
* Refactor master list into an attribute of Archive
* Roll back x number of steps rather than by date
* Try to factor out populate_locations_list to be common between the
different dialogs

View File

@@ -1,635 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* archive.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include "archive.h"
typedef struct _GRealTree GRealTree;
typedef struct _GTreeNode GTreeNode;
typedef struct _foreach_t foreach_t;
struct _foreach_t
{
Archive *archive;
LocationCB callback;
Location *parent;
gpointer user_data;
};
static GtkObjectClass *parent_class;
static Archive *user_archive;
static Archive *global_archive;
enum {
ARG_0,
ARG_PREFIX
};
static void archive_init (Archive *archive);
static void archive_class_init (ArchiveClass *klass);
static void archive_destroy (GtkObject *object);
static void archive_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void archive_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static gboolean do_load (Archive *archive);
static void load_all_locations (Archive *archive);
guint
archive_get_type (void)
{
static guint archive_type;
if (!archive_type) {
GtkTypeInfo archive_info = {
"Archive",
sizeof (Archive),
sizeof (ArchiveClass),
(GtkClassInitFunc) archive_class_init,
(GtkObjectInitFunc) archive_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
archive_type =
gtk_type_unique (gtk_object_get_type (),
&archive_info);
}
return archive_type;
}
static void
archive_init (Archive *archive)
{
archive->prefix = NULL;
archive->locations = g_tree_new ((GCompareFunc) strcmp);
archive->current_location_id = NULL;
}
static void
archive_class_init (ArchiveClass *klass)
{
GtkObjectClass *object_class;
object_class = GTK_OBJECT_CLASS (klass);
object_class->destroy = archive_destroy;
object_class->set_arg = archive_set_arg;
object_class->get_arg = archive_get_arg;
gtk_object_add_arg_type ("Archive::prefix",
GTK_TYPE_POINTER,
GTK_ARG_READWRITE,
ARG_PREFIX);
parent_class = gtk_type_class (gtk_object_get_type ());
}
static void
archive_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
Archive *archive;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_ARCHIVE (object));
g_return_if_fail (arg != NULL);
archive = ARCHIVE (object);
switch (arg_id) {
case ARG_PREFIX:
if (GTK_VALUE_POINTER (*arg) != NULL)
archive->prefix = g_strdup (GTK_VALUE_POINTER (*arg));
break;
default:
break;
}
}
static void
archive_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
Archive *archive;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_ARCHIVE (object));
g_return_if_fail (arg != NULL);
archive = ARCHIVE (object);
switch (arg_id) {
case ARG_PREFIX:
GTK_VALUE_POINTER (*arg) = archive->prefix;
break;
default:
arg->type = GTK_TYPE_INVALID;
break;
}
}
/**
* archive_load:
* @is_global: TRUE iff we should load the global archive
*
* Load either the global or per-user configuration archive
*
* Return value: Reference to archive
**/
GtkObject *
archive_load (gboolean is_global)
{
GtkObject *object;
gchar *prefix;
if (is_global && global_archive != NULL)
return GTK_OBJECT (global_archive);
else if (user_archive != NULL)
return GTK_OBJECT (user_archive);
if (is_global)
prefix = CONFIGDIR "/ximian-config";
else
prefix = g_concat_dir_and_file (g_get_home_dir (),
".gnome/ximian-config");
object = gtk_object_new (archive_get_type (),
"prefix", prefix,
NULL);
if (!is_global)
g_free (prefix);
if (do_load (ARCHIVE (object)) == FALSE) {
gtk_object_destroy (object);
return NULL;
}
ARCHIVE (object)->is_global = is_global;
ARCHIVE (object)->backend_list =
BACKEND_LIST (backend_list_new (is_global));
if (is_global)
global_archive = ARCHIVE (object);
else
user_archive = ARCHIVE (object);
return object;
}
static gint
free_location_cb (gchar *locid, Location *location)
{
location_close (location);
g_free (locid);
return FALSE;
}
static void
archive_destroy (GtkObject *object)
{
Archive *archive;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_ARCHIVE (object));
archive = ARCHIVE (object);
g_tree_traverse (archive->locations,
(GTraverseFunc) free_location_cb,
G_IN_ORDER,
NULL);
g_tree_destroy (archive->locations);
if (archive->current_location_id != NULL)
g_free (archive->current_location_id);
GTK_OBJECT_CLASS (parent_class)->destroy (GTK_OBJECT (archive));
}
/**
* archive_close:
* @archive:
*
* Closes the given archive handle. Also closes all locations under this
* archive.
**/
void
archive_close (Archive *archive)
{
g_return_if_fail (archive != NULL);
g_return_if_fail (IS_ARCHIVE (archive));
gtk_object_destroy (GTK_OBJECT (archive));
}
/**
* archive_get_location:
* @archive:
* @locid:
*
* Get a reference to the location with the given name.
*
* Return value: Reference to location, NULL if no such location exists
**/
Location *
archive_get_location (Archive *archive, const gchar *locid)
{
GtkObject *loc_obj;
g_return_val_if_fail (archive != NULL, NULL);
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
g_return_val_if_fail (locid != NULL, NULL);
loc_obj = g_tree_lookup (archive->locations, locid);
if (!loc_obj) {
loc_obj = location_open (archive, locid);
if (!loc_obj) return NULL;
if (loc_obj)
g_tree_insert (archive->locations,
g_strdup (locid), loc_obj);
}
if (loc_obj) {
gtk_object_ref (loc_obj);
return LOCATION (loc_obj);
} else {
return NULL;
}
}
/**
* archive_register_location:
* @archive:
* @location:
*
* Register a location with the archive; invoked by location_new
**/
void
archive_register_location (Archive *archive, Location *location)
{
g_return_if_fail (archive != NULL);
g_return_if_fail (IS_ARCHIVE (archive));
g_return_if_fail (location != NULL);
g_return_if_fail (IS_LOCATION (location));
g_tree_insert (archive->locations,
g_strdup (location_get_id (location)),
location);
}
/**
* archive_unregister_location:
* @archive:
* @location:
*
* Unregisters a location from the archive
**/
void
archive_unregister_location (Archive *archive, Location *location)
{
g_return_if_fail (archive != NULL);
g_return_if_fail (IS_ARCHIVE (archive));
g_return_if_fail (location != NULL);
g_return_if_fail (IS_LOCATION (location));
/* FIXME: We might be screwing things up here if we're traversing... */
g_tree_remove (archive->locations, location);
}
/**
* archive_get_current_location:
* @archive: object
*
* Convenience function to get a pointer to the current location
*
* Return value: Pointer to current location
**/
Location *
archive_get_current_location (Archive *archive)
{
g_return_val_if_fail (archive != NULL, NULL);
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
return archive_get_location (archive,
archive_get_current_location_id
(archive));
}
static int
add_location_cb (Location *location, gchar *backend_id, GList *backends)
{
g_list_insert (backends, backend_id, 1);
return 0;
}
/**
* archive_set_current_location:
* @archive: object
* @location: Location to which to set archive
*
* Set the current location in an archive to the location given; apply
* configuration for the new location to all backends necessary
**/
void
archive_set_current_location (Archive *archive, Location *location)
{
GList *location_path, *backends;
Location *old_location = archive_get_current_location (archive);
g_return_if_fail (archive != NULL);
g_return_if_fail (IS_ARCHIVE (archive));
g_return_if_fail (location != NULL);
g_return_if_fail (IS_LOCATION (location));
archive_set_current_location_id (archive, location_get_id (location));
location_path = location_find_path_from_common_parent
(location, old_location);
backends = g_list_append (NULL, NULL);
while (location_path != NULL) {
if (location_path->data != NULL) {
location_foreach_backend
(LOCATION (location_path->data),
(LocationBackendCB) add_location_cb,
backends);
}
location_path = location_path->next;
}
location_rollback_backends_to (location, NULL, backends->next, TRUE);
g_list_free (backends);
}
/**
* archive_set_current_location_id:
* @archive:
* @name:
*
* Sets the current location's name, but does not invoke any rollback
**/
void
archive_set_current_location_id (Archive *archive, const gchar *locid)
{
g_return_if_fail (archive != NULL);
g_return_if_fail (IS_ARCHIVE (archive));
g_return_if_fail (locid != NULL);
if (archive->current_location_id != NULL)
g_free (archive->current_location_id);
archive->current_location_id = g_strdup (locid);
if (archive->is_global)
gnome_config_push_prefix ("=" LOCATION_DIR "=");
else
gnome_config_push_prefix ("ximian-config/");
gnome_config_set_string ("config/current/location",
archive->current_location_id);
gnome_config_pop_prefix ();
gnome_config_sync ();
}
/**
* archive_get_current_location_id:
* @archive: object
*
* Get the name of the current location
*
* Return value: String containing current location, should not be freed
**/
const gchar *
archive_get_current_location_id (Archive *archive)
{
g_return_val_if_fail (archive != NULL, NULL);
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
if (archive->current_location_id == NULL) {
if (archive->is_global)
gnome_config_push_prefix ("=" LOCATION_DIR "=");
else
gnome_config_push_prefix ("ximian-config/");
archive->current_location_id =
gnome_config_get_string
("config/current/location=default");
gnome_config_pop_prefix ();
}
return archive->current_location_id;
}
/**
* archive_get_prefix:
* @archive:
*
* Get the prefix for locations in this archive
*
* Return value: String containing prefix; should not be freed
**/
const gchar *
archive_get_prefix (Archive *archive)
{
g_return_val_if_fail (archive != NULL, FALSE);
g_return_val_if_fail (IS_ARCHIVE (archive), FALSE);
return archive->prefix;
}
/**
* archive_is_global:
* @archive:
*
* Tell whether the archive is global or per-user
*
* Return value: TRUE if global, FALSE if per-user
**/
gboolean
archive_is_global (Archive *archive)
{
g_return_val_if_fail (archive != NULL, FALSE);
g_return_val_if_fail (IS_ARCHIVE (archive), FALSE);
return archive->is_global;
}
/**
* archive_get_backend_list:
* @archive:
*
* Get the master backend list for this archive
*
* Return value: Reference to the master backend list
**/
BackendList *
archive_get_backend_list (Archive *archive)
{
g_return_val_if_fail (archive != NULL, FALSE);
g_return_val_if_fail (IS_ARCHIVE (archive), FALSE);
return archive->backend_list;
}
static gint
foreach_cb (gchar *key, Location *value, foreach_t *data)
{
if (location_get_parent (value) == data->parent)
return data->callback (data->archive, value,
data->user_data);
else
return 0;
}
/**
* archive_foreach_child_location:
* @archive:
* @callback: Callback to invoke
* @parent: Iterate through the children of this location; iterate through
* toplevel locations if this is NULL
* @data: Arbitrary data to pass to the callback
*
* Invoke the given callback for each location that inherits the given
* location, or for each toplevel location if the parent given is
* NULL. Terminate the iteration if any child returns a nonzero value
**/
void
archive_foreach_child_location (Archive *archive, LocationCB callback,
Location *parent, gpointer data)
{
foreach_t f_data;
g_return_if_fail (archive != NULL);
g_return_if_fail (IS_ARCHIVE (archive));
load_all_locations (archive);
f_data.archive = archive;
f_data.callback = callback;
f_data.parent = parent;
f_data.user_data = data;
g_tree_traverse (archive->locations,
(GTraverseFunc) foreach_cb,
G_IN_ORDER,
&f_data);
}
/* Load the archive information from disk; return TRUE on success and FALSE on
* failure
*/
static gboolean
do_load (Archive *archive)
{
gint ret = 0;
g_return_val_if_fail (archive != NULL, FALSE);
g_return_val_if_fail (IS_ARCHIVE (archive), FALSE);
g_return_val_if_fail (archive->prefix != NULL, FALSE);
if (g_file_test (archive->prefix, G_FILE_TEST_ISDIR) == FALSE)
ret = mkdir (archive->prefix, S_IREAD | S_IWRITE | S_IEXEC);
if (ret == -1) return FALSE;
return TRUE;
}
/* Load and register all the locations for this archive */
static void
load_all_locations (Archive *archive)
{
DIR *archive_dir;
struct dirent entry, *entryp;
gchar *filename;
archive_dir = opendir (archive->prefix);
if (archive_dir == NULL) {
g_warning ("load_all_locations: %s", g_strerror (errno));
return;
}
while (1) {
if (readdir_r (archive_dir, &entry, &entryp)) {
g_warning ("load_all_locations: %s",
g_strerror (errno));
break;
}
if (entryp == NULL) break;
if (strcmp (entry.d_name, ".") &&
strcmp (entry.d_name, ".."))
{
filename = g_concat_dir_and_file (archive->prefix,
entry.d_name);
if (g_file_test (filename, G_FILE_TEST_ISDIR))
archive_get_location (archive, entry.d_name);
}
}
}

View File

@@ -1,88 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* archive.h
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __ARCHIVE_H
#define __ARCHIVE_H
#include <gnome.h>
#include "location.h"
#include "backend-list.h"
#define ARCHIVE(obj) GTK_CHECK_CAST (obj, archive_get_type (), Archive)
#define ARCHIVE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, archive_get_type (), ArchiveClass)
#define IS_ARCHIVE(obj) GTK_CHECK_TYPE (obj, archive_get_type ())
typedef struct _ArchiveClass ArchiveClass;
typedef gint (*LocationCB) (Archive *, Location *, gpointer);
struct _Archive
{
GtkObject object;
gchar *prefix;
GTree *locations;
gboolean is_global;
gchar *current_location_id;
BackendList *backend_list;
};
struct _ArchiveClass
{
GtkObjectClass parent;
};
guint archive_get_type (void);
GtkObject *archive_load (gboolean is_global);
void archive_close (Archive *archive);
Location *archive_get_location (Archive *archive,
const gchar *location);
void archive_register_location (Archive *archive,
Location *location);
void archive_unregister_location (Archive *archive,
Location *location);
Location *archive_get_current_location (Archive *archive);
void archive_set_current_location (Archive *archive,
Location *location);
const gchar *archive_get_current_location_id (Archive *archive);
void archive_set_current_location_id (Archive *archive,
const gchar *locid);
const gchar *archive_get_prefix (Archive *archive);
gboolean archive_is_global (Archive *archive);
BackendList *archive_get_backend_list (Archive *archive);
void archive_foreach_child_location (Archive *archive,
LocationCB callback,
Location *parent,
gpointer data);
#endif /* __ARCHIVE */

View File

@@ -1,122 +0,0 @@
Rollback archiving internals
Copyright (C) 2001 Ximian Code, Inc.
Written by Bradford Hovinen <hovinen@ximian.com>
1. Directory format
Diagram:
+ toplevel
|-+ Location 1
| |- <id>.xml
| | .
| | .
| | .
| |- metadata.log:
| | [<id> <date> <time> <backend> ] ^
| | [ . ] | Time
| | [ . ] |
| | [ . ] |
| \- metadata.xml:
| [... ]
| [<inherits>location</inherits> ]
| [<contains backend-id="backend" type="full|partial"/> ]
| [... ]
|-+ Location 2
| ...
There is one toplevel directory for each archive. This directory
contains one or more location directories. Each location directory
must contain two files: an XML file describing the location and a log
of changes made in that location. Each change corresponds to an XML
file containing a snapshot of the configuration as modified. There is
one XML file per backend. Each change has an id number that is
incremented atomicall by the archiving script when it stores
configuration changes. The id number, as well as the date and time of
storage, form a filename that uniquely identifies each configuration
change. The archiving script must also store in the log file a line
with the id number, date and time of storage, and backend used
whenever it stores XML data. New entries are stored at the head of the
file, so that during rollback, the file may be foreward scanned to
find the appropriate identifier for the configuration file. The
per-location XML configuration file contains information on what the
location's parent is and what configurations that location defines.
For now, the backend shall be referred to by its executable name. When
the backends gain CORBA interfaces, I suggest that the OAF id be used
instead. This reduces the problem of setting a backend's configuration
to a simple object activation and method invocation. The OAF id may
also be used to resolve the backend's human-readable name.
2. Meta-configuration details
In order that this system be complete, there must be a way to
ascertain the current location and to roll back changes in location. I
propose that there be a special archive in the configuration hierarchy
that contains location history in the same format as other
locations. The archiver can then be a single script that accepts
command-line arguments describing the request action: `archive this
data', `roll back this backend's configuration', and `switch to this
location'. It then handles all the details of interfacing with the
archive and applying the changes in the correct order. Conceptually,
the archiver becomes a backend in and of itself, where the frontend is
located in the GUI of HCM. It would therefore be adviseable to use the
same standards for the archiver as for other backends and hence make
it a CORBA service, where the tool-specific interface is as described
above.
3. Fine-grained location management
A slight modification of the basic location management system allows
individual settings to be covered by a location as well as entire
backends. The contains tag in a location's metadata file contains the
attribute type, which may either by "full" or "partial". In the former
case, rollback proceeds as described above. If it is the latter, the
archiver, upon rolling back or setting configuration for the relevant
backend in that location, first retrieves the required configuration
from both the location and its parent using the same algorithm. It
then uses an XML merging algorithm to combine the two XML files into
one, allowing the child location's data to override its parent's
data. This can be accomplished using the same technique as Bonobo uses
to allow components to override toolbars and menus in the container.
When a child location partially defines the data for a particular
backend, it must store only those configuration settings that the user
explicitly changed when updating that backend's configuration under
that location. If the frontend simply dumped its entire XML snapshot
to the log, all of the configuration settings would be reflected in
that snapshot, and under the method indicated above, partial
containment would be equivalent to full containment. Therefore, when a
frontend stores its configuration under partial containment, the
archiver must run a node-for-node comparison between the XML data of
the parent location (retrieved using the method indicated above) and
that of the child location. Only those nodes that are different are
actually stored in the configuration log.
When comparing XML nodes, there must be a way to identify distinct
nodes for comparison. For example, in a network configuration backend,
there might be one node for each interface. If, under the parent
location, the nodes are ordered with interface "eth0" before interface
"eth1", while under the child location, they are in reverse order, but
the configuration is otherwise identical, it is not the intention of
the user that child location should override any configuration data of
the parent location. Therefore, the best method for comparing XML data
is to compare each child of a given node in one source to all the
children of the relevant node in the other source. If any child in the
other source matches, then the XML node is a duplicate and may be
thrown out. If there is another node such that the name and attributes
are the same, but the children are different, then the algorithm
should be invoked recursively to determine the differences among the
children. If there is no such node, then the node should be included.
4. Future directions
The metafile log structure may run into scalability problems for
installations have have been in place for a long time. An alternative
structure that uses binary indexing might be in order. A command line
utility (with GUI interface) could be written to recover the file in
the case of corruption; such a utility could simply introspect each of
the XML files in a directory. Provided that each XML file contains
enough information to create a file entry, which is trivial, recovery
is assured.

View File

@@ -1,305 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* backend-list.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <parser.h>
#include <tree.h>
#include "backend-list.h"
enum {
ARG_0,
ARG_IS_GLOBAL
};
struct _BackendListPrivate
{
gboolean is_global;
gchar *filename;
GList *backend_ids;
};
static GtkObjectClass *parent_class;
static void backend_list_init (BackendList *backend_list);
static void backend_list_class_init (BackendListClass *class);
static void backend_list_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void backend_list_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void backend_list_finalize (GtkObject *object);
static void do_load (BackendList *backend_list);
static void do_save (BackendList *backend_list);
guint
backend_list_get_type (void)
{
static guint backend_list_type = 0;
if (!backend_list_type) {
GtkTypeInfo backend_list_info = {
"BackendList",
sizeof (BackendList),
sizeof (BackendListClass),
(GtkClassInitFunc) backend_list_class_init,
(GtkObjectInitFunc) backend_list_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
backend_list_type =
gtk_type_unique (gtk_object_get_type (),
&backend_list_info);
}
return backend_list_type;
}
static void
backend_list_init (BackendList *backend_list)
{
backend_list->p = g_new0 (BackendListPrivate, 1);
}
static void
backend_list_class_init (BackendListClass *class)
{
GtkObjectClass *object_class;
gtk_object_add_arg_type ("BackendList::is-global",
GTK_TYPE_INT,
GTK_ARG_CONSTRUCT_ONLY | GTK_ARG_READWRITE,
ARG_IS_GLOBAL);
object_class = GTK_OBJECT_CLASS (class);
object_class->finalize = backend_list_finalize;
object_class->set_arg = backend_list_set_arg;
object_class->get_arg = backend_list_get_arg;
parent_class = GTK_OBJECT_CLASS
(gtk_type_class (gtk_object_get_type ()));
}
static void
backend_list_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
BackendList *backend_list;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_BACKEND_LIST (object));
backend_list = BACKEND_LIST (object);
switch (arg_id) {
case ARG_IS_GLOBAL:
backend_list->p->is_global = GTK_VALUE_INT (*arg);
backend_list->p->filename = backend_list->p->is_global ?
LOCATION_DIR "/default-global.xml" :
LOCATION_DIR "/default-user.xml";
do_load (backend_list);
break;
default:
g_warning ("Bad argument set");
break;
}
}
static void
backend_list_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
BackendList *backend_list;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_BACKEND_LIST (object));
backend_list = BACKEND_LIST (object);
switch (arg_id) {
case ARG_IS_GLOBAL:
GTK_VALUE_INT (*arg) = backend_list->p->is_global;
break;
default:
g_warning ("Bad argument get");
break;
}
}
static void
backend_list_finalize (GtkObject *object)
{
BackendList *backend_list;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_BACKEND_LIST (object));
backend_list = BACKEND_LIST (object);
g_list_foreach (backend_list->p->backend_ids, (GFunc) g_free, NULL);
g_list_free (backend_list->p->backend_ids);
g_free (backend_list->p);
GTK_OBJECT_CLASS (parent_class)->finalize (object);
}
GtkObject *
backend_list_new (gboolean is_global)
{
return gtk_object_new (backend_list_get_type (),
"is-global", is_global,
NULL);
}
gboolean
backend_list_contains (BackendList *backend_list, gchar *backend_id)
{
g_return_val_if_fail (backend_list != NULL, FALSE);
g_return_val_if_fail (IS_BACKEND_LIST (backend_list), FALSE);
return (g_list_find (backend_list->p->backend_ids, backend_id) !=
NULL);
}
/**
* backend_list_foreach:
* @backend_list:
* @callback:
* @data:
*
* Iterates through all the backends, invoking the callback given and aborting
* if any callback returns a nonzero value
*
* Return value: TRUE iff no callback issued a nonzero value, FALSE otherwise
**/
gboolean
backend_list_foreach (BackendList *backend_list, BackendCB callback,
gpointer data)
{
GList *node;
g_return_val_if_fail (backend_list != NULL, FALSE);
g_return_val_if_fail (IS_BACKEND_LIST (backend_list), FALSE);
g_return_val_if_fail (callback != NULL, FALSE);
for (node = backend_list->p->backend_ids; node; node = node->next)
if (callback (backend_list, node->data, data)) return FALSE;
return TRUE;
}
void
backend_list_add (BackendList *backend_list, gchar *backend_id)
{
g_return_if_fail (backend_list != NULL);
g_return_if_fail (IS_BACKEND_LIST (backend_list));
g_return_if_fail (backend_id != NULL);
backend_list->p->backend_ids =
g_list_prepend (backend_list->p->backend_ids, backend_id);
}
void
backend_list_remove (BackendList *backend_list, gchar *backend_id)
{
g_return_if_fail (backend_list != NULL);
g_return_if_fail (IS_BACKEND_LIST (backend_list));
g_return_if_fail (backend_id != NULL);
backend_list->p->backend_ids =
g_list_remove (backend_list->p->backend_ids, backend_id);
}
void
backend_list_save (BackendList *backend_list)
{
g_return_if_fail (backend_list != NULL);
g_return_if_fail (IS_BACKEND_LIST (backend_list));
do_save (backend_list);
}
static void
do_load (BackendList *backend_list)
{
xmlNodePtr root_node, node;
xmlDocPtr doc;
GList *list_tail = NULL;
gchar *contains_str;
doc = xmlParseFile (backend_list->p->filename);
if (doc == NULL) return;
root_node = xmlDocGetRootElement (doc);
for (node = root_node->childs; node; node = node->next) {
if (!strcmp (node->name, "contains")) {
contains_str = xmlGetProp (node, "backend");
if (contains_str != NULL) {
contains_str = g_strdup (contains_str);
list_tail = g_list_append (list_tail,
contains_str);
if (backend_list->p->backend_ids == NULL)
backend_list->p->backend_ids =
list_tail;
else
list_tail = list_tail->next;
} else {
g_warning ("Bad backends list: " \
"contains element with no " \
"backend attribute");
}
}
}
}
static void
do_save (BackendList *backend_list)
{
xmlNodePtr root_node, child_node;
xmlDocPtr doc;
GList *node;
doc = xmlNewDoc ("1.0");
root_node = xmlNewDocNode (doc, NULL, "location", NULL);
for (node = backend_list->p->backend_ids; node; node = node->next) {
child_node = xmlNewChild (root_node, NULL, "contains", NULL);
xmlNewProp (child_node, "backend", node->data);
}
xmlDocSetRootElement (doc, root_node);
xmlSaveFile (backend_list->p->filename, doc);
xmlFreeDoc (doc);
}

View File

@@ -1,73 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* backend-list.h
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __BACKEND_LIST_H
#define __BACKEND_LIST_H
#include <gnome.h>
BEGIN_GNOME_DECLS
#define BACKEND_LIST(obj) GTK_CHECK_CAST (obj, backend_list_get_type (), BackendList)
#define BACKEND_LIST_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, backend_list_get_type (), BackendListClass)
#define IS_BACKEND_LIST(obj) GTK_CHECK_TYPE (obj, backend_list_get_type ())
typedef struct _BackendList BackendList;
typedef struct _BackendListClass BackendListClass;
typedef struct _BackendListPrivate BackendListPrivate;
typedef gint (*BackendCB) (BackendList *, gchar *, gpointer);
struct _BackendList
{
GtkObject parent;
BackendListPrivate *p;
};
struct _BackendListClass
{
GtkObjectClass gtk_object_class;
};
guint backend_list_get_type (void);
GtkObject *backend_list_new (gboolean is_global);
gboolean backend_list_contains (BackendList *backend_list,
gchar *backend_id);
gboolean backend_list_foreach (BackendList *backend_list,
BackendCB callback,
gpointer data);
void backend_list_add (BackendList *backend_list,
gchar *backend_id);
void backend_list_remove (BackendList *backend_list,
gchar *backend_id);
void backend_list_save (BackendList *backend_list);
END_GNOME_DECLS
#endif /* __BACKEND_LIST_H */

View File

@@ -1,935 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* config-log.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include "config-log.h"
#include "location.h"
#include "util.h"
static GtkObjectClass *parent_class;
enum {
ARG_0,
ARG_LOCATION
};
typedef struct _ConfigLogEntry ConfigLogEntry;
struct _ConfigLogEntry
{
gint id;
struct tm *date;
gchar *backend_id;
};
static void config_log_init (ConfigLog *config_log);
static void config_log_class_init (ConfigLogClass *klass);
static void config_log_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void config_log_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void config_log_destroy (GtkObject *object);
static GList *find_config_log_entry_id (ConfigLog *config_log,
GList *start,
gint id);
static GList *find_config_log_entry_date (ConfigLog *config_log,
GList *start,
struct tm *date);
static GList *find_config_log_entry_backend (ConfigLog *config_log,
GList *start,
gchar *backend_id);
static GList *load_next_log_entry (ConfigLog *config_log,
GList *last);
static gchar *get_line (FILE *file);
static gboolean parse_line (char *buffer,
int *id,
struct tm *time,
char **backend_id);
static gboolean time_geq (struct tm *time1,
struct tm *time2);
static gboolean do_load (ConfigLog *config_log);
static void do_unload (ConfigLog *config_log);
static gint get_next_id (ConfigLog *config_log);
static struct tm *get_current_date (void);
static void write_log (FILE *output,
ConfigLogEntry *entry);
static void dump_log (ConfigLog *config_log);
static void config_log_entry_destroy (ConfigLogEntry *entry);
guint
config_log_get_type (void)
{
static guint config_log_type;
if (!config_log_type) {
GtkTypeInfo config_log_info = {
"ConfigLog",
sizeof (ConfigLog),
sizeof (ConfigLogClass),
(GtkClassInitFunc) config_log_class_init,
(GtkObjectInitFunc) config_log_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
config_log_type =
gtk_type_unique (gtk_object_get_type (),
&config_log_info);
}
return config_log_type;
}
static void
config_log_init (ConfigLog *config_log)
{
config_log->location = NULL;
}
static void
config_log_class_init (ConfigLogClass *klass)
{
GtkObjectClass *object_class;
object_class = GTK_OBJECT_CLASS (klass);
object_class->destroy = config_log_destroy;
object_class->set_arg = config_log_set_arg;
object_class->get_arg = config_log_get_arg;
gtk_object_add_arg_type ("ConfigLog::location",
GTK_TYPE_POINTER,
GTK_ARG_READWRITE,
ARG_LOCATION);
parent_class = gtk_type_class (gtk_object_get_type ());
}
static void
config_log_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
ConfigLog *config_log;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_CONFIG_LOG (object));
g_return_if_fail (arg != NULL);
config_log = CONFIG_LOG (object);
switch (arg_id) {
case ARG_LOCATION:
g_return_if_fail (GTK_VALUE_POINTER (*arg) != NULL);
g_return_if_fail (IS_LOCATION (GTK_VALUE_POINTER (*arg)));
config_log->location = GTK_VALUE_POINTER (*arg);
break;
default:
break;
}
}
static void
config_log_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
ConfigLog *config_log;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_CONFIG_LOG (object));
g_return_if_fail (arg != NULL);
config_log = CONFIG_LOG (object);
switch (arg_id) {
case ARG_LOCATION:
GTK_VALUE_POINTER (*arg) = config_log->location;
break;
default:
arg->type = GTK_TYPE_INVALID;
break;
}
}
/* Loads a configuration log. Creates it if it has not been created
* already
*/
GtkObject *
config_log_open (Location *location)
{
GtkObject *object;
object = gtk_object_new (config_log_get_type (),
"location", location,
NULL);
do_load (CONFIG_LOG (object));
return object;
}
/* Destroys a configuration log data structure and frees all memory
* associated with it, dumping the existing log out to disk
*/
static void
config_log_destroy (GtkObject *object)
{
ConfigLog *config_log;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_CONFIG_LOG (object));
config_log = CONFIG_LOG (object);
do_unload (config_log);
GTK_OBJECT_CLASS (parent_class)->destroy (GTK_OBJECT (config_log));
}
/**
* config_log_delete:
* @config_log:
*
* Permanently destroy a config log, including its log file. Also destory the
* object
**/
void
config_log_delete (ConfigLog *config_log)
{
g_return_if_fail (config_log != NULL);
g_return_if_fail (IS_CONFIG_LOG (config_log));
if (config_log->file != NULL) {
fclose (config_log->file);
config_log->file = NULL;
}
if (config_log->filename != NULL)
unlink (config_log->filename);
gtk_object_destroy (GTK_OBJECT (config_log));
}
/* Return the id number of the most recent data written by the given
* backend prior to the given date. If date is NULL, it is assumed to
* be today.
*/
gint
config_log_get_rollback_id_for_date (ConfigLog *config_log,
struct tm *date,
gchar *backend_id)
{
GList *node;
g_return_val_if_fail (config_log != NULL, -1);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), -1);
g_return_val_if_fail (backend_id != NULL, -1);
if (config_log->log_data == NULL)
config_log->log_data =
load_next_log_entry (config_log, NULL);
if (date == NULL)
node = config_log->log_data;
else
node = find_config_log_entry_date (config_log,
config_log->log_data,
date);
node = find_config_log_entry_backend (config_log, node, backend_id);
if (!node)
return -1;
else
return ((ConfigLogEntry *) node->data)->id;
}
/* Given a linked list of backend ids and a date, return an array of
* ids corresponding to the most recent data written by each of the
* backends prior to the given date. The array is in the same order as
* the backends and should be freed when done. If date is NULL, it is
* assumed to be today.
*
* FIXME: This should really sort the ids by date.
*/
gint *
config_log_get_rollback_ids_for_date (ConfigLog *config_log,
struct tm *date,
GList *backend_ids)
{
GList *start_node, *node;
gint *id_array, i = 0;
g_return_val_if_fail (config_log != NULL, NULL);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), NULL);
g_return_val_if_fail (backend_ids != NULL, NULL);
if (config_log->log_data == NULL)
config_log->log_data =
load_next_log_entry (config_log, NULL);
if (date == NULL)
start_node = config_log->log_data;
else
start_node = find_config_log_entry_date (config_log,
config_log->log_data,
date);
id_array = g_new (gint, g_list_length (backend_ids));
for (; backend_ids; backend_ids = backend_ids->next) {
node = find_config_log_entry_backend (config_log,
start_node,
backend_ids->data);
if (!node)
id_array[i] = -1;
else
id_array[i] = ((ConfigLogEntry *) node->data)->id;
i++;
}
return id_array;
}
/* Return the rollback id that is the given number of steps back from the
* current revision, or -1 if there is no such id
*/
gint
config_log_get_rollback_id_by_steps (ConfigLog *config_log,
guint steps, gchar *backend_id)
{
GList *node;
g_return_val_if_fail (config_log != NULL, -1);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), -1);
g_return_val_if_fail (backend_id != NULL, -1);
node = config_log->log_data;
if (node == NULL)
node = load_next_log_entry (config_log, node);
while (node != NULL && steps-- > 0) {
node = find_config_log_entry_backend
(config_log, node, backend_id);
if (steps > 0) {
if (node->next == NULL)
node = load_next_log_entry (config_log, node);
else
node = node->next;
}
}
if (node != NULL)
return ((ConfigLogEntry *) node->data)->id;
else
return -1;
}
/* Return the backend that generated the data with the given id */
gchar *
config_log_get_backend_id_for_id (ConfigLog *config_log, gint id)
{
GList *node;
g_return_val_if_fail (config_log != NULL, NULL);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), NULL);
g_return_val_if_fail (id >= 0, NULL);
if (config_log->log_data == NULL)
config_log->log_data =
load_next_log_entry (config_log, NULL);
node = find_config_log_entry_id (config_log,
config_log->log_data, id);
if (!node)
return NULL;
else
return ((ConfigLogEntry *) node->data)->backend_id;
}
/* Return the date the data with the given id was written */
struct tm *
config_log_get_date_for_id (ConfigLog *config_log, gint id)
{
GList *node;
g_return_val_if_fail (config_log != NULL, NULL);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), NULL);
g_return_val_if_fail (id >= 0, NULL);
if (config_log->log_data == NULL)
config_log->log_data =
load_next_log_entry (config_log, NULL);
node = find_config_log_entry_id (config_log,
config_log->log_data, id);
if (!node)
return NULL;
else
return ((ConfigLogEntry *) node->data)->date;
}
gint
config_log_write_entry (ConfigLog *config_log, gchar *backend_id)
{
ConfigLogEntry *entry;
g_return_val_if_fail (config_log != NULL, -1);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), -1);
g_return_val_if_fail (backend_id != NULL, -1);
entry = g_new0 (ConfigLogEntry, 1);
entry->id = get_next_id (config_log);
entry->date = get_current_date ();
entry->backend_id = g_strdup (backend_id);
config_log->log_data = g_list_prepend (config_log->log_data, entry);
return entry->id;
}
/**
* config_log_iterate:
* @config_log:
* @callback:
* @data:
*
* Iterate through all log entries an invoke the given callback on each one,
* passing the id, date created, and backend id to it
**/
void
config_log_iterate (ConfigLog *config_log, ConfigLogIteratorCB callback,
gpointer data)
{
GList *node;
ConfigLogEntry *entry;
g_return_if_fail (config_log != NULL);
g_return_if_fail (IS_CONFIG_LOG (config_log));
g_return_if_fail (callback != NULL);
node = config_log->log_data;
while (node != NULL) {
entry = (ConfigLogEntry *) node->data;
if (callback (config_log, entry->id, entry->backend_id,
entry->date, node->data)) break;
if (node->next == NULL)
node = load_next_log_entry (config_log, node);
else
node = node->next;
}
}
/**
* config_log_reset_filenames:
* @config_log:
*
* Rereads the log's location data to determine filenames
**/
void
config_log_reset_filenames (ConfigLog *config_log)
{
g_return_if_fail (config_log != NULL);
g_return_if_fail (IS_CONFIG_LOG (config_log));
if (config_log->filename != NULL)
g_free (config_log->filename);
config_log->filename =
g_concat_dir_and_file (location_get_path
(config_log->location),
"config.log");
if (config_log->lock_filename != NULL)
g_free (config_log->lock_filename);
config_log->lock_filename =
g_concat_dir_and_file (location_get_path
(config_log->location),
"config.log.lock");
}
/* Find the config log entry with the id given, starting at the given
* node. Return a pointer to the node.
*/
static GList *
find_config_log_entry_id (ConfigLog *config_log, GList *start, gint id)
{
GList *last;
ConfigLogEntry *entry;
g_return_val_if_fail (config_log != NULL, NULL);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), NULL);
g_return_val_if_fail (id >= 0, NULL);
if (!start) return NULL;
while (start != NULL) {
last = start;
entry = (ConfigLogEntry *) start->data;
if (entry->id == id)
return start;
else if (entry->id < id)
return NULL;
start = start->next;
}
while (1) {
start = load_next_log_entry (config_log, last);
if (start == NULL) return NULL;
entry = (ConfigLogEntry *) start->data;
if (entry->id == id)
return start;
else if (entry->id < id)
return NULL;
}
return NULL;
}
/* Find the first config log entry made prior to the given date,
* starting at the given node. Return a pointer to the node.
*/
static GList *
find_config_log_entry_date (ConfigLog *config_log, GList *start,
struct tm *date)
{
GList *last;
ConfigLogEntry *entry;
g_return_val_if_fail (config_log != NULL, NULL);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), NULL);
g_return_val_if_fail (date != NULL, NULL);
if (!start) return NULL;
while (start != NULL) {
last = start;
entry = (ConfigLogEntry *) start->data;
if (time_geq (date, entry->date))
return start;
start = start->next;
}
while (1) {
start = load_next_log_entry (config_log, last);
if (start == NULL) return NULL;
entry = (ConfigLogEntry *) start->data;
if (time_geq (date, entry->date))
return start;
}
return NULL;
}
/* Find the first config log entry made by the given backend,
* starting at the given node. Return a pointer to the node.
*/
static GList *
find_config_log_entry_backend (ConfigLog *config_log, GList *start,
gchar *backend_id)
{
GList *last;
ConfigLogEntry *entry;
g_return_val_if_fail (config_log != NULL, NULL);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), NULL);
g_return_val_if_fail (backend_id != NULL, NULL);
if (!start) return NULL;
while (start != NULL) {
last = start;
entry = (ConfigLogEntry *) start->data;
if (!strcmp (entry->backend_id, backend_id))
return start;
start = start->next;
}
while (1) {
start = load_next_log_entry (config_log, last);
if (start == NULL) return NULL;
entry = (ConfigLogEntry *) start->data;
if (!strcmp (entry->backend_id, backend_id))
return start;
}
return NULL;
}
static GList *
load_next_log_entry (ConfigLog *config_log, GList *last)
{
gchar *buffer, *backend_id;
ConfigLogEntry *entry;
gboolean success;
g_return_val_if_fail (config_log != NULL, NULL);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), NULL);
if (!config_log->file || feof (config_log->file)) return NULL;
buffer = get_line (config_log->file);
entry = g_new0 (ConfigLogEntry, 1);
entry->date = g_new0 (struct tm, 1);
success = parse_line (buffer, &entry->id,
entry->date, &backend_id);
if (success) {
entry->backend_id = g_strdup (backend_id);
last = g_list_append (last, entry);
if (!config_log->log_data) {
config_log->log_data = last;
config_log->first_old = last;
}
return g_list_find (last, entry);
} else {
g_free (entry);
return NULL;
}
}
/* Read an entire line from the given file, returning a pointer to an
* allocated string. Strip the trailing newline from the line.
*/
static gchar *
get_line (FILE *file)
{
int buf_size = 0;
char *buf = NULL, *tmp = NULL;
size_t distance = 0, amt_read = 0;
g_return_val_if_fail (file != NULL, NULL);
while (amt_read == buf_size - distance) {
distance = tmp - buf;
if (distance >= buf_size) {
if (buf == NULL) {
buf_size = 1024;
buf = g_new (char, buf_size);
} else {
buf_size *= 2;
buf = g_renew (char, buf, buf_size);
}
tmp = buf + distance;
}
fgets (tmp, buf_size - distance, file);
amt_read = strlen (tmp);
tmp += amt_read;
}
if (tmp) *(tmp - 1) = '\0';
return buf;
}
/* Parse a line from the log file. All pointers must be valid.
*
* Note: backend just points to somewhere in buffer, so it becomes
* invalid the next time the buffer is overwritten. If there's a
* trailing newline, it is not chopped off.
*
* Returns TRUE on success and FALSE on parse error; if FALSE is
* returned, the values placed in the variables given are undefined.
*/
static gboolean
parse_line (char *buffer, int *id, struct tm *date, char **backend_id)
{
sscanf (buffer, "%x", id);
while (isxdigit (*buffer)) buffer++;
if (!isspace (*buffer) || !isdigit (*(buffer + 1))) return FALSE;
buffer++;
if (extract_number (&buffer, &date->tm_year, 4) == FALSE)
return FALSE;
if (extract_number (&buffer, &date->tm_mon, 2) == FALSE)
return FALSE;
if (extract_number (&buffer, &date->tm_mday, 2) == FALSE)
return FALSE;
date->tm_year -= 1900;
date->tm_mon--;
if (!isspace (*buffer) || !isdigit (*(buffer + 1))) return FALSE;
buffer++;
if (extract_number (&buffer, &date->tm_hour, 2) == FALSE)
return FALSE;
if (*buffer != ':') return FALSE; buffer++;
if (extract_number (&buffer, &date->tm_min, 2) == FALSE)
return FALSE;
if (*buffer != ':') return FALSE; buffer++;
if (extract_number (&buffer, &date->tm_sec, 2) == FALSE)
return FALSE;
if (!isspace (*buffer) || *(buffer + 1) == '\0') return FALSE;
buffer++;
*backend_id = buffer;
return TRUE;
}
/* Return TRUE if the first given struct tm is greater than or equal
* to the second given struct tm; FALSE otherwise
*/
static gboolean
time_geq (struct tm *time1, struct tm *time2)
{
if (time1->tm_year > time2->tm_year) return TRUE;
if (time1->tm_year < time2->tm_year) return FALSE;
if (time1->tm_mon > time2->tm_mon) return TRUE;
if (time1->tm_mon < time2->tm_mon) return FALSE;
if (time1->tm_mday > time2->tm_mday) return TRUE;
if (time1->tm_mday < time2->tm_mday) return FALSE;
if (time1->tm_hour > time2->tm_hour) return TRUE;
if (time1->tm_hour < time2->tm_hour) return FALSE;
if (time1->tm_min > time2->tm_min) return TRUE;
if (time1->tm_min < time2->tm_min) return FALSE;
if (time1->tm_sec >= time2->tm_sec) return TRUE;
return FALSE;
}
/* Opens up a configuration log. Assumes all the structures are
* already initialized. Creates the log if not already done.
*
* Returns TRUE on success and FALSE on failure (unable to open output
* file or log is locked)
*/
static gboolean
do_load (ConfigLog *config_log)
{
FILE *lock_file;
g_return_val_if_fail (config_log != NULL, FALSE);
g_return_val_if_fail (IS_CONFIG_LOG (config_log), FALSE);
g_return_val_if_fail (config_log->location != NULL, FALSE);
g_return_val_if_fail (IS_LOCATION (config_log->location), FALSE);
do_unload (config_log);
config_log_reset_filenames (config_log);
#if 0 /* Locking disabled for now */
/* FIXME: Race condition here, plus lock handling should be
* better */
if (g_file_test (config_log->lock_filename, G_FILE_TEST_ISFILE))
return FALSE;
lock_file = fopen (config_log->lock_filename, "w");
fclose (lock_file);
#endif
config_log->file = fopen (config_log->filename, "r");
return TRUE;
}
/* Closes the input file for a given log and dumps and clears the
* cache
*/
static void
do_unload (ConfigLog *config_log)
{
GList *tmp;
g_return_if_fail (config_log != NULL);
g_return_if_fail (IS_CONFIG_LOG (config_log));
dump_log (config_log);
if (config_log->file) {
fclose (config_log->file);
config_log->file = NULL;
}
if (config_log->filename) {
g_free (config_log->filename);
config_log->filename = NULL;
}
if (config_log->lock_filename) {
unlink (config_log->lock_filename);
g_free (config_log->lock_filename);
config_log->lock_filename = NULL;
}
while (config_log->log_data) {
tmp = config_log->log_data->next;
config_log_entry_destroy
((ConfigLogEntry *) config_log->log_data->data);
g_list_free_1 (config_log->log_data);
config_log->log_data = tmp;
}
}
/* Returns the next id number in the sequence */
static gint
get_next_id (ConfigLog *config_log)
{
if (config_log->log_data == NULL) {
if (load_next_log_entry (config_log, NULL) == NULL)
return 0;
}
return ((ConfigLogEntry *) config_log->log_data->data)->id + 1;
}
/* Return a newly allocated struct tm with the current time */
static struct tm *
get_current_date (void)
{
time_t current_time;
struct tm *time_1, *ret;
current_time = time (NULL);
time_1 = localtime (&current_time);
ret = g_new (struct tm, 1);
memcpy (ret, time_1, sizeof (struct tm));
return ret;
}
/* Write out a log entry */
static void
write_log (FILE *output, ConfigLogEntry *entry)
{
g_return_if_fail (output != NULL);
g_return_if_fail (entry != NULL);
g_return_if_fail (entry->id >= 0);
g_return_if_fail (entry->date != NULL);
g_return_if_fail (entry->backend_id != NULL);
fprintf (output, "%08x %04d%02d%02d %02d:%02d:%02d %s\n",
entry->id, entry->date->tm_year + 1900,
entry->date->tm_mon + 1, entry->date->tm_mday,
entry->date->tm_hour, entry->date->tm_min,
entry->date->tm_sec, entry->backend_id);
}
static void
dump_log (ConfigLog *config_log)
{
char *filename_out;
FILE *output;
GList *first;
char buffer[16384];
size_t size;
g_return_if_fail (config_log != NULL);
g_return_if_fail (IS_CONFIG_LOG (config_log));
g_return_if_fail (config_log->location != NULL);
g_return_if_fail (IS_LOCATION (config_log->location));
g_return_if_fail (location_get_path (config_log->location) != NULL);
filename_out = g_concat_dir_and_file (location_get_path
(config_log->location),
"config.log.out");
output = fopen (filename_out, "w");
if (!output) {
g_warning ("Could not open output file: %s",
g_strerror (errno));
return;
}
for (first = config_log->log_data; first != config_log->first_old;
first = first->next)
write_log (output, first->data);
if (config_log->file) {
rewind (config_log->file);
while (!feof (config_log->file)) {
size = fread (buffer, sizeof (char),
16384, config_log->file);
fwrite (buffer, sizeof (char), size, output);
}
}
fclose (output);
if (config_log->filename)
rename (filename_out, config_log->filename);
}
static void
config_log_entry_destroy (ConfigLogEntry *entry)
{
g_return_if_fail (entry != NULL);
g_return_if_fail (entry->date != NULL);
g_return_if_fail (entry->backend_id != NULL);
g_free (entry->date);
g_free (entry->backend_id);
g_free (entry);
}

View File

@@ -1,92 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* config-log.h
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __CONFIG_LOG_H
#define __CONFIG_LOG_H
#include <gnome.h>
#include <stdio.h>
#include <time.h>
#define CONFIG_LOG(obj) GTK_CHECK_CAST (obj, config_log_get_type (), ConfigLog)
#define CONFIG_LOG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, config_log_get_type (), ConfigLogClass)
#define IS_CONFIG_LOG(obj) GTK_CHECK_TYPE (obj, config_log_get_type ())
typedef struct _ConfigLog ConfigLog;
typedef struct _ConfigLogClass ConfigLogClass;
typedef struct _Location Location;
typedef gint (*ConfigLogIteratorCB) (ConfigLog *, gint, gchar *,
struct tm *, gpointer);
struct _ConfigLog
{
GtkObject object;
Location *location;
FILE *file;
char *filename;
char *lock_filename;
GList *log_data;
GList *first_old;
};
struct _ConfigLogClass
{
GtkObjectClass parent;
};
guint config_log_get_type (void);
GtkObject *config_log_open (Location *location);
void config_log_delete (ConfigLog *config_log);
gint config_log_get_rollback_id_for_date (ConfigLog *config_log,
struct tm *date,
gchar *backend_id);
gint *config_log_get_rollback_ids_for_date (ConfigLog *config_log,
struct tm *date,
GList *backend_ids);
gint config_log_get_rollback_id_by_steps (ConfigLog *config_log,
guint steps,
gchar *backend_id);
gchar *config_log_get_backend_id_for_id (ConfigLog *config_log,
gint id);
struct tm *config_log_get_date_for_id (ConfigLog *config_log,
gint id);
gint config_log_write_entry (ConfigLog *config_log,
gchar *backend_id);
void config_log_iterate (ConfigLog *config_log,
ConfigLogIteratorCB callback,
gpointer data);
void config_log_reset_filenames (ConfigLog *config_log);
#endif /* __CONFIG_LOG */

View File

@@ -1,625 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* config-manager-dialog.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <time.h>
#include <glade/glade.h>
#include "config-manager-dialog.h"
#include "create-location-dialog.h"
#include "archive.h"
#include "location.h"
#include "backend-list.h"
#include "location-list.h"
#define WID(str) (glade_xml_get_widget (dialog->p->config_dialog_data, str))
enum {
ARG_0,
ARG_TYPE
};
struct _ConfigManagerDialogPrivate
{
GladeXML *config_dialog_data;
CMDialogType type;
struct tm *date;
gboolean rollback_all;
gchar *backend_id;
gchar *selected_location_id;
Archive *global_archive;
Archive *user_archive;
BackendList *global_list;
BackendList *user_list;
Location *current_global;
Location *current_user;
LocationList *location_list;
};
static GnomeDialogClass *parent_class;
static void config_manager_dialog_init (ConfigManagerDialog *dialog);
static void config_manager_dialog_class_init (ConfigManagerDialogClass *class);
static void config_manager_dialog_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void config_manager_dialog_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void config_manager_dialog_finalize (GtkObject *object);
static void ok_cb (GtkWidget *widget,
ConfigManagerDialog *dialog);
static void apply_cb (GtkWidget *widget,
ConfigManagerDialog *dialog);
static void cancel_cb (GtkWidget *widget,
ConfigManagerDialog *dialog);
static void time_count_changed_cb (GtkSpinButton *button,
ConfigManagerDialog *dialog);
static void rollback_all_toggled_cb (GtkToggleButton *button,
ConfigManagerDialog *dialog);
static void rollback_one_toggled_cb (GtkToggleButton *button,
ConfigManagerDialog *dialog);
static void backend_select_cb (GtkMenuItem *menu_item,
ConfigManagerDialog *dialog);
static void create_cb (GtkWidget *button,
ConfigManagerDialog *dialog);
static void rename_cb (GtkWidget *button,
ConfigManagerDialog *dialog);
static void destroy_cb (GtkWidget *button,
ConfigManagerDialog *dialog);
static void change_location_cb (GtkWidget *button,
ConfigManagerDialog *dialog);
static void edit_location_cb (GtkWidget *button,
ConfigManagerDialog *dialog);
static void real_create_cb (CreateLocationDialog
*create_dialog,
gchar *name,
Location *parent,
ConfigManagerDialog *dialog);
static void do_rollback (ConfigManagerDialog *dialog);
static void reset_time (ConfigManagerDialog *dialog,
guint sub_days);
static gint populate_backends_cb (BackendList *list,
gchar *backend_id,
ConfigManagerDialog *dialog);
static void populate_backends_list (ConfigManagerDialog *dialog,
BackendList *list);
static void set_backend_controls_sensitive (ConfigManagerDialog *dialog,
gboolean s);
guint
config_manager_dialog_get_type (void)
{
static guint config_manager_dialog_type = 0;
if (!config_manager_dialog_type) {
GtkTypeInfo config_manager_dialog_info = {
"ConfigManagerDialog",
sizeof (ConfigManagerDialog),
sizeof (ConfigManagerDialogClass),
(GtkClassInitFunc) config_manager_dialog_class_init,
(GtkObjectInitFunc) config_manager_dialog_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
config_manager_dialog_type =
gtk_type_unique (gnome_dialog_get_type (),
&config_manager_dialog_info);
}
return config_manager_dialog_type;
}
static void
config_manager_dialog_init (ConfigManagerDialog *dialog)
{
static char *buttons[] = {
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_APPLY,
GNOME_STOCK_BUTTON_CANCEL,
NULL
};
gnome_dialog_constructv (GNOME_DIALOG (dialog),
_("Rollback and Location Management"),
buttons);
dialog->p = g_new0 (ConfigManagerDialogPrivate, 1);
dialog->p->config_dialog_data =
glade_xml_new (GLADE_DIR "/rollback-location-management.glade",
"config_dialog_data");
gtk_box_pack_start (GTK_BOX
(GNOME_DIALOG (dialog)->vbox),
WID ("config_dialog_data"), 0, TRUE, TRUE);
gtk_window_set_policy (GTK_WINDOW (dialog),
TRUE, FALSE, TRUE);
gnome_dialog_button_connect (GNOME_DIALOG (dialog),
0, GTK_SIGNAL_FUNC (ok_cb),
dialog);
gnome_dialog_button_connect (GNOME_DIALOG (dialog),
1, GTK_SIGNAL_FUNC (apply_cb),
dialog);
gnome_dialog_button_connect (GNOME_DIALOG (dialog),
2, GTK_SIGNAL_FUNC (cancel_cb),
dialog);
glade_xml_signal_connect_data (dialog->p->config_dialog_data,
"time_count_changed_cb",
time_count_changed_cb,
dialog);
glade_xml_signal_connect_data (dialog->p->config_dialog_data,
"rollback_all_toggled_cb",
rollback_all_toggled_cb,
dialog);
glade_xml_signal_connect_data (dialog->p->config_dialog_data,
"rollback_one_toggled_cb",
rollback_one_toggled_cb,
dialog);
glade_xml_signal_connect_data (dialog->p->config_dialog_data,
"create_cb",
create_cb,
dialog);
glade_xml_signal_connect_data (dialog->p->config_dialog_data,
"rename_cb",
rename_cb,
dialog);
glade_xml_signal_connect_data (dialog->p->config_dialog_data,
"destroy_cb",
destroy_cb,
dialog);
glade_xml_signal_connect_data (dialog->p->config_dialog_data,
"change_location_cb",
change_location_cb,
dialog);
glade_xml_signal_connect_data (dialog->p->config_dialog_data,
"edit_location_cb",
edit_location_cb,
dialog);
dialog->p->rollback_all = TRUE;
dialog->p->date = g_new (struct tm, 1);
dialog->p->location_list =
LOCATION_LIST (location_list_new (FALSE, NULL, NULL));
gtk_widget_show (GTK_WIDGET (dialog->p->location_list));
gtk_container_add (GTK_CONTAINER (WID ("location_tree_location")),
GTK_WIDGET (dialog->p->location_list));
set_backend_controls_sensitive (dialog, FALSE);
reset_time (dialog, 0);
}
static void
config_manager_dialog_class_init (ConfigManagerDialogClass *class)
{
GtkObjectClass *object_class;
gtk_object_add_arg_type ("ConfigManagerDialog::type",
GTK_TYPE_INT,
GTK_ARG_CONSTRUCT_ONLY | GTK_ARG_READWRITE,
ARG_TYPE);
object_class = GTK_OBJECT_CLASS (class);
object_class->finalize = config_manager_dialog_finalize;
object_class->set_arg = config_manager_dialog_set_arg;
object_class->get_arg = config_manager_dialog_get_arg;
parent_class = GNOME_DIALOG_CLASS
(gtk_type_class (gnome_dialog_get_type ()));
}
static void
config_manager_dialog_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
ConfigManagerDialog *dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (object));
dialog = CONFIG_MANAGER_DIALOG (object);
switch (arg_id) {
case ARG_TYPE:
dialog->p->type = GTK_VALUE_INT (*arg);
switch (dialog->p->type) {
case CM_DIALOG_USER_ONLY:
dialog->p->user_archive =
ARCHIVE (archive_load (FALSE));
dialog->p->global_archive = NULL;
break;
case CM_DIALOG_GLOBAL_ONLY:
dialog->p->global_archive =
ARCHIVE (archive_load (TRUE));
dialog->p->user_archive = NULL;
break;
case CM_DIALOG_BOTH:
dialog->p->user_archive =
ARCHIVE (archive_load (FALSE));
dialog->p->global_archive =
ARCHIVE (archive_load (TRUE));
break;
}
if (dialog->p->user_archive != NULL) {
dialog->p->user_list =
archive_get_backend_list
(dialog->p->user_archive);
dialog->p->current_user =
archive_get_current_location
(dialog->p->user_archive);
populate_backends_list
(dialog, dialog->p->user_list);
}
if (dialog->p->global_archive != NULL) {
dialog->p->global_list =
archive_get_backend_list
(dialog->p->global_archive);
dialog->p->current_global =
archive_get_current_location
(dialog->p->global_archive);
populate_backends_list
(dialog, dialog->p->global_list);
}
gtk_object_set (GTK_OBJECT (dialog->p->location_list),
"user-archive", dialog->p->user_archive,
"global-archive", dialog->p->global_archive,
NULL);
break;
default:
g_warning ("Bad argument set");
break;
}
}
static void
config_manager_dialog_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
ConfigManagerDialog *dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (object));
dialog = CONFIG_MANAGER_DIALOG (object);
switch (arg_id) {
case ARG_TYPE:
GTK_VALUE_INT (*arg) = dialog->p->type;
break;
default:
g_warning ("Bad argument get");
break;
}
}
static void
config_manager_dialog_finalize (GtkObject *object)
{
ConfigManagerDialog *dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (object));
dialog = CONFIG_MANAGER_DIALOG (object);
if (dialog->p->date != NULL)
g_free (dialog->p->date);
if (dialog->p->type == CM_DIALOG_USER_ONLY ||
dialog->p->type == CM_DIALOG_BOTH)
{
gtk_object_unref (GTK_OBJECT (dialog->p->current_user));
gtk_object_unref (GTK_OBJECT (dialog->p->user_list));
gtk_object_unref (GTK_OBJECT (dialog->p->user_archive));
}
if (dialog->p->type == CM_DIALOG_GLOBAL_ONLY ||
dialog->p->type == CM_DIALOG_BOTH)
{
gtk_object_unref (GTK_OBJECT (dialog->p->current_global));
gtk_object_unref (GTK_OBJECT (dialog->p->global_list));
gtk_object_unref (GTK_OBJECT (dialog->p->global_archive));
}
g_free (dialog->p);
GTK_OBJECT_CLASS (parent_class)->finalize (object);
}
GtkWidget *
config_manager_dialog_new (CMDialogType type)
{
return gtk_widget_new (config_manager_dialog_get_type (),
"type", type,
NULL);
}
static void
ok_cb (GtkWidget *widget, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
do_rollback (dialog);
gnome_dialog_close (GNOME_DIALOG (dialog));
}
static void
apply_cb (GtkWidget *widget, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
do_rollback (dialog);
}
static void
cancel_cb (GtkWidget *widget, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
/* This little hack will trick the location manager into rolling back
* to the last known configuration
*/
g_free (dialog->p->date);
dialog->p->date = NULL;
do_rollback (dialog);
gnome_dialog_close (GNOME_DIALOG (dialog));
}
static void
time_count_changed_cb (GtkSpinButton *button, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
reset_time (dialog, gtk_spin_button_get_value_as_int (button));
}
static void
rollback_all_toggled_cb (GtkToggleButton *button, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
if (gtk_toggle_button_get_active (button)) {
dialog->p->rollback_all = TRUE;
set_backend_controls_sensitive (dialog, FALSE);
}
}
static void
rollback_one_toggled_cb (GtkToggleButton *button, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
if (gtk_toggle_button_get_active (button)) {
dialog->p->rollback_all = FALSE;
set_backend_controls_sensitive (dialog, TRUE);
}
}
static void
backend_select_cb (GtkMenuItem *menu_item, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
dialog->p->backend_id = gtk_object_get_data (GTK_OBJECT (menu_item),
"backend-id");
}
static void
create_cb (GtkWidget *button, ConfigManagerDialog *dialog)
{
CreateLocationDialog *create_dialog;
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
create_dialog = CREATE_LOCATION_DIALOG
(create_location_dialog_new (dialog->p->type));
gtk_signal_connect (GTK_OBJECT (create_dialog),
"create-location",
GTK_SIGNAL_FUNC (real_create_cb),
dialog);
gtk_widget_show (GTK_WIDGET (create_dialog));
}
static void
rename_cb (GtkWidget *button, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
}
static void
destroy_cb (GtkWidget *button, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
}
static void
change_location_cb (GtkWidget *button, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
/* FIXME */
archive_set_current_location (dialog->p->user_archive,
location_list_get_selected_location
(dialog->p->location_list));
}
static void
edit_location_cb (GtkWidget *button, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
}
static void
real_create_cb (CreateLocationDialog *create_dialog, gchar *name,
Location *parent, ConfigManagerDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CONFIG_MANAGER_DIALOG (dialog));
/* FIXME */
location_new (dialog->p->user_archive, name, parent);
location_list_reread (dialog->p->location_list);
}
static void
do_rollback (ConfigManagerDialog *dialog)
{
switch (dialog->p->type) {
case CM_DIALOG_USER_ONLY:
if (dialog->p->rollback_all)
location_rollback_all_to
(dialog->p->current_user,
dialog->p->date, TRUE);
else
location_rollback_backend_to
(dialog->p->current_user,
dialog->p->date,
dialog->p->backend_id, TRUE);
break;
case CM_DIALOG_GLOBAL_ONLY:
if (dialog->p->rollback_all)
location_rollback_all_to
(dialog->p->current_global,
dialog->p->date, TRUE);
else
location_rollback_backend_to
(dialog->p->current_global,
dialog->p->date,
dialog->p->backend_id, TRUE);
break;
case CM_DIALOG_BOTH:
if (dialog->p->rollback_all) {
location_rollback_all_to
(dialog->p->current_global,
dialog->p->date, TRUE);
location_rollback_all_to
(dialog->p->current_user,
dialog->p->date, TRUE);
}
else if (backend_list_contains
(dialog->p->global_list, dialog->p->backend_id))
{
location_rollback_backend_to
(dialog->p->current_global,
dialog->p->date,
dialog->p->backend_id, TRUE);
} else {
location_rollback_backend_to
(dialog->p->current_user,
dialog->p->date,
dialog->p->backend_id, TRUE);
}
break;
}
}
static void
reset_time (ConfigManagerDialog *dialog, guint sub_days)
{
time_t current_time;
time (&current_time);
current_time -= sub_days * 24 * 60 * 60;
localtime_r (&current_time, dialog->p->date);
}
static gint
populate_backends_cb (BackendList *list, gchar *backend_id,
ConfigManagerDialog *dialog)
{
GtkWidget *menu_item;
GtkWidget *menu;
menu_item = gtk_menu_item_new_with_label (backend_id);
gtk_widget_show (menu_item);
gtk_object_set_data (GTK_OBJECT (menu_item),
"backend-id", backend_id);
gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
GTK_SIGNAL_FUNC (backend_select_cb), dialog);
menu = gtk_option_menu_get_menu
(GTK_OPTION_MENU (WID ("backend_select")));
gtk_menu_append (GTK_MENU (menu), menu_item);
return 0;
}
static void
populate_backends_list (ConfigManagerDialog *dialog, BackendList *list)
{
backend_list_foreach (list, (BackendCB) populate_backends_cb, dialog);
gtk_option_menu_set_history
(GTK_OPTION_MENU (WID ("backend_select")), 0);
}
static void
set_backend_controls_sensitive (ConfigManagerDialog *dialog, gboolean s)
{
gtk_widget_set_sensitive (WID ("backend_select"), s);
}

View File

@@ -1,63 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* config-manager-dialog.h
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __CONFIG_MANAGER_DIALOG_H
#define __CONFIG_MANAGER_DIALOG_H
#include <gnome.h>
BEGIN_GNOME_DECLS
#define CONFIG_MANAGER_DIALOG(obj) GTK_CHECK_CAST (obj, config_manager_dialog_get_type (), ConfigManagerDialog)
#define CONFIG_MANAGER_DIALOG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, config_manager_dialog_get_type (), ConfigManagerDialogClass)
#define IS_CONFIG_MANAGER_DIALOG(obj) GTK_CHECK_TYPE (obj, config_manager_dialog_get_type ())
typedef struct _ConfigManagerDialog ConfigManagerDialog;
typedef struct _ConfigManagerDialogClass ConfigManagerDialogClass;
typedef struct _ConfigManagerDialogPrivate ConfigManagerDialogPrivate;
typedef enum _CMDialogType CMDialogType;
struct _ConfigManagerDialog
{
GnomeDialog parent;
ConfigManagerDialogPrivate *p;
};
struct _ConfigManagerDialogClass
{
GnomeDialogClass gnome_dialog_class;
};
enum _CMDialogType {
CM_DIALOG_USER_ONLY, CM_DIALOG_GLOBAL_ONLY, CM_DIALOG_BOTH
};
guint config_manager_dialog_get_type (void);
GtkWidget *config_manager_dialog_new (CMDialogType type);
END_GNOME_DECLS
#endif /* __CONFIG_MANAGER_DIALOG_H */

View File

@@ -1,53 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* config-manager.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gnome.h>
#include <glade/glade.h>
#include "config-manager-dialog.h"
int
main (int argc, char **argv)
{
GtkWidget *dialog;
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
textdomain (PACKAGE);
gnome_init ("config-manager", VERSION, argc, argv);
glade_gnome_init ();
dialog = config_manager_dialog_new (CM_DIALOG_USER_ONLY);
gtk_widget_show (dialog);
gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
gtk_main_quit, NULL);
gtk_main ();
return 0;
}

View File

@@ -1,291 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* create-location-dialog.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glade/glade.h>
#include "create-location-dialog.h"
#include "location-list.h"
#define WID(str) (glade_xml_get_widget (dialog->p->create_dialog_data, str))
enum {
ARG_0,
ARG_TYPE
};
enum {
CREATE_LOCATION_SIGNAL,
LAST_SIGNAL
};
struct _CreateLocationDialogPrivate
{
GladeXML *create_dialog_data;
CMDialogType type;
gchar *selected_location_id;
Archive *global_archive;
Archive *user_archive;
LocationList *location_list;
};
static GnomeDialogClass *parent_class;
static guint create_location_dialog_signals[LAST_SIGNAL] = { 0 };
static void create_location_dialog_init (CreateLocationDialog *dialog);
static void create_location_dialog_class_init (CreateLocationDialogClass *class);
static void create_location_dialog_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void create_location_dialog_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void ok_cb (GtkWidget *widget,
CreateLocationDialog *dialog);
static void cancel_cb (GtkWidget *widget,
CreateLocationDialog *dialog);
static void create_location_dialog_finalize (GtkObject *object);
guint
create_location_dialog_get_type (void)
{
static guint create_location_dialog_type = 0;
if (!create_location_dialog_type) {
GtkTypeInfo create_location_dialog_info = {
"CreateLocationDialog",
sizeof (CreateLocationDialog),
sizeof (CreateLocationDialogClass),
(GtkClassInitFunc) create_location_dialog_class_init,
(GtkObjectInitFunc) create_location_dialog_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
create_location_dialog_type =
gtk_type_unique (gnome_dialog_get_type (),
&create_location_dialog_info);
}
return create_location_dialog_type;
}
static void
create_location_dialog_init (CreateLocationDialog *dialog)
{
static char *buttons[] = {
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
NULL
};
gnome_dialog_constructv (GNOME_DIALOG (dialog),
_("Rollback and Location Management"),
buttons);
dialog->p = g_new0 (CreateLocationDialogPrivate, 1);
dialog->p->create_dialog_data =
glade_xml_new (GLADE_DIR "/rollback-location-management.glade",
"create_dialog_data");
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox),
WID ("create_dialog_data"), 0, TRUE, TRUE);
gtk_window_set_policy (GTK_WINDOW (dialog), TRUE, FALSE, TRUE);
gnome_dialog_button_connect (GNOME_DIALOG (dialog),
0, GTK_SIGNAL_FUNC (ok_cb),
dialog);
gnome_dialog_button_connect (GNOME_DIALOG (dialog),
1, GTK_SIGNAL_FUNC (cancel_cb),
dialog);
dialog->p->location_list =
LOCATION_LIST (location_list_new (FALSE, NULL, NULL));
gtk_widget_show (GTK_WIDGET (dialog->p->location_list));
gtk_container_add (GTK_CONTAINER (WID ("location_list_location")),
GTK_WIDGET (dialog->p->location_list));
}
static void
create_location_dialog_class_init (CreateLocationDialogClass *class)
{
GtkObjectClass *object_class;
gtk_object_add_arg_type ("CreateLocationDialog::type",
GTK_TYPE_INT,
GTK_ARG_CONSTRUCT_ONLY | GTK_ARG_READWRITE,
ARG_TYPE);
object_class = GTK_OBJECT_CLASS (class);
object_class->finalize = create_location_dialog_finalize;
object_class->set_arg = create_location_dialog_set_arg;
object_class->get_arg = create_location_dialog_get_arg;
create_location_dialog_signals[CREATE_LOCATION_SIGNAL] =
gtk_signal_new ("create-location", GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET (CreateLocationDialogClass,
create_location),
gtk_marshal_NONE__POINTER_POINTER,
GTK_TYPE_NONE, 2, GTK_TYPE_POINTER,
GTK_TYPE_POINTER);
gtk_object_class_add_signals (object_class,
create_location_dialog_signals,
LAST_SIGNAL);
parent_class = GNOME_DIALOG_CLASS
(gtk_type_class (gnome_dialog_get_type ()));
}
static void
create_location_dialog_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
CreateLocationDialog *dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_CREATE_LOCATION_DIALOG (object));
dialog = CREATE_LOCATION_DIALOG (object);
switch (arg_id) {
case ARG_TYPE:
dialog->p->type = GTK_VALUE_INT (*arg);
switch (dialog->p->type) {
case CM_DIALOG_USER_ONLY:
dialog->p->user_archive =
ARCHIVE (archive_load (FALSE));
dialog->p->global_archive = NULL;
break;
case CM_DIALOG_GLOBAL_ONLY:
dialog->p->global_archive =
ARCHIVE (archive_load (TRUE));
dialog->p->user_archive = NULL;
break;
case CM_DIALOG_BOTH:
dialog->p->user_archive =
ARCHIVE (archive_load (FALSE));
dialog->p->global_archive =
ARCHIVE (archive_load (TRUE));
break;
}
gtk_object_set (GTK_OBJECT (dialog->p->location_list),
"user-archive", dialog->p->user_archive,
"global-archive", dialog->p->global_archive,
NULL);
break;
default:
g_warning ("Bad argument set");
break;
}
}
static void
create_location_dialog_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
CreateLocationDialog *dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_CREATE_LOCATION_DIALOG (object));
dialog = CREATE_LOCATION_DIALOG (object);
switch (arg_id) {
case ARG_TYPE:
GTK_VALUE_INT (*arg) = dialog->p->type;
break;
default:
g_warning ("Bad argument get");
break;
}
}
static void
create_location_dialog_finalize (GtkObject *object)
{
CreateLocationDialog *dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_CREATE_LOCATION_DIALOG (object));
dialog = CREATE_LOCATION_DIALOG (object);
g_free (dialog->p);
GTK_OBJECT_CLASS (parent_class)->finalize (object);
}
GtkObject *
create_location_dialog_new (CMDialogType type)
{
return gtk_object_new (create_location_dialog_get_type (),
"type", type,
NULL);
}
static void
ok_cb (GtkWidget *widget, CreateLocationDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CREATE_LOCATION_DIALOG (dialog));
gtk_signal_emit (GTK_OBJECT (dialog),
create_location_dialog_signals
[CREATE_LOCATION_SIGNAL],
gtk_entry_get_text
(GTK_ENTRY (WID ("location_name_entry"))),
location_list_get_selected_location
(dialog->p->location_list));
gnome_dialog_close (GNOME_DIALOG (dialog));
}
static void
cancel_cb (GtkWidget *widget, CreateLocationDialog *dialog)
{
g_return_if_fail (dialog != NULL);
g_return_if_fail (IS_CREATE_LOCATION_DIALOG (dialog));
gnome_dialog_close (GNOME_DIALOG (dialog));
}

View File

@@ -1,62 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* create-location-dialog.h
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __CREATE_LOCATION_DIALOG_H
#define __CREATE_LOCATION_DIALOG_H
#include <gnome.h>
#include "config-manager-dialog.h"
#include "location.h"
BEGIN_GNOME_DECLS
#define CREATE_LOCATION_DIALOG(obj) GTK_CHECK_CAST (obj, create_location_dialog_get_type (), CreateLocationDialog)
#define CREATE_LOCATION_DIALOG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, create_location_dialog_get_type (), CreateLocationDialogClass)
#define IS_CREATE_LOCATION_DIALOG(obj) GTK_CHECK_TYPE (obj, create_location_dialog_get_type ())
typedef struct _CreateLocationDialog CreateLocationDialog;
typedef struct _CreateLocationDialogClass CreateLocationDialogClass;
typedef struct _CreateLocationDialogPrivate CreateLocationDialogPrivate;
struct _CreateLocationDialog
{
GnomeDialog parent;
CreateLocationDialogPrivate *p;
};
struct _CreateLocationDialogClass
{
GnomeDialogClass gnome_dialog_class;
void (*create_location) (CreateLocationDialog *, gchar *, Location *);
};
guint create_location_dialog_get_type (void);
GtkObject *create_location_dialog_new (CMDialogType type);
END_GNOME_DECLS
#endif /* __CREATE_LOCATION_DIALOG_H */

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<location>
<contains>time-conf</contains>
<contains>shares-conf</contains>
</location>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<location>
<contains backend="background-properties-capplet"/>
<contains backend="bell-properties-capplet"/>
<contains backend="gnome-edit-properties-capplet"/>
<contains backend="keyboard-properties-capplet"/>
<contains backend="mouse-properties-capplet"/>
<contains backend="screensaver-properties-capplet"/>
<contains backend="session-properties-capplet"/>
<contains backend="wm-properties"/>
</location>

View File

@@ -1,95 +0,0 @@
Changes to the Helix Configuration Manager
Copyright (C) 2000 Ximian, Inc.
Written by Bradford Hovinen <hovinen@ximian.com>
As it stands, capplets and Ximian Setup Tools are both run as separate
processes through the exec() facility. It is planned that the capplets
shall become Bonobo controls in the future, once the OAF/gnorba
compatibility problems are worked out. This changes the design of the
configuration system considerably, and several things should be done
to take full advantage of these changes.
1. Capplets become Bonobo controls
It stands to reason that the front ends for Ximian Setup Tools should
become Bonobo controls at the same time as capplets. They can each
implement the same interface (say, Bonobo::Capplet) with methods
getXML(), setXML(), ok(), cancel(), and init() and hence look the same
to the shell. This means that the front ends for the Ximian Setup Tools
run as the same user as XCM and respond in the same way as capplets do
to requests to embed them in the XCM shell window. This is essential
for a consistent user interface that will not result in end-user
confusion [1]. XCM itself may then export an interface that includes
the method runBackend(), to which the frontend supplies a stream of
XML that XCM passes through the root manager to the backend via a
standard pipe [2]. The backend is then responsible for running the
program that archives the XML -- there is no other way to place that
XML in a central, system-wide repository. I suggest, therefore, that
we modify the design of the current system to make that change, so
that we do not have to undo existing work later.
2. Backends get CORBA interfaces through Perl/ORBit
At this point, there must be a way for the root manager to forward
CORBA sockets to the user securely. This could be done by modifying
ORBit so as to give the running program very precise control over the
nature of the socket. Access could be granted specifically to the user
running the root manager by placing the socket in a directory owned by
that user with permissions no more lax than 0700. When the CORBA
interfaces are created, applications will be able to make use of it to
make system-wide changes as necessary (say, to add a new user during
the installation of a piece of software). This means that the
traditional rollback facilities must be extended to allow users to
roll back changes made by applications. In addition, the application
must treat the backend as a black box -- it should never be expected
to do anything unusual to support rollback, since buggy or
poorly-written applications would otherwise cause trouble for
unsuspecting users.
At this point I suggest that each backend export two interfaces: one
that is universal to all backends and one that is specific to that
particular tool. The former may include the methods getXML(),
setXML(), and commit(). When changes are made through the
tool-specific interface, the tool decides whether or not to apply
those changes immediately or to queue them up until a commit() is
invoked. If changes are made through the backend's CORBA interface and
it is deactivated before a commit(), the backend must roll back those
changes under the assumption that they are not intended to be
permanent.
Of course, this makes implementation of the cancel() interface on the
frontends very easy -- simply deactivate the backend without
commit()ing. ok() can be implemented by flushing any remaining
changes, calling commit(), and then deactivating the backend. The
frontend can and should use the CORBA interface to invoke changes
whenever they are made, as long as it makes sense. It is then the
backend that sets the policy of whether or not the updates are live,
as described above. The frontend must still be able to read XML,
though, since it is through that that it will get an initial
description of the setup with which to fill in the dialog. In
addition, since the frontend may be invoked to make changes to an
inactive location, it should be able to write out an XML description
of the dialog's contents so that those changes may be archived rather
than applied immediately.
Notes
[1] A visual cue that signals to the user that he is running a
system-wide configuration tool rather than a personal one would be
advantageous. Such could take the form of an icon on the dialog, a
layout or formatting convention for the dialog proper, or some sort of
coloring convention of some of the controls. However, simply having
the tool run with root's Gtk+ theme and ignoring the embedding
preference, as would be the case if we do not Bonobize the HST
frontends, is inconsistent as many users will leave their themes as
the default and elect not to embed capplets -- eliminating all visual
cues. In addition, it is not particularly lucid and many users will
merely be confused by the inconsistent interface. One may imagine many
users filing bug reports in the belief that the behavior is
erroneous. Hence, that solution is insufficient.
[2] There must then be a method of multiplexing I/O throught the root
manager, as there may be multiple backends running concurrently. A
simple protocol could be implemented to do this, or a named pipe could
be created if done very carefully as to ensure a high degree of
security.

View File

@@ -1,364 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* location-list.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "location-list.h"
typedef struct _pair_t pair_t;
struct _pair_t
{
gpointer a, b;
};
enum {
ARG_0,
ARG_USER_ARCHIVE,
ARG_GLOBAL_ARCHIVE,
ARG_SEPARATE_LOCATIONS
};
struct _LocationListPrivate
{
gchar *selected_location_id;
Location *selected_location;
gboolean separate_locations;
Archive *user_archive;
Archive *global_archive;
};
static GtkCTreeClass *parent_class;
static void location_list_init (LocationList *location_list);
static void location_list_class_init (LocationListClass *class);
static void location_list_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void location_list_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void select_row_cb (LocationList *list,
GList *node, gint column);
static void location_list_finalize (GtkObject *object);
static gint populate_locations_cb (Archive *archive,
Location *location,
pair_t *data);
static void populate_locations_list (LocationList *list,
gboolean do_global);
guint
location_list_get_type (void)
{
static guint location_list_type = 0;
if (!location_list_type) {
GtkTypeInfo location_list_info = {
"LocationList",
sizeof (LocationList),
sizeof (LocationListClass),
(GtkClassInitFunc) location_list_class_init,
(GtkObjectInitFunc) location_list_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
location_list_type =
gtk_type_unique (gtk_ctree_get_type (),
&location_list_info);
}
return location_list_type;
}
static void
location_list_init (LocationList *location_list)
{
static char *titles = { "Location" };
gtk_ctree_construct (GTK_CTREE (location_list),
1, 0, &titles);
gtk_clist_column_titles_hide (GTK_CLIST (location_list));
location_list->p = g_new0 (LocationListPrivate, 1);
gtk_signal_connect (GTK_OBJECT (location_list),
"tree-select-row", GTK_SIGNAL_FUNC (select_row_cb),
NULL);
}
static void
location_list_class_init (LocationListClass *class)
{
GtkObjectClass *object_class;
gtk_object_add_arg_type ("LocationList::user-archive",
GTK_TYPE_POINTER,
GTK_ARG_READWRITE,
ARG_USER_ARCHIVE);
gtk_object_add_arg_type ("LocationList::global-archive",
GTK_TYPE_POINTER,
GTK_ARG_READWRITE,
ARG_GLOBAL_ARCHIVE);
gtk_object_add_arg_type ("LocationList::separate-locations",
GTK_TYPE_POINTER,
GTK_ARG_READWRITE,
ARG_SEPARATE_LOCATIONS);
object_class = GTK_OBJECT_CLASS (class);
object_class->finalize = location_list_finalize;
object_class->set_arg = location_list_set_arg;
object_class->get_arg = location_list_get_arg;
parent_class = GTK_CTREE_CLASS
(gtk_type_class (gtk_ctree_get_type ()));
}
static void
location_list_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
LocationList *location_list;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_LOCATION_LIST (object));
location_list = LOCATION_LIST (object);
switch (arg_id) {
case ARG_USER_ARCHIVE:
g_return_if_fail (GTK_VALUE_POINTER (*arg) == NULL ||
IS_ARCHIVE (GTK_VALUE_POINTER (*arg)));
if (GTK_VALUE_POINTER (*arg) == NULL) return;
location_list->p->user_archive =
ARCHIVE (GTK_VALUE_POINTER (*arg));
gtk_object_ref (GTK_OBJECT (location_list->p->user_archive));
populate_locations_list (location_list, FALSE);
break;
case ARG_GLOBAL_ARCHIVE:
g_return_if_fail (GTK_VALUE_POINTER (*arg) == NULL ||
IS_ARCHIVE (GTK_VALUE_POINTER (*arg)));
if (GTK_VALUE_POINTER (*arg) == NULL) return;
location_list->p->global_archive =
ARCHIVE (GTK_VALUE_POINTER (*arg));
gtk_object_ref (GTK_OBJECT (location_list->p->global_archive));
populate_locations_list (location_list, TRUE);
break;
case ARG_SEPARATE_LOCATIONS:
location_list->p->separate_locations =
GTK_VALUE_INT (*arg);
break;
default:
g_warning ("Bad argument set");
break;
}
}
static void
location_list_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
LocationList *location_list;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_LOCATION_LIST (object));
location_list = LOCATION_LIST (object);
switch (arg_id) {
case ARG_USER_ARCHIVE:
GTK_VALUE_POINTER (*arg) = location_list->p->user_archive;
break;
case ARG_GLOBAL_ARCHIVE:
GTK_VALUE_POINTER (*arg) = location_list->p->global_archive;
break;
case ARG_SEPARATE_LOCATIONS:
GTK_VALUE_INT (*arg) = location_list->p->separate_locations;
break;
default:
g_warning ("Bad argument get");
break;
}
}
static void
location_list_finalize (GtkObject *object)
{
LocationList *location_list;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_LOCATION_LIST (object));
location_list = LOCATION_LIST (object);
if (location_list->p->user_archive != NULL)
gtk_object_unref
(GTK_OBJECT (location_list->p->user_archive));
if (location_list->p->global_archive != NULL)
gtk_object_unref
(GTK_OBJECT (location_list->p->global_archive));
g_free (location_list->p);
GTK_OBJECT_CLASS (parent_class)->finalize (object);
}
GtkWidget *
location_list_new (gboolean sep_locations, Archive *user_archive,
Archive *global_archive)
{
return gtk_widget_new (location_list_get_type (),
"separate-locations", sep_locations,
"user-archive", user_archive,
"global-archive", global_archive,
NULL);
}
gchar *
location_list_get_selected_location_id (LocationList *list)
{
g_return_val_if_fail (list != NULL, NULL);
g_return_val_if_fail (IS_LOCATION_LIST (list), NULL);
return list->p->selected_location_id;
}
Location *
location_list_get_selected_location (LocationList *list)
{
g_return_val_if_fail (list != NULL, NULL);
g_return_val_if_fail (IS_LOCATION_LIST (list), NULL);
return list->p->selected_location;
}
void
location_list_reread (LocationList *list)
{
g_return_if_fail (list != NULL);
g_return_if_fail (IS_LOCATION_LIST (list));
gtk_clist_freeze (GTK_CLIST (list));
gtk_clist_clear (GTK_CLIST (list));
if (list->p->global_archive)
populate_locations_list (list, TRUE);
if (list->p->user_archive)
populate_locations_list (list, FALSE);
gtk_clist_thaw (GTK_CLIST (list));
}
static void
select_row_cb (LocationList *list, GList *node, gint column)
{
GtkCTreeRow *row;
g_return_if_fail (list != NULL);
g_return_if_fail (IS_LOCATION_LIST (list));
row = GTK_CTREE_ROW (node);
list->p->selected_location = row->row.data;
list->p->selected_location_id =
GTK_CELL_PIXTEXT (row->row.cell[0])->text;
}
static gint
populate_locations_cb (Archive *archive, Location *location, pair_t *data)
{
pair_t new_pair;
char *label;
label = g_strdup (location_get_label (location));
new_pair.b = gtk_ctree_insert_node (GTK_CTREE (data->a),
(GtkCTreeNode *) data->b, NULL,
&label, GNOME_PAD_SMALL, NULL,
NULL, NULL, NULL, FALSE, TRUE);
gtk_ctree_node_set_row_data (GTK_CTREE (data->a),
(GtkCTreeNode *) new_pair.b,
location);
new_pair.a = data->a;
archive_foreach_child_location (archive,
(LocationCB) populate_locations_cb,
location, &new_pair);
return 0;
}
static void
populate_locations_list (LocationList *list, gboolean do_global)
{
pair_t pair;
Archive *archive;
char *label;
if (do_global) {
archive = list->p->global_archive;
label = _("Global locations");
} else {
archive = list->p->user_archive;
label = _("User locations");
}
pair.a = list;
if (list->p->separate_locations)
pair.b = gtk_ctree_insert_node (GTK_CTREE (list),
NULL, NULL, &label,
GNOME_PAD_SMALL, NULL,
NULL, NULL, NULL, FALSE,
TRUE);
else
pair.b = NULL;
archive_foreach_child_location (archive,
(LocationCB) populate_locations_cb,
NULL, &pair);
}

View File

@@ -1,68 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* location-list.h
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __LOCATION_LIST_H
#define __LOCATION_LIST_H
#include <gnome.h>
#include "archive.h"
#include "location.h"
#include "config-manager-dialog.h"
BEGIN_GNOME_DECLS
#define LOCATION_LIST(obj) GTK_CHECK_CAST (obj, location_list_get_type (), LocationList)
#define LOCATION_LIST_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, location_list_get_type (), LocationListClass)
#define IS_LOCATION_LIST(obj) GTK_CHECK_TYPE (obj, location_list_get_type ())
typedef struct _LocationList LocationList;
typedef struct _LocationListClass LocationListClass;
typedef struct _LocationListPrivate LocationListPrivate;
struct _LocationList
{
GtkCTree parent;
LocationListPrivate *p;
};
struct _LocationListClass
{
GtkCTreeClass gtk_ctree_class;
};
guint location_list_get_type (void);
GtkWidget *location_list_new (gboolean sep_locations,
Archive *user_archive,
Archive *global_archive);
gchar *location_list_get_selected_location_id (LocationList *list);
Location *location_list_get_selected_location (LocationList *list);
void location_list_reread (LocationList *list);
END_GNOME_DECLS
#endif /* __LOCATION_LIST_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,117 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* location.h
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __LOCATION_H
#define __LOCATION_H
#include <gnome.h>
#include <tree.h>
#include "config-log.h"
#define LOCATION(obj) GTK_CHECK_CAST (obj, location_get_type (), Location)
#define LOCATION_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, location_get_type (), LocationClass)
#define IS_LOCATION(obj) GTK_CHECK_TYPE (obj, location_get_type ())
typedef struct _LocationClass LocationClass;
typedef struct _LocationPrivate LocationPrivate;
typedef struct _Archive Archive;
typedef int (*LocationBackendCB) (Location *, gchar *, gpointer);
struct _Location
{
GtkObject object;
LocationPrivate *p;
};
struct _LocationClass
{
GtkObjectClass parent;
};
guint location_get_type (void);
GtkObject *location_new (Archive *archive,
const gchar *locid,
Location *inherits);
GtkObject *location_open (Archive *archive,
const gchar *locid);
void location_close (Location *location);
void location_delete (Location *location);
void location_store (Location *location,
gchar *backend_id,
FILE *input);
void location_store_xml (Location *location,
gchar *backend_id,
xmlDocPtr xml_doc);
void location_rollback_backend_to (Location *location,
struct tm *date,
gchar *backend_id,
gboolean parent_chain);
void location_rollback_backends_to (Location *location,
struct tm *date,
GList *backends,
gboolean parent_chain);
void location_rollback_all_to (Location *location,
struct tm *date,
gboolean parent_chain);
void location_rollback_backend_by (Location *location,
guint steps,
gchar *backend_id,
gboolean parent_chain);
void location_rollback_id (Location *location,
gint id);
void location_dump_rollback_data (Location *location,
struct tm *date,
guint steps,
gchar *backend_id,
gboolean parent_chain,
FILE *output);
gboolean location_contains (Location *location, gchar *backend_id);
gint location_add_backend (Location *location, gchar *backend_id);
void location_remove_backend (Location *location, gchar *backend_id);
void location_foreach_backend (Location *location,
LocationBackendCB callback,
gpointer data);
GList *location_find_path_from_common_parent (Location *location,
Location *location2);
Location *location_get_parent (Location *location);
const gchar *location_get_path (Location *location);
const gchar *location_get_label (Location *location);
const gchar *location_get_id (Location *location);
void location_set_id (Location *location, const gchar *locid);
#endif /* __LOCATION */

View File

@@ -1,316 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* main.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/file.h>
#include <unistd.h>
#include <errno.h>
#include <gnome.h>
#include "util.h"
#include "archive.h"
/* Variables resulting from command line parsing */
static gboolean store;
static gboolean rollback;
static gboolean change_location;
static gboolean rename_location;
static gboolean push_config;
static gboolean add_location;
static gboolean remove_location;
static gboolean add_backend;
static gboolean remove_backend;
static gboolean global;
static const gchar *location_id;
static gchar *backend_id;
static gchar *date_str;
static gboolean all;
static gchar *revision_id;
static gboolean last;
static guint steps;
static gboolean show;
static gchar *parent_str;
static gchar *new_name;
static gboolean master;
static struct poptOption archiver_operations[] = {
{"store", 's', POPT_ARG_NONE, &store, 0,
N_("Store XML data in the archive")},
{"rollback", 'r', POPT_ARG_NONE, &rollback, 0,
N_("Roll back the configuration to a given point")},
{"change-location", 'c', POPT_ARG_NONE, &change_location, 0,
N_("Change the location profile to the given one")},
{"push-config", 'p', POPT_ARG_NONE, &push_config, 0,
N_("Push configuration data out to client machines (UNIMPLEMENTED)")},
{"rename-location", '\0', POPT_ARG_NONE, &rename_location, 0,
N_("Rename a location to a new name")},
{"add-location", '\0', POPT_ARG_NONE, &add_location, 0,
N_("Add a new location to the archive")},
{"remove-location", '\0', POPT_ARG_NONE, &remove_location, 0,
N_("Remove a location from the archive")},
{"add-backend", '\0', POPT_ARG_NONE, &add_backend, 0,
N_("Add a given backend to the given location")},
{"remove-backend", '\0', POPT_ARG_NONE, &remove_backend, 0,
N_("Remove the given backend from the given location")},
{NULL, '\0', 0, NULL, 0}
};
static struct poptOption global_options[] = {
{"global", 'g', POPT_ARG_NONE, &global, 0,
N_("Use the global repository")},
{"location", 'l', POPT_ARG_STRING, &location_id, 0,
N_("Identifier of location profile on which to operate"),
N_("LOCATION")},
{"backend", 'b', POPT_ARG_STRING, &backend_id, 0,
N_("Backend being used for this operation"), N_("BACKEND_ID")},
{NULL, '\0', 0, NULL, 0}
};
static struct poptOption rollback_options[] = {
{"date", 'd', POPT_ARG_STRING, &date_str, 0,
N_("Date to which to roll back"), N_("DATE")},
{"all", 'a', POPT_ARG_NONE, &all, 0,
N_("Roll back all configuration items")},
{"revision-id", 'i', POPT_ARG_INT, &revision_id, 0,
N_("Roll back to the revision REVISION_ID"), N_("REVISION_ID")},
{"last", 't', POPT_ARG_NONE, &last, 0,
N_("Roll back to the last known revision")},
{"steps", '\0', POPT_ARG_INT, &steps, 0,
N_("Roll back by STEPS revisions"), N_("STEPS")},
{"show", 'h', POPT_ARG_NONE, &show, 0,
N_("Don't run the backend, just dump the output")},
{NULL, '\0', 0, NULL, 0}
};
static struct poptOption add_rename_location_options[] = {
{"parent", '\0', POPT_ARG_STRING, &parent_str, 0,
N_("Parent location for the new location"), N_("PARENT")},
{"new-name", '\0', POPT_ARG_STRING, &new_name, 0,
N_("New name to assign to the location"), N_("NEW_NAME")},
{NULL, '\0', 0, NULL, 0}
};
static struct poptOption add_remove_backend_options[] = {
{"master", '\0', POPT_ARG_NONE, &master, 0,
N_("Add/remove this backend to/from the master backend list")},
{NULL, '\0', 0, NULL, 0}
};
static void
do_store (Location *location)
{
if (!backend_id) {
g_message ("No backend specified");
return;
}
location_store (location, backend_id, stdin);
}
static void
do_rollback (Location *location)
{
gint id;
struct tm *date = NULL;
if (date_str)
date = parse_date (date_str);
else if (last || steps > 0)
date = NULL;
else if (!revision_id) {
g_message ("No date specified");
return;
}
if (all) {
location_rollback_all_to (location, date, TRUE);
}
else if (backend_id && (date || last)) {
/* FIXME: Need to support specifying multiple backends */
if (show)
location_dump_rollback_data (location, date, 0,
backend_id, TRUE, stdout);
else
location_rollback_backend_to (location, date,
backend_id, TRUE);
}
else if (backend_id && steps) {
if (show)
location_dump_rollback_data (location, NULL, steps,
backend_id, TRUE, stdout);
else
location_rollback_backend_by (location, steps,
backend_id, TRUE);
}
else if (revision_id) {
sscanf (revision_id, "%x", &id);
if (id >= 0)
location_rollback_id (location, id);
else
g_message ("Bad id specified");
} else {
g_message ("No backend specified");
return;
}
}
static void
do_change_location (Archive *archive, Location *location)
{
archive_set_current_location (archive, location);
}
static void
do_rename_location (Archive *archive, Location *location)
{
gboolean is_current;
if (new_name == NULL) {
g_message ("You did not specify a new name. Try --help");
} else {
if (!strcmp (location_get_id (location),
archive_get_current_location_id (archive)))
is_current = TRUE;
else
is_current = FALSE;
location_set_id (location, new_name);
if (is_current)
archive_set_current_location_id (archive, new_name);
}
}
static void
do_add_location (Archive *archive)
{
GtkObject *location;
Location *parent_location = NULL;
if (parent_str != NULL)
parent_location = archive_get_location (archive, parent_str);
location = location_new (archive, location_id, parent_location);
}
static void
do_remove_location (Location *location)
{
location_delete (location);
}
static void
do_add_backend (Location *location)
{
location_add_backend (location, backend_id);
}
static void
do_remove_backend (Location *location)
{
location_remove_backend (location, backend_id);
}
int
main (int argc, char **argv)
{
Archive *archive;
Location *location = NULL;
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
textdomain (PACKAGE);
gnomelib_register_popt_table (global_options,
_("Global archiver options"));
gnomelib_register_popt_table (archiver_operations,
_("Archiver commands"));
gnomelib_register_popt_table (rollback_options,
_("Options for rolling back"));
gnomelib_register_popt_table (add_rename_location_options,
_("Options for adding or renaming " \
"locations"));
gnomelib_register_popt_table (add_remove_backend_options,
_("Options for adding and removing " \
"backends"));
gtk_type_init ();
gnomelib_init ("archiver", VERSION);
gnomelib_parse_args (argc, argv, 0);
archive = ARCHIVE (archive_load (global));
if (archive == NULL)
g_error ("Could not open archive");
if (location_id == NULL)
location_id = archive_get_current_location_id (archive);
if (!add_location) {
location = archive_get_location (archive, location_id);
if (location == NULL) {
if (strcmp (location_id, "default")) {
g_message ("Could not open location");
return -1;
} else {
location = LOCATION
(location_new (archive, location_id,
NULL));
}
}
}
if (store)
do_store (location);
else if (rollback)
do_rollback (location);
else if (change_location)
do_change_location (archive, location);
else if (rename_location)
do_rename_location (archive, location);
else if (add_location)
do_add_location (archive);
else if (remove_location)
do_remove_location (location);
else if (add_backend)
do_add_backend (location);
else if (remove_backend)
do_remove_backend (location);
archive_close (archive);
return 0;
}

View File

@@ -1,647 +0,0 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>Rollback-location-management</name>
<program_name>rollback-location-management</program_name>
<directory></directory>
<source_directory>src</source_directory>
<pixmaps_directory>pixmaps</pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
</project>
<widget>
<class>GnomeDialog</class>
<name>rollback_location_dialog</name>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox1</name>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area1</name>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>button1</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button2</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_APPLY</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button3</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
<widget>
<class>GtkNotebook</class>
<name>config_dialog_data</name>
<can_focus>True</can_focus>
<show_tabs>True</show_tabs>
<show_border>True</show_border>
<tab_pos>GTK_POS_TOP</tab_pos>
<scrollable>False</scrollable>
<tab_hborder>2</tab_hborder>
<tab_vborder>2</tab_vborder>
<popup_enable>False</popup_enable>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkTable</class>
<name>table1</name>
<border_width>5</border_width>
<rows>4</rows>
<columns>2</columns>
<homogeneous>False</homogeneous>
<row_spacing>5</row_spacing>
<column_spacing>5</column_spacing>
<widget>
<class>GtkRadioButton</class>
<name>rollback_all_toggle</name>
<can_focus>True</can_focus>
<signal>
<name>toggled</name>
<handler>rollback_all_toggled_cb</handler>
<last_modification_time>Tue, 19 Dec 2000 20:58:48 GMT</last_modification_time>
</signal>
<label>Restore all tools</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<group>restore_type</group>
<child>
<left_attach>0</left_attach>
<right_attach>2</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkButton</class>
<name>button4</name>
<can_focus>True</can_focus>
<label>View Logs...</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>3</top_attach>
<bottom_attach>4</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkButton</class>
<name>button5</name>
<can_focus>True</can_focus>
<label>Advanced...</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>3</top_attach>
<bottom_attach>4</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox2</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<left_attach>0</left_attach>
<right_attach>2</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>True</yfill>
</child>
<widget>
<class>GtkRadioButton</class>
<name>rollback_one_toggle</name>
<can_focus>True</can_focus>
<signal>
<name>toggled</name>
<handler>rollback_one_toggled_cb</handler>
<last_modification_time>Tue, 19 Dec 2000 20:58:59 GMT</last_modification_time>
</signal>
<label>Restore only</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<group>restore_type</group>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkOptionMenu</class>
<name>backend_select</name>
<can_focus>True</can_focus>
<items></items>
<initial_choice>0</initial_choice>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox1</name>
<homogeneous>False</homogeneous>
<spacing>5</spacing>
<child>
<left_attach>0</left_attach>
<right_attach>2</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>True</yfill>
</child>
<widget>
<class>GtkLabel</class>
<name>label3</name>
<label>Restore configuration from</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkSpinButton</class>
<name>time_count</name>
<can_focus>True</can_focus>
<signal>
<name>changed</name>
<handler>time_count_changed_cb</handler>
<last_modification_time>Tue, 19 Dec 2000 20:15:27 GMT</last_modification_time>
</signal>
<climb_rate>1</climb_rate>
<digits>0</digits>
<numeric>False</numeric>
<update_policy>GTK_UPDATE_ALWAYS</update_policy>
<snap>False</snap>
<wrap>False</wrap>
<value>1</value>
<lower>0</lower>
<upper>1000</upper>
<step>1</step>
<page>10</page>
<page_size>10</page_size>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label4</name>
<label>days ago</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>Notebook:tab</child_name>
<name>label1</name>
<label>Configuration Restoration</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkHBox</class>
<name>location_tree_box</name>
<border_width>5</border_width>
<homogeneous>False</homogeneous>
<spacing>5</spacing>
<widget>
<class>GtkVBox</class>
<name>vbox1</name>
<homogeneous>False</homogeneous>
<spacing>5</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>create_button</name>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>create_cb</handler>
<last_modification_time>Wed, 20 Dec 2000 23:51:41 GMT</last_modification_time>
</signal>
<label>Create...</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkButton</class>
<name>destroy_button</name>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>destroy_cb</handler>
<last_modification_time>Wed, 20 Dec 2000 23:51:56 GMT</last_modification_time>
</signal>
<label>Destroy...</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkButton</class>
<name>rename_button</name>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>rename_cb</handler>
<last_modification_time>Wed, 20 Dec 2000 23:52:13 GMT</last_modification_time>
</signal>
<label>Rename...</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator1</name>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkButton</class>
<name>change_location_button</name>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>change_location_cb</handler>
<last_modification_time>Wed, 20 Dec 2000 23:52:33 GMT</last_modification_time>
</signal>
<label>Change to this Location</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkButton</class>
<name>edit_button</name>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>edit_location_cb</handler>
<last_modification_time>Wed, 20 Dec 2000 23:52:51 GMT</last_modification_time>
</signal>
<label>Edit this Location</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkScrolledWindow</class>
<name>location_tree_location</name>
<hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>Placeholder</class>
</widget>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>Notebook:tab</child_name>
<name>label2</name>
<label>Location Management</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GnomeDialog</class>
<name>create_location_dialog</name>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>False</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox2</name>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area2</name>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>button11</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button12</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_APPLY</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button13</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
<widget>
<class>GtkVBox</class>
<name>create_dialog_data</name>
<homogeneous>False</homogeneous>
<spacing>5</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHBox</class>
<name>hbox4</name>
<homogeneous>False</homogeneous>
<spacing>5</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label7</name>
<label>Location name:</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>location_name_entry</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<name>label8</name>
<label>Parent Location:</label>
<justify>GTK_JUSTIFY_LEFT</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkScrolledWindow</class>
<name>location_list_location</name>
<hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>Placeholder</class>
</widget>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface>

View File

@@ -1,163 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* rollback-widget.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "rollback-widget.h"
enum {
ARG_0,
ARG_SAMPLE
};
struct _RollbackWidgetPrivate
{
/* Private data members */
};
static GtkWidgetClass *parent_class;
static void rollback_widget_init (RollbackWidget *rollback_widget);
static void rollback_widget_class_init (RollbackWidgetClass *class);
static void rollback_widget_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void rollback_widget_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void rollback_widget_finalize (GtkObject *object);
guint
rollback_widget_get_type (void)
{
static guint rollback_widget_type = 0;
if (!rollback_widget_type) {
GtkTypeInfo rollback_widget_info = {
"RollbackWidget",
sizeof (RollbackWidget),
sizeof (RollbackWidgetClass),
(GtkClassInitFunc) rollback_widget_class_init,
(GtkObjectInitFunc) rollback_widget_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
rollback_widget_type =
gtk_type_unique (gtk_widget_get_type (),
&rollback_widget_info);
}
return rollback_widget_type;
}
static void
rollback_widget_init (RollbackWidget *rollback_widget)
{
rollback_widget->p = g_new0 (RollbackWidgetPrivate, 1);
}
static void
rollback_widget_class_init (RollbackWidgetClass *class)
{
GtkObjectClass *object_class;
gtk_object_add_arg_type ("RollbackWidget::sample",
GTK_TYPE_POINTER,
GTK_ARG_READWRITE,
ARG_SAMPLE);
object_class = GTK_OBJECT_CLASS (class);
object_class->finalize = rollback_widget_finalize;
object_class->set_arg = rollback_widget_set_arg;
object_class->get_arg = rollback_widget_get_arg;
parent_class = GTK_WIDGET_CLASS
(gtk_type_class (gtk_widget_get_type ()));
}
static void
rollback_widget_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
RollbackWidget *rollback_widget;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_ROLLBACK_WIDGET (object));
rollback_widget = ROLLBACK_WIDGET (object);
switch (arg_id) {
case ARG_SAMPLE:
break;
default:
g_warning ("Bad argument set");
break;
}
}
static void
rollback_widget_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
RollbackWidget *rollback_widget;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_ROLLBACK_WIDGET (object));
rollback_widget = ROLLBACK_WIDGET (object);
switch (arg_id) {
case ARG_SAMPLE:
break;
default:
g_warning ("Bad argument get");
break;
}
}
static void
rollback_widget_finalize (GtkObject *object)
{
RollbackWidget *rollback_widget;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_ROLLBACK_WIDGET (object));
rollback_widget = ROLLBACK_WIDGET (object);
g_free (rollback_widget->p);
GTK_OBJECT_CLASS (parent_class)->finalize (object);
}
GtkObject *
rollback_widget_new (void)
{
return gtk_object_new (rollback_widget_get_type (),
NULL);
}

View File

@@ -1,57 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* rollback-widget.h
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __ROLLBACK_WIDGET_H
#define __ROLLBACK_WIDGET_H
#include <gnome.h>
BEGIN_GNOME_DECLS
#define ROLLBACK_WIDGET(obj) GTK_CHECK_CAST (obj, rollback_widget_get_type (), RollbackWidget)
#define ROLLBACK_WIDGET_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, rollback_widget_get_type (), RollbackWidgetClass)
#define IS_ROLLBACK_WIDGET(obj) GTK_CHECK_TYPE (obj, rollback_widget_get_type ())
typedef struct _RollbackWidget RollbackWidget;
typedef struct _RollbackWidgetClass RollbackWidgetClass;
typedef struct _RollbackWidgetPrivate RollbackWidgetPrivate;
struct _RollbackWidget
{
GtkWidget parent;
RollbackWidgetPrivate *p;
};
struct _RollbackWidgetClass
{
GtkWidgetClass gtk_widget_class;
};
guint rollback_widget_get_type (void);
GtkObject *rollback_widget_new (void);
END_GNOME_DECLS
#endif /* __ROLLBACK_WIDGET_H */

View File

@@ -1,97 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* util.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
/* Read a fixed-digit number from a string, advancing the string
* pointer. Return TRUE if the extraction was successful, FALSE if
* there was no number to extract or if the number was too short.
*/
gboolean
extract_number (char **str, int *number, int digits)
{
char buf[64];
if (!isdigit (**str)) return FALSE;
if (digits > 63) digits = 63;
strncpy (buf, *str, digits);
buf[digits] = '\0';
*number = atoi (buf);
if (strlen (buf) < digits) return FALSE;
*str += digits;
return TRUE;
}
struct tm *
parse_date (char *str)
{
struct tm *date;
gboolean ok;
gint value;
ok = extract_number (&str, &value, 4);
if (!ok) return NULL;
date = g_new (struct tm, 1);
date->tm_year = value - 1900;
date->tm_mon = 11;
date->tm_mday = 31;
date->tm_hour = 23;
date->tm_min = 59;
date->tm_sec = 59;
if (extract_number (&str, &value, 2))
date->tm_mon = value - 1;
else
return date;
if (extract_number (&str, &value, 2))
date->tm_mday = value;
else
return date;
if (extract_number (&str, &value, 2))
date->tm_hour = value;
else
return date;
if (extract_number (&str, &value, 2))
date->tm_min = value;
else
return date;
if (extract_number (&str, &value, 2))
date->tm_sec = value;
return date;
}

View File

@@ -1,33 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* util.h
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __UTIL_H
#define __UTIL_H
#include <time.h>
#include <glib.h>
gboolean extract_number (char **str, int *number, int digits);
struct tm *parse_date (char *str);
#endif /* __UTIL_H */

View File

@@ -1,193 +0,0 @@
Configuration rollback, location management, and cluster support
Copyright (C) 2001 Ximian, Inc.
Written by Bradford Hovinen <hovinen@ximian.com>
I. Basic architecture
A. Components
1. Ximian Configuration Manager
The GUI shell, here referred to as the Ximian Configuration Manager
(XCM), acts as launching point for the capplets and Ximian Tools,
and a control center for managing rollback, location management, and
clustering. It launches other components and knows how to find
archived configuration data for rollback. When rollback or a change of
location is required, it invokes the required backends or capplets
with the --set option and feeds the required XML to them.
2. Capplets
Capplets handle user configuration; they combine the front and back
ends into one process. They will eventually run as Bonobo controls
implementing the Bonobo::Capplet interface, but for now they are run
as regular processes. They all support the --get and --set command
line options (which will be methods in the Bonobo::Capplet
interface). --get returns an XML description of the capplet's state
for archival purposes and --set takes an XML description of the
capplet's state and applies those settings to the desktop.
3. Ximian Setup Tools (XSTs)
These programs are for system-wide configuration and must run as root
in order to apply changes. They may also run as a regular user in
`read-only' mode. They have separate front- and backends, the former
typically written in C and the latter normally written in Perl. This
facilitates in-place modification of existing configuration files
without the need for creating out own separate, incompatible way of
configuring the system. The backends support the --get and --set
arguments, analogous to the arguments in capplets mentioned above.
2. Root manager
The root manager process runs as root and is launched through
gnome-su. It accepts on stdin a set of programs to launch, one per
line, with command line arguments. XCM uses it to launch Ximian Setup
Tools so that they run as root, without needing to ask the user for a
password each time a tool is run. The root manager is run exactly once
through console-helper the first time a tool that must be run as root
is invoked. On subsequent occasions the command to start the tool is
passed to the root manager through stdin.
3. The script do-changes
do-changes is responsible for archiving changes made to the system's
configuration and passing them on to the backend, if appropriate. It
accepts a stream of XML on stdin and stores this XML in the
configuration archive directory. If a backend is specified on the
command line, it also spawns the backend process with the --set option
and feeds the XML to it through stdin.
II. Configuration process
When a user makes changes to either his own configuration or that of
the system, those changes must be archived so that the system may be
rolled back in the future. In the case of capplets, the capplet
currently dumps an XML snapshot of its current state to the script
do-changes when the user clicks `Ok'. do-changes then archives the
state in ~/.gnome/config/<location>/<revision> where <location> is the
name of the active location (cf. section IV) and <revision> is
incremented after each change.
When the capplets are converted into Bonobo controls, the situation
will be slightly different. XCM will be the recipient of the `Ok'
signal, so it will invoke the OKClicked() method of the
Bonobo::Capplet interface on the appropriate capplet. It will also
invoke the GetXML() method of the same interface in order to retrieve
an XML snapshot of the state and store that snapshot with
do-changes. Hence, much of the action moves from the capplet to XCM.
In the case of Ximian Setup Tools, the frontend passes the XML through
the do-changes script to the backend whenever the `Ok' button is
clicked. It passes to do-changes the argument --backend <backend name>
so that do-changes will also invoke the indicated backend and pass the
XML to it.
III. Rollback process
From within the XCM, the user may elect to roll back either his
personal configuration or that of the system to a particular
date. XCM looks for a revision directory in the current location
profile with the most recent modification date that is not more recent
than the date specified by the user. XCM also has a list of what
capplets (or XSTs) constitute a complete snapshot of the system's
configuration. In order to perform a complete rollback, it backtracks
through the revision directories, picking up XML snapshots of capplets
until it has a complete set and applies them through the --set
method. In the case of XSTs, the XCM knows how to invoke the backend
and does so as necessary.
IV. Location management
The system may have one or more profiles, each giving different system
configurations. For example, a user may own a laptop and wish to hook
that laptop up to different networks at different times. Each network
may be located in a different time zone, have different network
configuration parameters (e.g., DHCP vs. static IPs), and use different
default printers. When the user hooks his laptop up in a particular
network, it would be advantageous to switch to that network's
configuration with a minimum of hassle.
As mentioned above, configuration data is stored in separate
directories corresponding to the name of a given location. XCM has the
ability to apply a set of configuration files from a given location in
a manner similar to the rollback procedure described above. When the
user selects an alternative configuration, it simply goes through the
revision history for that location, pulls a complete set of
configuration files, and applies them. The procedure is similar for
both capplets and XSTs.
In addition, locations may be expressed hierarchically. For example, a
user might specify a location called `Boston' that describes language,
time zone, currency, and other locale data, and another location called
`Boston Office' that includes network parameters. `Boston Office'
inherits its locale data from `Boston', overriding the latter's
network configuration.
To implement this, each location directory contains some metadata that
describes what configuration data is valid for it and what other
configuration it inherits from. There are one or more root
configurations that contain a complete set of data. When applying a
new location, XCM looks first at that location's directory, pulling a
complete set of all the configuration data defined by that location,
and then goes to the next level up in the location hierarchy and does
the same thing. It also keeps track of the common subtree root between
the old and new locations so that only the configuration items that
actually change are collected.
From a user's perspective, the XCM will present a tree showing the
existing locations. Users may create a new location derived from an
existing one. When the user elects to configure a particular location,
the XCM shell includes icons that are grayed out, indicating that
those configuration items are not set in this particular location. If
the user attempts to change them, they become specific to that
particular location and are recolored accordingly.
V. Clustering
A single server may archive the configuration for a large number of
individual workstations, providing configuration data to each of the
clients on demand. An administrator can then push configuration
updates out to each machine with the press of a button, rather than
having to go to each machine and update it manually.
To enable this, each client machine will run a daemon that accepts
configuration data pushed out by the server. Some sort of public key
signing will be implemented to ensure that this is done securely. On
the server end, a series of host groups is maintained, each one
containing a set of hosts. These form the top two levels of a
configuration hierarchy not unlike what is described above. Each host
may override certain configuration values for the cluster as a
whole. The cluster may also have multiple `locations', e.g. for
configuring a computer lab for computer science during one class and
for math during another. Locations may be selected down to the
granularity of a single host, or for the entire cluster at
once. Cluster-wide configurations occur between the cluster and host
level in the configuration hierarchy.
VI. Issues
1. We need a way to get an XML state without actually applying
changes, so that the user can configure a location without switching
to it.
2. Can we make the XST frontends Bonobo controls, and can we have them
run as the regular user rather than as root? This would ensure that
certain user interface preferences, such as themes, are kept
consistent for a given user between capplets and XSTs. The way to
implement this is to have a method on the XCM interface called
RunBackend() which returns a BonoboObject referring to the backend
that implements the Bonobo::XSTBackend interface, which is similar to
the Bonobo::Capplet interface mentioned above. The interface defines
the GetXML and SetXML methods. The object should also implement
another, XST-specific interface to facilitate setting specific
configuration variables, so that live update may be implemented. The
root manager must then be extended to support some sort of secure
forwarding, allowing the user to access that particular CORBA object.
3. If we make the XSTs into Bonobo controls, can we give them the same
Bonobo::Capplet interface that is given to the Capplets? This would
make everything a bit simpler from the XCM's perspective, since it
then does not need to know the difference between Capplets and
XSTs -- it then only needs to implement the RunBackend() method for
the benefit of the XSTs.

View File

@@ -1,4 +0,0 @@
XIMIAN_ARCHIVER_LIBDIR="@GNOME_LIBDIR@"
XIMIAN_ARCHIVER_LIBS="-lximian_archiver @GNOMEUI_LIBS@"
XIMIAN_ARCHIVER_INCLUDEDIR="@GNOME_INCLUDEDIR@"
MODULE_VERSION="ximian-archiver-@VERSION@"

View File

@@ -1,141 +0,0 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="GNOME Control Center"
(test -f $srcdir/configure.in \
&& test -d $srcdir/capplets \
&& test -d $srcdir/control-center) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level "\`$PKG_NAME\'" directory"
exit 1
}
ORIGDIR=`pwd`
cd $srcdir
PROJECT=control-center
TEST_TYPE=-f
DIE=0
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have autoconf installed to compile $PROJECT."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have automake installed to compile $PROJECT."
echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.4.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
(grep "^AM_PROG_LIBTOOL" configure.in >/dev/null) && {
(libtool --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`libtool' installed to compile $PROJECT."
echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2d.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
}
grep "^AM_GNU_GETTEXT" configure.in >/dev/null && {
grep "sed.*POTFILES" $srcdir/configure.in >/dev/null || \
(gettext --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`gettext' installed to compile $PROJECT."
echo "Get ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
}
if test "$DIE" -eq 1; then
exit 1
fi
if test -z "$*"; then
echo "I am going to run ./configure with no arguments - if you wish "
echo "to pass any to it, please specify them on the $0 command line."
fi
case $CC in
*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;;
esac
for coin in `find . -name configure.in -print`
do
dr=`dirname $coin`
if test -f $dr/NO-AUTO-GEN; then
echo skipping $dr -- flagged as no auto-gen
else
echo processing $dr
macrodirs=`sed -n -e 's,AM_ACLOCAL_INCLUDE(\(.*\)),\1,gp' < $coin`
( cd $dr
aclocalinclude="$ACLOCAL_FLAGS"
for k in $macrodirs; do
if test -d $k; then
aclocalinclude="$aclocalinclude -I $k"
##else
## echo "**Warning**: No such directory \`$k'. Ignored."
fi
done
if grep "^AM_GNU_GETTEXT" configure.in >/dev/null; then
if grep "sed.*POTFILES" configure.in >/dev/null; then
: do nothing -- we still have an old unmodified configure.in
else
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running gettextize... Ignore non-fatal messages."
echo "no" | gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
fi
if grep "^AM_GNOME_GETTEXT" configure.in >/dev/null; then
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running gettextize... Ignore non-fatal messages."
echo "no" | gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then
echo "Running libtoolize..."
libtoolize --force --copy
fi
echo "Running aclocal $aclocalinclude ..."
aclocal $aclocalinclude
if grep "^AM_CONFIG_HEADER" configure.in >/dev/null; then
echo "Running autoheader..."
autoheader
fi
echo "Running automake --gnu $am_opt ..."
automake --add-missing --gnu $am_opt
echo "Running autoconf ..."
autoconf
)
fi
done
conf_flags="--enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c
cd "$ORIGDIR"
if test x$NOCONFIGURE = x; then
echo Running $srcdir/configure $conf_flags "$@" ...
$srcdir/configure $conf_flags "$@" \
&& echo Now type \`make\' to compile $PROJECT || exit 1
else
echo Skipping configure process.
fi

View File

@@ -1,9 +0,0 @@
always_built_SUBDIRS = desktop-links new-mouse-properties \
new-screensaver-properties new-background-properties \
theme-switcher new-sound-properties new-bell-properties \
new-ui-properties url-properties gnome-edit-properties \
session-properties wm-properties new-keyboard-properties \
mime-type
SUBDIRS = $(always_built_SUBDIRS)

View File

@@ -1,8 +0,0 @@
Makefile
Makefile.in
.deps
.libs
*.o
*.lo
*.la
background-properties-capplet

View File

@@ -1,37 +0,0 @@
Applicationsdir = $(datadir)/control-center/Desktop
Applications_DATA = \
background-properties.desktop
pApplicationsdir = $(datadir)/gnome/apps/Settings/Desktop
pApplications_DATA = \
background-properties.desktop
Gladedir = $(datadir)/control-center-data
Glade_DATA = \
background-properties.glade
glade_msgs = \
background-properties.glade.h
EXTRA_DIST = $(Applications_DATA) $(Glade_DATA) $(glade_msgs)
INCLUDES = \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-DGNOME_ICONDIR=\""${prefix}/share/pixmaps"\" \
-DG_LOG_DOMAIN=\"background-properties\" \
-DGLADE_DATADIR=\""$(Gladedir)"\" \
$(GNOME_INCLUDEDIR) \
$(BG_CAPPLET_CFLAGS) \
-I$(top_srcdir)/ \
-I$(top_srcdir)/intl
bin_PROGRAMS = background-properties-capplet
background_properties_capplet_SOURCES = \
prefs-widget.c prefs-widget.h \
preferences.c preferences.h \
applier.c applier.h \
main.c
background_properties_capplet_LDADD = \
$(GNOME_LIBDIR) $(BG_CAPPLET_LIBS)

File diff suppressed because it is too large Load Diff

View File

@@ -1,64 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* applier.h
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen <hovinen@helixcode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __APPLIER_H
#define __APPLIER_H
#include <gtk/gtk.h>
#include <X11/Xlib.h>
#include <pthread.h>
#include "preferences.h"
#define APPLIER(obj) GTK_CHECK_CAST (obj, applier_get_type (), Applier)
#define APPLIER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, applier_get_type (), ApplierClass)
#define IS_APPLIER(obj) GTK_CHECK_TYPE (obj, applier_get_type ())
typedef struct _Applier Applier;
typedef struct _ApplierClass ApplierClass;
typedef struct _ApplierPrivate ApplierPrivate;
struct _Applier
{
GtkObject object;
ApplierPrivate *private;
};
struct _ApplierClass
{
GtkObjectClass klass;
};
guint applier_get_type (void);
GtkObject *applier_new (void);
void applier_destroy (GtkObject *object);
void applier_apply_prefs (Applier *applier, Preferences *prefs,
gboolean do_root, gboolean do_preview);
GtkWidget *applier_class_get_preview_widget (void);
#endif /* __APPLIER_H */

View File

@@ -1,54 +0,0 @@
[Desktop Entry]
Name=Background
Name[da]=Baggrund
Name[ca]=Propietats del fons
Name[cs]=Pozadí
Name[de]=Hintergrund
Name[es]=Propiedades del tapiz
Name[et]=Taust
Name[fi]=Tausta
Name[fr]=Arrière-plan
Name[gl]=Propiedades do tapiz
Name[hu]=Háttér
Name[it]=Sfondo
Name[ja]=¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É
Name[ko]=¹è°æ
Name[lt]=Fonas
Name[no]=Bakgrunn
Name[pl]=T³o
Name[pt]=Propriedades do Fundo
Name[pt_BR]=Fundo
Name[ro]=Fundal
Name[ru]=æÏÎ
Name[sl]=Ozadje
Name[sv]=Bakgrund
Name[uk]=ôÌÏ
Name[wa]=Fond do scribanne
Name[zh_TW.Big5]=®à­±­I´º
Name[zh_CN.GB2312]=×ÀÃæ±³¾°
Comment=Configuration of the desktop's background
Comment[cs]=Nastavení pozadí pracovní plochy
Comment[da]=Indstil din skrivebordsbaggrund
Comment[de]=Konfiguration des Desktophintergrundes
Comment[es]=Configuración del tapiz del escritorio
Comment[et]=Töölaua tausta häälestus
Comment[fi]=Työpöydän taustan asetukset
Comment[fr]=Configuration des propriétés de l'arrière-plan
Comment[gl]=Configuración do tapiz do escritorio
Comment[it]=Impostazioni dello sfondo del desktop
Comment[ja]=¥Ç¥¹¥¯¥È¥Ã¥×ÇØ·Ê¤ÎÀßÄê
Comment[lt]=Darbalaukio fono nustatymas
Comment[no]=Konfigurasjon av skrivebordsbakgrunn
Comment[pl]=Konfiguracja t³a
Comment[pt_BR]=Configuração do fundo da área de trabalho
Comment[ro]=Configuraþia fundalului de desktop
Comment[sl]=Nastavitev ozadja namizja
Comment[sv]=Konfiguration av skrivbordsbakgrund
Comment[uk]=ëÏÎÆ¦ÇÕÒÕ×ÁÎÎÑ ÔÌÁ
Comment[wa]=Apontiaedje do fond do scribanne
Comment[zh_TW.Big5]=³]©w®à­±­I´º¼Ë¦¡
Comment[zh_CN.GB2312]=É趨×ÀÃæ±³¾°Ñùʽ
Exec=background-properties-capplet
Icon=gnome-ccbackground.png
Terminal=0
Type=Application

View File

@@ -1,540 +0,0 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>New-background-properties</name>
<program_name>new-background-properties</program_name>
<directory></directory>
<source_directory>src</source_directory>
<pixmaps_directory>pixmaps</pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
<output_translatable_strings>True</output_translatable_strings>
<translatable_strings_file>background-properties.glade.h</translatable_strings_file>
</project>
<widget>
<class>GtkWindow</class>
<name>window1</name>
<title>window1</title>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<widget>
<class>GtkVBox</class>
<name>prefs_widget</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<widget>
<class>GtkEventBox</class>
<name>monitor_frame</name>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>Placeholder</class>
</widget>
</widget>
<widget>
<class>GtkCheckButton</class>
<name>disable_toggle</name>
<can_focus>True</can_focus>
<signal>
<name>toggled</name>
<handler>disable_toggled_cb</handler>
<last_modification_time>Wed, 06 Sep 2000 00:15:45 GMT</last_modification_time>
</signal>
<label>Use GNOME for setting background</label>
<active>True</active>
<draw_indicator>True</draw_indicator>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox2</name>
<homogeneous>False</homogeneous>
<spacing>4</spacing>
<child>
<padding>4</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkFrame</class>
<name>color_frame</name>
<label>Colors</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkTable</class>
<name>table4</name>
<border_width>4</border_width>
<rows>3</rows>
<columns>2</columns>
<homogeneous>False</homogeneous>
<row_spacing>4</row_spacing>
<column_spacing>4</column_spacing>
<widget>
<class>GtkLabel</class>
<name>label5</name>
<label>Effect</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label6</name>
<label>Color 1</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label7</name>
<label>Color 2</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GnomeColorPicker</class>
<name>color1_select</name>
<can_focus>True</can_focus>
<signal>
<name>color_set</name>
<handler>color1_select_color_set_cb</handler>
<last_modification_time>Sat, 09 Dec 2000 01:18:26 GMT</last_modification_time>
</signal>
<dither>True</dither>
<use_alpha>False</use_alpha>
<title>Pick a color</title>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GnomeColorPicker</class>
<name>color2_select</name>
<can_focus>True</can_focus>
<signal>
<name>color_set</name>
<handler>color2_select_color_set_cb</handler>
<last_modification_time>Sat, 09 Dec 2000 01:18:35 GMT</last_modification_time>
</signal>
<dither>True</dither>
<use_alpha>False</use_alpha>
<title>Pick a color</title>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkOptionMenu</class>
<name>color_option</name>
<can_focus>True</can_focus>
<items>Solid Color
Vertical Gradient
Horizontal Gradient
</items>
<initial_choice>1</initial_choice>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
</widget>
</widget>
<widget>
<class>GtkFrame</class>
<name>wallpaper_frame</name>
<label>Wallpaper</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkTable</class>
<name>table3</name>
<border_width>4</border_width>
<rows>2</rows>
<columns>3</columns>
<homogeneous>False</homogeneous>
<row_spacing>4</row_spacing>
<column_spacing>4</column_spacing>
<widget>
<class>GtkLabel</class>
<name>label3</name>
<label>File</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label4</name>
<label>Effect</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkOptionMenu</class>
<name>wp_effect_option</name>
<can_focus>True</can_focus>
<items>Tiled
Centered
Scaled (keep aspect ratio)
Stretched (change aspect ratio)
Embossed
</items>
<initial_choice>0</initial_choice>
<child>
<left_attach>1</left_attach>
<right_attach>3</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkButton</class>
<name>browse_button</name>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>browse_button_cb</handler>
<last_modification_time>Fri, 08 Dec 2000 21:55:52 GMT</last_modification_time>
</signal>
<label>Browse...</label>
<child>
<left_attach>2</left_attach>
<right_attach>3</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>False</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkOptionMenu</class>
<name>wp_file_option</name>
<width>66</width>
<can_focus>True</can_focus>
<items>(None)
</items>
<initial_choice>0</initial_choice>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GtkCheckButton</class>
<name>adjust_opacity_toggle</name>
<can_focus>True</can_focus>
<signal>
<name>toggled</name>
<handler>adjust_opacity_toggled_cb</handler>
<last_modification_time>Thu, 21 Dec 2000 19:54:21 GMT</last_modification_time>
</signal>
<label>Adjust wallpaper's opacity</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>opacity_box</name>
<homogeneous>False</homogeneous>
<spacing>4</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label10</name>
<width>16</width>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label8</name>
<label>More Transparent</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHScale</class>
<name>opacity_adjust</name>
<can_focus>True</can_focus>
<draw_value>False</draw_value>
<value_pos>GTK_POS_TOP</value_pos>
<digits>1</digits>
<policy>GTK_UPDATE_CONTINUOUS</policy>
<value>0</value>
<lower>0</lower>
<upper>0</upper>
<step>0</step>
<page>0</page>
<page_size>0</page_size>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label9</name>
<label>More Solid</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkCheckButton</class>
<name>auto_apply</name>
<can_focus>True</can_focus>
<signal>
<name>toggled</name>
<handler>auto_apply_toggled_cb</handler>
<last_modification_time>Thu, 21 Dec 2000 19:52:25 GMT</last_modification_time>
</signal>
<label>Apply changes automatically</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
</widget>
</GTK-Interface>

View File

@@ -1,33 +0,0 @@
/*n * Fil med oversettbare strenger generert av Glade.
* Legg till denne filen i ditt prosjekts POTFILES.in.
* IKKE kompiler den som en del av applikasjonen din.
*/
gchar *s = N_("window1");
gchar *s = N_("Use GNOME for setting background");
gchar *s = N_("Colors");
gchar *s = N_("Effect");
gchar *s = N_("Color 1");
gchar *s = N_("Color 2");
gchar *s = N_("Pick a color");
gchar *s = N_("Pick a color");
gchar *s = N_("Solid Color\n"
"Vertical Gradient\n"
"Horizontal Gradient\n"
"");
gchar *s = N_("Wallpaper");
gchar *s = N_("File");
gchar *s = N_("Effect");
gchar *s = N_("Tiled\n"
"Centered\n"
"Scaled (keep aspect ratio)\n"
"Stretched (change aspect ratio)\n"
"Embossed\n"
"");
gchar *s = N_("Browse...");
gchar *s = N_("(None)\n"
"");
gchar *s = N_("Adjust wallpaper's opacity");
gchar *s = N_("More Transparent");
gchar *s = N_("More Solid");
gchar *s = N_("Apply changes automatically");

View File

@@ -1,230 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* main.c
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen (hovinen@helixcode.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gtk/gtk.h>
#include <gnome.h>
#include <libgnomeui/gnome-window-icon.h>
#include <tree.h>
#include <parser.h>
#include <glade/glade.h>
#include <capplet-widget.h>
#include <ximian-archiver/archive.h>
#include <ximian-archiver/location.h>
#include "preferences.h"
#include "prefs-widget.h"
static Preferences *prefs;
static Preferences *old_prefs;
static PrefsWidget *prefs_widget;
static guint ok_handler_id;
static guint cancel_handler_id;
static void
store_archive_data (void)
{
Archive *archive;
Location *location;
xmlDocPtr xml_doc;
archive = ARCHIVE (archive_load (FALSE));
location = archive_get_current_location (archive);
xml_doc = preferences_write_xml (prefs);
location_store_xml (location, "background-properties-capplet",
xml_doc);
xmlFreeDoc (xml_doc);
archive_close (archive);
}
static void
ok_cb (GtkWidget *widget)
{
preferences_save (prefs);
preferences_apply_now (prefs);
gtk_signal_disconnect (GTK_OBJECT (prefs_widget), ok_handler_id);
gtk_signal_disconnect (GTK_OBJECT (prefs_widget), cancel_handler_id);
gtk_object_destroy (GTK_OBJECT (prefs_widget));
store_archive_data ();
}
static void
cancel_cb (GtkWidget *widget)
{
preferences_save (old_prefs);
preferences_apply_now (old_prefs);
gtk_signal_disconnect (GTK_OBJECT (prefs_widget), ok_handler_id);
gtk_signal_disconnect (GTK_OBJECT (prefs_widget), cancel_handler_id);
gtk_object_destroy (GTK_OBJECT (prefs_widget));
}
static void
setup_capplet_widget (void)
{
preferences_freeze (prefs);
prefs_widget = PREFS_WIDGET (prefs_widget_new (prefs));
ok_handler_id =
gtk_signal_connect (GTK_OBJECT (prefs_widget), "ok",
GTK_SIGNAL_FUNC (ok_cb), NULL);
cancel_handler_id =
gtk_signal_connect (GTK_OBJECT (prefs_widget), "cancel",
GTK_SIGNAL_FUNC (cancel_cb), NULL);
gtk_widget_show_all (GTK_WIDGET (prefs_widget));
preferences_thaw (prefs);
}
static void
do_get_xml (void)
{
Preferences *prefs;
xmlDocPtr doc;
prefs = PREFERENCES (preferences_new ());
preferences_load (prefs);
doc = preferences_write_xml (prefs);
xmlDocDump (stdout, doc);
gtk_object_destroy (GTK_OBJECT (prefs));
}
static void
do_set_xml (void)
{
Preferences *prefs;
xmlDocPtr doc;
char *buffer = NULL;
int len = 0;
while (!feof (stdin)) {
if (!len) buffer = g_new (char, 16384);
else buffer = g_renew (char, buffer, len + 16384);
fread (buffer + len, 1, 16384, stdin);
len += 16384;
}
doc = xmlParseMemory (buffer, strlen (buffer));
prefs = preferences_read_xml (doc);
if (prefs) {
preferences_save (prefs);
preferences_apply_now (prefs);
} else {
g_warning ("Error while reading the screensaver config file");
}
}
static void
do_restore_from_defaults (void)
{
prefs = PREFERENCES (preferences_new ());
preferences_save (prefs);
preferences_apply_now (prefs);
}
int
main (int argc, char **argv)
{
GnomeClient *client;
GnomeClientFlags flags;
gint token, res;
gchar *restart_args[3];
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
textdomain (PACKAGE);
glade_gnome_init ();
res = gnome_capplet_init ("background-properties-capplet",
VERSION, argc, argv, NULL,
0, NULL);
if (res < 0) {
g_error ("Could not initialize the capplet.");
}
else if (res == 3) {
do_get_xml ();
return 0;
}
else if (res == 4) {
do_set_xml ();
return 0;
}
else if (res == 5) {
do_restore_from_defaults ();
return 0;
}
client = gnome_master_client ();
flags = gnome_client_get_flags (client);
if (flags & GNOME_CLIENT_IS_CONNECTED) {
token = gnome_startup_acquire_token
("GNOME_BACKGROUND_PROPERTIES",
gnome_client_get_id (client));
if (token) {
gnome_client_set_priority (client, 20);
gnome_client_set_restart_style (client,
GNOME_RESTART_ANYWAY);
restart_args[0] = argv[0];
restart_args[1] = "--init-session-settings";
restart_args[2] = NULL;
gnome_client_set_restart_command (client, 2,
restart_args);
} else {
gnome_client_set_restart_style (client,
GNOME_RESTART_NEVER);
}
} else {
token = 1;
}
gnome_window_icon_set_default_from_file
(GNOME_ICONDIR"/gnome-ccbackground.png");
prefs = PREFERENCES (preferences_new ());
preferences_load (prefs);
if (token) {
preferences_apply_now (prefs);
}
if (!res) {
old_prefs = PREFERENCES (preferences_clone (prefs));
setup_capplet_widget ();
capplet_gtk_main ();
}
return 0;
}

View File

@@ -1,542 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* preferences.c
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen <hovinen@helixcode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <gnome.h>
#include <gdk-pixbuf/gdk-pixbuf-xlibrgb.h>
#include "preferences.h"
#include "applier.h"
static GtkObjectClass *parent_class;
static Applier *applier = NULL;
static void preferences_init (Preferences *prefs);
static void preferences_class_init (PreferencesClass *class);
static gint xml_read_int (xmlNodePtr node,
gchar *propname);
static xmlNodePtr xml_write_int (gchar *name,
gchar *propname,
gint number);
static gint apply_timeout_cb (Preferences *prefs);
static GdkColor *read_color_from_string (gchar *string);
guint
preferences_get_type (void)
{
static guint preferences_type = 0;
if (!preferences_type) {
GtkTypeInfo preferences_info = {
"Preferences",
sizeof (Preferences),
sizeof (PreferencesClass),
(GtkClassInitFunc) preferences_class_init,
(GtkObjectInitFunc) preferences_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
preferences_type =
gtk_type_unique (gtk_object_get_type (),
&preferences_info);
}
return preferences_type;
}
static void
preferences_init (Preferences *prefs)
{
prefs->frozen = FALSE;
prefs->color1 = NULL;
prefs->color2 = NULL;
prefs->wallpaper_filename = NULL;
prefs->wallpaper_sel_path = NULL;
}
static void
preferences_class_init (PreferencesClass *class)
{
GtkObjectClass *object_class;
object_class = (GtkObjectClass *) class;
object_class->destroy = preferences_destroy;
parent_class =
GTK_OBJECT_CLASS (gtk_type_class (gtk_object_get_type ()));
if (applier == NULL)
applier = APPLIER (applier_new ());
}
GtkObject *
preferences_new (void)
{
GtkObject *object;
object = gtk_type_new (preferences_get_type ());
return object;
}
GtkObject *
preferences_clone (Preferences *prefs)
{
GtkObject *object;
Preferences *new_prefs;
g_return_val_if_fail (prefs != NULL, NULL);
g_return_val_if_fail (IS_PREFERENCES (prefs), NULL);
object = preferences_new ();
new_prefs = PREFERENCES (object);
new_prefs->enabled = prefs->enabled;
new_prefs->gradient_enabled = prefs->gradient_enabled;
new_prefs->wallpaper_enabled = prefs->wallpaper_enabled;
new_prefs->orientation = prefs->orientation;
new_prefs->wallpaper_type = prefs->wallpaper_type;
if (prefs->color1)
new_prefs->color1 = gdk_color_copy (prefs->color1);
if (prefs->color2)
new_prefs->color2 = gdk_color_copy (prefs->color2);
new_prefs->wallpaper_filename = g_strdup (prefs->wallpaper_filename);
new_prefs->wallpaper_sel_path = g_strdup (prefs->wallpaper_sel_path);;
new_prefs->auto_apply = prefs->auto_apply;
new_prefs->adjust_opacity = prefs->adjust_opacity;
new_prefs->opacity = prefs->opacity;
return object;
}
void
preferences_destroy (GtkObject *object)
{
Preferences *prefs;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_PREFERENCES (object));
prefs = PREFERENCES (object);
g_free (prefs->wallpaper_filename);
g_free (prefs->wallpaper_sel_path);
parent_class->destroy (object);
}
void
preferences_load (Preferences *prefs)
{
gchar *string, *wp, *wp1;
int i, wps;
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
if (prefs->color1) g_free (prefs->color1);
string = gnome_config_get_string
("/Background/Default/color1=#39374b");
prefs->color1 = read_color_from_string (string);
g_free (string);
if (prefs->color2) g_free (prefs->color2);
string = gnome_config_get_string
("/Background/Default/color2=#42528f");
prefs->color2 = read_color_from_string (string);
g_free (string);
string = gnome_config_get_string ("/Background/Default/Enabled=True");
prefs->enabled = !(g_strcasecmp (string, "True"));
g_free (string);
string = gnome_config_get_string ("/Background/Default/type=simple");
if (!g_strcasecmp (string, "wallpaper"))
prefs->wallpaper_enabled = TRUE;
else if (g_strcasecmp (string, "simple"))
prefs->wallpaper_enabled = FALSE;
g_free (string);
string = gnome_config_get_string ("/Background/Default/simple=gradent");
if (!g_strcasecmp (string, "gradient"))
prefs->gradient_enabled = TRUE;
else if (g_strcasecmp (string, "solid"))
prefs->gradient_enabled = FALSE;
g_free (string);
string = gnome_config_get_string
("/Background/Default/gradient=vertical");
if (!g_strcasecmp (string, "vertical"))
prefs->orientation = ORIENTATION_VERT;
else if (!g_strcasecmp (string, "horizontal"))
prefs->orientation = ORIENTATION_HORIZ;
g_free (string);
prefs->wallpaper_type =
gnome_config_get_int ("/Background/Default/wallpaperAlign=0");
prefs->wallpaper_filename =
gnome_config_get_string ("/Background/Default/wallpaper=(None)");
prefs->wallpaper_sel_path =
gnome_config_get_string
("/Background/Default/wallpapers_dir=./");
prefs->auto_apply = gnome_config_get_bool ("/Background/Default/autoApply=true");
if (!g_strcasecmp (prefs->wallpaper_filename, "(None)")) {
g_free(prefs->wallpaper_filename);
prefs->wallpaper_filename = NULL;
prefs->wallpaper_enabled = FALSE;
} else {
prefs->wallpaper_enabled = TRUE;
}
wps = gnome_config_get_int ("/Background/Default/wallpapers=0");
for (i = 0; i < wps; i++) {
wp = g_strdup_printf ("/Background/Default/wallpaper%d", i+1);
wp1 = gnome_config_get_string (wp);
g_free (wp);
if (!wp1) continue;
prefs->wallpapers = g_slist_prepend (prefs->wallpapers, wp1);
}
prefs->wallpapers = g_slist_reverse (prefs->wallpapers);
prefs->adjust_opacity = gnome_config_get_bool ("/Background/Default/adjustOpacity=true");
prefs->opacity = gnome_config_get_int ("/Background/Default/opacity=255");
}
void
preferences_save (Preferences *prefs)
{
char buffer[16];
char *wp;
GSList *item;
int i;
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
snprintf (buffer, sizeof(buffer), "#%02x%02x%02x",
prefs->color1->red >> 8,
prefs->color1->green >> 8,
prefs->color1->blue >> 8);
gnome_config_set_string ("/Background/Default/color1", buffer);
snprintf (buffer, sizeof(buffer), "#%02x%02x%02x",
prefs->color2->red >> 8,
prefs->color2->green >> 8,
prefs->color2->blue >> 8);
gnome_config_set_string ("/Background/Default/color2", buffer);
gnome_config_set_string ("/Background/Default/Enabled",
(prefs->enabled) ? "True" : "False");
gnome_config_set_string ("/Background/Default/simple",
(prefs->gradient_enabled) ?
"gradient" : "solid");
gnome_config_set_string ("/Background/Default/gradient",
(prefs->orientation == ORIENTATION_VERT) ?
"vertical" : "horizontal");
gnome_config_set_string ("/Background/Default/wallpaper",
(prefs->wallpaper_enabled) ?
prefs->wallpaper_filename : "none");
gnome_config_set_int ("/Background/Default/wallpaperAlign",
prefs->wallpaper_type);
gnome_config_set_int ("/Background/Default/wallpapers",
g_slist_length (prefs->wallpapers));
for (i = 1, item = prefs->wallpapers; item; i++, item = item->next) {
wp = g_strdup_printf ("/Background/Default/wallpaper%d", i);
gnome_config_set_string (wp, (char *)item->data);
g_free (wp);
}
gnome_config_set_bool ("/Background/Default/autoApply", prefs->auto_apply);
gnome_config_set_bool ("/Background/Default/adjustOpacity", prefs->adjust_opacity);
gnome_config_set_int ("/Background/Default/opacity",
prefs->opacity);
gnome_config_sync ();
}
void
preferences_changed (Preferences *prefs)
{
if (prefs->frozen) return;
if (prefs->timeout_id)
gtk_timeout_remove (prefs->timeout_id);
if (prefs->auto_apply)
prefs->timeout_id =
gtk_timeout_add (2000, (GtkFunction) apply_timeout_cb,
prefs);
applier_apply_prefs (applier, prefs, FALSE, TRUE);
}
void
preferences_apply_now (Preferences *prefs)
{
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
if (prefs->timeout_id)
gtk_timeout_remove (prefs->timeout_id);
prefs->timeout_id = 0;
applier_apply_prefs (applier, prefs, TRUE, FALSE);
}
void
preferences_apply_preview (Preferences *prefs)
{
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
applier_apply_prefs (applier, prefs, FALSE, TRUE);
}
void
preferences_freeze (Preferences *prefs)
{
prefs->frozen = TRUE;
}
void
preferences_thaw (Preferences *prefs)
{
prefs->frozen = FALSE;
}
Preferences *
preferences_read_xml (xmlDocPtr xml_doc)
{
Preferences *prefs;
xmlNodePtr root_node, node;
char *str;
prefs = PREFERENCES (preferences_new ());
root_node = xmlDocGetRootElement (xml_doc);
if (strcmp (root_node->name, "background-properties"))
return NULL;
prefs->wallpaper_enabled = FALSE;
prefs->gradient_enabled = FALSE;
prefs->orientation = ORIENTATION_VERT;
if (prefs->color1) {
gdk_color_free (prefs->color1);
prefs->color1 = NULL;
}
if (prefs->color2) {
gdk_color_free (prefs->color2);
prefs->color2 = NULL;
}
for (node = root_node->childs; node; node = node->next) {
if (!strcmp (node->name, "bg-color1"))
prefs->color1 = read_color_from_string
(xmlNodeGetContent (node));
else if (!strcmp (node->name, "bg-color2"))
prefs->color2 = read_color_from_string
(xmlNodeGetContent (node));
else if (!strcmp (node->name, "enabled"))
prefs->enabled = TRUE;
else if (!strcmp (node->name, "wallpaper"))
prefs->wallpaper_enabled = TRUE;
else if (!strcmp (node->name, "gradient"))
prefs->gradient_enabled = TRUE;
else if (!strcmp (node->name, "orientation")) {
str = xmlNodeGetContent (node);
if (!g_strcasecmp (str, "horizontal"))
prefs->orientation = ORIENTATION_HORIZ;
else if (!g_strcasecmp (str, "vertical"))
prefs->orientation = ORIENTATION_VERT;
}
else if (!strcmp (node->name, "wallpaper-type"))
prefs->wallpaper_type = xml_read_int (node, NULL);
else if (!strcmp (node->name, "wallpaper-filename"))
prefs->wallpaper_filename =
g_strdup (xmlNodeGetContent (node));
else if (!strcmp (node->name, "wallpaper-sel-path"))
prefs->wallpaper_sel_path =
g_strdup (xmlNodeGetContent (node));
else if (!strcmp (node->name, "auto-apply"))
prefs->auto_apply = TRUE;
else if (!strcmp (node->name, "adjust-opacity"))
prefs->adjust_opacity = TRUE;
else if (!strcmp (node->name, "opacity"))
prefs->opacity = xml_read_int (node, NULL);
}
return prefs;
}
xmlDocPtr
preferences_write_xml (Preferences *prefs)
{
xmlDocPtr doc;
xmlNodePtr node;
char tmp[16];
doc = xmlNewDoc ("1.0");
node = xmlNewDocNode (doc, NULL, "background-properties", NULL);
snprintf (tmp, sizeof (tmp), "#%02x%02x%02x",
prefs->color1->red >> 8,
prefs->color1->green >> 8,
prefs->color1->blue >> 8);
xmlNewChild (node, NULL, "bg-color1", tmp);
snprintf (tmp, sizeof (tmp), "#%02x%02x%02x",
prefs->color2->red >> 8,
prefs->color2->green >> 8,
prefs->color2->blue >> 8);
xmlNewChild (node, NULL, "bg-color2", tmp);
if (prefs->enabled)
xmlNewChild (node, NULL, "enabled", NULL);
if (prefs->wallpaper_enabled)
xmlNewChild (node, NULL, "wallpaper", NULL);
if (prefs->gradient_enabled)
xmlNewChild (node, NULL, "gradient", NULL);
xmlNewChild (node, NULL, "orientation",
(prefs->orientation == ORIENTATION_VERT) ?
"vertical" : "horizontal");
xmlAddChild (node, xml_write_int ("wallpaper-type", NULL,
prefs->wallpaper_type));
xmlNewChild (node, NULL, "wallpaper-filename",
prefs->wallpaper_filename);
xmlNewChild (node, NULL, "wallpaper-sel-path",
prefs->wallpaper_sel_path);
if (prefs->auto_apply)
xmlNewChild (node, NULL, "auto-apply", NULL);
if (prefs->adjust_opacity)
xmlNewChild (node, NULL, "adjust-opacity", NULL);
xmlAddChild (node, xml_write_int ("opacity", NULL,
prefs->opacity));
xmlDocSetRootElement (doc, node);
return doc;
}
/* Read a numeric value from a node */
static gint
xml_read_int (xmlNodePtr node, char *propname)
{
char *text;
if (propname == NULL)
text = xmlNodeGetContent (node);
else
text = xmlGetProp (node, propname);
if (text == NULL)
return 0;
else
return atoi (text);
}
/* Write out a numeric value in a node */
static xmlNodePtr
xml_write_int (gchar *name, gchar *propname, gint number)
{
xmlNodePtr node;
gchar *str;
g_return_val_if_fail (name != NULL, NULL);
str = g_strdup_printf ("%d", number);
node = xmlNewNode (NULL, name);
if (propname == NULL)
xmlNodeSetContent (node, str);
else
xmlSetProp (node, propname, str);
g_free (str);
return node;
}
static gint
apply_timeout_cb (Preferences *prefs)
{
preferences_apply_now (prefs);
return TRUE;
}
static GdkColor *
read_color_from_string (gchar *string)
{
GdkColor *color;
gint32 rgb;
color = g_new0 (GdkColor, 1);
gdk_color_parse (string, color);
rgb = ((color->red >> 8) << 16) ||
((color->green >> 8) << 8) ||
(color->blue >> 8);
color->pixel = xlib_rgb_xpixel_from_rgb (rgb);
return color;
}

View File

@@ -1,96 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* preferences.h
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen <hovinen@helixcode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __PREFERENCES_H
#define __PREFERENCES_H
#include <gtk/gtk.h>
#include <tree.h>
#define PREFERENCES(obj) GTK_CHECK_CAST (obj, preferences_get_type (), Preferences)
#define PREFERENCES_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, preferences_get_type (), PreferencesClass)
#define IS_PREFERENCES(obj) GTK_CHECK_TYPE (obj, preferences_get_type ())
typedef struct _Preferences Preferences;
typedef struct _PreferencesClass PreferencesClass;
typedef enum _orientation_t {
ORIENTATION_HORIZ, ORIENTATION_VERT
} orientation_t;
typedef enum _wallpaper_type_t {
WPTYPE_TILED, WPTYPE_CENTERED, WPTYPE_SCALED_ASPECT,
WPTYPE_SCALED, WPTYPE_EMBOSSED
} wallpaper_type_t;
struct _Preferences
{
GtkObject object;
gboolean frozen;
gboolean auto_apply;
guint timeout_id;
gboolean enabled;
gboolean gradient_enabled;
gboolean wallpaper_enabled;
orientation_t orientation;
wallpaper_type_t wallpaper_type;
GdkColor *color1;
GdkColor *color2;
gchar *wallpaper_filename;
gchar *wallpaper_sel_path;
GSList *wallpapers;
gboolean adjust_opacity;
gint opacity;
};
struct _PreferencesClass
{
GtkObjectClass klass;
};
guint preferences_get_type (void);
GtkObject *preferences_new (void);
GtkObject *preferences_clone (Preferences *prefs);
void preferences_destroy (GtkObject *object);
void preferences_load (Preferences *prefs);
void preferences_save (Preferences *prefs);
void preferences_changed (Preferences *prefs);
void preferences_apply_now (Preferences *prefs);
void preferences_apply_preview (Preferences *prefs);
void preferences_freeze (Preferences *prefs);
void preferences_thaw (Preferences *prefs);
Preferences *preferences_read_xml (xmlDocPtr xml_doc);
xmlDocPtr preferences_write_xml (Preferences *prefs);
#endif /* __PREFERENCES_H */

View File

@@ -1,761 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* prefs-widget.c
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen <hovinen@helixcode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "prefs-widget.h"
#include "applier.h"
#include <gdk-pixbuf/gdk-pixbuf-xlibrgb.h>
#define WID(str) (glade_xml_get_widget (prefs_widget->dialog_data, str))
enum {
ARG_0,
ARG_PREFERENCES
};
static CappletWidgetClass *parent_class;
static void
set_background_controls_sensitive (PrefsWidget *prefs_widget, gboolean s)
{
gtk_widget_set_sensitive (WID ("color_frame"), s);
gtk_widget_set_sensitive (WID ("wallpaper_frame"), s);
gtk_widget_set_sensitive (WID ("adjust_opacity_toggle"), s);
gtk_widget_set_sensitive (WID ("opacity_box"), s && prefs_widget->prefs->adjust_opacity);
gtk_widget_set_sensitive (WID ("auto_apply"), s);
}
GtkWidget *
prefs_widget_new (Preferences *prefs)
{
g_return_val_if_fail (prefs == NULL || IS_PREFERENCES (prefs), NULL);
return gtk_widget_new (prefs_widget_get_type (),
"preferences", prefs,
NULL);
}
void
prefs_widget_set_preferences (PrefsWidget *prefs_widget, Preferences *prefs)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
gtk_object_set (GTK_OBJECT (prefs_widget), "preferences", prefs, NULL);
}
static void
wallpaper_entry_changed_cb (GtkWidget *e, PrefsWidget *prefs_widget)
{
char *filename;
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
g_free (prefs_widget->prefs->wallpaper_filename);
prefs_widget->prefs->wallpaper_filename =
g_strdup (gtk_object_get_data (GTK_OBJECT (e), "wallpaper_filename"));
prefs_widget->prefs->wallpaper_enabled =
prefs_widget->prefs->wallpaper_filename &&
g_file_exists (prefs_widget->prefs->wallpaper_filename);
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
append_wallpaper (GtkMenu *menu, char *label, char *path, PrefsWidget *prefs_widget)
{
GtkWidget *item;
item = gtk_menu_item_new_with_label (label);
if (path)
gtk_object_set_data (GTK_OBJECT (item), "wallpaper_filename", path);
gtk_signal_connect (GTK_OBJECT (item), "activate",
GTK_SIGNAL_FUNC (wallpaper_entry_changed_cb),
prefs_widget);
gtk_menu_append (menu, item);
}
static void
read_preferences (PrefsWidget *prefs_widget, Preferences *prefs)
{
GtkWidget *widget;
GtkAdjustment *adjustment;
GtkWidget *menu;
gint i;
gint thing;
GSList *item;
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
gnome_color_picker_set_i16
(GNOME_COLOR_PICKER (WID ("color1_select")),
prefs->color1->red, prefs->color1->green,
prefs->color1->blue, 0xffff);
gnome_color_picker_set_i16
(GNOME_COLOR_PICKER (WID ("color2_select")),
prefs->color2->red, prefs->color2->green,
prefs->color2->blue, 0xffff);
gtk_widget_set_sensitive (
glade_xml_get_widget (prefs_widget->dialog_data,
"color2_select"),
prefs_widget->prefs->gradient_enabled);
thing = prefs->gradient_enabled
? (prefs->orientation == ORIENTATION_VERT
? 1 : 2) : 0;
gtk_option_menu_set_history (GTK_OPTION_MENU (WID ("color_option")), thing);
widget = WID ("wallpaper_entry");
#if 0
if (prefs->wallpaper_sel_path)
gnome_file_entry_set_default_path
(GNOME_FILE_ENTRY (widget),
prefs->wallpaper_sel_path);
#endif
menu = gtk_menu_new ();
append_wallpaper (GTK_MENU (menu), _("(None)"), NULL, prefs_widget);
#warning FIXME: add a small snapshot of the image? that would rule.
for (thing = 0, i = 1, item = prefs->wallpapers; item; i++, item = item->next) {
append_wallpaper (GTK_MENU (menu), g_basename (item->data),
item->data, prefs_widget);
if (prefs->wallpaper_filename &&
!strcmp (prefs->wallpaper_filename, item->data))
thing = i;
}
if (!thing && prefs->wallpaper_filename) {
thing = 1;
append_wallpaper (GTK_MENU (menu),
g_basename (prefs->wallpaper_filename),
prefs->wallpaper_filename, prefs_widget);
}
gtk_option_menu_set_history (GTK_OPTION_MENU (WID ("wp_effect_option")),
prefs->wallpaper_type);
gtk_option_menu_set_menu (GTK_OPTION_MENU (WID ("wp_file_option")), menu);
gtk_option_menu_set_history (GTK_OPTION_MENU (WID ("wp_file_option")), thing);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("disable_toggle")),
prefs->enabled);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
(WID ("auto_apply")),
prefs->auto_apply);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
(WID ("adjust_opacity_toggle")),
prefs->adjust_opacity);
gtk_widget_set_sensitive (GTK_WIDGET (WID ("opacity_box")),
prefs->adjust_opacity && prefs->enabled);
adjustment = gtk_range_get_adjustment
(GTK_RANGE (WID ("opacity_adjust")));
gtk_adjustment_set_value (adjustment, prefs->opacity);
preferences_apply_preview (prefs);
}
static void
color1_select_color_set_cb (GnomeColorPicker *cp, guint r, guint g,
guint b, guint a, PrefsWidget *prefs_widget)
{
guint32 rgb;
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
prefs_widget->prefs->color1->red = r;
prefs_widget->prefs->color1->green = g;
prefs_widget->prefs->color1->blue = b;
rgb = ((r >> 8) << 16) || ((g >> 8) << 8) || (b >> 8);
prefs_widget->prefs->color1->pixel = xlib_rgb_xpixel_from_rgb (rgb);
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
color2_select_color_set_cb (GnomeColorPicker *cp, guint r, guint g,
guint b, guint a, PrefsWidget *prefs_widget)
{
guint32 rgb;
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
prefs_widget->prefs->color2->red = r;
prefs_widget->prefs->color2->green = g;
prefs_widget->prefs->color2->blue = b;
rgb = ((r >> 8) << 16) || ((g >> 8) << 8) || (b >> 8);
prefs_widget->prefs->color2->pixel = xlib_rgb_xpixel_from_rgb (rgb);
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
solid_select_toggled_cb (GtkToggleButton *tb, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
if (gtk_toggle_button_get_active (tb)) {
prefs_widget->prefs->gradient_enabled = FALSE;
preferences_changed (prefs_widget->prefs);
}
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
gradient_select_toggled_cb (GtkToggleButton *tb, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
if (gtk_toggle_button_get_active (tb)) {
prefs_widget->prefs->gradient_enabled = TRUE;
preferences_changed (prefs_widget->prefs);
}
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
vertical_select_toggled_cb (GtkToggleButton *tb, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
if (gtk_toggle_button_get_active (tb)) {
prefs_widget->prefs->orientation = ORIENTATION_VERT;
preferences_changed (prefs_widget->prefs);
}
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
horizontal_select_toggled_cb (GtkToggleButton *tb, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
if (gtk_toggle_button_get_active (tb)) {
prefs_widget->prefs->orientation = ORIENTATION_HORIZ;
preferences_changed (prefs_widget->prefs);
}
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
tiled_select_toggled_cb (GtkToggleButton *tb, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
if (gtk_toggle_button_get_active (tb)) {
prefs_widget->prefs->wallpaper_type = WPTYPE_TILED;
preferences_changed (prefs_widget->prefs);
}
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
centered_select_toggled_cb (GtkToggleButton *tb, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
if (gtk_toggle_button_get_active (tb)) {
prefs_widget->prefs->wallpaper_type = WPTYPE_CENTERED;
preferences_changed (prefs_widget->prefs);
}
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
scaled_aspect_select_toggled_cb (GtkToggleButton *tb,
PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
if (gtk_toggle_button_get_active (tb)) {
prefs_widget->prefs->wallpaper_type = WPTYPE_SCALED_ASPECT;
preferences_changed (prefs_widget->prefs);
}
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
scaled_select_toggled_cb (GtkToggleButton *tb, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
if (gtk_toggle_button_get_active (tb)) {
prefs_widget->prefs->wallpaper_type = WPTYPE_SCALED;
preferences_changed (prefs_widget->prefs);
}
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
disable_toggled_cb (GtkToggleButton *tb, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
prefs_widget->prefs->enabled = gtk_toggle_button_get_active (tb);
set_background_controls_sensitive (prefs_widget,
prefs_widget->prefs->enabled);
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
color_effect_cb (GtkWidget *w, PrefsWidget *prefs_widget)
{
switch (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (w), "index"))) {
case 0:
prefs_widget->prefs->gradient_enabled = FALSE;
break;
case 1:
prefs_widget->prefs->gradient_enabled = TRUE;
prefs_widget->prefs->orientation = ORIENTATION_VERT;
break;
case 2:
prefs_widget->prefs->gradient_enabled = TRUE;
prefs_widget->prefs->orientation = ORIENTATION_HORIZ;
break;
default:
break;
}
gtk_widget_set_sensitive (
glade_xml_get_widget (prefs_widget->dialog_data,
"color2_select"),
prefs_widget->prefs->gradient_enabled);
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
wallpaper_effect_cb (GtkWidget *w, PrefsWidget *prefs_widget)
{
gint i;
i = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (w), "index"));
prefs_widget->prefs->wallpaper_type = i;
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
setup_preview(GtkWidget *widget, PrefsWidget *prefs)
{
char *p;
GList *l;
GtkWidget *pp = NULL;
GdkImlibImage *im;
int w,h;
GtkWidget *frame;
GtkFileSelection *fs;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
frame = gtk_object_get_data(GTK_OBJECT(widget),"frame");
fs = gtk_object_get_data(GTK_OBJECT(frame),"fs");
if((l = gtk_container_children(GTK_CONTAINER(frame))) != NULL) {
pp = l->data;
g_list_free(l);
}
if(pp)
gtk_widget_destroy(pp);
p = gtk_file_selection_get_filename(fs);
if(!p || !g_file_test (p,G_FILE_TEST_ISLINK|G_FILE_TEST_ISFILE) ||
!(im = gdk_imlib_load_image (p)))
return;
w = im->rgb_width;
h = im->rgb_height;
if(w>h) {
if(w>100) {
h = h*(100.0/w);
w = 100;
}
} else {
if(h>100) {
w = w*(100.0/h);
h = 100;
}
}
pp = gnome_pixmap_new_from_imlib_at_size (im, w, h);
gtk_widget_show(pp);
gtk_container_add(GTK_CONTAINER(frame),pp);
gdk_imlib_destroy_image(im);
}
static void
browse_button_cb (GtkWidget *w, PrefsWidget *prefs_widget)
{
GtkWidget *hbox, *widg;
GtkFileSelection *filesel;
if (prefs_widget->filesel) {
gdk_window_show (prefs_widget->filesel->window);
gdk_window_raise (prefs_widget->filesel->window);
return;
}
prefs_widget->filesel = gtk_file_selection_new (_("Wallpaper Selection"));
filesel = GTK_FILE_SELECTION (prefs_widget->filesel);
hbox = filesel->file_list;
do {
hbox = hbox->parent;
if(!hbox) {
g_warning(_("Can't find an hbox, using a normal file "
"selection"));
goto signal_setup;
}
} while (!GTK_IS_HBOX (hbox));
widg = gtk_frame_new (_("Preview"));
gtk_widget_show (widg);
gtk_box_pack_end (GTK_BOX (hbox), widg, FALSE, FALSE, 0);
gtk_widget_set_usize (widg, 110, 110);
gtk_object_set_data (GTK_OBJECT (widg), "fs", filesel);
gtk_object_set_data (GTK_OBJECT (filesel->file_list), "frame", widg);
gtk_object_set_data (GTK_OBJECT (filesel->selection_entry), "frame", widg);
gtk_signal_connect (GTK_OBJECT (filesel->file_list),"select_row",
GTK_SIGNAL_FUNC (setup_preview), prefs_widget);
gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "changed",
GTK_SIGNAL_FUNC (setup_preview), prefs_widget);
signal_setup:
#if 0
if (wpFileSelName)
gtk_file_selection_set_filename (filesel, wpFileSelName);
else if (origState.wpFileName)
gtk_file_selection_set_filename (filesel, origState.wpFileName);
#endif
gtk_signal_connect (GTK_OBJECT (filesel), "destroy",
GTK_SIGNAL_FUNC (gtk_widget_destroyed),
&prefs_widget->filesel);
#if 0
gtk_signal_connect (GTK_OBJECT (filesel->ok_button), "clicked",
GTK_SIGNAL_FUNC (wp_selection_ok), prefs_widget);
gtk_signal_connect (GTK_OBJECT (filesel->cancel_button), "clicked",
GTK_SIGNAL_FUNC (wp_selection_cancel), prefs_widget);
#endif
gtk_widget_show (filesel);
}
static void
auto_apply_toggled_cb (GtkToggleButton *tb, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
if (gtk_toggle_button_get_active (tb))
prefs_widget->prefs->auto_apply = TRUE;
else
prefs_widget->prefs->auto_apply = FALSE;
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
adjust_opacity_toggled_cb (GtkToggleButton *tb, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
prefs_widget->prefs->adjust_opacity = gtk_toggle_button_get_active (tb);
gtk_widget_set_sensitive (WID ("opacity_box"), prefs_widget->prefs->enabled && prefs_widget->prefs->adjust_opacity);
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
opacity_adjust_changed_cb (GtkAdjustment *adjustment,
PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
prefs_widget_init (PrefsWidget *prefs_widget)
{
GtkWidget *widget;
GtkAdjustment *adjustment;
GList *node;
int i;
prefs_widget->dialog_data =
glade_xml_new (GLADE_DATADIR "/background-properties.glade",
"prefs_widget");
widget = glade_xml_get_widget (prefs_widget->dialog_data,
"prefs_widget");
gtk_container_add (GTK_CONTAINER (prefs_widget), widget);
widget = glade_xml_get_widget (prefs_widget->dialog_data,
"monitor_frame");
prefs_widget->preview = applier_class_get_preview_widget ();
gtk_container_add (GTK_CONTAINER (widget), prefs_widget->preview);
glade_xml_signal_connect_data (prefs_widget->dialog_data,
"color1_select_color_set_cb",
color1_select_color_set_cb,
prefs_widget);
glade_xml_signal_connect_data (prefs_widget->dialog_data,
"color2_select_color_set_cb",
color2_select_color_set_cb,
prefs_widget);
glade_xml_signal_connect_data (prefs_widget->dialog_data,
"disable_toggled_cb",
disable_toggled_cb,
prefs_widget);
glade_xml_signal_connect_data (prefs_widget->dialog_data,
"browse_button_cb",
browse_button_cb,
prefs_widget);
glade_xml_signal_connect_data (prefs_widget->dialog_data,
"auto_apply_toggled_cb",
auto_apply_toggled_cb,
prefs_widget);
glade_xml_signal_connect_data (prefs_widget->dialog_data,
"adjust_opacity_toggled_cb",
adjust_opacity_toggled_cb,
prefs_widget);
/*adjustment = gtk_range_get_adjustment (GTK_RANGE (WID ("opacity_adjust")));*/
adjustment = gtk_adjustment_new (100.0, 0.0, 100.0, 1.0, 10.0, 10.0);
gtk_range_set_adjustment (GTK_RANGE (WID ("opacity_adjust")), adjustment);
gtk_signal_connect (GTK_OBJECT (adjustment), "value-changed",
GTK_SIGNAL_FUNC (opacity_adjust_changed_cb),
prefs_widget);
widget = WID ("color_option");
node = GTK_MENU_SHELL (gtk_option_menu_get_menu (GTK_OPTION_MENU (widget)))->children;
for (i=0; node; i++, node = node->next) {
gtk_signal_connect (GTK_OBJECT (node->data), "activate",
GTK_SIGNAL_FUNC (color_effect_cb),
prefs_widget);
gtk_object_set_data (GTK_OBJECT (node->data), "index",
GINT_TO_POINTER (i));
}
widget = WID ("wp_effect_option");
node = GTK_MENU_SHELL (gtk_option_menu_get_menu (GTK_OPTION_MENU (widget)))->children;
for (i=0; node; i++, node = node->next) {
gtk_signal_connect (GTK_OBJECT (node->data), "activate",
GTK_SIGNAL_FUNC (wallpaper_effect_cb),
prefs_widget);
gtk_object_set_data (GTK_OBJECT (node->data), "index",
GINT_TO_POINTER (i));
}
}
static void
prefs_widget_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
PrefsWidget *prefs_widget;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_PREFS_WIDGET (object));
prefs_widget = PREFS_WIDGET (object);
switch (arg_id) {
case ARG_PREFERENCES:
if (prefs_widget->prefs)
gtk_object_unref (GTK_OBJECT (prefs_widget->prefs));
prefs_widget->prefs = GTK_VALUE_POINTER (*arg);
if (prefs_widget->prefs) {
gtk_object_ref (GTK_OBJECT (prefs_widget->prefs));
read_preferences (prefs_widget, prefs_widget->prefs);
}
break;
default:
g_warning ("Bad argument set");
break;
}
}
static void
prefs_widget_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
PrefsWidget *prefs_widget;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_PREFS_WIDGET (object));
prefs_widget = PREFS_WIDGET (object);
switch (arg_id) {
case ARG_PREFERENCES:
GTK_VALUE_POINTER (*arg) = prefs_widget->prefs;
break;
default:
g_warning ("Bad argument get");
break;
}
}
static void
prefs_widget_class_init (PrefsWidgetClass *class)
{
GtkObjectClass *object_class;
gtk_object_add_arg_type ("PrefsWidget::preferences",
GTK_TYPE_POINTER,
GTK_ARG_READWRITE,
ARG_PREFERENCES);
object_class = GTK_OBJECT_CLASS (class);
object_class->set_arg = prefs_widget_set_arg;
object_class->get_arg = prefs_widget_get_arg;
parent_class = CAPPLET_WIDGET_CLASS
(gtk_type_class (capplet_widget_get_type ()));
}
guint
prefs_widget_get_type (void)
{
static guint prefs_widget_type = 0;
if (!prefs_widget_type) {
GtkTypeInfo prefs_widget_info = {
"PrefsWidget",
sizeof (PrefsWidget),
sizeof (PrefsWidgetClass),
(GtkClassInitFunc) prefs_widget_class_init,
(GtkObjectInitFunc) prefs_widget_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
prefs_widget_type =
gtk_type_unique (capplet_widget_get_type (),
&prefs_widget_info);
}
return prefs_widget_type;
}

View File

@@ -1,64 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* prefs-widget.h
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen <hovinen@helixcode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __PREFS_WIDGET_H
#define __PREFS_WIDGET_H
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <capplet-widget.h>
#include "preferences.h"
#define PREFS_WIDGET(obj) GTK_CHECK_CAST (obj, prefs_widget_get_type (), PrefsWidget)
#define PREFS_WIDGET_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, prefs_widget_get_type (), PrefsWidgetClass)
#define IS_PREFS_WIDGET(obj) GTK_CHECK_TYPE (obj, prefs_widget_get_type ())
typedef struct _PrefsWidget PrefsWidget;
typedef struct _PrefsWidgetClass PrefsWidgetClass;
struct _PrefsWidget
{
CappletWidget capplet_widget;
Preferences *prefs;
GladeXML *dialog_data;
GtkWidget *preview;
GtkWidget *menu;
GtkWidget *filesel;
};
struct _PrefsWidgetClass
{
CappletWidgetClass parent_class;
};
guint prefs_widget_get_type (void);
GtkWidget *prefs_widget_new (Preferences *prefs);
void prefs_widget_set_preferences (PrefsWidget *prefs_widget,
Preferences *prefs);
#endif /* __PREFS_WIDGET_H */

View File

@@ -2,4 +2,5 @@ Makefile
Makefile.in
.deps
.libs
nautilus-mime-type-capplet
file-types-capplet
file-types-capplet.desktop

View File

@@ -1,6 +1,10 @@
INCLUDES = -I. \
-I$(top_srcdir) \
-I$(srcdir) \
NULL =
SUBDIRS = libuuid
INCLUDES = -I. \
-I$(top_srcdir) \
-I$(srcdir) \
-I$(top_srcdir)/intl -I$(top_builddir)/intl \
-I$(top_srcdir)/libgnomevfs \
$(CAPPLET_INCLUDEDIR) \
@@ -9,36 +13,49 @@ INCLUDES = -I. \
$(GTK_CFLAGS) \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-I$(includedir) \
$(VFS_CFLAGS) $(WERROR)
$(VFS_CFLAGS) $(WERROR) \
$(NULL)
bin_PROGRAMS = nautilus-mime-type-capplet
nautilus_mime_type_capplet_SOURCES = \
bin_PROGRAMS = file-types-capplet
file_types_capplet_SOURCES = \
nautilus-mime-type-capplet.h \
nautilus-mime-type-capplet-dialogs.h \
nautilus-mime-type-icon-entry.h \
nautilus-mime-type-capplet.c \
nautilus-mime-type-capplet-dialogs.c \
nautilus-mime-type-icon-entry.c
nautilus-mime-type-icon-entry.c \
$(NULL)
nautilus_mime_type_capplet_LDADD = \
file_types_capplet_LDADD = \
$(CAPPLET_LIBDIR) \
$(CAPPLET_LIBS) \
$(ORBIT_LIBS) \
$(OAF_LIBS) \
$(INTLLIBS) \
$(top_builddir)/libgnomevfs/libgnomevfs.la \
-lgdk_pixbuf
-lgdk_pixbuf \
$/libuuid/libuuid.a \
$(NULL)
sysdir = $(datadir)/control-center
sys_DATA = nautilus-mime-type.desktop
sysdir = $(datadir)/control-center/Documents
sys_in_files = file-types-capplet.desktop.in
sys_DATA = $(sys_in_files:.desktop.in=.desktop)
settingsdir = $(datadir)/gnome/apps/Settings
settings_DATA = nautilus-mime-type.desktop
settings_DATA = $(sys_DATA)
desktop_in_file = file-types-capplet.desktop.in
desktop_file = $(desktop_in_file:.desktop.in=.desktop)
@XML_I18N_MERGE_DESKTOP_RULE@
EXTRA_DIST = \
$(sys_DATA)
$(sys_DATA) $(desktop_in_file)

View File

@@ -35,7 +35,9 @@
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <libgnomevfs/gnome-vfs-application-registry.h>
#include <libgnomevfs/gnome-vfs-mime-info.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include "libuuid/uuid.h"
#include "nautilus-mime-type-capplet.h"
#include "nautilus-mime-type-capplet-dialogs.h"
@@ -67,7 +69,8 @@ static edit_dialog_details *edit_component_details = NULL;
static void show_new_application_window (GtkWidget *button, GtkWidget *list);
static void show_edit_application_window (GtkWidget *button, GtkWidget *list);
static void delete_selected_application (GtkWidget *button, GtkWidget *list);
static void add_item_to_application_list (GtkWidget *list, const char *name, const char *mime_type, int position);
static void add_item_to_application_list (GtkWidget *list, const char *id, const char *name, const char *mime_type,
gboolean user_owned, int position);
static void find_message_label_callback (GtkWidget *widget, gpointer callback_data);
static void find_message_label (GtkWidget *widget, const char *message);
@@ -138,13 +141,74 @@ application_button_toggled_callback (GtkToggleButton *button, gpointer user_data
}
}
static void
insert_item (GtkList *list_widget, GtkListItem *item, int position)
{
GList *singleton_list;
g_assert (GTK_IS_LIST (list_widget));
g_assert (GTK_IS_LIST_ITEM (item));
/* Due to GTK inheritance stupidity, the "Add" signal, which we
* rely on for widget sensitivity updates, is not sent if you
* use the GtkList API to add items. So when we add new items,
* which always go at the end, we must use the GtkContainer API.
*/
if (position < 0) {
gtk_container_add (GTK_CONTAINER (list_widget), GTK_WIDGET (item));
} else {
singleton_list = g_list_prepend (NULL, item);
gtk_list_insert_items (list_widget, singleton_list, position);
/* This looks like a leak of a singleton_list, but believe it or not
* gtk_list takes ownership of the list of items.
*/
}
}
static GtkListItem *
create_application_list_item (const char *id, const char *name, const char *mime_type,
gboolean user_owned, GList *short_list)
{
GtkWidget *list_item;
GtkWidget *hbox, *check_button, *label;
list_item = gtk_list_item_new ();
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_container_add (GTK_CONTAINER (list_item), hbox);
check_button = gtk_check_button_new ();
gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
label = gtk_label_new (name);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show_all (list_item);
/* Save ID and mime type*/
gtk_object_set_data_full (GTK_OBJECT (check_button), "application_id", g_strdup (id), g_free);
gtk_object_set_data_full (GTK_OBJECT (check_button), "mime_type", g_strdup (mime_type), g_free);
gtk_object_set_data_full (GTK_OBJECT (list_item), "application_id", g_strdup (id), g_free);
gtk_object_set_data_full (GTK_OBJECT (list_item), "mime_type", g_strdup (mime_type), g_free);
gtk_object_set_data (GTK_OBJECT (list_item), "user_owned", GINT_TO_POINTER(user_owned));
/* Check and see if component is in preferred list */
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
application_is_in_list (id, short_list));
/* Connect to toggled signal */
gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
GTK_SIGNAL_FUNC (application_button_toggled_callback), NULL);
return GTK_LIST_ITEM (list_item);
}
static void
populate_default_applications_list (GtkWidget *list, const char *mime_type)
{
GList *short_list, *app_list, *list_element;
GnomeVFSMimeApplication *application;
GtkWidget *button, *list_item;
GtkWidget *hbox, *label;
GtkListItem *list_item;
/* Get the application short list */
short_list = gnome_vfs_mime_get_short_list_applications (mime_type);
@@ -156,43 +220,20 @@ populate_default_applications_list (GtkWidget *list, const char *mime_type)
application = list_element->data;
/* Create list item */
list_item = gtk_list_item_new ();
/* Create check button */
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_container_add (GTK_CONTAINER (list_item), hbox);
button = gtk_check_button_new ();
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
list_item = create_application_list_item (application->id, application->name,
mime_type,
gnome_vfs_application_is_user_owned_application (application),
short_list);
label = gtk_label_new (application->name);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
insert_item (GTK_LIST (list), list_item, -1);
/* Add list item to list */
gtk_container_add (GTK_CONTAINER (list), list_item);
/* Save ID and mime type*/
gtk_object_set_data_full (GTK_OBJECT (button), "application_id", g_strdup (application->id), g_free);
gtk_object_set_data_full (GTK_OBJECT (button), "mime_type", g_strdup (mime_type), g_free);
gtk_object_set_data_full (GTK_OBJECT (list_item), "application_id", g_strdup (application->id), g_free);
gtk_object_set_data_full (GTK_OBJECT (list_item), "mime_type", g_strdup (mime_type), g_free);
/* Check and see if component is in preferred list */
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
application_is_in_list (application->id, short_list));
/* Connect to toggled signal */
gtk_signal_connect (GTK_OBJECT (button), "toggled",
GTK_SIGNAL_FUNC (application_button_toggled_callback), NULL);
}
}
gnome_vfs_mime_application_list_free (app_list);
}
if (short_list != NULL) {
gnome_vfs_mime_application_list_free (short_list);
}
gnome_vfs_mime_application_list_free (short_list);
}
@@ -314,11 +355,17 @@ check_button_status (GtkList *list, GtkWidget *widget, ButtonHolder *button_hold
gtk_widget_set_sensitive (button_holder->delete_button, FALSE);
gtk_widget_set_sensitive (button_holder->edit_button, FALSE);
} else {
gtk_widget_set_sensitive (button_holder->delete_button, TRUE);
gtk_widget_set_sensitive (button_holder->edit_button, TRUE);
}
}
static void
update_delete_button (GtkList *list, GtkWidget *widget, ButtonHolder *button_holder)
{
gtk_widget_set_sensitive (button_holder->delete_button,
GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (widget), "user_owned")));
}
/*
* initialize_edit_applications_dialog
@@ -342,6 +389,8 @@ initialize_edit_applications_dialog (const char *mime_type)
NULL,
NULL);
/* FIXME: dialog should be parented on Control Center window */
gtk_container_set_border_width (GTK_CONTAINER (edit_application_details->window), GNOME_PAD);
gtk_window_set_policy (GTK_WINDOW (edit_application_details->window), FALSE, TRUE, FALSE);
gtk_window_set_default_size (GTK_WINDOW (edit_application_details->window),
@@ -357,7 +406,7 @@ initialize_edit_applications_dialog (const char *mime_type)
main_vbox = GNOME_DIALOG (edit_application_details->window)->vbox;
/* Add label */
label_text = g_strdup_printf (_("Select applications to appear in menu for mime type \"%s\""), mime_type);
label_text = g_strdup_printf (_("Select applications to appear in menu for MIME type \"%s\""), mime_type);
label = gtk_label_new (label_text);
g_free (label_text);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
@@ -403,11 +452,12 @@ initialize_edit_applications_dialog (const char *mime_type)
/* Watch container so we can update buttons */
gtk_signal_connect (GTK_OBJECT (list), "add", check_button_status, button_holder);
gtk_signal_connect_full (GTK_OBJECT (list), "remove", check_button_status, NULL, button_holder,
g_free, FALSE, FALSE);
g_free, FALSE, FALSE);
gtk_signal_connect (GTK_OBJECT (list), "select_child", update_delete_button, button_holder);
populate_default_applications_list (list, mime_type);
gtk_widget_show_all (main_vbox);
populate_default_applications_list (list, mime_type);
}
@@ -447,7 +497,7 @@ initialize_edit_components_dialog (const char *mime_type)
main_vbox = GNOME_DIALOG (edit_component_details->window)->vbox;
/* Add label */
label_text = g_strdup_printf (_("Select views to appear in menu for mime type \"%s\""), mime_type);
label_text = g_strdup_printf (_("Select views to appear in menu for MIME type \"%s\""), mime_type);
label = gtk_label_new (label_text);
g_free (label_text);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
@@ -482,19 +532,13 @@ show_edit_applications_dialog (const char *mime_type)
if (edit_application_details == NULL) {
initialize_edit_applications_dialog (mime_type);
}
switch(gnome_dialog_run (GNOME_DIALOG (edit_application_details->window))) {
case 0:
nautilus_mime_type_capplet_update_application_info (mime_type);
/* Delete the dialog so the lists are repopulated on next lauch */
gtk_widget_destroy (edit_application_details->window);
break;
case 1:
/* Delete the dialog so the lists are repopulated on next lauch */
gtk_widget_destroy (edit_application_details->window);
break;
}
/* FIXME: This is a modal dialog with no Cancel button, so the close box
* has to do the same thing as the OK button, which is pretty darn confusing.
* It would be better to make it modeless someday.
*/
gnome_dialog_run_and_close (GNOME_DIALOG (edit_application_details->window));
nautilus_mime_type_capplet_update_application_info (mime_type);
}
@@ -511,18 +555,13 @@ show_edit_components_dialog (const char *mime_type)
initialize_edit_components_dialog (mime_type);
}
switch(gnome_dialog_run (GNOME_DIALOG (edit_component_details->window))) {
case 0:
nautilus_mime_type_capplet_update_viewer_info (mime_type);
/* Delete the dialog so the lists are repopulated on next lauch */
gtk_widget_destroy (edit_component_details->window);
break;
case 1:
/* Delete the dialog so the lists are repopulated on next lauch */
gtk_widget_destroy (edit_component_details->window);
break;
}
/* FIXME: This is a modal dialog with no Cancel button, so the close box
* has to do the same thing as the OK button, which is pretty darn confusing.
* It would be better to make it modeless someday.
*/
gnome_dialog_run_and_close (GNOME_DIALOG (edit_component_details->window));
nautilus_mime_type_capplet_update_viewer_info (mime_type);
}
@@ -688,6 +727,30 @@ display_upper_case_dialog (void)
gnome_dialog_run_and_close (dialog);
}
/* Do some basic validation of the text entry and enable the OK button if the text is
* determined to be a valid string.
*/
static void
validate_text_and_update_button (GtkEntry *entry, gpointer data)
{
char *text, *token;
gboolean sensitize;
sensitize = TRUE;
text = gtk_entry_get_text (entry);
if (text == NULL) {
sensitize = FALSE;
} else {
token = strtok (text, " ");
if (token == NULL || strlen (token) <= 0) {
/* Entered text is invalid as best as we can detect. */
sensitize = FALSE;
}
}
gtk_widget_set_sensitive (GTK_WIDGET (data), sensitize);
}
char *
nautilus_mime_type_capplet_show_new_mime_window (void)
@@ -696,8 +759,6 @@ nautilus_mime_type_capplet_show_new_mime_window (void)
GtkWidget *mime_entry;
GtkWidget *label;
GtkWidget *desc_entry;
GtkWidget *hbox;
GtkWidget *vbox;
const char *description;
char *mime_type, *tmp_str, c;
gboolean upper_case_alert;
@@ -705,70 +766,62 @@ nautilus_mime_type_capplet_show_new_mime_window (void)
mime_type = NULL;
upper_case_alert = FALSE;
dialog = gnome_dialog_new (_("Add Mime Type"), GNOME_STOCK_BUTTON_OK,
dialog = gnome_dialog_new (_("Add MIME Type"), GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL, NULL);
gnome_dialog_set_default (GNOME_DIALOG (dialog), 1);
label = gtk_label_new (_("Add a new Mime Type\n"
"For example: image/tiff; text/x-scheme"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new (_("Mime Type:"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
label = gtk_label_new (_("New MIME type (e.g. image/x-thumper):"));
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, TRUE, TRUE, 0);
mime_entry = gtk_entry_new ();
gtk_box_pack_start (GTK_BOX (hbox), mime_entry, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), mime_entry, TRUE, TRUE, 0);
vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), vbox, FALSE, FALSE, 0);
gtk_container_set_border_width (GTK_CONTAINER (vbox), GNOME_PAD_SMALL);
label = gtk_label_new (_("Type in a description for this mime-type."));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Description:")), FALSE, FALSE, 0);
label = gtk_label_new (_("Description (e.g. Thumper image):"));
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, TRUE, TRUE, 0);
desc_entry = gtk_entry_new ();
gtk_box_pack_start (GTK_BOX (hbox), desc_entry, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), desc_entry, TRUE, TRUE, 0);
/* Set up text entry validation signal */
gtk_signal_connect (GTK_OBJECT (mime_entry), "changed",
GTK_SIGNAL_FUNC (validate_text_and_update_button), GNOME_DIALOG (dialog)->buttons->data);
gnome_dialog_set_close (GNOME_DIALOG (dialog), FALSE);
/* Set initial OK button state to desensitized */
gtk_widget_set_sensitive (GTK_WIDGET (GNOME_DIALOG (dialog)->buttons->data), FALSE);
/* Set focus to text entry widget */
gtk_widget_grab_focus (mime_entry);
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
case 0:
mime_type = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
g_assert (mime_type != NULL);
/* Handle illegal mime types as best we can */
for (tmp_str = mime_type; (c = *tmp_str) != '\0'; tmp_str++) {
if (isascii (c) && isupper (c)) {
*tmp_str = tolower (c);
upper_case_alert = TRUE;
}
if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_OK) {
mime_type = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
g_assert (mime_type != NULL);
/* Handle illegal mime types as best we can */
for (tmp_str = mime_type; (c = *tmp_str) != '\0'; tmp_str++) {
if (isascii ((guchar) c) && isupper ((guchar) c)) {
*tmp_str = tolower (c);
upper_case_alert = TRUE;
}
description = gtk_entry_get_text (GTK_ENTRY (desc_entry));
/* Add new mime type here */
if (strlen (mime_type) > 3) {
gnome_vfs_mime_set_value (mime_type,
"description",
description);
}
/* Fall through to close dialog */
break;
case 1:
default:
break;
}
description = gtk_entry_get_text (GTK_ENTRY (desc_entry));
/* Add new mime type here */
if (strlen (mime_type) > 3) {
/* This call creates the key */
gnome_vfs_mime_set_registered_type_key (mime_type,
"description",
description);
/* Ths call sets the user information */
gnome_vfs_mime_set_value (mime_type,
"description",
description);
}
}
gnome_dialog_close (GNOME_DIALOG (dialog));
@@ -793,6 +846,13 @@ add_extension_clicked (GtkWidget *widget, gpointer data)
extension_list = GTK_LIST (data);
new_extension = nautilus_mime_type_capplet_show_new_extension_window ();
/* Filter out bogus extensions */
if (new_extension == NULL || strlen (new_extension) <= 0 || new_extension[0] == ' ') {
g_free (new_extension);
return;
}
new_list_item = gtk_list_item_new_with_label (new_extension);
gtk_widget_show (new_list_item);
@@ -874,14 +934,16 @@ get_extensions_from_gtk_list (GtkList *list)
}
char *
nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type)
nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type, gboolean *new_list)
{
GtkWidget *dialog;
GtkWidget *hbox;
GtkWidget *button;
GtkWidget *list;
char *extensions_list;
char *extensions_list_str;
*new_list = FALSE;
dialog = gnome_dialog_new (_("File Extensions "),
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
@@ -933,7 +995,6 @@ nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type)
extensions_list = gnome_vfs_mime_get_extensions_list (mime_type);
if (extensions_list != NULL) {
widget_list = NULL;
for (temp = extensions_list; temp != NULL; temp = temp->next) {
@@ -950,22 +1011,21 @@ nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type)
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
case 0:
extensions_list = get_extensions_from_gtk_list (GTK_LIST (list));
if (extensions_list == NULL) {
extensions_list = g_strdup ("");
}
break;
case 1:
default:
extensions_list = g_strdup ("");
break;
}
extensions_list_str = NULL;
if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_OK) {
*new_list = TRUE;
extensions_list_str = get_extensions_from_gtk_list (GTK_LIST (list));
if (extensions_list_str == NULL) {
extensions_list_str = g_strdup ("");
}
}
if (extensions_list_str == NULL) {
extensions_list_str = g_strdup ("");
}
gnome_dialog_close (GNOME_DIALOG (dialog));
return extensions_list;
return extensions_list_str;
}
@@ -982,7 +1042,9 @@ nautilus_mime_type_capplet_show_new_extension_window (void)
GNOME_STOCK_BUTTON_CANCEL, NULL);
gnome_dialog_set_default (GNOME_DIALOG (dialog), 0);
gnome_dialog_set_close (GNOME_DIALOG (dialog), FALSE);
label = gtk_label_new (_("Type in the extensions for this mime-type.\nFor example: .html, .htm"));
label = gtk_label_new (_("Type in the extensions for this mime-type (without dot).\n"
"You can enter several extensions seperated by a space,\n"
"for example: html htm"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
@@ -998,17 +1060,13 @@ nautilus_mime_type_capplet_show_new_extension_window (void)
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
/* Set focus to text entry widget */
gtk_window_set_focus (GTK_WINDOW (dialog), mime_entry);
gtk_widget_grab_focus (mime_entry);
new_extension = g_strdup ("");
switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
case 0:
new_extension = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
case 1:
break;
default:
break;
}
if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_OK) {
new_extension = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
} else {
new_extension = g_strdup ("");
}
gnome_dialog_close (GNOME_DIALOG (dialog));
@@ -1020,17 +1078,19 @@ nautilus_mime_type_capplet_show_new_extension_window (void)
* Create or update a GnomeVFSMimeApplication and register
* it with the mime database.
*/
static void
static char *
add_or_update_application (GtkWidget *list, const char *name, const char *command,
gboolean multiple, gboolean expects_uris,
gboolean update)
{
GnomeVFSMimeApplication app, *original;
const char *mime_type;
uuid_t app_uuid;
char app_uuid_string[100];
/* Check for empty strings. Command can be empty. */
if (name[0] == '\0') {
return;
return NULL;
}
mime_type = nautilus_mime_type_capplet_get_selected_item_mime_type ();
@@ -1039,7 +1099,11 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
/* It's ok to cast, we don't modify the application
* structure and thus the name/command, this should really
* use the application registry explicitly */
app.id = (char *)name;
/* Generate unique application id */
uuid_generate(app_uuid);
uuid_unparse(app_uuid, app_uuid_string);
app.id = app_uuid_string;
app.name = (char *)name;
app.command = (char *)command;
app.can_open_multiple_files = multiple;
@@ -1049,7 +1113,7 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
app.requires_terminal = FALSE;
if (update) {
original = gnome_vfs_mime_application_new_from_id (name);
original = gnome_vfs_mime_application_new_from_id (app.id);
if (original == NULL) {
const char *original_id;
GList *selection;
@@ -1059,20 +1123,20 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
/* If there isn't a selection we cannot allow an edit */
selection = GTK_LIST (list)->selection;
if (selection == NULL || g_list_length (selection) <= 0) {
return;
return NULL;
}
/* Get application id and info */
item = GTK_LIST_ITEM (selection->data);
if (item == NULL) {
return;
return NULL;
}
original_id = gtk_object_get_data (GTK_OBJECT (item), "application_id");
if (original_id == NULL) {
return;
return NULL;
}
/* Remove original application data */
gnome_vfs_application_registry_remove_mime_type (original_id, mime_type);
gnome_vfs_application_registry_sync ();
@@ -1083,77 +1147,122 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
gtk_container_remove (GTK_CONTAINER (list), GTK_WIDGET (item));
/* Add new widget and restore position */
add_item_to_application_list (list, name, mime_type, position);
add_item_to_application_list (list, original_id, name, mime_type,
gnome_vfs_application_is_user_owned_application (original),
position);
}
}
gnome_vfs_application_registry_save_mime_application (&app);
gnome_vfs_application_registry_add_mime_type (name, mime_type);
gnome_vfs_application_registry_add_mime_type (app.id, mime_type);
gnome_vfs_application_registry_sync ();
gnome_vfs_mime_add_application_to_short_list (mime_type, app.id);
return g_strdup (app.id);
}
static void
add_item_to_application_list (GtkWidget *list, const char *name, const char *mime_type, int position)
add_item_to_application_list (GtkWidget *list, const char *id, const char *name, const char *mime_type,
gboolean user_owned, int position)
{
GtkWidget *check_button, *list_item, *hbox, *label;
/* Create list item */
list_item = gtk_list_item_new ();
/* Create check button */
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_container_add (GTK_CONTAINER (list_item), hbox);
check_button = gtk_check_button_new ();
gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
GtkListItem *list_item;
GList *short_list;
label = gtk_label_new (name);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
/* Add list item to list */
if (position == -1) {
gtk_container_add (GTK_CONTAINER (list), list_item);
} else {
GList *items;
items = g_list_alloc ();
items->data = list_item;
gtk_list_insert_items (GTK_LIST (list), items, position);
gtk_list_select_child (GTK_LIST (list), list_item);
short_list = gnome_vfs_mime_get_short_list_applications (mime_type);
list_item = create_application_list_item (id, name, mime_type, user_owned, short_list);
gnome_vfs_mime_application_list_free (short_list);
insert_item (GTK_LIST (list), list_item, position);
gtk_list_select_child (GTK_LIST (list), GTK_WIDGET (list_item));
}
static gboolean
handle_invalid_application_input (GtkWindow *parent_window, const char *name, const char *command)
{
char *message;
char *stripped_name;
GnomeDialog *error_dialog;
gboolean error_in_name;
message = NULL;
error_in_name = FALSE;
stripped_name = g_strstrip (g_strdup (name));
if (strlen (stripped_name) == 0) {
message = g_strdup (_("You must enter a name."));
error_in_name = TRUE;
} else if (strlen (command) == 0) {
message = g_strdup (_("You must enter a command."));
} else if (!gnome_vfs_is_executable_command_string (command)) {
if (command[0] == '/') {
/* FIXME: Should strip parameters off before using in this message. */
/* FIXME: Should use separate messages for doesn't exist/isn't executable. */
/* Both of these FIXMEs would need to handle quoting to work correctly,
* since otherwise a space might be part of path or separator before parameters.
*/
/* FIXME: Should use some line-wrapping technology a la nautilus-stock-dialogs.c */
message = g_strdup_printf
(_("\"%s\" does not exist or is not executable.\n"
"Check your spelling and make sure you have\n"
"the right permissions to execute this file."), command);
} else {
/* FIXME: Should strip parameters off before using in this message */
message = g_strdup_printf
(_("The command \"%s\" cannot be found.\n"
"You must use a command that can work from any command line."), command);
}
}
gtk_widget_show_all (list);
/* Save ID and mime type*/
gtk_object_set_data_full (GTK_OBJECT (check_button), "application_id", g_strdup (name), g_free);
gtk_object_set_data_full (GTK_OBJECT (check_button), "mime_type", g_strdup (mime_type), g_free);
gtk_object_set_data_full (GTK_OBJECT (list_item), "application_id", g_strdup (name), g_free);
gtk_object_set_data_full (GTK_OBJECT (list_item), "mime_type", g_strdup (mime_type), g_free);
/* Check and see if component is in preferred list */
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
g_free (stripped_name);
if (message != NULL) {
error_dialog = GNOME_DIALOG (gnome_error_dialog_parented (message,
parent_window));
gtk_window_set_title (GTK_WINDOW (error_dialog),
error_in_name
? _("Bad Application Name")
: _("Bad Application Command"));
gnome_dialog_run (error_dialog);
g_free (message);
return TRUE;
}
/* Connect to toggled signal */
gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
GTK_SIGNAL_FUNC (application_button_toggled_callback), NULL);
return FALSE;
}
static void
show_new_application_window (GtkWidget *button, GtkWidget *list)
run_edit_or_new_application_dialog (const char *mime_type, GtkWidget *list, GnomeVFSMimeApplication *application)
{
GtkWidget *app_entry, *command_entry;
GtkWidget *dialog;
GtkWidget *app_entry, *command_entry;
GtkWidget *label;
GtkWidget *behavior_frame, *frame_vbox;
GtkWidget *multiple_check_box, *uri_check_box;
GtkWidget *table;
char *name, *command, *mime_type;
gboolean multiple, uri;
gboolean initial_toggle_state;
const char *name;
const char *command;
int dialog_result;
gboolean entry_validated;
char *invalid_entry_message, *app_id;
dialog = gnome_dialog_new (_("New Application"), GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL);
g_assert (mime_type != NULL || application != NULL);
g_assert (GTK_IS_WIDGET (list));
dialog = gnome_dialog_new (
application == NULL
? _("Add Application")
: _("Edit Application"),
GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL);
/* FIXME: Dialog should be parented on Edit Applications dialog */
/* Create table */
table = gtk_table_new (3, 2, FALSE);
table = gtk_table_new (4, 2, FALSE);
gtk_container_add (GTK_CONTAINER (GNOME_DIALOG (dialog)->vbox), table);
gtk_table_set_row_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
gtk_table_set_col_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
@@ -1161,21 +1270,26 @@ show_new_application_window (GtkWidget *button, GtkWidget *list)
/* Application Name label and entry */
label = gtk_label_new (_("Application Name:"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
gtk_table_attach_defaults ( GTK_TABLE (table), label, 0, 1, 0, 1);
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
app_entry = gtk_entry_new ();
gtk_table_attach_defaults ( GTK_TABLE (table), app_entry, 1, 2, 0, 1);
if (application != NULL) {
gtk_entry_set_text (GTK_ENTRY (app_entry), application->name);
}
/* Application Command label and entry */
label = gtk_label_new (_("Application Command:"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
gtk_table_attach_defaults ( GTK_TABLE (table), label, 0, 1, 1, 2);
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
command_entry = gtk_entry_new ();
gtk_table_attach_defaults ( GTK_TABLE (table), command_entry, 1, 2, 1, 2);
gtk_table_attach_defaults (GTK_TABLE (table), command_entry, 1, 2, 1, 2);
if (application != NULL) {
gtk_entry_set_text (GTK_ENTRY (command_entry), application->command);
}
/* Open Behavior frame */
/* FIXME bugzilla.eazel.com 6066: Need to add expected uri schemes */
behavior_frame = gtk_frame_new (_("Open Behavior"));
gtk_table_attach_defaults ( GTK_TABLE (table), behavior_frame, 0, 2, 2, 3);
@@ -1184,52 +1298,70 @@ show_new_application_window (GtkWidget *button, GtkWidget *list)
multiple_check_box = gtk_check_button_new_with_label (_("Can open multiple files"));
gtk_box_pack_start (GTK_BOX (frame_vbox), multiple_check_box, FALSE, FALSE, 0);
initial_toggle_state = application == NULL
? FALSE
: application->can_open_multiple_files;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (multiple_check_box), initial_toggle_state);
uri_check_box = gtk_check_button_new_with_label (_("Expects URIs as arguments"));
/* FIXME bugzilla.eazel.com 6066: This needs to be three options now: "yes", "no", and "use uris for non-file locations" */
uri_check_box = gtk_check_button_new_with_label (_("Can open from URI"));
gtk_box_pack_start (GTK_BOX (frame_vbox), uri_check_box, FALSE, FALSE, 0);
initial_toggle_state = application == NULL
? FALSE
: application->expects_uris;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (uri_check_box), initial_toggle_state);
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
/* Set focus to text entry widget */
gtk_window_set_focus (GTK_WINDOW (dialog), app_entry);
gtk_widget_grab_focus (app_entry);
switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
case 0:
do {
dialog_result = gnome_dialog_run (GNOME_DIALOG (dialog));
entry_validated = FALSE;
if (dialog_result == GNOME_OK) {
name = gtk_entry_get_text (GTK_ENTRY (app_entry));
command = gtk_entry_get_text (GTK_ENTRY (command_entry));
multiple = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box));
uri = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box));
if (strlen (name) > 0 && strlen (command) > 0) {
mime_type = gtk_object_get_data (GTK_OBJECT (button), "mime_type");
add_or_update_application (list,
gtk_entry_get_text (GTK_ENTRY (app_entry)),
gtk_entry_get_text (GTK_ENTRY (command_entry)),
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box)),
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box)),
FALSE);
add_item_to_application_list (list, name, mime_type, -1);
invalid_entry_message = NULL;
if (!handle_invalid_application_input (GTK_WINDOW (dialog), name, command)) {
entry_validated = TRUE;
app_id = add_or_update_application (list,
name,
command,
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box)),
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box)),
application != NULL);
if (application == NULL && app_id != NULL) {
add_item_to_application_list (list, app_id, name, mime_type, TRUE, -1);
}
g_free (app_id);
}
case 1:
gtk_widget_destroy (dialog);
break;
default:
break;
}
}
} while (dialog_result == GNOME_OK && !entry_validated);
/* FIXME: Close box is treated like Cancel, which loses user changes silently.
* Would be better to either do nothing at all (force use of OK or Cancel) or
* even put up a little dialog telling them they have to use OK or Cancel.
* Too bad we can't prevent the close box from appearing. Window Managers suck.
*/
if (dialog_result >= 0) {
gnome_dialog_close (GNOME_DIALOG (dialog));
}
}
static void
show_new_application_window (GtkWidget *button, GtkWidget *list)
{
run_edit_or_new_application_dialog (gtk_object_get_data (GTK_OBJECT (button), "mime_type"), list, NULL);
}
static void
show_edit_application_window (GtkWidget *button, GtkWidget *list)
{
GtkWidget *app_entry, *command_entry;
GtkWidget *dialog;
GtkWidget *label;
GtkWidget *behavior_frame, *frame_vbox;
GtkWidget *multiple_check_box, *uri_check_box;
GtkWidget *table;
GList *selection;
const char *id;
GnomeVFSMimeApplication *application;
@@ -1257,78 +1389,16 @@ show_edit_application_window (GtkWidget *button, GtkWidget *list)
return;
}
dialog = gnome_dialog_new (_("Edit Application"), GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL);
/* Create table */
table = gtk_table_new (4, 2, FALSE);
gtk_container_add (GTK_CONTAINER (GNOME_DIALOG (dialog)->vbox), table);
gtk_table_set_row_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
gtk_table_set_col_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
run_edit_or_new_application_dialog (NULL, list, application);
/* Application Name label and entry */
label = gtk_label_new (_("Application Name:"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
app_entry = gtk_entry_new ();
gtk_table_attach_defaults ( GTK_TABLE (table), app_entry, 1, 2, 0, 1);
gtk_entry_set_text (GTK_ENTRY (app_entry), application->name);
/* Application Command label and entry */
label = gtk_label_new (_("Application Command:"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
command_entry = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (command_entry), application->command);
gtk_table_attach_defaults (GTK_TABLE (table), command_entry, 1, 2, 1, 2);
/* Open Behavior frame */
behavior_frame = gtk_frame_new (_("Open Behavior"));
gtk_table_attach_defaults ( GTK_TABLE (table), behavior_frame, 0, 2, 2, 3);
frame_vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
gtk_container_add (GTK_CONTAINER (behavior_frame), frame_vbox);
multiple_check_box = gtk_check_button_new_with_label (_("Can open multiple files"));
gtk_box_pack_start (GTK_BOX (frame_vbox), multiple_check_box, FALSE, FALSE, 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (multiple_check_box), application->can_open_multiple_files);
/* FIXME bugzilla.eazel.com 6066: This needs to be three options now: "yes", "no", and "use uris for non-file locations" */
uri_check_box = gtk_check_button_new_with_label (_("Can open from URI"));
gtk_box_pack_start (GTK_BOX (frame_vbox), uri_check_box, FALSE, FALSE, 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (uri_check_box), application->expects_uris);
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
/* Set focus to text entry widget */
gtk_window_set_focus (GTK_WINDOW (dialog), app_entry);
switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
case 0:
add_or_update_application (list,
gtk_entry_get_text (GTK_ENTRY (app_entry)),
gtk_entry_get_text (GTK_ENTRY (command_entry)),
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box)),
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box)),
TRUE);
case 1:
gnome_vfs_mime_application_free (application);
gtk_widget_destroy (dialog);
break;
default:
break;
}
gnome_vfs_mime_application_free (application);
}
static void
delete_selected_application (GtkWidget *button, GtkWidget *list)
{
GtkListItem *item;
const char *mime_type, *name;
const char *mime_type, *id;
GList *selection;
/* Get selected list item */
@@ -1342,14 +1412,16 @@ delete_selected_application (GtkWidget *button, GtkWidget *list)
return;
}
name = gtk_object_get_data (GTK_OBJECT (item), "application_id");
g_return_if_fail (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (item), "user_owned")));
id = gtk_object_get_data (GTK_OBJECT (item), "application_id");
mime_type = gtk_object_get_data (GTK_OBJECT (item), "mime_type");
/* Remove mime data */
if (name != NULL && mime_type != NULL) {
gnome_vfs_application_registry_remove_mime_type (name, mime_type);
/* Remove application if it is user owned */
if (id != NULL && mime_type != NULL) {
gnome_vfs_application_registry_remove_mime_type (id, mime_type);
gnome_vfs_application_registry_sync ();
gnome_vfs_mime_remove_application_from_short_list (mime_type, name);
gnome_vfs_mime_remove_application_from_short_list (mime_type, id);
}
/* Remove widget from list */

View File

@@ -30,6 +30,7 @@ void show_edit_components_dialog (const char *mime_type);
char *name_from_oaf_server_info (OAF_ServerInfo *server);
char *nautilus_mime_type_capplet_show_new_mime_window (void);
char *nautilus_mime_type_capplet_show_new_extension_window (void);
char *nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type);
char *nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type,
gboolean *new_list);
#endif /* NAUTILUS_MIME_TYPE_CAPPLET_DIALOGS_H */

View File

@@ -48,8 +48,11 @@
#include "nautilus-mime-type-capplet.h"
#define DEFAULT_REGULAR_ICON "/nautilus/i-regular-24.png"
#define DEFAULT_ACTION_ICON "/nautilus/i-executable.png"
#define DEFAULT_REGULAR_ICON "nautilus/i-regular-24.png"
#define DEFAULT_ACTION_ICON "nautilus/i-executable.png"
#define MAX_ICON_WIDTH_IN_LIST 18
#define MAX_ICON_HEIGHT_IN_LIST 18
enum {
COLUMN_DESCRIPTION = 0,
@@ -90,6 +93,8 @@ static void populate_mime_list (GList *type_li
static GdkPixbuf *capplet_get_icon_pixbuf (const char *mime_string,
gboolean is_executable);
/* FIXME: Using global variables here is yucky */
GtkWidget *capplet;
GtkWidget *delete_button;
GtkWidget *remove_button;
@@ -99,6 +104,8 @@ GtkWidget *default_menu;
GtkWidget *application_button, *viewer_button;
GtkLabel *mime_label;
GtkWidget *description_entry;
gboolean description_has_changed;
gboolean sort_column_clicked [TOTAL_COLUMNS];
/*
* main
@@ -261,11 +268,6 @@ nautilus_mime_type_capplet_add_extension (const char *extension)
return;
}
/* Check for starting space in string */
if (extension[0] == ' ') {
return;
}
/* Copy only contiguous part of string. No spaces allowed. */
search_string = g_strdup (extension);
token = strtok (search_string, " ");
@@ -274,7 +276,7 @@ nautilus_mime_type_capplet_add_extension (const char *extension)
title[0] = g_strdup (extension);
} else if (strlen (token) <= 0) {
return;
}else {
} else {
title[0] = g_strdup (token);
}
g_free (search_string);
@@ -377,26 +379,34 @@ get_selected_mime_type (void)
static void
really_change_icon (gpointer user_data)
{
NautilusMimeIconEntry *icon_entry;
char *filename;
const char *mime_type;
g_assert (NAUTILUS_MIME_IS_ICON_ENTRY (user_data));
mime_type = get_selected_mime_type ();
if (mime_type == NULL) {
return;
}
filename = nautilus_mime_type_icon_entry_get_relative_filename (NAUTILUS_MIME_ICON_ENTRY (user_data));
icon_entry = NAUTILUS_MIME_ICON_ENTRY (user_data);
filename = nautilus_mime_type_icon_entry_get_relative_filename (icon_entry);
if (filename == NULL) {
filename = nautilus_mime_type_icon_entry_get_full_filename (icon_entry);
}
gnome_vfs_mime_set_icon (mime_type, filename);
nautilus_mime_type_capplet_update_mime_list_icon (mime_type);
nautilus_mime_type_capplet_update_mime_list_icon_and_description (mime_type);
nautilus_mime_type_capplet_update_info (mime_type);
g_free (filename);
}
static void
gil_icon_selected_cb (GnomeIconList *gil, gint num, GdkEvent *event, gpointer user_data)
icon_chosen_callback (GnomeIconList *gil, gint num, GdkEvent *event, gpointer user_data)
{
NautilusMimeIconEntry *icon_entry;
const gchar * icon;
@@ -420,6 +430,7 @@ gil_icon_selected_cb (GnomeIconList *gil, gint num, GdkEvent *event, gpointer us
if(event && event->type == GDK_2BUTTON_PRESS && ((GdkEventButton *)event)->button == 1) {
gnome_icon_selection_stop_loading(gis);
really_change_icon (user_data);
gtk_widget_hide(icon_entry->pick_dialog);
}
@@ -428,7 +439,7 @@ gil_icon_selected_cb (GnomeIconList *gil, gint num, GdkEvent *event, gpointer us
static void
change_icon_clicked_cb_real (GnomeDialog *dialog, gint button_number, gpointer user_data)
{
if (button_number == 0) {
if (button_number == GNOME_OK) {
really_change_icon (user_data);
}
}
@@ -440,13 +451,14 @@ change_icon_clicked (GtkWidget *entry, gpointer user_data)
GnomeIconSelection * gis;
nautilus_mime_type_show_icon_selection (NAUTILUS_MIME_ICON_ENTRY (user_data));
dialog = GNOME_DIALOG (NAUTILUS_MIME_ICON_ENTRY (user_data)->pick_dialog);
gtk_signal_connect (GTK_OBJECT (dialog), "clicked", change_icon_clicked_cb_real, user_data);
gis = gtk_object_get_user_data(GTK_OBJECT(user_data));
gtk_signal_connect_after (GTK_OBJECT(GNOME_ICON_SELECTION(gis)->gil),
"select_icon", gil_icon_selected_cb, user_data);
"select_icon", icon_chosen_callback, user_data);
}
@@ -474,15 +486,17 @@ change_file_extensions_clicked (GtkWidget *widget, gpointer user_data)
{
const char *mime_type;
char *new_extensions;
gboolean use_new_list;
mime_type = get_selected_mime_type ();
if (mime_type == NULL) {
return;
}
new_extensions = nautilus_mime_type_capplet_show_change_extension_window (mime_type);
gnome_vfs_mime_set_extensions_list (mime_type, new_extensions);
new_extensions = nautilus_mime_type_capplet_show_change_extension_window (mime_type, &use_new_list);
if (use_new_list) {
gnome_vfs_mime_set_extensions_list (mime_type, new_extensions);
}
update_extensions_list (mime_type);
}
@@ -551,6 +565,97 @@ list_reveal_row (GtkCList *clist, int row_index)
}
}
static int
find_row_for_mime_type (const char *mime_type, GtkCList *mime_list)
{
gboolean found_one;
int index;
const char *row_data;
if (mime_type == NULL) {
return -1;
}
found_one = FALSE;
for (index = 0; index < mime_list->rows; index++) {
row_data = gtk_clist_get_row_data (mime_list, index);
if (row_data != NULL && strcmp (row_data, mime_type) == 0) {
found_one = TRUE;
break;
}
}
if (found_one) {
return index;
}
return -1;
}
static void
update_description_from_input (GtkEntry *entry)
{
char *new_description;
const char *mime_type;
g_assert (GTK_IS_ENTRY (entry));
g_assert ((gpointer)entry == (gpointer)description_entry);
description_has_changed = FALSE;
mime_type = get_selected_mime_type ();
if (mime_type == NULL) {
return;
}
new_description = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
gnome_vfs_mime_set_description (mime_type, new_description);
nautilus_mime_type_capplet_update_mime_list_icon_and_description (mime_type);
g_free (new_description);
}
static void
description_entry_activate (GtkEntry *entry, gpointer user_data)
{
g_assert (GTK_IS_ENTRY (entry));
g_assert ((gpointer)entry == (gpointer)description_entry);
g_assert (user_data == NULL);
if (description_has_changed) {
update_description_from_input (entry);
}
}
static void
description_entry_changed (GtkEntry *entry, gpointer user_data)
{
g_assert (GTK_IS_ENTRY (entry));
g_assert ((gpointer)entry == (gpointer)description_entry);
g_assert (user_data == NULL);
description_has_changed = TRUE;
}
static gboolean
description_entry_lost_focus (GtkEntry *entry,
GdkEventFocus *event,
gpointer user_data)
{
g_assert (GTK_IS_ENTRY (entry));
g_assert ((gpointer)entry == (gpointer)description_entry);
g_assert (user_data == NULL);
if (description_has_changed) {
update_description_from_input (entry);
}
return FALSE;
}
static void
init_mime_capplet (const char *scroll_to_mime_type)
{
@@ -560,9 +665,7 @@ init_mime_capplet (const char *scroll_to_mime_type)
GtkWidget *mime_list_container;
GtkWidget *frame;
GtkWidget *table;
int index, list_width, column_width;
gboolean found_one;
const char *row_data;
int index, list_width, column_width, found_index;
capplet = capplet_widget_new ();
@@ -610,13 +713,26 @@ init_mime_capplet (const char *scroll_to_mime_type)
(GtkAttachOptions) (GTK_FILL), 0, 0);
description_entry = gtk_entry_new ();
description_has_changed = FALSE;
gtk_box_pack_start (GTK_BOX (vbox), description_entry, FALSE, FALSE, 0);
gtk_widget_make_bold (GTK_WIDGET (description_entry));
gtk_signal_connect (GTK_OBJECT (description_entry), "activate",
GTK_SIGNAL_FUNC (description_entry_activate),
NULL);
gtk_signal_connect (GTK_OBJECT (description_entry), "changed",
GTK_SIGNAL_FUNC (description_entry_changed),
NULL);
gtk_signal_connect (GTK_OBJECT (description_entry), "focus_out_event",
GTK_SIGNAL_FUNC (description_entry_lost_focus),
NULL);
hbox = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (hbox), FALSE, FALSE, 0);
mime_label = GTK_LABEL (gtk_label_new (_("Mime Type")));
mime_label = GTK_LABEL (gtk_label_new (_("MIME Type")));
gtk_label_set_justify (GTK_LABEL (mime_label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (mime_label), FALSE, FALSE, 0);
@@ -665,11 +781,10 @@ init_mime_capplet (const char *scroll_to_mime_type)
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
default_menu = gtk_option_menu_new();
gtk_widget_set_usize (GTK_WIDGET (default_menu), 170, 0);
gtk_box_pack_start (GTK_BOX (hbox), default_menu, TRUE, TRUE, 0);
button = gtk_button_new_with_label (_("Edit List"));
gtk_widget_set_usize (GTK_WIDGET (button), 70, 0);
gtk_misc_set_padding (GTK_MISC (GTK_BIN(button)->child), 2, 1);
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "clicked", edit_default_clicked, mime_list);
}
@@ -693,13 +808,13 @@ init_mime_capplet (const char *scroll_to_mime_type)
(GtkAttachOptions) (0), 0, 0);
gtk_widget_set_usize (hbox, 1, 11);
button = gtk_button_new_with_label (_("Add new Mime type..."));
button = gtk_button_new_with_label (_("Add New MIME Type..."));
gtk_signal_connect (GTK_OBJECT (button), "clicked", add_mime_clicked, NULL);
gtk_table_attach (GTK_TABLE (small_table), button, 0, 1, 1, 2,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
button = gtk_button_new_with_label (_("Delete this Mime type..."));
button = gtk_button_new_with_label (_("Delete This MIME Type"));
gtk_signal_connect (GTK_OBJECT (button), "clicked", delete_mime_clicked, NULL);
gtk_table_attach (GTK_TABLE (small_table), button, 0, 1, 2, 3,
(GtkAttachOptions) (GTK_FILL),
@@ -718,12 +833,6 @@ init_mime_capplet (const char *scroll_to_mime_type)
}
/* FIXME bugzilla.eazel.com 2765: this call generates a
Gtk-WARNING **: gtk_signal_disconnect_by_data(): could not find handler containing data (0x80FA6F8)
I think it is a bug in the control-center...
*/
/* Yes, show all widgets */
gtk_widget_show_all (capplet);
@@ -744,32 +853,80 @@ init_mime_capplet (const char *scroll_to_mime_type)
/* Sort by description. The description is the first column in the list. */
gtk_clist_set_sort_column (GTK_CLIST (mime_list), COLUMN_DESCRIPTION);
gtk_clist_sort (GTK_CLIST (mime_list));
GTK_CLIST (mime_list)->sort_type = GTK_SORT_ASCENDING;
/* Set up initial column click tracking state. We do this so the initial clicks on
* columns will allow us to set the proper sort state for the user.
*/
sort_column_clicked[0] = TRUE; /* First sort column has been click by us in setup code */
for (index = 1; index < TOTAL_COLUMNS; index++) {
sort_column_clicked[index] = FALSE;
}
/* Attempt to select specified mime type in list */
if (scroll_to_mime_type != NULL) {
found_one = FALSE;
for (index = 0; index < GTK_CLIST (mime_list)->rows; index++) {
row_data = gtk_clist_get_row_data (GTK_CLIST (mime_list), index);
if (row_data != NULL && strcmp (row_data, scroll_to_mime_type) == 0) {
/* Select mime type and bail */
found_one = TRUE;
gtk_clist_select_row (GTK_CLIST (mime_list), index, 1);
list_reveal_row (GTK_CLIST (mime_list), index);
break;
}
}
if (!found_one) {
gtk_clist_select_row (GTK_CLIST (mime_list), 0, 0);
if (scroll_to_mime_type != NULL) {
found_index = find_row_for_mime_type (scroll_to_mime_type, GTK_CLIST (mime_list));
if (found_index != -1) {
gtk_clist_select_row (GTK_CLIST (mime_list), found_index, 1);
list_reveal_row (GTK_CLIST (mime_list), found_index);
} else {
gtk_clist_select_row (GTK_CLIST (mime_list), 0, 1);
list_reveal_row (GTK_CLIST (mime_list), 0);
}
} else {
gtk_clist_select_row (GTK_CLIST (mime_list), 0, 0);
list_reveal_row (GTK_CLIST (mime_list), 0);
}
capplet_widget_state_changed (CAPPLET_WIDGET (capplet), TRUE);
/* Inform control center that our changes are immediate */
capplet_widget_changes_are_immediate (CAPPLET_WIDGET (capplet));
}
static gboolean
is_full_path (const char *path_or_name)
{
return path_or_name[0] == '/';
}
static char *
capplet_get_icon_path (const char *path_or_name)
{
char *result;
char *alternate_relative_filename;
if (is_full_path (path_or_name) && g_file_exists (path_or_name)) {
return g_strdup (path_or_name);
}
result = gnome_vfs_icon_path_from_filename (path_or_name);
if (result != NULL) {
return result;
}
/* FIXME bugzilla.eazel.com 639:
* It is somewhat evil to special-case the nautilus directory here.
* We should clean this up if/when we come up with a way to handle
* Nautilus themes here.
*/
alternate_relative_filename = g_strconcat ("nautilus/", path_or_name, NULL);
result = gnome_vfs_icon_path_from_filename (alternate_relative_filename);
g_free (alternate_relative_filename);
if (result != NULL) {
return result;
}
/* FIXME bugzilla.eazel.com 639:
* To work correctly with Nautilus themed icons, if there's no
* suffix we will also try looking in the nautilus dir for a ".png" name.
* This will return the icon for the default theme; there is no
* mechanism for getting a themed icon in the capplet.
*/
alternate_relative_filename = g_strconcat ("nautilus/", path_or_name, ".png", NULL);
result = gnome_vfs_icon_path_from_filename (alternate_relative_filename);
g_free (alternate_relative_filename);
return result;
}
/*
* nautilus_mime_type_capplet_update_info
@@ -788,14 +945,9 @@ nautilus_mime_type_capplet_update_info (const char *mime_type) {
gtk_label_set_text (GTK_LABEL (mime_label), mime_type);
description = gnome_vfs_mime_get_description (mime_type);
if (description != NULL && strlen (description) > 0) {
gtk_entry_set_text (GTK_ENTRY (description_entry), description);
} else {
gtk_entry_set_text (GTK_ENTRY (description_entry), _("No Description"));
}
gtk_entry_set_text (GTK_ENTRY (description_entry), description != NULL ? description : "");
description_has_changed = FALSE;
gtk_editable_set_editable (GTK_EDITABLE (description_entry), FALSE);
/* Update menus */
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (application_button))) {
populate_application_menu (default_menu, mime_type);
@@ -810,23 +962,16 @@ nautilus_mime_type_capplet_update_info (const char *mime_type) {
/* Set icon for mime type */
icon_name = gnome_vfs_mime_get_icon (mime_type);
path = NULL;
if (icon_name != NULL) {
path = gnome_vfs_icon_path_from_filename (icon_name);
if (path != NULL) {
nautilus_mime_type_icon_entry_set_icon (NAUTILUS_MIME_ICON_ENTRY (icon_entry), path);
g_free (path);
} else {
/* No icon */
nautilus_mime_type_icon_entry_set_icon (NAUTILUS_MIME_ICON_ENTRY (icon_entry),
NULL);
}
} else {
/* No icon */
path = gnome_vfs_icon_path_from_filename (DEFAULT_REGULAR_ICON);
nautilus_mime_type_icon_entry_set_icon (NAUTILUS_MIME_ICON_ENTRY (icon_entry),
path);
g_free (path);
path = capplet_get_icon_path (icon_name);
}
if (path == NULL) {
/* No custom icon specified, or custom icon not found, use default */
path = capplet_get_icon_path (DEFAULT_REGULAR_ICON);
}
nautilus_mime_type_icon_entry_set_icon (NAUTILUS_MIME_ICON_ENTRY (icon_entry), path);
g_free (path);
/* Indicate default action */
action = gnome_vfs_mime_get_default_action (mime_type);
@@ -1147,9 +1292,18 @@ revert_real_cb (gint reply, gpointer data)
gnome_vfs_mime_info_reload ();
mime_types_list = gnome_vfs_get_registered_mime_types ();
gtk_clist_freeze (GTK_CLIST (mime_list));
gtk_clist_clear (GTK_CLIST (mime_list));
populate_mime_list (mime_types_list, GTK_CLIST (mime_list));
/* Sort list using current sort type and select the first item. */
gtk_clist_sort (GTK_CLIST (mime_list));
gtk_clist_select_row (GTK_CLIST (mime_list), 0, 0);
list_reveal_row (GTK_CLIST (mime_list), 0);
gtk_clist_thaw (GTK_CLIST (mime_list));
} else {
/* NO */
}
@@ -1161,10 +1315,9 @@ revert_mime_clicked (GtkWidget *widget, gpointer data)
{
GtkWidget *dialog;
dialog = gnome_question_dialog_modal (_("Reverting to system settings\n"
"will lose all your personal \n"
"Mime configuration.\n"
"Revert to System Settings ?\n"),
dialog = gnome_question_dialog_modal (_("Reverting to system settings will lose any changes\n"
"you have ever made to File Types and Programs.\n"
"Revert anyway?"),
revert_real_cb, NULL);
}
@@ -1204,9 +1357,10 @@ add_mime_clicked (GtkWidget *widget, gpointer data)
GnomeVFSMimeAction *action;
GnomeVFSMimeApplication *default_app;
OAF_ServerInfo *default_component;
int found_index;
mime_string = nautilus_mime_type_capplet_show_new_mime_window ();
if (mime_string != NULL) {
if (mime_string != NULL && mime_string[0] != '\0') {
/* Add new type to mime list */
pixbuf = NULL;
@@ -1240,7 +1394,7 @@ add_mime_clicked (GtkWidget *widget, gpointer data)
pixbuf = capplet_get_icon_pixbuf (mime_string, FALSE);
if (pixbuf != NULL) {
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (GTK_CLIST (mime_list), row, 0, text[0], 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
@@ -1257,7 +1411,11 @@ add_mime_clicked (GtkWidget *widget, gpointer data)
g_free (text[3]);
text[3] = g_strdup (default_app->name);
pixbuf = capplet_get_icon_pixbuf (mime_string, TRUE);
filename = capplet_get_icon_path (DEFAULT_ACTION_ICON);
if (filename != NULL) {
pixbuf = gdk_pixbuf_new_from_file (filename);
g_free (filename);
}
gnome_vfs_mime_application_free (default_app);
break;
@@ -1269,9 +1427,11 @@ add_mime_clicked (GtkWidget *widget, gpointer data)
tmp_text = name_from_oaf_server_info (default_component);
text[3] = g_strdup_printf (_("View as %s"), tmp_text);
g_free (tmp_text);
filename = gnome_vfs_icon_path_from_filename ("nautilus/gnome-library.png");
pixbuf = gdk_pixbuf_new_from_file (filename);
g_free (filename);
filename = capplet_get_icon_path ("nautilus/gnome-library.png");
if (filename != NULL) {
pixbuf = gdk_pixbuf_new_from_file (filename);
g_free (filename);
}
CORBA_free (default_component);
break;
@@ -1283,12 +1443,20 @@ add_mime_clicked (GtkWidget *widget, gpointer data)
/* Set column icon */
if (pixbuf != NULL) {
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (GTK_CLIST (mime_list), row, 3, text[3], 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
}
/* Sort, select and scroll to new mime type */
gtk_clist_sort (GTK_CLIST (mime_list));
found_index = find_row_for_mime_type (mime_string, GTK_CLIST (mime_list));
if (found_index != -1) {
gtk_clist_select_row (GTK_CLIST (mime_list), found_index, 1);
list_reveal_row (GTK_CLIST (mime_list), found_index);
}
g_free (text[0]);
g_free (text[1]);
g_free (text[2]);
@@ -1336,7 +1504,7 @@ edit_default_clicked (GtkWidget *widget, gpointer data)
void
nautilus_mime_type_capplet_update_mime_list_icon (const char *mime_string)
nautilus_mime_type_capplet_update_mime_list_icon_and_description (const char *mime_string)
{
char *text;
const char *description;
@@ -1366,7 +1534,7 @@ nautilus_mime_type_capplet_update_mime_list_icon (const char *mime_string)
pixbuf = capplet_get_icon_pixbuf (mime_string, FALSE);
if (pixbuf != NULL) {
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (clist, row, 0, text, 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
@@ -1410,9 +1578,7 @@ update_mime_list_action (const char *mime_string)
GnomeVFSMimeAction *action;
GnomeVFSMimeApplication *default_app;
OAF_ServerInfo *default_component;
const char *action_icon_name;
char *text, *tmp_text;
char *action_icon_path;
char *text, *tmp_text, *icon_path;
int row;
pixbuf = NULL;
@@ -1423,22 +1589,19 @@ update_mime_list_action (const char *mime_string)
action = gnome_vfs_mime_get_default_action (mime_string);
if (action != NULL) {
switch (action->action_type) {
/* FIXME: Big hunks of this code are copied/pasted in several
* places in this file. Need to use common routines. One way
* to find them is to search for "nautilus/gnome-library.png"
*/
case GNOME_VFS_MIME_ACTION_TYPE_APPLICATION:
/* Get the default application */
default_app = gnome_vfs_mime_get_default_application (mime_string);
g_free (text);
text = g_strdup (default_app->name);
action_icon_name = gnome_vfs_mime_get_icon (mime_string);
if (action_icon_name != NULL) {
/* Get custom icon */
action_icon_path = gnome_pixmap_file (action_icon_name);
if (action_icon_path != NULL) {
pixbuf = gdk_pixbuf_new_from_file (action_icon_path);
g_free (action_icon_path);
}
} else {
/* Use default icon */
pixbuf = gdk_pixbuf_new_from_file (DEFAULT_ACTION_ICON);
text = g_strdup (default_app->name);
icon_path = capplet_get_icon_path (DEFAULT_ACTION_ICON);
if (icon_path != NULL) {
pixbuf = gdk_pixbuf_new_from_file (icon_path);
g_free (icon_path);
}
gnome_vfs_mime_application_free (default_app);
break;
@@ -1450,7 +1613,11 @@ update_mime_list_action (const char *mime_string)
tmp_text = name_from_oaf_server_info (default_component);
text = g_strdup_printf (_("View as %s"), tmp_text);
g_free (tmp_text);
pixbuf = gdk_pixbuf_new_from_file ("/gnome/share/pixmaps/nautilus/gnome-library.png");
icon_path = capplet_get_icon_path ("nautilus/gnome-library.png");
if (icon_path != NULL) {
pixbuf = gdk_pixbuf_new_from_file (icon_path);
g_free (icon_path);
}
CORBA_free (default_component);
break;
@@ -1462,7 +1629,7 @@ update_mime_list_action (const char *mime_string)
/* Set column icon */
if (pixbuf != NULL) {
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (GTK_CLIST (mime_list), row, 3, text, 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
@@ -1473,30 +1640,30 @@ update_mime_list_action (const char *mime_string)
g_free (text);
}
/* FIXME:
* This routine is never called with is_executable TRUE anymore. It
* could be simplified, possibly out of existence.
*/
static GdkPixbuf *
capplet_get_icon_pixbuf (const char *mime_string, gboolean is_executable)
{
const char *description_icon_name;
char *description_icon_path;
const char *icon_name;
char *icon_path;
GdkPixbuf *pixbuf;
pixbuf = NULL;
description_icon_name = gnome_vfs_mime_get_icon (mime_string);
if (description_icon_name != NULL) {
/* Get custom icon */
description_icon_path = gnome_vfs_icon_path_from_filename (description_icon_name);
if (description_icon_path != NULL) {
pixbuf = gdk_pixbuf_new_from_file (description_icon_path);
g_free (description_icon_path);
}
} else {
if (!is_executable) {
description_icon_path = gnome_vfs_icon_path_from_filename (DEFAULT_REGULAR_ICON);
} else {
description_icon_path = gnome_vfs_icon_path_from_filename (DEFAULT_ACTION_ICON);
}
pixbuf = gdk_pixbuf_new_from_file (description_icon_path);
icon_name = gnome_vfs_mime_get_icon (mime_string);
if (icon_name == NULL) {
icon_name = is_executable
? DEFAULT_ACTION_ICON
: DEFAULT_REGULAR_ICON;
}
icon_path = capplet_get_icon_path (icon_name);
if (icon_path != NULL) {
pixbuf = gdk_pixbuf_new_from_file (icon_path);
g_free (icon_path);
}
return pixbuf;
@@ -1507,6 +1674,7 @@ populate_mime_list (GList *type_list, GtkCList *clist)
{
char *text[4], *tmp_text;
const char *description;
char *icon_path;
char *extensions, *mime_string;
gint row;
GList *element;
@@ -1552,7 +1720,11 @@ populate_mime_list (GList *type_list, GtkCList *clist)
pixbuf = capplet_get_icon_pixbuf (mime_string, FALSE);
if (pixbuf != NULL) {
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
/* FIXME: Big hunks of this code are copied/pasted in several
* places in this file. Need to use common routines. One way
* to find them is to search for MAX_ICON_WIDTH_IN_LIST
*/
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (clist, row, 0, text[0], 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
@@ -1569,7 +1741,11 @@ populate_mime_list (GList *type_list, GtkCList *clist)
g_free (text[3]);
text[3] = g_strdup (default_app->name);
pixbuf = capplet_get_icon_pixbuf (mime_string, TRUE);
icon_path = capplet_get_icon_path (DEFAULT_ACTION_ICON);
if (icon_path != NULL) {
pixbuf = gdk_pixbuf_new_from_file (icon_path);
g_free (icon_path);
}
gnome_vfs_mime_application_free (default_app);
break;
@@ -1580,7 +1756,11 @@ populate_mime_list (GList *type_list, GtkCList *clist)
tmp_text = name_from_oaf_server_info (default_component);
text[3] = g_strdup_printf (_("View as %s"), tmp_text);
g_free (tmp_text);
pixbuf = gdk_pixbuf_new_from_file ("/gnome/share/pixmaps/nautilus/gnome-library.png");
icon_path = capplet_get_icon_path ("nautilus/gnome-library.png");
if (icon_path != NULL) {
pixbuf = gdk_pixbuf_new_from_file (icon_path);
g_free (icon_path);
}
CORBA_free (default_component);
break;
@@ -1592,7 +1772,7 @@ populate_mime_list (GList *type_list, GtkCList *clist)
/* Set column icon */
if (pixbuf != NULL) {
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, 18, 18);
pixbuf = capplet_gdk_pixbuf_scale_to_fit (pixbuf, MAX_ICON_WIDTH_IN_LIST, MAX_ICON_HEIGHT_IN_LIST);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &bitmap, 100);
gtk_clist_set_pixtext (clist, row, 3, text[3], 5, pixmap, bitmap);
gdk_pixbuf_unref (pixbuf);
@@ -1650,16 +1830,22 @@ sort_case_insensitive (GtkCList *clist, gpointer ptr1, gpointer ptr2)
return strcasecmp (text1, text2);
}
static void
column_clicked (GtkCList *clist, gint column, gpointer user_data)
{
gtk_clist_set_sort_column (clist, column);
/* If the user has not clicked the column yet, make sure
* that the sort type is descending the first time.
*/
if (!sort_column_clicked [column]) {
clist->sort_type = GTK_SORT_DESCENDING;
sort_column_clicked [column] = TRUE;
}
/* Toggle sort type */
if (clist->sort_type == GTK_SORT_ASCENDING) {
gtk_clist_set_sort_type (clist, GTK_SORT_DESCENDING);
} else {
gtk_clist_set_sort_type (clist, GTK_SORT_ASCENDING);
}
@@ -1667,6 +1853,17 @@ column_clicked (GtkCList *clist, gint column, gpointer user_data)
gtk_clist_sort (clist);
}
static void
mime_list_reset_row_height (GtkCList *list)
{
guint height_for_icon;
guint height_for_text;
height_for_icon = MAX_ICON_HEIGHT_IN_LIST + 1;
height_for_text = GTK_WIDGET (list)->style->font->ascent +
GTK_WIDGET (list)->style->font->descent + 1;
gtk_clist_set_row_height (list, MAX (height_for_icon, height_for_text));
}
static GtkWidget *
create_mime_list_and_scroller (void)
@@ -1677,7 +1874,7 @@ create_mime_list_and_scroller (void)
int index;
titles[0] = _("Description");
titles[1] = _("Mime Type");
titles[1] = _("MIME Type");
titles[2] = _("Extension");
titles[3] = _("Default Action");
@@ -1706,6 +1903,17 @@ create_mime_list_and_scroller (void)
for (index = 0; index < TOTAL_COLUMNS; index++) {
gtk_clist_set_column_auto_resize (GTK_CLIST (mime_list), index, FALSE);
}
/* Make height tall enough for icons to look good.
* This must be done after the list widget is realized, due to
* a bug/design flaw in nautilus_clist_set_row_height. Connecting to
* the "realize" signal is slightly too early, so we connect to
* "map".
*/
gtk_signal_connect (GTK_OBJECT (mime_list),
"map",
mime_list_reset_row_height,
NULL);
return window;
}

View File

@@ -0,0 +1,7 @@
[Desktop Entry]
_Name=File Types and Programs
_Comment=Specify which programs are used to open or view each file type
Icon=gnome-ccmime.png
Exec=file-types-capplet
Terminal=0
Type=Application

View File

@@ -25,11 +25,11 @@
#ifndef NAUTILUS_MIME_TYPE_CAPPLET_H
#define NAUTILUS_MIME_TYPE_CAPPLET_H
void nautilus_mime_type_capplet_update_info (const char *mime_type);
void nautilus_mime_type_capplet_update_application_info (const char *mime_type);
void nautilus_mime_type_capplet_update_viewer_info (const char *mime_type);
void nautilus_mime_type_capplet_add_extension (const char *extension);
const char *nautilus_mime_type_capplet_get_selected_item_mime_type (void);
void nautilus_mime_type_capplet_update_mime_list_icon (const char *mime_string);
void nautilus_mime_type_capplet_update_info (const char *mime_type);
void nautilus_mime_type_capplet_update_application_info (const char *mime_type);
void nautilus_mime_type_capplet_update_viewer_info (const char *mime_type);
void nautilus_mime_type_capplet_add_extension (const char *extension);
const char *nautilus_mime_type_capplet_get_selected_item_mime_type (void);
void nautilus_mime_type_capplet_update_mime_list_icon_and_description (const char *mime_string);
#endif /* NAUTILUS_MIME_TYPE_CAPPLET_H */

View File

@@ -142,6 +142,7 @@ entry_activated(GtkWidget *widget, NautilusMimeIconEntry *ientry)
struct stat buf;
GnomeIconSelection * gis;
gchar *filename;
GtkButton *OK_button;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_ENTRY (widget));
@@ -161,9 +162,11 @@ entry_activated(GtkWidget *widget, NautilusMimeIconEntry *ientry)
if (gis->file_list)
gnome_icon_selection_show_icons(gis);
} else {
/* We pretend like ok has been called */
entry_changed (NULL, ientry);
gtk_widget_hide (ientry->pick_dialog);
/* FIXME: This is a hack to act exactly like we've clicked the
* OK button. This should be structured more cleanly.
*/
OK_button = GTK_BUTTON (GNOME_DIALOG (ientry->pick_dialog)->buttons->data);
gtk_button_clicked (OK_button);
}
}
@@ -274,41 +277,6 @@ browse_clicked (GnomeFileEntry *fentry, NautilusMimeIconEntry *ientry)
GTK_OBJECT(fs));
}
static void
icon_selected_cb (GtkButton *button, NautilusMimeIconEntry *icon_entry)
{
const gchar *icon;
GnomeIconSelection *gis;
gchar *path, *filename;
const char *mime_type;
GtkWidget *entry;
g_return_if_fail (icon_entry != NULL);
g_return_if_fail (NAUTILUS_MIME_IS_ICON_ENTRY (icon_entry));
gis = gtk_object_get_user_data (GTK_OBJECT (icon_entry));
gnome_icon_selection_stop_loading (gis);
icon = gnome_icon_selection_get_icon (gis, TRUE);
if (icon != NULL) {
entry = nautilus_mime_type_icon_entry_gtk_entry (icon_entry);
gtk_entry_set_text (GTK_ENTRY (entry), icon);
entry_changed (NULL, icon_entry);
path = nautilus_mime_type_icon_entry_get_relative_filename (NAUTILUS_MIME_ICON_ENTRY (icon_entry));
if (path != NULL) {
filename = strrchr (path, '/');
if (filename != NULL) {
filename++;
mime_type = nautilus_mime_type_capplet_get_selected_item_mime_type ();
gnome_vfs_mime_set_icon (mime_type, filename);
nautilus_mime_type_capplet_update_mime_list_icon (mime_type);
}
g_free (path);
}
}
}
static void
cancel_pressed (GtkButton * button, NautilusMimeIconEntry * icon_entry)
{
@@ -322,31 +290,6 @@ cancel_pressed (GtkButton * button, NautilusMimeIconEntry * icon_entry)
}
static void
gil_icon_selected_cb (GnomeIconList *gil, gint num, GdkEvent *event, NautilusMimeIconEntry *icon_entry)
{
const gchar * icon;
GnomeIconSelection * gis;
g_return_if_fail (icon_entry != NULL);
g_return_if_fail (NAUTILUS_MIME_IS_ICON_ENTRY (icon_entry));
gis = gtk_object_get_user_data(GTK_OBJECT(icon_entry));
icon = gnome_icon_selection_get_icon(gis, TRUE);
if (icon != NULL) {
GtkWidget *e = nautilus_mime_type_icon_entry_gtk_entry(icon_entry);
gtk_entry_set_text(GTK_ENTRY(e),icon);
}
if(event && event->type == GDK_2BUTTON_PRESS && ((GdkEventButton *)event)->button == 1) {
gnome_icon_selection_stop_loading(gis);
entry_changed (NULL, icon_entry);
gtk_widget_hide(icon_entry->pick_dialog);
}
}
void
nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry *icon_entry)
{
@@ -360,7 +303,7 @@ nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry *icon_entry)
fe = GNOME_FILE_ENTRY (icon_entry->fentry);
p = gnome_file_entry_get_full_path (fe, FALSE);
curfile = nautilus_mime_type_icon_entry_get_filename (icon_entry);
curfile = nautilus_mime_type_icon_entry_get_full_filename (icon_entry);
/* Are we part of a modal window? If so, we need to be modal too. */
tl = gtk_widget_get_toplevel (GTK_WIDGET (icon_entry->frame));
@@ -434,12 +377,12 @@ nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry *icon_entry)
gtk_object_set_user_data(GTK_OBJECT(icon_entry), iconsel);
gnome_icon_selection_add_directory (GNOME_ICON_SELECTION(iconsel), icon_entry->pick_dialog_dir);
/* Hide the file entry until we figure out how to deal with icon paths
outside of the standard gnome paths */
/*gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (icon_entry->pick_dialog)->vbox),
gtk_window_set_title (GTK_WINDOW (icon_entry->pick_dialog), _("Select an icon"));
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (icon_entry->pick_dialog)->vbox),
icon_entry->fentry, FALSE, FALSE, 0);
*/
gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(icon_entry->pick_dialog)->vbox),
iconsel, TRUE, TRUE, 0);
@@ -451,17 +394,15 @@ nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry *icon_entry)
gnome_icon_selection_select_icon(GNOME_ICON_SELECTION(iconsel),
g_filename_pointer(curfile));
gnome_dialog_button_connect(GNOME_DIALOG (icon_entry->pick_dialog),
0, /* OK button */
GTK_SIGNAL_FUNC (icon_selected_cb),
icon_entry);
/* FIXME:
* OK button is handled by caller, Cancel button is handled here.
* This could be cleaned up further.
*/
gnome_dialog_button_connect(GNOME_DIALOG(icon_entry->pick_dialog),
1, /* Cancel button */
GTK_SIGNAL_FUNC(cancel_pressed),
icon_entry);
gtk_signal_connect_after(GTK_OBJECT(GNOME_ICON_SELECTION(iconsel)->gil), "select_icon",
GTK_SIGNAL_FUNC(gil_icon_selected_cb),
icon_entry);
} else {
GnomeIconSelection *gis =
gtk_object_get_user_data(GTK_OBJECT(icon_entry));
@@ -476,27 +417,24 @@ nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry *icon_entry)
gchar *
nautilus_mime_type_icon_entry_get_relative_filename (NautilusMimeIconEntry *ientry)
{
char *filename;
char **path_parts;
char *filename;
char *result;
char **path_parts;
result = NULL;
filename = nautilus_mime_type_icon_entry_get_full_filename (NAUTILUS_MIME_ICON_ENTRY (ientry));
if (filename != NULL) {
path_parts = g_strsplit (filename, "/share/pixmaps/", 0);
g_free (filename);
filename = nautilus_mime_type_icon_entry_get_filename (NAUTILUS_MIME_ICON_ENTRY (ientry));
if (path_parts[1] != NULL) {
result = g_strdup (path_parts[1]);
}
path_parts = g_strsplit (filename, "/share/pixmaps/", 0);
g_free (filename);
filename = NULL;
if (path_parts[1] != NULL) {
filename = g_strdup (path_parts[1]);
} else {
/* FIXME: bugzilla.eazel.com 4797 */
g_warning ("user picked up an icon not in $(prefix)/share/pixmaps\n");
filename = g_strdup ("");
g_strfreev (path_parts);
}
g_strfreev (path_parts);
return filename;
return result;
}
static void
@@ -690,7 +628,7 @@ nautilus_mime_type_icon_entry_set_icon (NautilusMimeIconEntry *ientry, const gch
}
/**
* nautilus_mime_type_icon_entry_get_filename:
* nautilus_mime_type_icon_entry_get_full_filename:
* @ientry: the NautilusMimeIconEntry to work with
*
* Description: Gets the file name of the image if it was possible
@@ -701,7 +639,7 @@ nautilus_mime_type_icon_entry_set_icon (NautilusMimeIconEntry *ientry, const gch
* couldn't load the file
**/
gchar *
nautilus_mime_type_icon_entry_get_filename (NautilusMimeIconEntry *ientry)
nautilus_mime_type_icon_entry_get_full_filename (NautilusMimeIconEntry *ientry)
{
GtkWidget *child;

View File

@@ -63,7 +63,7 @@ GtkWidget *nautilus_mime_type_icon_entry_gnome_entry (NautilusMimeIconEntry *ien
GtkWidget *nautilus_mime_type_icon_entry_gtk_entry (NautilusMimeIconEntry *ientry);
/*only return a file if it was possible to load it with imlib*/
gchar *nautilus_mime_type_icon_entry_get_filename (NautilusMimeIconEntry *ientry);
gchar *nautilus_mime_type_icon_entry_get_full_filename (NautilusMimeIconEntry *ientry);
gchar *nautilus_mime_type_icon_entry_get_relative_filename (NautilusMimeIconEntry *ientry);
void nautilus_mime_type_show_icon_selection (NautilusMimeIconEntry * ientry);

View File

@@ -1,2 +1,3 @@
Makefile.in
Makefile
Makefile.in
.deps

View File

@@ -0,0 +1,27 @@
NULL =
noinst_LIBRARIES = libuuid.a
noinst_HEADERS = \
uuid.h \
uuidP.h \
$(NULL)
libuuid_a_SOURCES = \
clear.c \
compare.c \
copy.c \
gen_uuid.c \
isnull.c \
pack.c \
parse.c \
unpack.c \
unparse.c \
uuid_time.c \
$(NULL)
INCLUDES = \
$(GLIB_CFLAGS) \
$(WERROR) \
$(NULL)

View File

@@ -0,0 +1,20 @@
/*
* clear.c -- Clear a UUID
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "string.h"
#include "uuidP.h"
void uuid_clear(uuid_t uu)
{
memset(uu, 0, 16);
}

View File

@@ -0,0 +1,32 @@
/*
* compare.c --- compare whether or not two UUID's are the same
*
* Returns 0 if the two UUID's are different, and 1 if they are the same.
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "uuidP.h"
#include <string.h>
#define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1);
int uuid_compare(uuid_t uu1, uuid_t uu2)
{
struct uuid uuid1, uuid2;
uuid_unpack(uu1, &uuid1);
uuid_unpack(uu2, &uuid2);
UUCMP(uuid1.time_low, uuid2.time_low);
UUCMP(uuid1.time_mid, uuid2.time_mid);
UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
UUCMP(uuid1.clock_seq, uuid2.clock_seq);
return memcmp(uuid1.node, uuid2.node, 6);
}

View File

@@ -0,0 +1,21 @@
/*
* copy.c --- copy UUIDs
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "uuidP.h"
void uuid_copy(uuid_t uu1, uuid_t uu2)
{
unsigned char *cp1, *cp2;
int i;
for (i=0, cp1 = uu1, cp2 = uu2; i < 16; i++)
*cp1++ = *cp2++;
}

View File

@@ -0,0 +1,257 @@
/*
* gen_uuid.c --- generate a DCE-compatible uuid
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <config.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include "uuidP.h"
#ifdef HAVE_SRANDOM
#define srand(x) srandom(x)
#define rand() random()
#endif
/*
* Generate a series of random bytes. Use /dev/urandom if possible,
* and if not, use srandom/random.
*/
static void get_random_bytes(void *buf, int nbytes)
{
static int fd = -2;
int i;
char *cp = (char *) buf;
if (fd == -2) {
fd = open("/dev/urandom", O_RDONLY);
srand((getpid() << 16) ^ getuid() ^ time(0));
}
if (fd >= 0) {
while (nbytes > 0) {
i = read(fd, cp, nbytes);
if (i < 0) {
if ((errno == EINTR) || (errno == EAGAIN))
continue;
break;
}
nbytes -= i;
cp += i;
}
}
if (nbytes == 0)
return;
/* XXX put something better here if no /dev/random! */
for (i=0; i < nbytes; i++)
*cp++ = rand() & 0xFF;
return;
}
/*
* Get the ethernet hardware address, if we can find it...
*/
static int get_node_id(unsigned char *node_id)
{
#ifdef HAVE_NET_IF_H
int sd;
struct ifreq ifr, *ifrp;
struct ifconf ifc;
char buf[1024];
int n, i;
unsigned char *a;
/*
* BSD 4.4 defines the size of an ifreq to be
* max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
* However, under earlier systems, sa_len isn't present, so the size is
* just sizeof(struct ifreq)
*/
#ifdef HAVE_SA_LEN
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#define ifreq_size(i) max(sizeof(struct ifreq),\
sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
#else
#define ifreq_size(i) sizeof(struct ifreq)
#endif /* HAVE_SA_LEN*/
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sd < 0) {
return -1;
}
memset(buf, 0, sizeof(buf));
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
close(sd);
return -1;
}
n = ifc.ifc_len;
for (i = 0; i < n; i+= ifreq_size(*ifr) ) {
ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
#ifdef SIOCGIFHWADDR
if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
continue;
a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
#else
#ifdef SIOCGENADDR
if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
continue;
a = (unsigned char *) ifr.ifr_enaddr;
#else
/*
* XXX we don't have a way of getting the hardware
* address
*/
close(sd);
return 0;
#endif /* SIOCGENADDR */
#endif /* SIOCGIFHWADDR */
if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
continue;
if (node_id) {
memcpy(node_id, a, 6);
close(sd);
return 1;
}
}
close(sd);
#endif
return 0;
}
/* Assume that the gettimeofday() has microsecond granularity */
#define MAX_ADJUSTMENT 10
static int get_clock(guint32 *clock_high, guint32 *clock_low, guint16 *ret_clock_seq)
{
static int adjustment = 0;
static struct timeval last = {0, 0};
static guint16 clock_seq;
struct timeval tv;
unsigned long long clock_reg;
try_again:
gettimeofday(&tv, 0);
if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
get_random_bytes(&clock_seq, sizeof(clock_seq));
clock_seq &= 0x1FFF;
last = tv;
last.tv_sec--;
}
if ((tv.tv_sec < last.tv_sec) ||
((tv.tv_sec == last.tv_sec) &&
(tv.tv_usec < last.tv_usec))) {
clock_seq = (clock_seq+1) & 0x1FFF;
adjustment = 0;
} else if ((tv.tv_sec == last.tv_sec) &&
(tv.tv_usec == last.tv_usec)) {
if (adjustment >= MAX_ADJUSTMENT)
goto try_again;
adjustment++;
} else
adjustment = 0;
clock_reg = tv.tv_usec*10 + adjustment;
clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
*clock_high = clock_reg >> 32;
*clock_low = clock_reg;
*ret_clock_seq = clock_seq;
return 0;
}
void uuid_generate_time(uuid_t out)
{
static unsigned char node_id[6];
static int has_init = 0;
struct uuid uu;
guint32 clock_mid;
if (!has_init) {
if (get_node_id(node_id) <= 0) {
get_random_bytes(node_id, 6);
/*
* Set multicast bit, to prevent conflicts
* with IEEE 802 addresses obtained from
* network cards
*/
node_id[0] |= 0x80;
}
has_init = 1;
}
get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
uu.clock_seq |= 0x8000;
uu.time_mid = (guint16) clock_mid;
uu.time_hi_and_version = (clock_mid >> 16) | 0x1000;
memcpy(uu.node, node_id, 6);
uuid_pack(&uu, out);
}
void uuid_generate_random(uuid_t out)
{
uuid_t buf;
struct uuid uu;
get_random_bytes(buf, sizeof(buf));
uuid_unpack(buf, &uu);
uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
uuid_pack(&uu, out);
}
/*
* This is the generic front-end to uuid_generate_random and
* uuid_generate_time. It uses uuid_generate_random only if
* /dev/urandom is available, since otherwise we won't have
* high-quality randomness.
*/
void uuid_generate(uuid_t out)
{
static int has_random = -1;
if (has_random < 0) {
if (access("/dev/urandom", R_OK) == 0)
has_random = 1;
else
has_random = 0;
}
if (has_random)
uuid_generate_random(out);
else
uuid_generate_time(out);
}

View File

@@ -0,0 +1,92 @@
/*
* gen_uuid_nt.c -- Use NT api to generate uuid
*
* Written by Andrey Shedel (andreys@ns.cr.cyco.com)
*/
#include "uuidP.h"
#pragma warning(push,4)
#pragma comment(lib, "ntdll.lib")
//
// Here is a nice example why it's not a good idea
// to use native API in ordinary applications.
// Number of parameters in function below was changed from 3 to 4
// for NT5.
//
//
// NTSYSAPI
// NTSTATUS
// NTAPI
// NtAllocateUuids(
// OUT PULONG p1,
// OUT PULONG p2,
// OUT PULONG p3,
// OUT PUCHAR Seed // 6 bytes
// );
//
//
unsigned long
__stdcall
NtAllocateUuids(
void* p1, // 8 bytes
void* p2, // 4 bytes
void* p3 // 4 bytes
);
typedef
unsigned long
(__stdcall*
NtAllocateUuids_2000)(
void* p1, // 8 bytes
void* p2, // 4 bytes
void* p3, // 4 bytes
void* seed // 6 bytes
);
//
// Nice, but instead of including ntddk.h ot winnt.h
// I should define it here because they MISSED __stdcall in those headers.
//
__declspec(dllimport)
struct _TEB*
__stdcall
NtCurrentTeb(void);
//
// The only way to get version information from the system is to examine
// one stored in PEB. But it's pretty dangerouse because this value could
// be altered in image header.
//
static
int
Nt5(void)
{
//return NtCuttentTeb()->Peb->OSMajorVersion >= 5;
return (int)*(int*)((char*)(int)(*(int*)((char*)NtCurrentTeb() + 0x30)) + 0xA4) >= 5;
}
void uuid_generate(uuid_t out)
{
if(Nt5())
{
unsigned char seed[6];
((NtAllocateUuids_2000)NtAllocateUuids)(out, ((char*)out)+8, ((char*)out)+12, &seed[0] );
}
else
{
NtAllocateUuids(out, ((char*)out)+8, ((char*)out)+12);
}
}

View File

@@ -0,0 +1,25 @@
/*
* isnull.c --- Check whether or not the UUID is null
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "uuidP.h"
/* Returns 1 if the uuid is the NULL uuid */
int uuid_is_null(uuid_t uu)
{
unsigned char *cp;
int i;
for (i=0, cp = uu; i < 16; i++)
if (*cp++)
return 0;
return 1;
}

View File

@@ -0,0 +1,46 @@
/*
* Internal routine for packing UUID's
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <string.h>
#include "uuidP.h"
void uuid_pack(struct uuid *uu, uuid_t ptr)
{
guint32 tmp;
unsigned char *out = ptr;
tmp = uu->time_low;
out[3] = (unsigned char) tmp;
tmp >>= 8;
out[2] = (unsigned char) tmp;
tmp >>= 8;
out[1] = (unsigned char) tmp;
tmp >>= 8;
out[0] = (unsigned char) tmp;
tmp = uu->time_mid;
out[5] = (unsigned char) tmp;
tmp >>= 8;
out[4] = (unsigned char) tmp;
tmp = uu->time_hi_and_version;
out[7] = (unsigned char) tmp;
tmp >>= 8;
out[6] = (unsigned char) tmp;
tmp = uu->clock_seq;
out[9] = (unsigned char) tmp;
tmp >>= 8;
out[8] = (unsigned char) tmp;
memcpy(out+10, uu->node, 6);
}

View File

@@ -0,0 +1,52 @@
/*
* parse.c --- UUID parsing
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "uuidP.h"
int uuid_parse(char *in, uuid_t uu)
{
struct uuid uuid;
int i;
char *cp, buf[3];
if (strlen(in) != 36)
return -1;
for (i=0, cp = in; i <= 36; i++,cp++) {
if ((i == 8) || (i == 13) || (i == 18) ||
(i == 23))
if (*cp == '-')
continue;
if (i== 36)
if (*cp == 0)
continue;
if (!isxdigit((guchar) *cp))
return -1;
}
uuid.time_low = strtoul(in, NULL, 16);
uuid.time_mid = strtoul(in+9, NULL, 16);
uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
uuid.clock_seq = strtoul(in+19, NULL, 16);
cp = in+24;
buf[2] = 0;
for (i=0; i < 6; i++) {
buf[0] = *cp++;
buf[1] = *cp++;
uuid.node[i] = strtoul(buf, NULL, 16);
}
uuid_pack(&uuid, uu);
return 0;
}

View File

@@ -0,0 +1,119 @@
/*
* tst_uuid.c --- test program from the UUID library
*
* Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
#include <linux/ext2_fs.h>
#include "uuid.h"
int
main(int argc, char **argv)
{
uuid_t buf, tst;
char str[100];
struct timeval tv;
time_t time_reg;
unsigned char *cp;
int i;
int failed = 0;
int type, variant;
uuid_generate(buf);
uuid_unparse(buf, str);
printf("UUID generate = %s\n", str);
printf("UUID: ");
for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
printf("%02x", *cp++);
}
printf("\n");
type = uuid_type(buf); variant = uuid_variant(buf);
printf("UUID type = %d, UUID variant = %d\n", type, variant);
if (variant != UUID_VARIANT_DCE) {
printf("Incorrect UUID Variant; was expecting DCE!\n");
failed++;
}
printf("\n");
uuid_generate_random(buf);
uuid_unparse(buf, str);
printf("UUID random string = %s\n", str);
printf("UUID: ");
for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
printf("%02x", *cp++);
}
printf("\n");
type = uuid_type(buf); variant = uuid_variant(buf);
printf("UUID type = %d, UUID variant = %d\n", type, variant);
if (variant != UUID_VARIANT_DCE) {
printf("Incorrect UUID Variant; was expecting DCE!\n");
failed++;
}
if (type != 4) {
printf("Incorrect UUID type; was expecting "
"4 (random type)!\n");
failed++;
}
printf("\n");
uuid_generate_time(buf);
uuid_unparse(buf, str);
printf("UUID string = %s\n", str);
printf("UUID time: ");
for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
printf("%02x", *cp++);
}
printf("\n");
type = uuid_type(buf); variant = uuid_variant(buf);
printf("UUID type = %d, UUID variant = %d\n", type, variant);
if (variant != UUID_VARIANT_DCE) {
printf("Incorrect UUID Variant; was expecting DCE!\n");
failed++;
}
if (type != 1) {
printf("Incorrect UUID type; was expecting "
"1 (time-based type)!\\n");
failed++;
}
tv.tv_sec = 0;
tv.tv_usec = 0;
time_reg = uuid_time(buf, &tv);
printf("UUID time is: (%d, %d): %s\n", tv.tv_sec, tv.tv_usec,
ctime(&time_reg));
uuid_parse(str, tst);
if (!uuid_compare(buf, tst))
printf("UUID parse and compare succeeded.\n");
else {
printf("UUID parse and compare failed!\n");
failed++;
}
uuid_clear(tst);
if (uuid_is_null(tst))
printf("UUID clear and is null succeeded.\n");
else {
printf("UUID clear and is null failed!\n");
failed++;
}
uuid_copy(buf, tst);
if (!uuid_compare(buf, tst))
printf("UUID copy and compare succeeded.\n");
else {
printf("UUID copy and compare failed!\n");
failed++;
}
if (failed) {
printf("%d failures.\n", failed);
exit(1);
}
return 0;
}

View File

@@ -0,0 +1,40 @@
/*
* Internal routine for unpacking UUID
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <string.h>
#include "uuidP.h"
void uuid_unpack(uuid_t in, struct uuid *uu)
{
guint8 *ptr = in;
guint32 tmp;
tmp = *ptr++;
tmp = (tmp << 8) | *ptr++;
tmp = (tmp << 8) | *ptr++;
tmp = (tmp << 8) | *ptr++;
uu->time_low = tmp;
tmp = *ptr++;
tmp = (tmp << 8) | *ptr++;
uu->time_mid = tmp;
tmp = *ptr++;
tmp = (tmp << 8) | *ptr++;
uu->time_hi_and_version = tmp;
tmp = *ptr++;
tmp = (tmp << 8) | *ptr++;
uu->clock_seq = tmp;
memcpy(uu->node, ptr, 6);
}

View File

@@ -0,0 +1,28 @@
/*
* unparse.c -- convert a UUID to string
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
#include "uuidP.h"
void uuid_unparse(uuid_t uu, char *out)
{
struct uuid uuid;
uuid_unpack(uu, &uuid);
sprintf(out,
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
uuid.node[0], uuid.node[1], uuid.node[2],
uuid.node[3], uuid.node[4], uuid.node[5]);
}

View File

@@ -0,0 +1,50 @@
/*
* Public include file for the UUID library
*
* Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
typedef unsigned char uuid_t[16];
/* UUID Variant definitions */
#define UUID_VARIANT_NCS 0
#define UUID_VARIANT_DCE 1
#define UUID_VARIANT_MICROSOFT 2
#define UUID_VARIANT_OTHER 3
/* clear.c */
void uuid_clear(uuid_t uu);
/* compare.c */
int uuid_compare(uuid_t uu1, uuid_t uu2);
/* copy.c */
void uuid_copy(uuid_t uu1, uuid_t uu2);
/* gen_uuid.c */
void uuid_generate(uuid_t out);
void uuid_generate_random(uuid_t out);
void uuid_generate_time(uuid_t out);
/* isnull.c */
int uuid_is_null(uuid_t uu);
/* parse.c */
int uuid_parse(char *in, uuid_t uu);
/* unparse.c */
void uuid_unparse(uuid_t uu, char *out);
/* uuid_time.c */
time_t uuid_time(uuid_t uu, struct timeval *ret_tv);
int uuid_type(uuid_t uu);
int uuid_variant(uuid_t uu);

View File

@@ -0,0 +1,40 @@
/*
* uuid.h -- private header file for uuids
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <sys/types.h>
#include <glib.h>
#include "uuid.h"
/*
* Offset between 15-Oct-1582 and 1-Jan-70
*/
#define TIME_OFFSET_HIGH 0x01B21DD2
#define TIME_OFFSET_LOW 0x13814000
struct uuid {
guint32 time_low;
guint16 time_mid;
guint16 time_hi_and_version;
guint16 clock_seq;
guint8 node[6];
};
/*
* prototypes
*/
void uuid_pack(struct uuid *uu, uuid_t ptr);
void uuid_unpack(uuid_t in, struct uuid *uu);

View File

@@ -0,0 +1,138 @@
/*
* uuid_time.c --- Interpret the time field from a uuid. This program
* violates the UUID abstraction barrier by reaching into the guts
* of a UUID and interpreting it.
*
* Copyright (C) 1998, 1999 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include "uuidP.h"
time_t uuid_time(uuid_t uu, struct timeval *ret_tv)
{
struct uuid uuid;
guint32 high;
struct timeval tv;
unsigned long long clock_reg;
uuid_unpack(uu, &uuid);
high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16);
clock_reg = uuid.time_low | ((unsigned long long) high << 32);
clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
tv.tv_sec = clock_reg / 10000000;
tv.tv_usec = (clock_reg % 10000000) / 10;
if (ret_tv)
*ret_tv = tv;
return tv.tv_sec;
}
int uuid_type(uuid_t uu)
{
struct uuid uuid;
uuid_unpack(uu, &uuid);
return ((uuid.time_hi_and_version >> 12) & 0xF);
}
int uuid_variant(uuid_t uu)
{
struct uuid uuid;
int var;
uuid_unpack(uu, &uuid);
var = uuid.clock_seq;
if ((var & 0x8000) == 0)
return UUID_VARIANT_NCS;
if ((var & 0x4000) == 0)
return UUID_VARIANT_DCE;
if ((var & 0x2000) == 0)
return UUID_VARIANT_MICROSOFT;
return UUID_VARIANT_OTHER;
}
#ifdef DEBUG
static const char *variant_string(int variant)
{
switch (variant) {
case UUID_VARIANT_NCS:
return "NCS";
case UUID_VARIANT_DCE:
return "DCE";
case UUID_VARIANT_MICROSOFT:
return "Microsoft";
default:
return "Other";
}
}
int
main(int argc, char **argv)
{
uuid_t buf;
time_t time_reg;
struct timeval tv;
int type, variant;
if (argc != 2) {
fprintf(stderr, "Usage: %s uuid\n", argv[0]);
exit(1);
}
if (uuid_parse(argv[1], buf)) {
fprintf(stderr, "Invalid UUID: %s\n", argv[1]);
exit(1);
}
variant = uuid_variant(buf);
type = uuid_type(buf);
time_reg = uuid_time(buf, &tv);
printf("UUID variant is %d (%s)\n", variant, variant_string(variant));
if (variant != UUID_VARIANT_DCE) {
printf("Warning: This program only knows how to interpret "
"DCE UUIDs.\n\tThe rest of the output is likely "
"to be incorrect!!\n");
}
printf("UUID type is %d", type);
switch (type) {
case 1:
printf(" (time based)\n");
break;
case 2:
printf(" (DCE)\n");
break;
case 3:
printf(" (name-based)\n");
break;
case 4:
printf(" (random)\n");
break;
default:
printf("\n");
}
if (type != 1) {
printf("Warning: not a time-based UUID, so UUID time "
"decoding will likely not work!\n");
}
printf("UUID time is: (%u, %u): %s\n", (unsigned)tv.tv_sec, (unsigned)tv.tv_usec,
ctime(&time_reg));
return 0;
}
#endif

View File

@@ -1,20 +0,0 @@
[Desktop Entry]
Name=File Types and Programs
Name[pt_BR]=Tipos de Arquivos e Programas
Name[da]=Filtyper og programmer
Name[fi]=Tiedostotyypit ja ohjelmat
Name[fr]=Type de fichiers et programmes
Name[no]=Filtyper og programmer
Name[sk]=Typy súborov a programy
Name[tr]=Dosya türleri ve uygulamarý
Comment=We need a good explanation here.
Comment[pt_BR]=Precisamos de uma boa explicação aqui.
Comment[da]=Vi har brug for en god forklaring her.
Comment[fr]=Éditeur d'association de type de fichiers et d'applications
Comment[no]=Koblinger mellom filtyper og programmer
Comment[sk]=Sem by to chcelo nejaké rozumné vysvetlenie...
Comment[tr]=Eh, buraya da iyi bir anlatým gerek ...
Icon=gnome-ccmime.png
Exec=nautilus-mime-type-capplet
Terminal=0
Type=Application

View File

@@ -1,9 +0,0 @@
Makefile
Makefile.in
.deps
.libs
*.lo
*.la
*.o
keyboard-properties
keyboard-properties-capplet

View File

@@ -1,13 +0,0 @@
2000-12-26 Jacob "Ulysses" Berkman <jacob@helixcode.com>
* keyboard-properties.glade: re-did the UI a bit
2000-10-08 Bradford Hovinen <hovinen@helixcode.com>
* Makefile.am (EXTRA_DIST): Add translation file
2000-09-12 Bradford Hovinen <hovinen@helixcode.com>
* preferences.c (preferences_clone): Added in missing code to copy
preferences over

View File

@@ -1,34 +0,0 @@
Applicationsdir = $(datadir)/control-center/Desktop
Applications_DATA = \
keyboard-properties.desktop
pApplicationsdir = $(datadir)/gnome/apps/Settings/Desktop
pApplications_DATA = \
keyboard-properties.desktop
Gladedir = $(datadir)/control-center-data
Glade_DATA = \
keyboard-properties.glade
glade_msgs = \
keyboard-properties.glade.h
EXTRA_DIST = ChangeLog $(Applications_DATA) $(Glade_DATA) $(glade_msgs)
INCLUDES = \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-DGNOME_ICONDIR=\""${prefix}/share/pixmaps"\" \
-DG_LOG_DOMAIN=\"keyboard-properties\" \
-DGLADE_DATADIR=\""$(Gladedir)"\" \
$(CAPPLET_CFLAGS) \
-I$(top_srcdir)/ \
-I$(top_srcdir)/intl
bin_PROGRAMS = keyboard-properties
keyboard_properties_SOURCES = \
prefs-widget.c prefs-widget.h \
preferences.c preferences.h \
main.c
keyboard_properties_LDADD = $(CAPPLET_LIBS) $(XF86MISC_LIBS)

View File

@@ -1,61 +0,0 @@
[Desktop Entry]
Name=Keyboard
Name[ca]=Propietats del teclat
Name[cs]=Klávesnice
Name[da]=Tastatur
Name[de]=Tastatur
Name[el]=Ñõèìßóåéò ðëçêôñïëïãßïõ
Name[es]=Propiedades del Teclado
Name[et]=Klaviatuur
Name[fi]=Näppäimistö
Name[fr]=Clavier
Name[gl]=Teclado
Name[hu]=Billentyûzet
Name[it]=Tastiera
Name[ja]=¥­¡¼¥Ü¡¼¥É
Name[ko]=ÀÚÆÇ
Name[lt]=Klaviatûra
Name[no]=Tastatur
Name[pl]=Klawiatura
Name[pt]=Propriedades do Teclado
Name[pt_BR]=Propriedades do Teclado
Name[ro]=Tastaturã
Name[ru]=ëÌÁ×ÉÁÔÕÒÁ
Name[sl]=Tipkovnica
Name[sv]=Tangentbord
Name[uk]=ëÌÁצÁÔÕÒÁ
Name[wa]=Prôpietés del taprece
Name[zh_TW.Big5]=Áä½L
Name[zh_CN.GB2312]=¼üÅÌ
Comment=Keyboard Properties
Comment[ca]=Configurar el teclat
Comment[cs]=Vlastnosti klávesnice
Comment[da]=Tastaturegenskaber
Comment[de]=Tastatureinstellungen
Comment[el]=Ôñïðïðïßçóç ôùí ñõèìßóåùí ôïõ ðëçêôñïëïãßïõ
Comment[es]=Modifica las propiedades del teclado
Comment[et]=Klaviatuuri häälestus
Comment[fi]=Näppäimistön asetukset
Comment[fr]=Configuration des propriétés du clavier
Comment[gl]=Propiedades do teclado
Comment[hu]=Billentyûzet beállításai
Comment[it]=Impostazioni della tastiera
Comment[ja]=¥­¡¼¥Ü¡¼¥É¤ÎÀßÄê
Comment[ko]=ÀÚÆÇ ¼Ó¼º
Comment[lt]=Klaviatûros savybës
Comment[no]=Egenskaper for tastatur
Comment[pl]=Ustawienia klawiatury
Comment[pt]=Propriedades do Teclado
Comment[pt_BR]=Propriedades do Teclado
Comment[ro]=Proprietãþi tastaturã
Comment[ru]=ó×ÏÊÓÔ×Á ËÌÁ×ÉÁÔÕÒÙ
Comment[sl]=Lastnosti Tipkovnice
Comment[sv]=Tangentbordsinställningar
Comment[uk]=÷ÌÁÓÔÉ×ÏÓÔ¦ ËÌÁצÁÔÕÒÉ
Comment[wa]=Candjî les prôpietés del taprece
Comment[zh_TW.Big5]=Áä½L³]©w
Comment[zh_CN.GB2312]=¼üÅÌÉ趨
Exec=keyboard-properties-capplet
Icon=gnome-cckeyboard.png
Terminal=0
Type=Application

View File

@@ -1,370 +0,0 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>New-keyboard-properties</name>
<program_name>new-keyboard-properties</program_name>
<directory></directory>
<source_directory>src</source_directory>
<pixmaps_directory>pixmaps</pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
<output_translatable_strings>True</output_translatable_strings>
<translatable_strings_file>keyboard-properties.glade.h</translatable_strings_file>
</project>
<widget>
<class>GtkWindow</class>
<name>window1</name>
<title>window1</title>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<widget>
<class>GtkVBox</class>
<name>prefs_widget</name>
<homogeneous>False</homogeneous>
<spacing>4</spacing>
<widget>
<class>GtkCheckButton</class>
<name>repeat_toggle</name>
<can_focus>True</can_focus>
<signal>
<name>toggled</name>
<handler>repeat_toggled_cb</handler>
<last_modification_time>Thu, 30 Nov 2000 23:56:30 GMT</last_modification_time>
</signal>
<label>Enable Keyboard Repeat</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkFrame</class>
<name>delay_frame</name>
<label>Delay Until Repeat</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkHBox</class>
<name>hbox2</name>
<border_width>4</border_width>
<homogeneous>True</homogeneous>
<spacing>4</spacing>
<widget>
<class>GtkLabel</class>
<name>label5</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkToggleButton</class>
<name>delay0</name>
<can_focus>True</can_focus>
<label>....a</label>
<relief>GTK_RELIEF_NORMAL</relief>
<active>False</active>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkToggleButton</class>
<name>delay1</name>
<can_focus>True</can_focus>
<label>...a</label>
<relief>GTK_RELIEF_NORMAL</relief>
<active>False</active>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkToggleButton</class>
<name>delay2</name>
<can_focus>True</can_focus>
<label>..a</label>
<relief>GTK_RELIEF_NORMAL</relief>
<active>False</active>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkToggleButton</class>
<name>delay3</name>
<can_focus>True</can_focus>
<label>.a</label>
<relief>GTK_RELIEF_NORMAL</relief>
<active>False</active>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label6</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
</widget>
<widget>
<class>GtkFrame</class>
<name>repeat_frame</name>
<label>Key Repeat Rate</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkHBox</class>
<name>hbox3</name>
<border_width>4</border_width>
<homogeneous>True</homogeneous>
<spacing>4</spacing>
<widget>
<class>GtkLabel</class>
<name>label7</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkToggleButton</class>
<name>repeat0</name>
<can_focus>True</can_focus>
<label>a....a</label>
<relief>GTK_RELIEF_NORMAL</relief>
<active>False</active>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkToggleButton</class>
<name>repeat1</name>
<can_focus>True</can_focus>
<label>a...a</label>
<relief>GTK_RELIEF_NORMAL</relief>
<active>False</active>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkToggleButton</class>
<name>repeat2</name>
<can_focus>True</can_focus>
<label>a..a</label>
<relief>GTK_RELIEF_NORMAL</relief>
<active>False</active>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkToggleButton</class>
<name>repeat3</name>
<can_focus>True</can_focus>
<label>a.a</label>
<relief>GTK_RELIEF_NORMAL</relief>
<active>False</active>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label8</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
</widget>
<widget>
<class>GtkCheckButton</class>
<name>click_toggle</name>
<can_focus>True</can_focus>
<signal>
<name>toggled</name>
<handler>click_toggled_cb</handler>
<last_modification_time>Mon, 11 Sep 2000 02:02:18 GMT</last_modification_time>
</signal>
<label>Enable Keyboard Click</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkFrame</class>
<name>click_frame</name>
<label>Keyboard click</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkHBox</class>
<name>hbox4</name>
<border_width>4</border_width>
<homogeneous>False</homogeneous>
<spacing>4</spacing>
<widget>
<class>GtkLabel</class>
<name>label3</name>
<label>Click volume</label>
<justify>GTK_JUSTIFY_RIGHT</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHScale</class>
<name>click_volume_entry</name>
<can_focus>True</can_focus>
<draw_value>False</draw_value>
<value_pos>GTK_POS_TOP</value_pos>
<digits>0</digits>
<policy>GTK_UPDATE_CONTINUOUS</policy>
<value>0</value>
<lower>0</lower>
<upper>100</upper>
<step>0</step>
<page>0</page>
<page_size>0</page_size>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
</widget>
<widget>
<class>GtkEntry</class>
<name>test_entry</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text>Type here to test setting</text>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
</widget>
</GTK-Interface>

View File

@@ -1,22 +0,0 @@
/*
* Translatable strings file generated by Glade.
* Add this file to your project's POTFILES.in.
* DO NOT compile it as part of your application.
*/
gchar *s = N_("window1");
gchar *s = N_("Enable Keyboard Repeat");
gchar *s = N_("Delay Until Repeat");
gchar *s = N_("....a");
gchar *s = N_("...a");
gchar *s = N_("..a");
gchar *s = N_(".a");
gchar *s = N_("Key Repeat Rate");
gchar *s = N_("a....a");
gchar *s = N_("a...a");
gchar *s = N_("a..a");
gchar *s = N_("a.a");
gchar *s = N_("Enable Keyboard Click");
gchar *s = N_("Keyboard click");
gchar *s = N_("Click volume");
gchar *s = N_("Type here to test setting");

View File

@@ -1,185 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* main.c
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen (hovinen@helixcode.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gtk/gtk.h>
#include <gnome.h>
#include <libgnomeui/gnome-window-icon.h>
#include <tree.h>
#include <parser.h>
#include <glade/glade.h>
#include <capplet-widget.h>
#include "preferences.h"
#include "prefs-widget.h"
static Preferences *prefs;
static Preferences *old_prefs;
static PrefsWidget *prefs_widget;
static void
ok_cb (GtkWidget *widget)
{
preferences_save (prefs);
preferences_apply_now (prefs);
}
static void
cancel_cb (GtkWidget *widget)
{
preferences_save (old_prefs);
preferences_apply_now (old_prefs);
}
static void
setup_capplet_widget (void)
{
preferences_freeze (prefs);
prefs_widget = PREFS_WIDGET (prefs_widget_new (prefs));
gtk_signal_connect (GTK_OBJECT (prefs_widget), "ok",
GTK_SIGNAL_FUNC (ok_cb), NULL);
gtk_signal_connect (GTK_OBJECT (prefs_widget), "cancel",
GTK_SIGNAL_FUNC (cancel_cb), NULL);
gtk_widget_show_all (GTK_WIDGET (prefs_widget));
preferences_thaw (prefs);
}
static void
do_get_xml (void)
{
Preferences *prefs;
xmlDocPtr doc;
prefs = PREFERENCES (preferences_new ());
preferences_load (prefs);
doc = preferences_write_xml (prefs);
xmlDocDump (stdout, doc);
gtk_object_destroy (GTK_OBJECT (prefs));
}
static void
do_set_xml (void)
{
Preferences *prefs;
xmlDocPtr doc;
char *buffer;
int len = 0;
while (!feof (stdin)) {
if (!len) buffer = g_new (char, 16384);
else buffer = g_renew (char, buffer, len + 16384);
fread (buffer + len, 1, 16384, stdin);
len += 16384;
}
doc = xmlParseMemory (buffer, strlen (buffer));
prefs = preferences_read_xml (doc);
if (prefs)
preferences_save (prefs);
else
g_warning ("Error while reading the screensaver config file");
}
int
main (int argc, char **argv)
{
GnomeClient *client;
GnomeClientFlags flags;
gint token, res;
gchar *restart_args[3];
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
textdomain (PACKAGE);
glade_gnome_init ();
res = gnome_capplet_init ("keyboard-properties-capplet",
VERSION, argc, argv, NULL,
0, NULL);
if (res < 0) {
g_error ("Could not initialize the capplet.");
}
else if (res == 3) {
do_get_xml ();
return 0;
}
else if (res == 4) {
do_set_xml ();
return 0;
}
client = gnome_master_client ();
flags = gnome_client_get_flags (client);
if (flags & GNOME_CLIENT_IS_CONNECTED) {
token = gnome_startup_acquire_token
("GNOME_KEYBOARD_PROPERTIES",
gnome_client_get_id (client));
if (token) {
gnome_client_set_priority (client, 20);
gnome_client_set_restart_style (client,
GNOME_RESTART_ANYWAY);
restart_args[0] = argv[0];
restart_args[1] = "--init-session-settings";
restart_args[2] = NULL;
gnome_client_set_restart_command (client, 2,
restart_args);
} else {
gnome_client_set_restart_style (client,
GNOME_RESTART_NEVER);
}
} else {
token = 1;
}
gnome_window_icon_set_default_from_file
(GNOME_ICONDIR"/gnome-cckeyboard.png");
prefs = PREFERENCES (preferences_new ());
preferences_load (prefs);
if (token) {
preferences_apply_now (prefs);
}
if (!res) {
old_prefs = PREFERENCES (preferences_clone (prefs));
setup_capplet_widget ();
capplet_gtk_main ();
}
return 0;
}

View File

@@ -1,378 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* preferences.c
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen <hovinen@helixcode.com>,
* Jaka Mocnik <jaka.mocnik@kiss.uni-lj.si>
*
* Based on gnome-core/desktop-properties/property-keyboard.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <gnome.h>
#include <gdk/gdkx.h>
#include <X11/X.h>
#ifdef HAVE_X11_EXTENSIONS_XF86MISC_H
#include <X11/extensions/xf86misc.h>
#endif
#include "preferences.h"
static GtkObjectClass *parent_class;
#ifdef HAVE_X11_EXTENSIONS_XF86MISC_H
static XF86MiscKbdSettings kbdsettings;
#endif
static void preferences_init (Preferences *prefs);
static void preferences_class_init (PreferencesClass *class);
static gint xml_read_int (xmlNodePtr node,
gchar *propname);
static xmlNodePtr xml_write_int (gchar *name,
gchar *propname,
gint number);
static gint apply_timeout_cb (Preferences *prefs);
guint
preferences_get_type (void)
{
static guint preferences_type = 0;
if (!preferences_type) {
GtkTypeInfo preferences_info = {
"Preferences",
sizeof (Preferences),
sizeof (PreferencesClass),
(GtkClassInitFunc) preferences_class_init,
(GtkObjectInitFunc) preferences_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
preferences_type =
gtk_type_unique (gtk_object_get_type (),
&preferences_info);
}
return preferences_type;
}
static void
preferences_init (Preferences *prefs)
{
prefs->frozen = FALSE;
/* Code to initialize preferences object to defaults */
}
static void
preferences_class_init (PreferencesClass *class)
{
GtkObjectClass *object_class;
object_class = (GtkObjectClass *) class;
object_class->destroy = preferences_destroy;
parent_class =
GTK_OBJECT_CLASS (gtk_type_class (gtk_object_get_type ()));
}
GtkObject *
preferences_new (void)
{
GtkObject *object;
object = gtk_type_new (preferences_get_type ());
return object;
}
GtkObject *
preferences_clone (Preferences *prefs)
{
GtkObject *object;
Preferences *new_prefs;
g_return_val_if_fail (prefs != NULL, NULL);
g_return_val_if_fail (IS_PREFERENCES (prefs), NULL);
object = preferences_new ();
new_prefs = PREFERENCES (object);
new_prefs->rate = prefs->rate;
new_prefs->delay = prefs->delay;
new_prefs->repeat = prefs->repeat;
new_prefs->volume = prefs->volume;
new_prefs->click = prefs->click;
return object;
}
void
preferences_destroy (GtkObject *object)
{
Preferences *prefs;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_PREFERENCES (object));
prefs = PREFERENCES (object);
parent_class->destroy (object);
}
void
preferences_load (Preferences *prefs)
{
XKeyboardState kbdstate;
gboolean repeat_default, click_default;
gint event_base_return, error_base_return;
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
prefs->rate = gnome_config_get_int ("/Desktop/Keyboard/rate=-");
prefs->delay = gnome_config_get_int ("/Desktop/Keyboard/delay=-1");
prefs->repeat = gnome_config_get_bool_with_default
("/Desktop/Keyboard/repeat=true", &repeat_default);
prefs->volume = gnome_config_get_int
("/Desktop/Keyboard/clickvolume=-1");
prefs->click = gnome_config_get_bool_with_default
("/Desktop/Keyboard/click=false", &click_default);
XGetKeyboardControl (GDK_DISPLAY (), &kbdstate);
if (repeat_default)
prefs->repeat = kbdstate.global_auto_repeat;
if (prefs->rate == -1 || prefs->delay == -1) {
#ifdef HAVE_X11_EXTENSIONS_XF86MISC_H
if (XF86MiscQueryExtension (GDK_DISPLAY (),
&event_base_return,
&error_base_return) == True)
{
XF86MiscGetKbdSettings (GDK_DISPLAY (), &kbdsettings);
prefs->rate = kbdsettings.rate;
prefs->delay = kbdsettings.delay;
} else {
prefs->rate = 5;
prefs->delay = 500;
}
#else
/* FIXME: how to get the keyboard speed on non-xf86? */
prefs->rate = 5;
prefs->delay = 500;
#endif
}
if (click_default)
prefs->click = (kbdstate.key_click_percent == 0);
if (prefs->volume == -1)
prefs->volume = kbdstate.key_click_percent;
}
void
preferences_save (Preferences *prefs)
{
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
gnome_config_set_bool ("/Desktop/Keyboard/repeat", prefs->repeat);
gnome_config_set_int ("/Desktop/Keyboard/delay", prefs->delay);
gnome_config_set_int ("/Desktop/Keyboard/rate", prefs->rate);
gnome_config_set_bool ("/Desktop/Keyboard/click", prefs->click);
gnome_config_set_int ("/Desktop/Keyboard/clickvolume", prefs->volume);
gnome_config_sync ();
}
void
preferences_changed (Preferences *prefs)
{
if (prefs->frozen) return;
if (prefs->timeout_id)
gtk_timeout_remove (prefs->timeout_id);
preferences_apply_now (prefs);
}
void
preferences_apply_now (Preferences *prefs)
{
XKeyboardControl kbdcontrol;
int event_base_return, error_base_return;
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
if (prefs->timeout_id)
gtk_timeout_remove (prefs->timeout_id);
prefs->timeout_id = 0;
if (prefs->repeat) {
XAutoRepeatOn (GDK_DISPLAY ());
#ifdef HAVE_X11_EXTENSIONS_XF86MISC_H
if (XF86MiscQueryExtension (GDK_DISPLAY (),
&event_base_return,
&error_base_return) == True)
{
kbdsettings.rate = prefs->rate;
kbdsettings.delay = prefs->delay;
XF86MiscSetKbdSettings (GDK_DISPLAY (), &kbdsettings);
} else {
XAutoRepeatOff (GDK_DISPLAY ());
}
#endif
} else {
XAutoRepeatOff (GDK_DISPLAY ());
}
kbdcontrol.key_click_percent =
prefs->click ? prefs->volume : 0;
XChangeKeyboardControl (GDK_DISPLAY (), KBKeyClickPercent,
&kbdcontrol);
}
void preferences_freeze (Preferences *prefs)
{
prefs->frozen = TRUE;
}
void preferences_thaw (Preferences *prefs)
{
prefs->frozen = FALSE;
}
Preferences *
preferences_read_xml (xmlDocPtr xml_doc)
{
Preferences *prefs;
xmlNodePtr root_node, node;
prefs = PREFERENCES (preferences_new ());
root_node = xmlDocGetRootElement (xml_doc);
if (strcmp (root_node->name, "keyboard-properties"))
return NULL;
for (node = root_node->childs; node; node = node->next) {
if (!strcmp (node->name, "rate"))
prefs->rate = xml_read_int (node, NULL);
else if (!strcmp (node->name, "delay"))
prefs->delay = xml_read_int (node, NULL);
else if (!strcmp (node->name, "repeat"))
prefs->repeat = TRUE;
else if (!strcmp (node->name, "volume"))
prefs->volume = xml_read_int (node, NULL);
else if (!strcmp (node->name, "click"))
prefs->click = TRUE;
}
return prefs;
}
xmlDocPtr
preferences_write_xml (Preferences *prefs)
{
xmlDocPtr doc;
xmlNodePtr node;
char *tmp;
doc = xmlNewDoc ("1.0");
node = xmlNewDocNode (doc, NULL, "keyboard-properties", NULL);
xmlAddChild (node, xml_write_int ("rate", NULL, prefs->rate));
xmlAddChild (node, xml_write_int ("delay", NULL, prefs->delay));
if (prefs->repeat)
xmlNewChild (node, NULL, "repeat", NULL);
xmlAddChild (node, xml_write_int ("volume", NULL,
prefs->volume));
if (prefs->click)
xmlNewChild (node, NULL, "click", NULL);
xmlDocSetRootElement (doc, node);
return doc;
}
/* Read a numeric value from a node */
static gint
xml_read_int (xmlNodePtr node, char *propname)
{
char *text;
if (propname == NULL)
text = xmlNodeGetContent (node);
else
text = xmlGetProp (node, propname);
if (text == NULL)
return 0;
else
return atoi (text);
}
/* Write out a numeric value in a node */
static xmlNodePtr
xml_write_int (gchar *name, gchar *propname, gint number)
{
xmlNodePtr node;
gchar *str;
g_return_val_if_fail (name != NULL, NULL);
str = g_strdup_printf ("%d", number);
node = xmlNewNode (NULL, name);
if (propname == NULL)
xmlNodeSetContent (node, str);
else
xmlSetProp (node, propname, str);
g_free (str);
return node;
}
static gint
apply_timeout_cb (Preferences *prefs)
{
preferences_apply_now (prefs);
return TRUE;
}

View File

@@ -1,75 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* preferences.h
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen <hovinen@helixcode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __PREFERENCES_H
#define __PREFERENCES_H
#include <gtk/gtk.h>
#include <tree.h>
#define PREFERENCES(obj) GTK_CHECK_CAST (obj, preferences_get_type (), Preferences)
#define PREFERENCES_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, preferences_get_type (), PreferencesClass)
#define IS_PREFERENCES(obj) GTK_CHECK_TYPE (obj, preferences_get_type ())
typedef struct _Preferences Preferences;
typedef struct _PreferencesClass PreferencesClass;
struct _Preferences
{
GtkObject object;
gboolean frozen;
guint timeout_id;
gint rate;
gint delay;
gint volume;
gboolean repeat;
gboolean click;
};
struct _PreferencesClass
{
GtkObjectClass klass;
};
guint preferences_get_type (void);
GtkObject *preferences_new (void);
GtkObject *preferences_clone (Preferences *prefs);
void preferences_destroy (GtkObject *object);
void preferences_load (Preferences *prefs);
void preferences_save (Preferences *prefs);
void preferences_changed (Preferences *prefs);
void preferences_apply_now (Preferences *prefs);
void preferences_freeze (Preferences *prefs);
void preferences_thaw (Preferences *prefs);
Preferences *preferences_read_xml (xmlDocPtr xml_doc);
xmlDocPtr preferences_write_xml (Preferences *prefs);
#endif /* __PREFERENCES_H */

View File

@@ -1,366 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* prefs-widget.c
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen <hovinen@helixcode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "prefs-widget.h"
#define WID(str) (glade_xml_get_widget (prefs_widget->dialog_data, str))
enum {
ARG_0,
ARG_PREFERENCES
};
static CappletWidgetClass *parent_class;
static void prefs_widget_init (PrefsWidget *prefs_widget);
static void prefs_widget_class_init (PrefsWidgetClass *class);
static void prefs_widget_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void prefs_widget_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void read_preferences (PrefsWidget *prefs_widget,
Preferences *prefs);
static void repeat_toggled_cb (GtkToggleButton *button,
PrefsWidget *prefs_widget);
static void rate_changed_cb (GtkToggleButton *toggle,
PrefsWidget *prefs_widget);
static void delay_changed_cb (GtkToggleButton *toggle,
PrefsWidget *prefs_widget);
static void click_toggled_cb (GtkToggleButton *button,
PrefsWidget *prefs_widget);
static void click_volume_changed_cb (GtkAdjustment *adjustment,
PrefsWidget *prefs_widget);
guint
prefs_widget_get_type (void)
{
static guint prefs_widget_type = 0;
if (!prefs_widget_type) {
GtkTypeInfo prefs_widget_info = {
"PrefsWidget",
sizeof (PrefsWidget),
sizeof (PrefsWidgetClass),
(GtkClassInitFunc) prefs_widget_class_init,
(GtkObjectInitFunc) prefs_widget_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
prefs_widget_type =
gtk_type_unique (capplet_widget_get_type (),
&prefs_widget_info);
}
return prefs_widget_type;
}
static void
prefs_widget_init (PrefsWidget *prefs_widget)
{
char delays[] = "delay0";
char rates[] = "repeat0";
int i;
GtkWidget *widget;
GtkAdjustment *adjustment;
prefs_widget->dialog_data =
glade_xml_new (GLADE_DATADIR "/keyboard-properties.glade",
"prefs_widget");
glade_xml_signal_connect_data
(prefs_widget->dialog_data, "repeat_toggled_cb",
repeat_toggled_cb, prefs_widget);
widget = glade_xml_get_widget (prefs_widget->dialog_data,
"prefs_widget");
gtk_container_add (GTK_CONTAINER (prefs_widget), widget);
glade_xml_signal_connect_data
(prefs_widget->dialog_data, "click_toggled_cb",
click_toggled_cb, prefs_widget);
adjustment = gtk_range_get_adjustment
(GTK_RANGE (WID ("click_volume_entry")));
gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
click_volume_changed_cb, prefs_widget);
for (i = 0; i < 4; i++) {
rates[6] = delays[5] = '0' + i;
prefs_widget->delay[i] = WID (delays);
prefs_widget->rate[i] = WID (rates);
gtk_signal_connect (GTK_OBJECT (prefs_widget->delay[i]), "toggled",
GTK_SIGNAL_FUNC (delay_changed_cb), prefs_widget);
gtk_signal_connect (GTK_OBJECT (prefs_widget->rate[i]), "toggled",
GTK_SIGNAL_FUNC (rate_changed_cb), prefs_widget);
}
}
static void
prefs_widget_class_init (PrefsWidgetClass *class)
{
GtkObjectClass *object_class;
gtk_object_add_arg_type ("PrefsWidget::preferences",
GTK_TYPE_POINTER,
GTK_ARG_READWRITE,
ARG_PREFERENCES);
object_class = GTK_OBJECT_CLASS (class);
object_class->set_arg = prefs_widget_set_arg;
object_class->get_arg = prefs_widget_get_arg;
parent_class = CAPPLET_WIDGET_CLASS
(gtk_type_class (capplet_widget_get_type ()));
}
static void
prefs_widget_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
PrefsWidget *prefs_widget;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_PREFS_WIDGET (object));
prefs_widget = PREFS_WIDGET (object);
switch (arg_id) {
case ARG_PREFERENCES:
if (prefs_widget->prefs)
gtk_object_unref (GTK_OBJECT (prefs_widget->prefs));
prefs_widget->prefs = GTK_VALUE_POINTER (*arg);
if (prefs_widget->prefs) {
gtk_object_ref (GTK_OBJECT (prefs_widget->prefs));
read_preferences (prefs_widget, prefs_widget->prefs);
}
break;
default:
g_warning ("Bad argument set");
break;
}
}
static void
prefs_widget_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
PrefsWidget *prefs_widget;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_PREFS_WIDGET (object));
prefs_widget = PREFS_WIDGET (object);
switch (arg_id) {
case ARG_PREFERENCES:
GTK_VALUE_POINTER (*arg) = prefs_widget->prefs;
break;
default:
g_warning ("Bad argument get");
break;
}
}
GtkWidget *
prefs_widget_new (Preferences *prefs)
{
g_return_val_if_fail (prefs == NULL || IS_PREFERENCES (prefs), NULL);
return gtk_widget_new (prefs_widget_get_type (),
"preferences", prefs,
NULL);
}
void
prefs_widget_set_preferences (PrefsWidget *prefs_widget, Preferences *prefs)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
gtk_object_set (GTK_OBJECT (prefs_widget), "preferences", prefs, NULL);
}
static void
read_preferences (PrefsWidget *prefs_widget, Preferences *prefs)
{
GtkAdjustment *adjustment;
int i;
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs));
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (WID ("repeat_toggle")), prefs->repeat);
i = CLAMP (prefs->rate * 3 / 255, 0, 3);
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (prefs_widget->rate[i]), TRUE);
i = CLAMP ((10000 - prefs->delay) * 3 / 10000, 0, 3);
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (prefs_widget->delay[i]), TRUE);
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (WID ("click_toggle")), prefs->click);
adjustment = gtk_range_get_adjustment
(GTK_RANGE (WID ("click_volume_entry")));
gtk_adjustment_set_value (adjustment, prefs->volume);
gtk_widget_set_sensitive (WID ("click_frame"), prefs_widget->prefs->click);
gtk_widget_set_sensitive (WID ("delay_frame"), prefs_widget->prefs->repeat);
gtk_widget_set_sensitive (WID ("repeat_frame"), prefs_widget->prefs->repeat);
}
static void
repeat_toggled_cb (GtkToggleButton *button, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
g_return_if_fail (button != NULL);
g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
prefs_widget->prefs->repeat =
gtk_toggle_button_get_active (button);
gtk_widget_set_sensitive (WID ("delay_frame"), prefs_widget->prefs->repeat);
gtk_widget_set_sensitive (WID ("repeat_frame"), prefs_widget->prefs->repeat);
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static int
set_scale (GtkToggleButton *toggle, GtkWidget **arr)
{
int i, retval = 0;
for (i = 0; i < 4; i++) {
if (arr[i] == toggle) retval = i;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (arr[i]), arr[i] == toggle);
}
return retval;
}
static void
rate_changed_cb (GtkToggleButton *toggle, PrefsWidget *prefs_widget)
{
int i;
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
g_return_if_fail (toggle != NULL);
g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle));
if (!toggle->active)
return;
i = set_scale (toggle, prefs_widget->rate);
prefs_widget->prefs->rate = i * 255 / 3;
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
delay_changed_cb (GtkToggleButton *toggle, PrefsWidget *prefs_widget)
{
int i;
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
g_return_if_fail (toggle != NULL);
g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle));
if (!toggle->active)
return;
i = set_scale (toggle, prefs_widget->delay);
prefs_widget->prefs->delay = (3 - i) * 10000 / 3;
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
click_toggled_cb (GtkToggleButton *button, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
g_return_if_fail (button != NULL);
g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
prefs_widget->prefs->click =
gtk_toggle_button_get_active (button);
gtk_widget_set_sensitive (WID ("click_frame"), prefs_widget->prefs->click);
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}
static void
click_volume_changed_cb (GtkAdjustment *adjustment, PrefsWidget *prefs_widget)
{
g_return_if_fail (prefs_widget != NULL);
g_return_if_fail (IS_PREFS_WIDGET (prefs_widget));
g_return_if_fail (prefs_widget->prefs != NULL);
g_return_if_fail (IS_PREFERENCES (prefs_widget->prefs));
g_return_if_fail (adjustment != NULL);
g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
prefs_widget->prefs->volume = adjustment->value;
preferences_changed (prefs_widget->prefs);
capplet_widget_state_changed (CAPPLET_WIDGET (prefs_widget), TRUE);
}

View File

@@ -1,63 +0,0 @@
/* -*- mode: c; style: linux -*- */
/* prefs-widget.h
* Copyright (C) 2000 Helix Code, Inc.
*
* Written by Bradford Hovinen <hovinen@helixcode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __PREFS_WIDGET_H
#define __PREFS_WIDGET_H
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <capplet-widget.h>
#include "preferences.h"
#define PREFS_WIDGET(obj) GTK_CHECK_CAST (obj, prefs_widget_get_type (), PrefsWidget)
#define PREFS_WIDGET_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, prefs_widget_get_type (), PrefsWidgetClass)
#define IS_PREFS_WIDGET(obj) GTK_CHECK_TYPE (obj, prefs_widget_get_type ())
typedef struct _PrefsWidget PrefsWidget;
typedef struct _PrefsWidgetClass PrefsWidgetClass;
struct _PrefsWidget
{
CappletWidget capplet_widget;
Preferences *prefs;
GladeXML *dialog_data;
GtkWidget *delay[4];
GtkWidget *rate[4];
};
struct _PrefsWidgetClass
{
CappletWidgetClass parent_class;
};
guint prefs_widget_get_type (void);
GtkWidget *prefs_widget_new (Preferences *prefs);
void prefs_widget_set_preferences (PrefsWidget *prefs_widget,
Preferences *prefs);
#endif /* __PREFS_WIDGET_H */

View File

@@ -1,23 +0,0 @@
INCLUDES = -I. -I$(srcdir) \
-I$(top_srcdir)/intl -I$(top_builddir)/intl \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
$(CAPPLET_CFLAGS)
bin_PROGRAMS = mime-type-capplet
mime_type_capplet_SOURCES = mime-type-capplet.c\
mime-data.h mime-data.c edit-window.c\
edit-window.h mime-info.c mime-info.h \
new-mime-window.h new-mime-window.c
mime_type_capplet_LDADD = $(CAPPLET_LIBS)
EXTRA_DIST = \
mime-type.desktop
sysdir = $(datadir)/control-center
sys_DATA = mime-type.desktop
install-data-local:
$(INSTALL_DATA) $(srcdir)/mime-type.desktop $(DESTDIR)$(datadir)/gnome/apps/Settings/mime-type.desktop

View File

@@ -1,578 +0,0 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "edit-window.h"
#include "mime-data.h"
#include "mime-info.h"
#include "capplet-widget.h"
extern GtkWidget *capplet;
extern GHashTable *user_mime_types;
typedef struct {
GtkWidget *window;
GtkWidget *icon_entry;
GtkWidget *mime_type;
/* GtkWidget *ext_tag_label; */
GtkWidget *regexp1_tag_label;
GtkWidget *regexp2_tag_label;
/* GtkWidget *ext_label; */
GtkWidget *regexp1_label;
GtkWidget *regexp2_label;
GtkWidget *open_entry;
GtkWidget *edit_entry;
GtkWidget *view_entry;
GtkWidget *ext_scroll;
GtkWidget *ext_clist;
GtkWidget *ext_entry;
GtkWidget *ext_add_button;
GtkWidget *ext_remove_button;
MimeInfo *mi;
MimeInfo *user_mi;
GList *tmp_ext[2];
} edit_window;
static edit_window *main_win = NULL;
static gboolean changing = TRUE;
static void
destruction_handler (GtkWidget *widget, gpointer data)
{
g_free (main_win);
main_win = NULL;
}
static void
entry_changed (GtkWidget *widget, gpointer data)
{
if (changing == FALSE)
capplet_widget_state_changed (CAPPLET_WIDGET (capplet),
TRUE);
}
static void
ext_clist_selected (GtkWidget *clist, gint row, gint column, gpointer data)
{
gboolean deletable;
deletable = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row));
if (deletable)
gtk_widget_set_sensitive (main_win->ext_remove_button, TRUE);
else
gtk_widget_set_sensitive (main_win->ext_remove_button, FALSE);
}
static void
ext_clist_deselected (GtkWidget *clist, gint row, gint column, gpointer data)
{
if (g_list_length (GTK_CLIST (clist)->selection) == 0)
gtk_widget_set_sensitive (main_win->ext_remove_button, FALSE);
}
static void
ext_entry_changed (GtkWidget *entry, gpointer data)
{
gchar *text;
text = gtk_entry_get_text (GTK_ENTRY (entry));
gtk_widget_set_sensitive (main_win->ext_add_button, (strlen (text) >0));
}
static void
ext_add (GtkWidget *widget, gpointer data)
{
gchar *row[1];
gint rownumber;
row[0] = g_strdup (gtk_entry_get_text (GTK_ENTRY (main_win->ext_entry)));
rownumber = gtk_clist_append (GTK_CLIST (main_win->ext_clist), row);
gtk_clist_set_row_data (GTK_CLIST (main_win->ext_clist), rownumber,
GINT_TO_POINTER (TRUE));
gtk_entry_set_text (GTK_ENTRY (main_win->ext_entry), "");
main_win->tmp_ext[0] = g_list_prepend (main_win->tmp_ext[0], row[0]);
if (changing == FALSE)
capplet_widget_state_changed (CAPPLET_WIDGET (capplet),
TRUE);
}
static void
ext_remove (GtkWidget *widget, gpointer data)
{
gint row;
gchar *text;
gchar *store;
GList *tmp;
text = (gchar *)g_malloc (sizeof (gchar) * 1024);
gtk_clist_freeze (GTK_CLIST (main_win->ext_clist));
row = GPOINTER_TO_INT (GTK_CLIST (main_win->ext_clist)->selection->data);
gtk_clist_get_text (GTK_CLIST (main_win->ext_clist), row, 0, &text);
store = g_strdup (text);
gtk_clist_remove (GTK_CLIST (main_win->ext_clist), row);
gtk_clist_thaw (GTK_CLIST (main_win->ext_clist));
for (tmp = main_win->tmp_ext[0]; tmp; tmp = tmp->next) {
GList *found;
if (strcmp (tmp->data, store) == 0) {
found = tmp;
main_win->tmp_ext[0] = g_list_remove_link (main_win->tmp_ext[0], found);
g_list_free_1 (found);
break;
}
}
if (changing == FALSE)
capplet_widget_state_changed (CAPPLET_WIDGET (capplet),
TRUE);
}
static void
apply_entry_change (GtkWidget *entry, gchar *key, MimeInfo *mi)
{
const gchar *buf;
gchar *text;
/* buf is the value that existed before when we
* started the capplet */
buf = local_mime_get_value (mi->mime_type, key);
if (buf == NULL)
buf = gnome_mime_get_value (mi->mime_type, key);
text = gtk_entry_get_text (GTK_ENTRY (entry));
if (text && !*text)
text = NULL;
/* First we see if they've added something. */
if (buf == NULL && text)
set_mime_key_value (mi->mime_type, key, text);
else {
/* Has the value changed? */
if (text && strcmp (text, buf))
set_mime_key_value (mi->mime_type, key, text);
else
/* We _REALLY_ need a way to specify in
* user.keys not to use the system defaults.
* (ie. override the system default and
* query it).
* If we could then we'd set it here. */
;
}
}
static GList*
copy_mi_extensions (GList *orig)
{
GList *tmp;
GList *list = NULL;
for (tmp = orig; tmp; tmp = tmp->next) {
list = g_list_append (list, g_strdup (tmp->data));
}
return list;
}
static void
make_readable (MimeInfo *mi)
{
GList *list;
GString *extension;
extension = g_string_new ("");
for (list = ((MimeInfo *) mi)->user_ext[0]; list; list = list->next) {
g_string_append (extension, (gchar *) list->data);
if (list->next != NULL)
g_string_append (extension, ", ");
}
mi->ext_readable[0] = extension->str;
g_string_free (extension, FALSE);
extension = g_string_new ("");
for (list = ((MimeInfo *) mi)->user_ext[1]; list; list = list->next) {
g_string_append (extension, (gchar *) list->data);
if (list->next != NULL)
g_string_append (extension, ", ");
}
mi->ext_readable[1] = extension->str;
g_string_free (extension, FALSE);
}
static void
apply_changes (MimeInfo *mi)
{
GList *tmp;
int i;
apply_entry_change (gnome_icon_entry_gtk_entry (GNOME_ICON_ENTRY (main_win->icon_entry)),
"icon-filename", mi);
apply_entry_change (gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (main_win->open_entry)),
"open", mi);
apply_entry_change (gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (main_win->view_entry)),
"view", mi);
apply_entry_change (gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (main_win->edit_entry)),
"edit", mi);
if (!main_win->user_mi) {
add_to_key (mi->mime_type, "ext: tmp", user_mime_types, TRUE);
/* the tmp extension will be removed when we copy the tmp_ext
* stuff over the top of it.
*/
main_win->user_mi = g_hash_table_lookup (user_mime_types,
mi->mime_type);
}
for (i = 0; i < 2; i++) {
if (main_win->tmp_ext[i]) {
main_win->user_mi->user_ext[i] = copy_mi_extensions (main_win->tmp_ext[i]);
mi->user_ext[i] = copy_mi_extensions (main_win->tmp_ext[i]);
} else {
main_win->user_mi->user_ext[i] = NULL;
mi->user_ext[i] = NULL;
}
}
make_readable (main_win->user_mi);
if (! (main_win->user_mi->ext[0] || main_win->user_mi->ext[1] ||
main_win->user_mi->user_ext[0] || main_win->user_mi->ext[1]))
g_hash_table_remove (user_mime_types, mi->mime_type);
/* Free the 2 tmp lists */
for (i = 0; i < 2; i++) {
if (main_win->tmp_ext[i])
for (tmp = main_win->tmp_ext[i]; tmp; tmp = tmp->next)
g_free (tmp->data);
}
if (changing == FALSE)
capplet_widget_state_changed (CAPPLET_WIDGET (capplet),
TRUE);
}
static void
browse_callback (GtkWidget *widget, gpointer data)
{
}
static void
initialize_main_win ()
{
GtkWidget *align, *vbox, *hbox, *vbox2, *vbox3;
GtkWidget *frame, *table, *label;
GtkWidget *button;
GString *extension;
gchar *title[2] = {"Extensions"};
main_win = g_new (edit_window, 1);
main_win->window = gnome_dialog_new ("",
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
NULL);
gtk_signal_connect (GTK_OBJECT (main_win->window),
"destroy",
destruction_handler,
NULL);
vbox = GNOME_DIALOG (main_win->window)->vbox;
/* icon box */
main_win->icon_entry = gnome_icon_entry_new ("mime_icon_entry", _("Select an icon..."));
align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_container_add (GTK_CONTAINER (align), main_win->icon_entry);
gtk_signal_connect (GTK_OBJECT (gnome_icon_entry_gtk_entry (GNOME_ICON_ENTRY (main_win->icon_entry))),
"changed",
entry_changed,
NULL);
gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Mime Type: ")), FALSE, FALSE, 0);
main_win->mime_type = gtk_label_new ("");
gtk_box_pack_start (GTK_BOX (hbox), main_win->mime_type, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
/* extension/regexp */
vbox2 = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
main_win->ext_clist = gtk_clist_new_with_titles (1, title);
gtk_clist_column_titles_passive (GTK_CLIST (main_win->ext_clist));
gtk_clist_set_auto_sort (GTK_CLIST (main_win->ext_clist), TRUE);
gtk_signal_connect (GTK_OBJECT (main_win->ext_clist),
"select-row",
GTK_SIGNAL_FUNC (ext_clist_selected),
NULL);
gtk_signal_connect (GTK_OBJECT (main_win->ext_clist),
"unselect-row",
GTK_SIGNAL_FUNC (ext_clist_deselected),
NULL);
main_win->ext_scroll = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (main_win->ext_scroll),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (main_win->ext_scroll),
main_win->ext_clist);
vbox3 = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
main_win->ext_add_button = gtk_button_new_with_label (_("Add"));
gtk_signal_connect (GTK_OBJECT (main_win->ext_add_button),
"clicked",
GTK_SIGNAL_FUNC (ext_add),
NULL);
gtk_box_pack_start (GTK_BOX (vbox3), main_win->ext_add_button, FALSE, FALSE, 0);
gtk_widget_set_sensitive (main_win->ext_add_button, FALSE);
main_win->ext_remove_button = gtk_button_new_with_label (_("Remove"));
gtk_signal_connect (GTK_OBJECT (main_win->ext_remove_button),
"clicked",
GTK_SIGNAL_FUNC (ext_remove),
NULL);
gtk_widget_set_sensitive (main_win->ext_remove_button, FALSE);
gtk_box_pack_start (GTK_BOX (vbox3), main_win->ext_remove_button,
FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), main_win->ext_scroll, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), vbox3, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox2), hbox, TRUE, TRUE, 0);
main_win->ext_entry = gtk_entry_new ();
gtk_signal_connect (GTK_OBJECT (main_win->ext_entry),
"changed",
ext_entry_changed,
NULL);
gtk_signal_connect (GTK_OBJECT (main_win->ext_entry),
"activate",
ext_add,
NULL);
gtk_box_pack_start (GTK_BOX (vbox2), main_win->ext_entry, TRUE, TRUE, 0);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
main_win->regexp1_label = gtk_label_new ("");
main_win->regexp1_tag_label = gtk_label_new (_("First Regular Expression: "));
gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), main_win->regexp1_tag_label,
FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), main_win->regexp1_label, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
main_win->regexp2_label = gtk_label_new ("");
main_win->regexp2_tag_label = gtk_label_new (_("Second Regular Expression: "));
gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), main_win->regexp2_tag_label,
FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), main_win->regexp2_label, FALSE, FALSE, 0);
/* Actions box */
frame = gtk_frame_new (_("Mime Type Actions"));
vbox2 = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
table = gtk_table_new (3, 2, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
gtk_container_set_border_width (GTK_CONTAINER (table), GNOME_PAD_SMALL);
gtk_container_add (GTK_CONTAINER (frame), vbox2);
label = gtk_label_new (_("Example: emacs %f"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_misc_set_padding (GTK_MISC (label), 2, 0);
gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox2), table, FALSE, FALSE, 0);
label = gtk_label_new (_("Open"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_misc_set_padding (GTK_MISC (label), 2, 0);
gtk_table_attach_defaults (GTK_TABLE (table),
label,
0, 1, 0, 1);
main_win->open_entry = gnome_file_entry_new ("MIME_CAPPLET_OPEN", _("Select a file..."));
gtk_signal_connect (GTK_OBJECT (gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (main_win->open_entry))),
"changed",
entry_changed,
NULL);
gtk_table_attach_defaults (GTK_TABLE (table),
main_win->open_entry,
1, 2, 0, 1);
label = gtk_label_new (_("View"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_misc_set_padding (GTK_MISC (label), 2, 0);
gtk_table_attach_defaults (GTK_TABLE (table),
label,
0, 1, 1, 2);
main_win->view_entry = gnome_file_entry_new ("MIME_CAPPLET_VIEW", _("Select a file..."));
gtk_signal_connect (GTK_OBJECT (gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (main_win->view_entry))),
"changed",
entry_changed,
NULL);
gtk_table_attach_defaults (GTK_TABLE (table),
main_win->view_entry,
1, 2, 1, 2);
label = gtk_label_new (_("Edit"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_misc_set_padding (GTK_MISC (label), 2, 0);
gtk_table_attach_defaults (GTK_TABLE (table),
label,
0, 1, 2, 3);
main_win->edit_entry = gnome_file_entry_new ("MIME_CAPPLET_EDIT", _("Select a file..."));
gtk_signal_connect (GTK_OBJECT (gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (main_win->edit_entry))),
"changed",
entry_changed,
NULL);
gtk_table_attach_defaults (GTK_TABLE (table),
main_win->edit_entry,
1, 2, 2, 3);
}
static void
setup_entry (gchar *key, GtkWidget *g_entry, MimeInfo *mi)
{
const gchar *buf;
GtkWidget *entry = gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (g_entry));
buf = local_mime_get_value (mi->mime_type, key);
if (buf == NULL)
buf = gnome_mime_get_value (mi->mime_type, key);
if (buf)
gtk_entry_set_text (GTK_ENTRY (entry), buf);
else
gtk_entry_set_text (GTK_ENTRY (entry), "");
}
void
initialize_main_win_vals (void)
{
MimeInfo *mi;
gchar *title;
gboolean showext = FALSE;
if (main_win == NULL)
return;
mi = main_win->mi;
if (mi == NULL)
return;
/* now we fill in the fields with the mi stuff. */
changing = TRUE;
gtk_label_set_text (GTK_LABEL (main_win->mime_type), mi->mime_type);
gnome_icon_entry_set_icon (GNOME_ICON_ENTRY (main_win->icon_entry),
gnome_mime_get_value (mi->mime_type,
"icon-filename"));
gtk_widget_show_all (GNOME_DIALOG (main_win->window)->vbox);
/* we initialize everything */
title = g_strdup_printf (_("Set actions for %s"), mi->mime_type);
gtk_window_set_title (GTK_WINDOW (main_win->window), title);
g_free (title);
/* not sure why this is necessary */
gtk_clist_clear (GTK_CLIST (main_win->ext_clist));
if (mi->ext[0]) {
GList *tmp;
gchar *extension[1];
gint row;
for (tmp = mi->ext[0]; tmp; tmp = tmp->next) {
extension[0] = g_strdup (tmp->data);
row = gtk_clist_append (GTK_CLIST (main_win->ext_clist),
extension);
gtk_clist_set_row_data (GTK_CLIST (main_win->ext_clist),
row, GINT_TO_POINTER (FALSE));
}
showext = TRUE;
}
if (mi->ext[1]) {
GList *tmp;
gchar *extension[1];
gint row;
for (tmp = mi->ext[1]; tmp; tmp = tmp->next) {
extension[0] = g_strdup (tmp->data);
row = gtk_clist_append (GTK_CLIST (main_win->ext_clist),
extension);
gtk_clist_set_row_data (GTK_CLIST (main_win->ext_clist),
row, GINT_TO_POINTER (FALSE));
}
showext = TRUE;
}
if (main_win->tmp_ext[0]) {
GList *tmp;
gchar *extension[1];
gint row;
for (tmp = main_win->tmp_ext[0]; tmp; tmp = tmp->next) {
extension[0] = g_strdup (tmp->data);
row = gtk_clist_append (GTK_CLIST (main_win->ext_clist),
extension);
gtk_clist_set_row_data (GTK_CLIST (main_win->ext_clist),
row, GINT_TO_POINTER (TRUE));
}
showext = TRUE;
}
if (main_win->tmp_ext[1]) {
GList *tmp;
gchar *extension[1];
gint row;
for (tmp = main_win->tmp_ext[0]; tmp; tmp = tmp->next) {
extension[0] = g_strdup (tmp->data);
row = gtk_clist_append (GTK_CLIST (main_win->ext_clist),
extension);
gtk_clist_set_row_data (GTK_CLIST (main_win->ext_clist),
row, GINT_TO_POINTER (TRUE));
}
showext = TRUE;
}
if (!showext) {
gtk_widget_hide (main_win->ext_clist);
gtk_widget_hide (main_win->ext_entry);
gtk_widget_hide (main_win->ext_add_button);
gtk_widget_hide (main_win->ext_remove_button);
gtk_widget_hide (main_win->ext_scroll);
}
if (mi->regex_readable[0])
gtk_label_set_text (GTK_LABEL (main_win->regexp1_label),
mi->regex_readable[0]);
else {
gtk_widget_hide (main_win->regexp1_label);
gtk_widget_hide (main_win->regexp1_tag_label);
}
if (mi->regex_readable[1])
gtk_label_set_text (GTK_LABEL (main_win->regexp2_label),
mi->regex_readable[1]);
else {
gtk_widget_hide (main_win->regexp2_label);
gtk_widget_hide (main_win->regexp2_tag_label);
}
/* initialize the entries */
setup_entry ("open", main_win->open_entry, mi);
setup_entry ("view", main_win->view_entry, mi);
setup_entry ("edit", main_win->edit_entry, mi);
changing = FALSE;
}
void
launch_edit_window (MimeInfo *mi)
{
gint size;
if (main_win == NULL)
initialize_main_win ();
main_win->mi = mi;
main_win->user_mi = g_hash_table_lookup (user_mime_types, mi->mime_type);
main_win->tmp_ext[0] = NULL;
main_win->tmp_ext[1] = NULL;
if (main_win->user_mi) {
if (main_win->user_mi->user_ext[0])
main_win->tmp_ext[0] = copy_mi_extensions (main_win->user_mi->user_ext[0]);
if (main_win->user_mi->user_ext[1])
main_win->tmp_ext[1] = copy_mi_extensions (main_win->user_mi->user_ext[1]);
}
initialize_main_win_vals ();
switch(gnome_dialog_run (GNOME_DIALOG (main_win->window))) {
case 0:
apply_changes (mi);
case 1:
main_win->mi = NULL;
gtk_widget_hide (main_win->window);
break;
}
}
void
hide_edit_window (void)
{
if (main_win && main_win->mi && main_win->window)
gtk_widget_hide (main_win->window);
}
void
show_edit_window (void)
{
if (main_win && main_win->mi && main_win->window)
gtk_widget_show (main_win->window);
}

View File

@@ -1,15 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* Copyright (C) 1998 Redhat Software Inc.
* Authors: Jonathan Blandford <jrb@redhat.com>
*/
#include "mime-data.h"
#ifndef _EDIT_WINDOW_H_
#define _EDIT_WINDOW_H_
void launch_edit_window (MimeInfo *mi);
void initialize_main_win_vals (void);
void hide_edit_window (void);
void show_edit_window (void);
#endif

View File

@@ -1,660 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* Copyright (C) 1998 Redhat Software Inc.
* Authors: Jonathan Blandford <jrb@redhat.com>
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "capplet-widget.h"
#include "gnome.h"
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <regex.h>
#include <ctype.h>
#include "edit-window.h"
#include "mime-data.h"
#include "mime-info.h"
#include "new-mime-window.h"
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
/* Prototypes */
static void mime_fill_from_file (const char *filename, gboolean init_user);
static void mime_load_from_dir (const char *mime_info_dir, gboolean system_dir);
void add_to_key (char *mime_type, char *def, GHashTable *table, gboolean init_user);
static char *get_priority (char *def, int *priority);
/* Global variables */
static char *current_lang;
static GHashTable *mime_types = NULL;
static GHashTable *initial_user_mime_types = NULL;
GHashTable *user_mime_types = NULL;
static GtkWidget *clist = NULL;
extern GtkWidget *delete_button;
extern GtkWidget *capplet;
/* Initialization functions */
static void
run_error (gchar *message)
{
GtkWidget *error_box;
error_box = gnome_message_box_new (
message,
GNOME_MESSAGE_BOX_ERROR,
GNOME_STOCK_BUTTON_OK,
NULL);
gnome_dialog_run_and_close (GNOME_DIALOG (error_box));
}
static char *
get_priority (char *def, int *priority)
{
*priority = 0;
if (*def == ','){
def++;
if (*def == '1'){
*priority = 0;
def++;
} else if (*def == '2'){
*priority = 1;
def++;
}
}
while (*def && *def == ':')
def++;
return def;
}
static void
free_mime_info (MimeInfo *mi)
{
}
void
add_to_key (char *mime_type, char *def, GHashTable *table, gboolean init_user)
{
int priority = 1;
char *s, *p, *ext;
int used;
MimeInfo *info;
info = g_hash_table_lookup (table, (const void *) mime_type);
if (info == NULL) {
info = g_malloc (sizeof (MimeInfo));
info->mime_type = g_strdup (mime_type);
info->regex[0] = NULL;
info->regex[1] = NULL;
info->ext[0] = NULL;
info->ext[1] = NULL;
info->user_ext[0] = NULL;
info->user_ext[1] = NULL;
info->regex_readable[0] = NULL;
info->regex_readable[1] = NULL;
info->ext_readable[0] = NULL;
info->ext_readable[1] = NULL;
info->keys = gnome_mime_get_keys (mime_type);
g_hash_table_insert (table, info->mime_type, info);
}
if (strncmp (def, "ext", 3) == 0){
char *tokp;
def += 3;
def = get_priority (def, &priority);
s = p = g_strdup (def);
used = 0;
while ((ext = strtok_r (s, " \t\n\r,", &tokp)) != NULL){
/* FIXME: We really need to check for duplicates before entering this. */
if (!init_user) {
info->ext[priority] = g_list_prepend (info->ext[priority], ext);
} else {
info->user_ext[priority] = g_list_prepend (info->user_ext[priority], ext);
}
used = 1;
s = NULL;
}
if (!used)
g_free (p);
}
if (strncmp (def, "regex", 5) == 0){
regex_t *regex;
regex = g_new (regex_t, 1);
def += 5;
def = get_priority (def, &priority);
while (*def && isspace (*def))
def++;
if (!*def)
return;
if (regcomp (regex, def, REG_EXTENDED | REG_NOSUB))
g_free (regex);
else {
info->regex[priority] = regex;
g_free (info->regex_readable[priority]);
info->regex_readable[priority] = g_strdup (def);
}
}
}
static void
mime_fill_from_file (const char *filename, gboolean init_user)
{
FILE *f;
char buf [1024];
char *current_key;
gboolean used;
g_assert (filename != NULL);
f = fopen (filename, "r");
if (!f)
return;
current_key = NULL;
used = FALSE;
while (fgets (buf, sizeof (buf), f)){
char *p;
if (buf [0] == '#')
continue;
/* Trim trailing spaces */
for (p = buf + strlen (buf) - 1; p >= buf; p--){
if (isspace (*p) || *p == '\n')
*p = 0;
else
break;
}
if (!buf [0])
continue;
if (buf [0] == '\t' || buf [0] == ' '){
if (current_key){
char *p = buf;
while (*p && isspace (*p))
p++;
if (*p == 0)
continue;
add_to_key (current_key, p, mime_types, init_user);
if (init_user) {
add_to_key (current_key, p,
initial_user_mime_types,
TRUE);
add_to_key (current_key, p,
user_mime_types, TRUE);
}
used = TRUE;
}
} else {
if (!used && current_key)
g_free (current_key);
current_key = g_strdup (buf);
if (current_key [strlen (current_key)-1] == ':')
current_key [strlen (current_key)-1] = 0;
used = FALSE;
}
}
fclose (f);
}
static void
mime_load_from_dir (const char *mime_info_dir, gboolean system_dir)
{
DIR *dir;
struct dirent *dent;
const int extlen = sizeof (".mime") - 1;
char *filename;
dir = opendir (mime_info_dir);
if (!dir)
return;
if (system_dir) {
filename = g_concat_dir_and_file (mime_info_dir, "gnome.mime");
mime_fill_from_file (filename, FALSE);
g_free (filename);
}
while ((dent = readdir (dir)) != NULL){
int len = strlen (dent->d_name);
if (len <= extlen)
continue;
if (strcmp (dent->d_name + len - extlen, ".mime"))
continue;
if (system_dir && !strcmp (dent->d_name, "gnome.mime"))
continue;
if (!system_dir && !strcmp (dent->d_name, "user.mime"))
continue;
filename = g_concat_dir_and_file (mime_info_dir, dent->d_name);
mime_fill_from_file (filename, FALSE);
g_free (filename);
}
if (!system_dir) {
filename = g_concat_dir_and_file (mime_info_dir, "user.mime");
mime_fill_from_file (filename, TRUE);
g_free (filename);
}
closedir (dir);
}
static int
add_mime_vals_to_clist (gchar *mime_type, gpointer mi, gpointer cl)
{
/* we also finalize the MimeInfo structure here, now that we're done
* loading it */
static gchar *text[2];
GList *list;
GString *extension;
gint row;
extension = g_string_new ("");
for (list = ((MimeInfo *) mi)->ext[0];list; list=list->next) {
g_string_append (extension, (gchar *) list->data);
if (list->next != NULL)
g_string_append (extension, ", ");
}
if (strcmp (extension->str, "") != 0 && ((MimeInfo *)mi)->user_ext[0])
g_string_append (extension, ", ");
for (list = ((MimeInfo *) mi)->user_ext[0]; list; list=list->next) {
g_string_append (extension, (gchar *) list->data);
if (list->next != NULL)
g_string_append (extension, ", ");
}
((MimeInfo *) mi)->ext_readable[0] = extension->str;
g_string_free (extension, FALSE);
extension = g_string_new ("");
for (list = ((MimeInfo *) mi)->ext[1];list; list=list->next) {
g_string_append (extension, (gchar *) list->data);
if (list->next)
g_string_append (extension, ", ");
}
if (strcmp (extension->str, "") != 0 && ((MimeInfo *)mi)->user_ext[1])
g_string_append (extension, ", ");
for (list = ((MimeInfo *) mi)->user_ext[1]; list; list=list->next) {
g_string_append (extension, (gchar *) list->data);
if (list->next != NULL)
g_string_append (extension, ", ");
}
((MimeInfo *) mi)->ext_readable[1] = extension->str;
g_string_free (extension, FALSE);
if (((MimeInfo *) mi)->ext[0] || ((MimeInfo *) mi)->user_ext[0]) {
extension = g_string_new ((((MimeInfo *) mi)->ext_readable[0]));
if (((MimeInfo *) mi)->ext[1] || ((MimeInfo *) mi)->user_ext[1]) {
g_string_append (extension, ", ");
g_string_append (extension, (((MimeInfo *) mi)->ext_readable[1]));
}
} else if (((MimeInfo *) mi)->ext[1] || ((MimeInfo *) mi)->user_ext[1])
extension = g_string_new ((((MimeInfo *) mi)->ext_readable[1]));
else
extension = g_string_new ("");
text[0] = ((MimeInfo *) mi)->mime_type;
text[1] = extension->str;
row = gtk_clist_insert (GTK_CLIST (cl), 1, text);
gtk_clist_set_row_data (GTK_CLIST (cl), row, mi);
g_string_free (extension, TRUE);
return row;
}
static void
selected_row_callback (GtkWidget *widget, gint row, gint column, GdkEvent *event, gpointer data)
{
MimeInfo *mi;
if (column < 0)
return;
mi = (MimeInfo *) gtk_clist_get_row_data (GTK_CLIST (widget),row);
if (event && event->type == GDK_2BUTTON_PRESS)
launch_edit_window (mi);
if (g_hash_table_lookup (user_mime_types, mi->mime_type)) {
gtk_widget_set_sensitive (delete_button, TRUE);
} else
gtk_widget_set_sensitive (delete_button, FALSE);
}
/* public functions */
void
delete_clicked (GtkWidget *widget, gpointer data)
{
MimeInfo *mi;
gint row = 0;
if (GTK_CLIST (clist)->selection)
row = GPOINTER_TO_INT ((GTK_CLIST (clist)->selection)->data);
else
return;
mi = (MimeInfo *) gtk_clist_get_row_data (GTK_CLIST (clist), row);
gtk_clist_remove (GTK_CLIST (clist), row);
g_hash_table_remove (user_mime_types, mi->mime_type);
remove_mime_info (mi->mime_type);
free_mime_info (mi);
capplet_widget_state_changed (CAPPLET_WIDGET (capplet),
TRUE);
}
void
edit_clicked (GtkWidget *widget, gpointer data)
{
MimeInfo *mi;
gint row = 0;
if (GTK_CLIST (clist)->selection)
row = GPOINTER_TO_INT ((GTK_CLIST (clist)->selection)->data);
else
return;
mi = (MimeInfo *) gtk_clist_get_row_data (GTK_CLIST (clist), row);
if (mi)
launch_edit_window (mi);
gtk_clist_remove (GTK_CLIST (clist), row);
row = add_mime_vals_to_clist (mi->mime_type, mi, clist);
gtk_clist_select_row (GTK_CLIST (clist), row, 0);
}
void
add_clicked (GtkWidget *widget, gpointer data)
{
launch_new_mime_window ();
}
GtkWidget *
get_mime_clist (void)
{
GtkWidget *retval;
gchar *titles[2];
titles[0] = _("Mime Type");
titles[1] = _("Extension");
retval = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (retval),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
clist = gtk_clist_new_with_titles (2, titles);
gtk_signal_connect (GTK_OBJECT (clist),
"select_row",
GTK_SIGNAL_FUNC (selected_row_callback),
NULL);
gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_BROWSE);
gtk_clist_set_auto_sort (GTK_CLIST (clist), TRUE);
if (clist)
g_hash_table_foreach (mime_types, (GHFunc) add_mime_vals_to_clist, clist);
gtk_clist_columns_autosize (GTK_CLIST (clist));
gtk_clist_select_row (GTK_CLIST (clist), 0, 0);
gtk_container_add (GTK_CONTAINER (retval), clist);
return retval;
}
static void
finalize_mime_type_foreach (gpointer mime_type, gpointer info, gpointer data)
{
MimeInfo *mi = (MimeInfo *)info;
GList *list;
GString *extension;
extension = g_string_new ("");
for (list = ((MimeInfo *) mi)->ext[0];list; list=list->next) {
g_string_append (extension, (gchar *) list->data);
if (list->next != NULL)
g_string_append (extension, ", ");
}
if (strcmp (extension->str, "") != 0 && mi->user_ext[0])
g_string_append (extension, ", ");
for (list = ((MimeInfo *) mi)->user_ext[0]; list; list=list->next) {
g_string_append (extension, (gchar *) list->data);
if (list->next != NULL)
g_string_append (extension, ", ");
}
((MimeInfo *) mi)->ext_readable[0] = extension->str;
g_string_free (extension, FALSE);
extension = g_string_new ("");
for (list = ((MimeInfo *) mi)->ext[1];list; list=list->next) {
g_string_append (extension, (gchar *) list->data);
if (list->next)
g_string_append (extension, ", ");
}
if (strcmp (extension->str, "") != 0 && mi->user_ext[1])
g_string_append (extension, ", ");
for (list = ((MimeInfo *) mi)->user_ext[1]; list; list=list->next) {
g_string_append (extension, (gchar *) list->data);
if (list->next != NULL)
g_string_append (extension, ", ");
}
((MimeInfo *) mi)->ext_readable[1] = extension->str;
g_string_free (extension, FALSE);
if (((MimeInfo *) mi)->ext[0] || ((MimeInfo *) mi)->user_ext[0]) {
extension = g_string_new ((((MimeInfo *) mi)->ext_readable[0]));
if (((MimeInfo *) mi)->ext[1] || ((MimeInfo *) mi)->user_ext[1]) {
g_string_append (extension, ", ");
g_string_append (extension, (((MimeInfo *) mi)->ext_readable[1]));
}
} else if (((MimeInfo *) mi)->ext[1] || ((MimeInfo *) mi)->user_ext[1])
extension = g_string_new ((((MimeInfo *) mi)->ext_readable[1]));
else
extension = g_string_new ("");
g_string_free (extension, TRUE);
}
static void
finalize_user_mime ()
{
g_hash_table_foreach (user_mime_types, finalize_mime_type_foreach, NULL);
g_hash_table_foreach (initial_user_mime_types, finalize_mime_type_foreach, NULL);
}
void
init_mime_type (void)
{
char *mime_info_dir;
mime_types = g_hash_table_new (g_str_hash, g_str_equal);
initial_user_mime_types = g_hash_table_new (g_str_hash, g_str_equal);
user_mime_types = g_hash_table_new (g_str_hash, g_str_equal);
mime_info_dir = gnome_unconditional_datadir_file ("mime-info");
mime_load_from_dir (mime_info_dir, TRUE);
g_free (mime_info_dir);
mime_info_dir = g_concat_dir_and_file (gnome_util_user_home (), ".gnome/mime-info");
mime_load_from_dir (mime_info_dir, FALSE);
g_free (mime_info_dir);
finalize_user_mime ();
init_mime_info ();
}
void
add_new_mime_type (gchar *mime_type, gchar *raw_ext, gchar *regexp1, gchar *regexp2)
{
gchar *temp;
MimeInfo *mi = NULL;
gint row;
gchar *ext = NULL;
gchar *ptr, *ptr2;
/* first we make sure that the information is good */
if (mime_type == NULL || *mime_type == '\000') {
run_error (_("You must enter a mime-type"));
return;
} else if ((raw_ext == NULL || *raw_ext == '\000') &&
(regexp1 == NULL || *regexp1 == '\000') &&
(regexp2 == NULL || *regexp2 == '\000')){
run_error (_("You must add either a regular-expression or\na file-name extension"));
return;
}
if (strchr (mime_type, '/') == NULL) {
run_error (_("Please put your mime-type in the format:\nCATEGORY/TYPE\n\nFor Example:\nimage/png"));
return;
}
if (g_hash_table_lookup (user_mime_types, mime_type) ||
g_hash_table_lookup (mime_types, mime_type)) {
run_error (_("This mime-type already exists"));
return;
}
if (raw_ext || *raw_ext) {
ptr2 = ext = g_malloc (sizeof (raw_ext));
for (ptr = raw_ext;*ptr; ptr++) {
if (*ptr != '.' && *ptr != ',') {
*ptr2 = *ptr;
ptr2 += 1;
}
}
*ptr2 = '\000';
}
/* passed check, now we add it. */
if (ext) {
temp = g_strconcat ("ext: ", ext, NULL);
add_to_key (mime_type, temp, user_mime_types, TRUE);
mi = (MimeInfo *) g_hash_table_lookup (user_mime_types, mime_type);
g_free (temp);
}
if (regexp1) {
temp = g_strconcat ("regex: ", regexp1, NULL);
add_to_key (mime_type, temp, user_mime_types, TRUE);
g_free (temp);
}
if (regexp2) {
temp = g_strconcat ("regex,2: ", regexp2, NULL);
add_to_key (mime_type, temp, user_mime_types, TRUE);
g_free (temp);
}
/* Finally add it to the clist */
if (mi) {
row = add_mime_vals_to_clist (mime_type, mi, clist);
gtk_clist_select_row (GTK_CLIST (clist), row, 0);
gtk_clist_moveto (GTK_CLIST (clist), row, 0, 0.5, 0.0);
}
g_free (ext);
}
static void
write_mime_foreach (gpointer mime_type, gpointer info, gpointer data)
{
gchar *buf;
MimeInfo *mi = (MimeInfo *) info;
fwrite ((char *) mi->mime_type, 1, strlen ((char *) mi->mime_type), (FILE *) data);
fwrite ("\n", 1, 1, (FILE *) data);
if (mi->ext_readable[0]) {
fwrite ("\text: ", 1, strlen ("\text: "), (FILE *) data);
fwrite (mi->ext_readable[0], 1,
strlen (mi->ext_readable[0]),
(FILE *) data);
fwrite ("\n", 1, 1, (FILE *) data);
}
if (mi->regex_readable[0]) {
fwrite ("\tregex: ", 1, strlen ("\tregex: "), (FILE *) data);
fwrite (mi->regex_readable[0], 1,
strlen (mi->regex_readable[0]),
(FILE *) data);
fwrite ("\n", 1, 1, (FILE *) data);
}
if (mi->regex_readable[1]) {
fwrite ("\tregex,2: ", 1, strlen ("\tregex,2: "), (FILE *) data);
fwrite (mi->regex_readable[1], 1,
strlen (mi->regex_readable[1]),
(FILE *) data);
fwrite ("\n", 1, 1, (FILE *) data);
}
fwrite ("\n", 1, 1, (FILE *) data);
}
static void
write_mime (GHashTable *hash)
{
struct stat s;
gchar *dirname, *filename;
FILE *file;
GtkWidget *error_box;
dirname = g_concat_dir_and_file (gnome_util_user_home (), ".gnome/mime-info");
if ((stat (dirname, &s) < 0) || !(S_ISDIR (s.st_mode))){
if (errno == ENOENT) {
if (mkdir (dirname, S_IRWXU) < 0) {
run_error (_("We are unable to create the directory\n"
"~/.gnome/mime-info\n\n"
"We will not be able to save the state."));
return;
}
} else {
run_error (_("We are unable to access the directory\n"
"~/.gnome/mime-info\n\n"
"We will not be able to save the state."));
return;
}
}
filename = g_concat_dir_and_file (dirname, "user.mime");
remove (filename);
file = fopen (filename, "w");
if (file == NULL) {
run_error (_("Cannot create the file\n~/.gnome/mime-info/user.mime\n\n"
"We will not be able to save the state"));
return;
}
g_hash_table_foreach (hash, write_mime_foreach, file);
fclose (file);
}
void
write_user_mime (void)
{
write_mime (user_mime_types);
}
void
write_initial_mime (void)
{
write_mime (initial_user_mime_types);
}
void
reread_list ()
{
gtk_clist_freeze (GTK_CLIST (clist));
gtk_clist_clear (GTK_CLIST (clist));
g_hash_table_foreach (mime_types, (GHFunc) add_mime_vals_to_clist, clist);
gtk_clist_thaw (GTK_CLIST (clist));
}
static void
clean_mime_type (gpointer mime_type, gpointer mime_info, gpointer data)
{
/* we should write this )-: */
}
void
discard_mime_info ()
{
gchar *filename;
g_hash_table_foreach (user_mime_types, clean_mime_type, NULL);
g_hash_table_destroy (user_mime_types);
g_hash_table_foreach (initial_user_mime_types, clean_mime_type, NULL);
g_hash_table_destroy (initial_user_mime_types);
user_mime_types = g_hash_table_new (g_str_hash, g_str_equal);
initial_user_mime_types = g_hash_table_new (g_str_hash, g_str_equal);
filename = g_concat_dir_and_file (gnome_util_user_home (), "/.gnome/mime-info/user.keys");
mime_fill_from_file (filename, TRUE);
finalize_user_mime ();
reread_list ();
g_free (filename);
}

View File

@@ -1,34 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* Copyright (C) 1998 Redhat Software Inc.
* Authors: Jonathan Blandford <jrb@redhat.com>
*/
#ifndef _MIME_DATA_H_
#define _MIME_DATA_H_
#include "gnome.h"
#include <regex.h>
/* Typedefs */
typedef struct {
char *mime_type;
regex_t *regex[2];
GList *ext[2];
GList *user_ext[2];
char *ext_readable[2];
char *regex_readable[2];
char *file_name;
GList *keys;
} MimeInfo;
extern GHashTable *user_mime_types;
extern void add_to_key (char *mime_type, char *def, GHashTable *table, gboolean init_user);
GtkWidget *get_mime_clist (void);
void init_mime_type (void);
void delete_clicked (GtkWidget *widget, gpointer data);
void add_clicked (GtkWidget *widget, gpointer data);
void edit_clicked (GtkWidget *widget, gpointer data);
void add_new_mime_type (gchar *mime_type, gchar *ext, gchar *regexp1, gchar *regexp2);
void write_user_mime (void);
void write_initial_mime (void);
void reread_list (void);
void discard_mime_info (void);
#endif

View File

@@ -1,492 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* Copyright (C) 1998 Redhat Software Inc.
* Authors: Jonathan Blandford <jrb@redhat.com>
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "capplet-widget.h"
#include "gnome.h"
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <regex.h>
#include <ctype.h>
#include "mime-info.h"
#include "mime-data.h"
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#if !defined getc_unlocked && !defined HAVE_GETC_UNLOCKED
# define getc_unlocked(fp) getc (fp)
#endif
typedef struct {
char *mime_type;
GHashTable *keys;
} GnomeMimeContext;
typedef enum {
STATE_NONE,
STATE_LANG,
STATE_LOOKING_FOR_KEY,
STATE_ON_MIME_TYPE,
STATE_ON_KEY,
STATE_ON_VALUE
} ParserState;
static char *current_lang = NULL;
/*
* A hash table containing all of the Mime records for specific
* mime types (full description, like image/png)
*/
static GHashTable *specific_types;
static GHashTable *initial_specific_types;
/*
* A hash table containing all of the Mime records for non-specific
* mime types (like image/\*)
*/
static GHashTable *generic_types;
static GHashTable *initial_generic_types;
#define SWITCH_TO_MIME_TYPE() {
static GnomeMimeContext *
context_new (GString *str, gboolean is_default_context)
{
GnomeMimeContext *context;
GHashTable *table;
char *mime_type, *p;
mime_type = g_strdup (str->str);
if (is_default_context) {
if ((p = strstr (mime_type, "/*")) == NULL){
table = initial_specific_types;
} else {
*(p+1) = 0;
table = initial_generic_types;
}
} else {
if ((p = strstr (mime_type, "/*")) == NULL){
table = specific_types;
} else {
*(p+1) = 0;
table = generic_types;
}
}
context = g_hash_table_lookup (table, mime_type);
if (context)
return context;
context = g_new (GnomeMimeContext, 1);
context->mime_type = mime_type;
context->keys = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (table, context->mime_type, context);
return context;
}
static gboolean
release_key_and_value (gpointer key, gpointer value, gpointer user_data)
{
g_free (key);
g_free (value);
return TRUE;
}
static gboolean
remove_this_key (gpointer key, gpointer value, gpointer user_data)
{
if (strcmp ((gchar *)key, (gchar *)user_data) == 0){
g_free (key);
g_free (value);
return TRUE;
}
return FALSE;
}
static void
context_add_key (GnomeMimeContext *context, char *key, char *value)
{
char *v;
v = g_hash_table_lookup (context->keys, key);
if (v)
g_hash_table_foreach_remove (context->keys, remove_this_key, key);
g_hash_table_insert (context->keys, g_strdup (key), g_strdup (value));
}
static void
context_destroy (GnomeMimeContext *context)
{
/*
* Remove the context from our hash tables, we dont know
* where it is: so just remove it from both (it can
* only be in one).
*/
if (context->mime_type) {
g_hash_table_remove (specific_types, context->mime_type);
g_hash_table_remove (generic_types, context->mime_type);
}
/*
* Destroy it
*/
if (context->keys) {
g_hash_table_foreach_remove (context->keys, release_key_and_value, NULL);
g_hash_table_destroy (context->keys);
}
g_free (context->mime_type);
g_free (context);
}
static void
load_mime_type_info_from (char *filename)
{
FILE *mime_file;
gboolean in_comment, context_used;
GString *line;
int column, c;
ParserState state;
GnomeMimeContext *context, *default_context;
char *key;
mime_file = fopen (filename, "r");
if (mime_file == NULL)
return;
in_comment = FALSE;
context_used = FALSE;
column = 0;
context = NULL;
default_context = NULL;
key = NULL;
line = g_string_sized_new (120);
state = STATE_NONE;
while ((c = getc_unlocked (mime_file)) != EOF){
column++;
if (c == '\r')
continue;
if (c == '#' && column == 0){
in_comment = TRUE;
continue;
}
if (c == '\n'){
in_comment = FALSE;
column = 0;
if (state == STATE_ON_MIME_TYPE){
context = context_new (line, FALSE);
default_context = context_new (line, TRUE);
context_used = FALSE;
g_string_assign (line, "");
state = STATE_LOOKING_FOR_KEY;
continue;
}
if (state == STATE_ON_VALUE){
context_used = TRUE;
context_add_key (context, key, line->str);
context_add_key (default_context, key, line->str);
g_string_assign (line, "");
g_free (key);
key = NULL;
state = STATE_LOOKING_FOR_KEY;
continue;
}
continue;
}
if (in_comment)
continue;
switch (state){
case STATE_NONE:
if (c != ' ' && c != '\t')
state = STATE_ON_MIME_TYPE;
else
break;
/* fall down */
case STATE_ON_MIME_TYPE:
if (c == ':'){
in_comment = TRUE;
break;
}
g_string_append_c (line, c);
break;
case STATE_LOOKING_FOR_KEY:
if (c == '\t' || c == ' ')
break;
if (c == '['){
state = STATE_LANG;
break;
}
if (column == 1){
state = STATE_ON_MIME_TYPE;
g_string_append_c (line, c);
break;
}
state = STATE_ON_KEY;
/* falldown */
case STATE_ON_KEY:
if (c == '\\'){
c = getc (mime_file);
if (c == EOF)
break;
}
if (c == '='){
key = g_strdup (line->str);
g_string_assign (line, "");
state = STATE_ON_VALUE;
break;
}
g_string_append_c (line, c);
break;
case STATE_ON_VALUE:
g_string_append_c (line, c);
break;
case STATE_LANG:
if (c == ']'){
state = STATE_ON_KEY;
if (current_lang && line->str [0]){
if (strcmp (current_lang, line->str) != 0){
in_comment = TRUE;
state = STATE_LOOKING_FOR_KEY;
}
} else {
in_comment = TRUE;
state = STATE_LOOKING_FOR_KEY;
}
g_string_assign (line, "");
break;
}
g_string_append_c (line, c);
break;
}
}
if (context){
if (key && line->str [0]) {
context_add_key (context, key, line->str);
context_add_key (default_context, key, line->str);
} else
if (!context_used) {
context_destroy (context);
context_destroy (default_context);
}
}
g_string_free (line, TRUE);
if (key)
g_free (key);
fclose (mime_file);
}
void
set_mime_key_value (gchar *mime_type, gchar *key, gchar *value)
{
GnomeMimeContext *context;
/* Assume no generic context's for now. */
context = g_hash_table_lookup (specific_types, mime_type);
if (context == NULL) {
GString *str = g_string_new (mime_type);
context = context_new (str, FALSE);
g_string_free (str, TRUE);
}
context_add_key (context, key, value);
}
void
init_mime_info (void)
{
gchar *filename;
current_lang = getenv ("LANG");
specific_types = g_hash_table_new (g_str_hash, g_str_equal);
generic_types = g_hash_table_new (g_str_hash, g_str_equal);
initial_specific_types = g_hash_table_new (g_str_hash, g_str_equal);
initial_generic_types = g_hash_table_new (g_str_hash, g_str_equal);
filename = g_concat_dir_and_file (gnome_util_user_home (), "/.gnome/mime-info/user.keys");
load_mime_type_info_from (filename);
g_free (filename);
}
const char *
local_mime_get_value (const char *mime_type, char *key)
{
char *value, *generic_type, *p;
GnomeMimeContext *context;
g_return_val_if_fail (mime_type != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
context = g_hash_table_lookup (specific_types, mime_type);
if (context){
value = g_hash_table_lookup (context->keys, key);
if (value)
return value;
}
generic_type = g_strdup (mime_type);
p = strchr (generic_type, '/');
if (p)
*(p+1) = 0;
context = g_hash_table_lookup (generic_types, generic_type);
g_free (generic_type);
if (context){
value = g_hash_table_lookup (context->keys, key);
if (value)
return value;
}
return NULL;
}
static void
clean_mime_foreach (gpointer mime_type, gpointer gmc, gpointer data)
{
context_destroy ((GnomeMimeContext *) gmc);
}
static void
write_mime_keys_foreach (gpointer key_name, gpointer value, gpointer data)
{
gchar *buf;
if (current_lang && strcmp (current_lang, "C"))
buf = g_strconcat ("\t[",
current_lang,
"]",
(gchar *) key_name,
"=",
(gchar *) value,
"\n", NULL);
else
buf = g_strconcat ("\t",
(gchar *) key_name,
"=",
(gchar *) value,
"\n", NULL);
fwrite (buf, 1, strlen (buf), (FILE *) data);
g_free (buf);
}
static void
write_mime_foreach (gpointer mime_type, gpointer gmc, gpointer data)
{
gchar *buf;
GnomeMimeContext *context = (GnomeMimeContext *) gmc;
buf = g_strconcat ((gchar *) mime_type, ":\n", NULL);
fwrite (buf, 1, strlen (buf), (FILE *) data);
g_free (buf);
g_hash_table_foreach (context->keys, write_mime_keys_foreach, data);
fwrite ("\n", 1, strlen ("\n"), (FILE *) data);
}
static void
run_error (gchar *message)
{
GtkWidget *error_box;
error_box = gnome_message_box_new (
message,
GNOME_MESSAGE_BOX_ERROR,
GNOME_STOCK_BUTTON_OK,
NULL);
gnome_dialog_run_and_close (GNOME_DIALOG (error_box));
}
static void
write_keys (GHashTable *spec_hash, GHashTable *generic_hash)
{
struct stat s;
gchar *dirname, *filename;
FILE *file;
GtkWidget *error_box;
dirname = g_concat_dir_and_file (gnome_util_user_home (), ".gnome/mime-info");
if ((stat (dirname, &s) < 0) || !(S_ISDIR (s.st_mode))){
if (errno == ENOENT) {
if (mkdir (dirname, S_IRWXU) < 0) {
run_error (_("We are unable to create the directory\n"
"~/.gnome/mime-info.\n\n"
"We will not be able to save the state."));
return;
}
} else {
run_error (_("We are unable to access the directory\n"
"~/.gnome/mime-info.\n\n"
"We will not be able to save the state."));
return;
}
}
filename = g_concat_dir_and_file (dirname, "user.keys");
remove (filename);
file = fopen (filename, "w");
if (file == NULL) {
run_error (_("Cannot create the file\n~/.gnome/mime-info/user.keys.\n\n"
"We will not be able to save the state"));
return;
}
g_hash_table_foreach (spec_hash, write_mime_foreach, file);
g_hash_table_foreach (generic_hash, write_mime_foreach, file);
fclose (file);
}
void
write_initial_keys (void)
{
write_keys (initial_generic_types, initial_specific_types);
}
void
write_user_keys (void)
{
write_keys (generic_types, specific_types);
}
static void
print_mime_foreach (gpointer mime_info, gpointer mi, gpointer data)
{
g_print ("mime_info:%s:\n", (char *)mime_info);
g_print ("\t:%s:\n", ((MimeInfo *)mi)->mime_type);
}
void
discard_key_info (void)
{
gchar *filename;
current_lang = getenv ("LANG");
g_hash_table_foreach (generic_types, clean_mime_foreach, NULL);
/* g_hash_table_foreach (specific_types, print_mime_foreach, NULL); */
g_hash_table_foreach (specific_types, clean_mime_foreach, NULL);
g_hash_table_destroy (generic_types);
g_hash_table_destroy (specific_types);
specific_types = g_hash_table_new (g_str_hash, g_str_equal);
generic_types = g_hash_table_new (g_str_hash, g_str_equal);
filename = g_concat_dir_and_file (gnome_util_user_home (), "/.gnome/mime-info/user.keys");
load_mime_type_info_from (filename);
reread_list ();
g_free (filename);
}
void
remove_mime_info (gchar *mime_type)
{
g_hash_table_remove (generic_types, mime_type);
g_hash_table_remove (specific_types, mime_type);
}

View File

@@ -1,17 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* Copyright (C) 1998 Redhat Software Inc.
* Authors: Jonathan Blandford <jrb@redhat.com>
*/
#ifndef _MIME_INFO_H_
#define _MIME_INFO_H_
#include "gnome.h"
#include <regex.h>
/* Typedefs */
void init_mime_info (void);
void discard_key_info (void);
void set_mime_key_value (gchar *mime_type, gchar *key, gchar *value);
const char * local_mime_get_value (const char *mime_type, char *key);
void write_user_keys (void);
void write_initial_keys (void);
void remove_mime_info (gchar *mime_type);
#endif

View File

@@ -1,142 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* Copyright (C) 1998 Redhat Software Inc.
* Authors: Jonathan Blandford <jrb@redhat.com>
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "capplet-widget.h"
#include "gnome.h"
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <regex.h>
#include <ctype.h>
#include "mime-data.h"
#include "mime-info.h"
#include "edit-window.h"
/* Prototypes */
static void try_callback ();
static void revert_callback ();
static void ok_callback ();
static void cancel_callback ();
static void help_callback ();
GtkWidget *capplet = NULL;
GtkWidget *delete_button = NULL;
static GtkWidget *
left_aligned_button (gchar *label)
{
GtkWidget *button = gtk_button_new_with_label (label);
gtk_misc_set_alignment (GTK_MISC (GTK_BIN (button)->child),
0.0, 0.5);
gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child),
GNOME_PAD_SMALL, 0);
return button;
}
static void
try_callback ()
{
write_user_keys ();
write_user_mime ();
}
static void
revert_callback ()
{
write_initial_keys ();
write_initial_mime ();
discard_key_info ();
discard_mime_info ();
initialize_main_win_vals ();
}
static void
ok_callback ()
{
write_user_keys ();
write_user_mime ();
}
static void
cancel_callback ()
{
write_initial_keys ();
write_initial_mime ();
}
static void
help_callback ()
{
/* Sigh... empty as always */
}
static void
init_mime_capplet ()
{
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *button;
capplet = capplet_widget_new ();
delete_button = left_aligned_button (_("Delete"));
gtk_signal_connect (GTK_OBJECT (delete_button), "clicked",
delete_clicked, NULL);
hbox = gtk_hbox_new (FALSE, GNOME_PAD);
gtk_container_set_border_width (GTK_CONTAINER (hbox), GNOME_PAD_SMALL);
gtk_container_add (GTK_CONTAINER (capplet), hbox);
gtk_box_pack_start (GTK_BOX (hbox), get_mime_clist (), TRUE, TRUE, 0);
vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
button = left_aligned_button (_("Add..."));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
add_clicked, NULL);
button = left_aligned_button (_("Edit..."));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
edit_clicked, NULL);
gtk_box_pack_start (GTK_BOX (vbox), delete_button, FALSE, FALSE, 0);
gtk_widget_show_all (capplet);
gtk_signal_connect(GTK_OBJECT(capplet), "try",
GTK_SIGNAL_FUNC(try_callback), NULL);
gtk_signal_connect(GTK_OBJECT(capplet), "revert",
GTK_SIGNAL_FUNC(revert_callback), NULL);
gtk_signal_connect(GTK_OBJECT(capplet), "ok",
GTK_SIGNAL_FUNC(ok_callback), NULL);
gtk_signal_connect(GTK_OBJECT(capplet), "cancel",
GTK_SIGNAL_FUNC(cancel_callback), NULL);
gtk_signal_connect(GTK_OBJECT(capplet), "page_hidden",
GTK_SIGNAL_FUNC(hide_edit_window), NULL);
gtk_signal_connect(GTK_OBJECT(capplet), "page_shown",
GTK_SIGNAL_FUNC(show_edit_window), NULL);
#if 0
gtk_signal_connect(GTK_OBJECT(capplet), "help",
GTK_SIGNAL_FUNC(help_callback), NULL);
#endif
}
int
main (int argc, char **argv)
{
int init_results;
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
textdomain (PACKAGE);
init_results = gnome_capplet_init("mime-type-capplet", VERSION,
argc, argv, NULL, 0, NULL);
if (init_results < 0) {
exit (0);
}
if (init_results == 0) {
init_mime_type ();
init_mime_capplet ();
capplet_gtk_main ();
}
return 0;
}

Some files were not shown because too many files have changed in this diff Show More