Commits

Erik Grinaker committed f54fce8

cleaned up dialog code

Comments (0)

Files changed (3)

 	the schema is automatically registered with the gconf
 	daemon
 
+	* cleaned up most of the dialog code
+
 2004-07-15  Erik Grinaker <erikg@codepoet.no>
 
 	* when adding an entry the default type is Generic (not Folder)
 	"Base class for dialogs"
 
 	def __init__(self, parent, title, buttons, default = None):
-		gtk.Dialog.__init__(self, title, parent, gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL | gtk.DIALOG_NO_SEPARATOR)
+		gtk.Dialog.__init__(
+			self, title, parent,
+			gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL | gtk.DIALOG_NO_SEPARATOR
+		)
 
 		self.set_border_width(6)
 		self.vbox.set_spacing(12)
 
 		if default is not None:
 			self.set_default_response(default)
+
 		else:
 			self.set_default_response(buttons[-1][1])
 
 
 		section = revelation.widget.InputSection(title, self.sizegroup, description)
 		self.vbox.pack_start(section)
+
 		return section
 
 
 
 
 # simple message dialogs
+
 class Error(Hig):
 	"Displays an error message"
 
 
 
 
+class FileChanged(Hig):
+	"Asks the user if she wants to save her changes"
+
+	def __init__(self, parent, pritext, sectext):
+		Hig.__init__(
+			self, parent, pritext, sectext, gtk.STOCK_DIALOG_WARNING,
+			[ [ revelation.stock.STOCK_DISCARD, gtk.RESPONSE_CANCEL ], [ gtk.STOCK_CANCEL, gtk.RESPONSE_CLOSE ], [ gtk.STOCK_SAVE, gtk.RESPONSE_OK ] ]
+		)
+
+
+	def run(self):
+		"Displays the dialog"
+
+		response = Hig.run(self)
+
+		if response == gtk.RESPONSE_OK:
+			return gtk.TRUE
+
+		elif response == gtk.RESPONSE_CANCEL:
+			return gtk.FALSE
+
+		else:
+			raise revelation.CancelError
+
+
+
+class FileChangedNew(FileChanged):
+	"Asks the user to save changes when creating a new file"
+
+	def __init__(self, parent):
+		FileChanged.__init__(
+			self, parent, "Save changes to current file?",
+			"You have made changes which have not been saved. If you create a new file without saving then these changes will be lost."
+		)
+
+
+class FileChangedOpen(FileChanged):
+	"Asks the user to save changes when opening a different file"
+
+	def __init__(self, parent):
+		FileChanged.__init__(
+			self, parent, "Save changes before opening?",
+			"You have made changes which have not been saved. If you open a different file without saving then these changes will be lost."
+		)
+
+
+
+class FileChangedQuit(FileChanged):
+	"Asks the user to save changes when quitting"
+
+	def __init__(self, parent):
+		FileChanged.__init__(
+			self, parent, "Save changes before quitting?",
+			"You have made changes which have not been saved. If you quit without saving, then these changes will be lost."
+		)
+
+
+
+class FileChangedRevert(Hig):
+	"Alerts the user about unsaved changes when reverting"
+
+	def __init__(self, parent):
+		Hig.__init__(
+			self, parent, "Ignore unsaved changes?",
+			"You have made changes which have not yet been saved. If you revert to the saved file then these changes will be lost.",
+			gtk.STOCK_DIALOG_WARNING, [ [ gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL ], [ gtk.STOCK_REVERT_TO_SAVED, gtk.RESPONSE_OK ] ], 0
+		)
+
+
+	def run(self):
+		"Displays the dialog, emulates the return codes of the FileChanged dialog"
+
+		response = Hig.run(self)
+
+		if response == gtk.RESPONSE_OK:
+			return gtk.FALSE
+
+		else:
+			raise revelation.CancelError
+
+
+
 class FileExportInsecure(Hig):
 	"Dialog which warns about exporting to insecure data format"
 
 
 
 
