Re: [Usability] An extended default applications dialog



Am Sonntag, den 14.01.2007, 13:31 +0100 schrieb Christian Neumair:
> (archived at [1])

I'm attaching the python script in a separate mail to get around the
usability list mail size limits.

[1] http://mail.gnome.org/archives/usability/2007-January/msg00064.html

-- 
Christian Neumair <chris gnome-de org>
#!/usr/bin/python
# * demo application for a new "default application" chooser
# * (partially) failed GUI experiment
# * new ideas:
#   http://mail.gnome.org/archives/usability/2007-January/msg00064.html

import pygtk
import gtk
import gobject
import gnomevfs
from sets import Set

class MimeCategory:
	def __init__ (self, name, mime_types, default_application_fallback):
		self.name = name
		self.mime_types = mime_types
		self.default_application_fallback = default_application_fallback
		self.update_from_vfs()

	def update_from_vfs (self):
		self.all_applications = {} # id->application
		self.applications = {} # MIME type -> application
		self.default_applications = {} # MIME type -> application

		# applications that can not handle all MIME types, TODO
		self.exception_applications = None

		unhandled_apps = None

		# find out available apps + default app for all mime types
		for mime_type in self.mime_types:
			self.applications[mime_type] = gnomevfs.mime_get_all_applications (mime_type)
			self.default_applications[mime_type] = gnomevfs.mime_get_default_application (mime_type)

			for application in self.applications[mime_type]:
				self.all_applications[application[0]] = (application)

		# find default app FIXME this should be read out somewhere
		default_app = None

		self.default_application = default_app and default_app[0] or self.default_application_fallback

class ApplicationChooserModel (gtk.ListStore):
	def __init__ (self, applications):
		gtk.ListStore.__init__ (self,
					gobject.TYPE_STRING, # application name
					gobject.TYPE_INT, # sort index
					gobject.TYPE_PYOBJECT) # GnomeVFSMIMEApplication
		self.set_default_sort_func (self.sort_func)
		self.set_sort_column_id (-1, gtk.SORT_ASCENDING)

		self.applications = applications 
		for application in applications:
			# application[1] is the name
			self.append ([application[1], -1, application])

		# TODO 
		#self.append ([None, 0, None])
		#self.append (['Custom...', 1, None])

	def sort_func (self, model, a, b):
		cmp = self.get_value (a, 1) - self.get_value (b, 1)
		if (cmp != 0):
			return cmp

		if self.get_value (a, 0) > self.get_value (b, 0):
			return 1
		elif self.get_value (a, 0) < self.get_value (b, 0):
			return -1
		else:
			return 0

class ApplicationChooser (gtk.ComboBox):
	def __init__ (self, applications, default_application):
		gtk.ComboBox.__init__ (self)
		self.set_row_separator_func(self.row_separator_func)

		self.set_model (ApplicationChooserModel (applications))

		iter = self.get_model().get_iter_first()
		i = 0
		while (iter != None):
			application = self.get_model().get_value (iter, 2)
			if application != None and application[0] == default_application:
				self.set_active (i)
				break
			i = i + 1
			iter = self.get_model().iter_next (iter)
			

		cell = gtk.CellRendererText()
		self.pack_start(cell, True)
		self.add_attribute(cell, 'text', 0)

	def row_separator_func (self, model, iter):
		return model.get_value (iter, 0) == None


# Details view allowing to define MIME types
class DetailsView (gtk.TreeView):
	def __init__(self, category):
		gtk.TreeView.__init__(self)

		self.category = category;

		liststore = gtk.ListStore(gobject.TYPE_STRING, # MIME Type
					  gobject.TYPE_STRING, # MIME Type (user-readable)
					  gtk.ListStore, # Application Model
					  gobject.TYPE_STRING, # Active Application (as string)
					  gobject.TYPE_PYOBJECT) # Active application
		self.set_model (liststore)

		cell = gtk.CellRendererText()
		column = gtk.TreeViewColumn ('File Type', cell, text=1)
		self.append_column (column);

		cell = gtk.CellRendererCombo ()
		cell.set_property ('text-column', 0)
		cell.set_property ('editable', True)
		cell.set_property ('has-entry', False)
		cell.set_property ('mode', gtk.CELL_RENDERER_MODE_EDITABLE)
		column = gtk.TreeViewColumn ('Application', cell, model=2, text=3)
		self.append_column (column);

		# add entries for all the MIME types
		for mime_type in self.category.mime_types:
			app = self.category.default_applications[mime_type]
			apps = self.category.applications[mime_type]
			desc = gnomevfs.mime_get_description (mime_type)
			liststore.append ([mime_type, gnomevfs.mime_get_description (mime_type) or mime_type, \
					   ApplicationChooserModel (apps), app and app[1] or None, app])