-class RemoveEntry(Hig):
-	"Asks for confirmation when removing entries"
-
-	def __init__(self, parent, pritext, sectext):
-		Hig.__init__(
-			self, parent, pritext, sectext, gtk.STOCK_DIALOG_WARNING,
-			[ [ gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL ], [ revelation.stock.STOCK_REMOVE, gtk.RESPONSE_OK ] ],
-			gtk.RESPONSE_CANCEL
-		)
-
-
-	def run(self):
-		"Displays the dialog"
-
-		return Hig.run(self) == gtk.RESPONSE_OK
-
-
-
-class SaveChanges(Hig):
-	"Asks the user if she wants to save her changes"
-
-	def __init__(self, parent, pritext, sectext):
-		Hig.__init__(
-			self, parent, pritext, sectext, gtk.STOCK_DIALOG_WARNING,
-			[ [ revelation.stock.STOCK_DISCARD, gtk.RESPONSE_CLOSE ], [ gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL ], [ gtk.STOCK_SAVE, gtk.RESPONSE_OK ] ]
-		)
-
-
-	def run(self):
-		"Displays the dialog"
-
-		response = Hig.run(self)
-
-		if response == gtk.RESPONSE_CANCEL:
-			raise revelation.CancelError
-		else:
-			return response == gtk.RESPONSE_OK
-
-
-
 # file selectors
 class FileSelector(gtk.FileSelection):
 	"A normal file selector"
 			raise revelation.CancelError
 	
 
+# entry-related dialogs
+
+class EntryEdit(Property):
+	"A dialog for editing entries"
+
+	def __init__(self, parent, title, entry = None):
+		Property.__init__(
+			self, parent, title,
+			[ [ gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL ], [ gtk.STOCK_OK, gtk.RESPONSE_OK ] ]
+		)
+
+		if entry is not None:
+			self.entry = entry.copy()
+
+		else:
+			self.entry = revelation.entry.Entry(revelation.entry.ENTRY_ACCOUNT_GENERIC)
+
+		self.sect_meta = self.add_section(title)
+		self.sect_fields = None
+		self.entry_field = {}
+
+		# entry name input
+		self.entry_name = revelation.widget.Entry(self.entry.name)
+		self.entry_name.set_width_chars(50)
+		self.tooltips.set_tip(self.entry_name, "The name of the entry")
+		self.sect_meta.add_inputrow("Name", self.entry_name)
+
+		# entry description input
+		self.entry_desc = revelation.widget.Entry(self.entry.description)
+		self.tooltips.set_tip(self.entry_desc, "A description of the entry")
+		self.sect_meta.add_inputrow("Description", self.entry_desc)
+
+		# entry type dropdown
+		self.dropdown = revelation.widget.EntryDropdown()
+		self.tooltips.set_tip(self.dropdown, "The type of entry - folders can contain other entries")
+		self.sect_meta.add_inputrow("Type", self.dropdown)
+
+		self.dropdown.connect("changed", self.__cb_dropdown_changed)
+		self.dropdown.set_type(self.entry.type)
+
+
+	def __cb_dropdown_changed(self, object):
+		"Updates the entry type"
+
+		type = self.dropdown.get_active_item().type
+
+		if type == self.entry.type and self.sect_fields is not None:
+			return
+
+		self.entry.set_type(type)
+		fields = self.entry.get_fields()
+		self.entry_field = {}
+
+		if self.sect_fields is not None:
+			self.sect_fields.destroy()
+			self.sect_fields = None
+
+		if len(fields) > 0:
+			self.sect_fields = self.add_section("Account data")
+			self.sect_fields.type = type
+
+		for field in fields:
+			self.__add_field(self.sect_fields, field)
+
+		self.show_all()
+
+
+	def __add_field(self, section, field):
+		"Adds an input for a field to a section"
+
+		if field.type == revelation.entry.FIELD_TYPE_PASSWORD:
+			entry = revelation.widget.PasswordEntry()
+
+		else:
+			entry = revelation.widget.Entry()
+
+
+		entry.set_text(field.value)
+		self.tooltips.set_tip(entry, field.description)
+		self.entry_field[field.id] = entry
+
+
+		if field.id == revelation.entry.FIELD_GENERIC_PASSWORD:
+			hbox = revelation.widget.HBox()
+			hbox.pack_start(entry)
+
+			button = revelation.widget.Button("Generate", lambda w: entry.set_text(revelation.misc.generate_password()))
+			hbox.pack_start(button, gtk.FALSE, gtk.FALSE)
+
+			section.add_inputrow(field.name, hbox)
+
+		else:
+			section.add_inputrow(field.name, entry)
+
+
+	def run(self):
+		"Displays the dialog"
+
+		self.show_all()
+
+		if Property.run(self) == gtk.RESPONSE_OK:
+
+			if self.entry_name.get_text() == "":
+				Error(self, "No name given", "You need to enter a name for the entry.").run()
+				return self.run()
+
+			self.entry.name = self.entry_name.get_text()
+			self.entry.desc = self.entry_desc.get_text()
+			self.entry.updated = int(time.time())
+
+			for id, entry in self.entry_field.items():
+				self.entry.set_field(id, entry.get_text())
+
+			self.destroy()
+			return self.entry
+
+		else:
+			self.destroy()
+			raise revelation.CancelError
+
+
+	def set_typechange_allowed(self, allow):
+		"Sets whether to allow type changes"
+
+		self.dropdown.set_sensitive(allow)
+
+
+
+class EntryRemove(Hig):
+	"Asks for confirmation when removing entries"
+
+	def __init__(self, parent, entries):
+
+		if len(entries) > 1:
+			pritext = "Really remove the " + str(len(entries)) + " selected entries?"
+			sectext = "By removing these entries you will also remove any entries they may contain."
+
+		elif entries[0].type == revelation.entry.ENTRY_FOLDER:
+			pritext = "Really remove folder '" + entries[0].name + "'?"
+			sectext = "By removing this folder you will also remove all accounts and folders it contains."
+
+		else:
+			pritext = "Really remove account '" + entries[0].name + "'?"
+			sectext = "Please confirm that you wish to remove this account."
+
+
+		Hig.__init__(
+			self, parent, pritext, sectext, gtk.STOCK_DIALOG_WARNING,
+			[ [ gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL ], [ revelation.stock.STOCK_REMOVE, gtk.RESPONSE_OK ] ],
+			gtk.RESPONSE_CANCEL
+		)
+
+
+	def run(self):
+		"Displays the dialog"
+
+		return Hig.run(self) == gtk.RESPONSE_OK
+
+
 
 # more complex dialogs
 class About(gnome.ui.About):
 
 
 