class ApplicationDialog (gtk.Dialog):
	def __init__ (self, categories):
		gtk.Dialog.__init__ (self)

		use_notebook = 0

		self.ensure_style ();
		self.set_border_width (7)
		self.action_area.set_border_width (0)
		self.vbox.set_spacing (14)
		self.set_has_separator (0)

		self.add_button (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)

		if use_notebook:
			notebook = gtk.Notebook()
			notebook.set_border_width (5)
			notebook.show()
			self.vbox.add (notebook);
		else:
			vbox = gtk.VBox ()
			vbox.set_border_width (5)
			vbox.set_spacing (18);
			vbox.show()
			self.vbox.add (vbox);

		self.categories = categories
		for category in self.categories:
			table = gtk.Table (2, 2, False)
			table.set_row_spacings (6)
			table.set_col_spacings (12)
			table.show ()

			if use_notebook:
				table.set_border_width (12)
				notebook.append_page (table, gtk.Label (category.name))
			else:
				table.set_border_width (0)

				page_table = gtk.Table (2, 2, False)
				page_table.set_row_spacings (6)
				vbox.add (page_table)
				page_table.show ()

				label = gtk.Label ()
				label.set_markup ('<b>' + category.name + '</b>')
				label.set_alignment (0.0, 0.5)
				page_table.attach (label, 0, 2, 0, 1, gtk.EXPAND|gtk.FILL, 0)
				label.show ()

				label = gtk.Label ()
				label.set_markup ('')
				label.set_size_request (12, -1)
				page_table.attach (label, 0, 1, 1, 2, 0, 0)
				label.show ()

				page_table.attach (table, 1, 2, 1, 2, gtk.EXPAND|gtk.FILL, 0)

			if category.default_applications.values():
				label = gtk.Label ('Default Application:')
				label.set_alignment (0.0, 0.5)
				table.attach (label, 0, 1, 0, 1, 0, 0)
				label.show ()

				chooser = ApplicationChooser (category.all_applications.values(),
							      category.default_application)
				table.attach (chooser, 1, 2, 0, 1, gtk.EXPAND|gtk.FILL, 0)
				chooser.show ()

				expander = gtk.Expander ('Details')
				table.attach (expander, 0, 2, 1, 2, gtk.EXPAND|gtk.FILL, gtk.EXPAND|gtk.FILL)
				if len (category.applications.keys()) > 1:
					expander.show ()
				else:
					expander.hide ()

				exception_view = DetailsView (category);
				expander.add (exception_view);
				exception_view.show ();
			else:
				print ('nothing handled for cat ' + category.name)



audio_category = MimeCategory ('Audio', [ 'audio/x-wav', 'audio/x-vorbis+ogg', 'audio/x-flac+ogg', 'audio/x-speex+ogg', 'audio/mpeg' ], 'totem.desktop' )
text_editor_category = MimeCategory ('Text Editor', [ 'text/plain' ], 'gedit.desktop' )
word_processing_category = MimeCategory ('Word Processing', [ 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.text-template','application/vnd.oasis.opendocument.text-master', 'application/vnd.sun.xml.writer', 'application/vnd.sun.xml.writer.template', 'application/vnd.sun.xml.writer.global', 'application/vnd.stardivision.writer', 'application/msword', 'application/rtf' ], 'abiword.desktop' )
spreadsheet_category = MimeCategory ('Spreadsheet', [ 'application/vnd.ms-excel', 'application/x-gnumeric' ], 'gnumeric.desktop')

dialog = ApplicationDialog ([audio_category, text_editor_category, word_processing_category, spreadsheet_category])
dialog.present()
dialog.run()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]