-class EditEntry(Property):
-	"A dialog for editing entries"
-
-	def __init__(self, parent, title, entry = None):
-		Property.__init__(
-			self, parent, title,
-			[ [ gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL ], [ gtk.STOCK_OK, gtk.RESPONSE_OK ] ]
-		)
-
-		if entry is not None:
-			self.entry = entry.copy()
-		else:
-			self.entry = revelation.entry.Entry(revelation.entry.ENTRY_ACCOUNT_GENERIC)
-
-		section = self.add_section(title)
-
-		entry = revelation.widget.Entry(self.entry.name)
-		entry.set_width_chars(50)
-		entry.connect("changed", self.__cb_entry_name_changed)
-		self.tooltips.set_tip(entry, "The name of the entry")
-		section.add_inputrow("Name", entry)
-
-		entry = revelation.widget.Entry(self.entry.description)
-		self.tooltips.set_tip(entry, "A description of the entry")
-		entry.connect("changed", self.__cb_entry_description_changed)
-		section.add_inputrow("Description", entry)
-
-		self.dropdown = revelation.widget.EntryDropdown()
-		self.tooltips.set_tip(self.dropdown, "The type of entry - folders can contain other entries")
-		section.add_inputrow("Type", self.dropdown)
-
-		self.dropdown.set_type(self.entry.type)
-		self.dropdown.connect("changed", self.__cb_dropdown_changed)
-
-		self.update()
-
-
-	def __cb_entry_description_changed(self, widget, data = None):
-		"Updates the description data"
-
-		self.entry.description = widget.get_text()
-
-
-	def __cb_entry_name_changed(self, widget, data = None):
-		"Updates the name data"
-
-		self.entry.name = widget.get_text()
-
-
-	def __cb_entry_field_changed(self, widget, id):
-		"Updates field data"
-
-		self.entry.set_field(id, widget.get_text())
-
-
-	def __cb_dropdown_changed(self, object):
-		"Updates the entry type data"
-
-		type = self.dropdown.get_active_item().type
-
-		if type != self.entry.type:
-			self.entry.set_type(type)
-			self.update()
-
-
-	def run(self):
-		"Displays the dialog"
-
-		if Property.run(self) == gtk.RESPONSE_OK:
-
-			if self.entry.name == "":
-				Error(self, "No name given", "You need to enter a name for the entry.").run()
-				return self.run()
-
-			self.entry.updated = int(time.time())
-
-			self.destroy()
-			return self.entry
-
-		else:
-			self.destroy()
-			raise revelation.CancelError
-
-
-	def set_typechange_allowed(self, allow):
-		"Sets whether to allow type changes"
-
-		self.dropdown.set_sensitive(allow)
-
-
-	def update(self, type = None):
-		"Updates the dialog to a given type"
-
-		if len(self.vbox.get_children()) > 2:
-			self.vbox.get_children().pop(1).destroy()
-
-		fields = self.entry.get_fields()
-
-		if len(fields) > 0:
-			section = self.add_section("Account data")
-
-		for field in fields:
-
-			if field.type == revelation.entry.FIELD_TYPE_PASSWORD:
-				entry = revelation.widget.PasswordEntry()
-
-			else:
-				entry = revelation.widget.Entry()
-
-			entry.set_text(field.value)
-			entry.connect("changed", self.__cb_entry_field_changed, field.id)
-			self.tooltips.set_tip(entry, field.description)
-
-			if field.id == revelation.entry.FIELD_GENERIC_PASSWORD:
-				hbox = revelation.widget.HBox()
-				section.add_inputrow(field.name, hbox)
-
-				hbox.pack_start(entry)
-
-				button = revelation.widget.Button("Generate", lambda w: entry.set_text(revelation.misc.generate_password()))
-				hbox.pack_start(button, gtk.FALSE, gtk.FALSE)
-
-
-			else:
-				section.add_inputrow(field.name, entry)
-
-		self.show_all()
-
-
-
 class Find(Property):
 	"A dialog for searching for entries"
 
 		"Displays the dialog"
 
 		self.show_all()
+
 		return Property.run(self)
 
 
 		"Sets up various application facilities"
 
 		try:
-			self.config	= revelation.data.Config()
+			self.config = revelation.data.Config()
 
 		except revelation.data.ConfigError:
 			revelation.dialog.Error(
 		"Adds an entry"
 
 		try:
-			entry = revelation.dialog.EditEntry(self, "Add entry").run()
+			entry = revelation.dialog.EntryEdit(self, "Add entry").run()
 			iter = self.data.add_entry(self.tree.get_active(), entry)
 
 			self.undoqueue.add_action(revelation.data.UNDO_ACTION_ADD, iter)
 
 		try:
 			entry = self.data.get_entry(iter)
-			dialog = revelation.dialog.EditEntry(self, "Edit entry", entry)
+			dialog = revelation.dialog.EntryEdit(self, "Edit entry", entry)
 
 			if entry.type == revelation.entry.ENTRY_FOLDER and self.data.iter_n_children(iter) > 0:
 				dialog.set_typechange_allowed(gtk.FALSE)
 		if len(iters) == 0:
 			return
 
-		elif len(iters) == 1:
-			entry = self.data.get_entry(iters[0])
 
-			if entry.type == revelation.entry.ENTRY_FOLDER:
-				pritext = "Really remove folder '" + entry.name + "'?"
-				sectext = "By removing this folder you will also remove all accounts and folders it contains."
+		entries = []
+
+		for iter in iters:
+			entries.append(self.data.get_entry(iter))
+
+
+		if revelation.dialog.EntryRemove(self, entries).run() == gtk.TRUE:
+
+			if len(iters) == 1:
+				statustext = "Removed entry '" + entries[0].name + "'"
 
 			else:
-				pritext = "Really remove account '" + entry.name + "'?"
-				sectext = "Please confirm that you wish to remove this account."
+				statustext = "Removed " + str(len(entries)) + " entries"
 
-			statustext = "Removed entry '" + entry.name + "'"
 
-		else:
-			pritext = "Really remove the " + str(len(iters)) + " selected entries?"
-			sectext = "By removing these entries you will also remove any entries they may contain."
-			statustext = "Removed " + str(len(iters)) + " entries"
-
-
-		if revelation.dialog.RemoveEntry(self, pritext, sectext).run() == gtk.TRUE:
 			iters = self.data.filter_parents(iters)
 			self.undoqueue.add_action(revelation.data.UNDO_ACTION_REMOVE, iters)
 
 			self.statusbar.set_status("Remove entry cancelled")
 
 
+
 	def file_export(self):
 		"Exports data to a foreign file format"
 
 	def file_new(self):
 		"Opens a new file"
 
-		if not self.save_changes("Save changes to current file?", "You have made changes which have not been saved. If you create a new file without saving, then these changes will be discarded."):
+		if not self.save_changes(revelation.dialog.FileChangedNew):
 			self.statusbar.set_status("New file cancelled")
 			return
 
 		"Opens a data file"
 
 		try:
-			if not self.save_changes("Save changes before opening?", "You have made changes which have not been saved. If you open another file without saving, then these changes will be discarded."):
+			if not self.save_changes(revelation.dialog.FileChangedOpen):
 				return
 
 			if file is None:
 	def file_revert(self):
 		"Reverts to the saved version of the file"
 
-		if self.data.changed == gtk.TRUE and revelation.dialog.Hig(
-			self, "Ignore unsaved changes?", "You have made changes which have not yet been saved. If you revert to the saved file then these changes will be lost.",
-			gtk.STOCK_DIALOG_WARNING, [ [ gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL ], [ gtk.STOCK_REVERT_TO_SAVED, gtk.RESPONSE_OK ] ], 0
-		).run() != gtk.RESPONSE_OK:
+		if not self.save_changes(revelation.dialog.FileChangedRevert):
+			self.statusbar.set_status("Revert cancelled")
 			return gtk.FALSE
 
-		self.file_open(self.file, self.filepassword, gtk.TRUE)
+		self.data.changed = gtk.FALSE
+		self.file_open(self.file, self.filepassword)
 
 
 	def file_save(self, file = None, password = None):
 
 
 
-	def save_changes(self, pritext, sectext):
+	def save_changes(self, dialog):
 		"Asks the user if she wants to save her changes"
 
-		if self.data.changed == gtk.FALSE:
+		if not self.data.changed:
 			return gtk.TRUE
 
+
 		try:
-			if revelation.dialog.SaveChanges(self, pritext, sectext).run() == gtk.TRUE and self.file_save(self.file, self.password) == gtk.FALSE:
-				return gtk.FALSE
+			
+			if dialog(self).run() == gtk.TRUE:
+				if self.file_save(self.file, self.password) == gtk.FALSE:
+					return gtk.FALSE
 
 		except revelation.CancelError:
 			return gtk.FALSE
 	def quit(self):
 		"Quits the application"
 
-		if not self.save_changes("Save changes before quitting?", "You have made changes which have not been saved. If you quit without saving, then these changes will be discarded."):
+		if not self.save_changes(revelation.dialog.FileChangedQuit):
 			self.statusbar.set_status("Quit cancelled")
 			return gtk.FALSE