Commits

Erik Grinaker committed f80290f

improved the searchbar, and use it instead of find dialog

Comments (0)

Files changed (8)

 
 	* added Shannon entropy test to password checker
 
+	* improved the searchbar, and use it instead of find dialog
+
 2006-01-20  Erik Grinaker <erikg@codepoet.no>
 
 	* strip xml entities from password on clipboard copy or
 ============================
 
 New features:
+- improved the searchbar, and use it instead of find dialog
 - new applet option to show/hide search entry
 - use icons instead of colors in password entries to indicate strength
 - added Shannon entropy test and other improvements to password checker
 - add import/export from browser (firefox, mozilla, epiphany, galeon)
 - sorting of the tree
 - make result label in password checker wrap when text overflows
-- next / prev buttons in searchbar
-- replace find dialog with searchbar?
 
 0.5.x:
 - ensure complete UTF-8 support

data/gconf/revelation.schemas

 		</schema>
 
 		<schema>
-			<key>/schemas/apps/revelation/search/folders</key>
-			<applyto>/apps/revelation/search/folders</applyto>
-			<owner>revelation</owner>
-			<type>bool</type>
-			<default>true</default>
-
-			<locale name="C">
-				<short>Search for folders</short>
-				<long>
-					When enabled, the entry searcher will search
-					for folders as well as normal accounts.
-				</long>
-			</locale>
-		</schema>
-
-		<schema>
-			<key>/schemas/apps/revelation/search/namedesc</key>
-			<applyto>/apps/revelation/search/namedesc</applyto>
-			<owner>revelation</owner>
-			<type>bool</type>
-			<default>false</default>
-
-			<locale name="C">
-				<short>Search in name and description only</short>
-				<long>
-					When enabled, the entry searcher will only
-					search in the name and description of
-					entries.
-				</long>
-			</locale>
-		</schema>
-
-		<schema>
-			<key>/schemas/apps/revelation/search/casesens</key>
-			<applyto>/apps/revelation/search/casesens</applyto>
-			<owner>revelation</owner>
-			<type>bool</type>
-			<default>false</default>
-
-			<locale name="C">
-				<short>Case-sensitive search</short>
-				<long>
-					When enabled, searches will be case-sensitive.
-				</long>
-			</locale>
-		</schema>
-
-		<schema>
 			<key>/schemas/apps/revelation/view/pane-position</key>
 			<applyto>/apps/revelation/view/pane-position</applyto>
 			<owner>revelation</owner>

data/ui/actions.xml

 		<action>
 			<name>find-next</name>
 			<label>Find Ne_xt</label>
+			<stock>revelation-next</stock>
 			<accel>&lt;Control&gt;G</accel>
 			<description>Find the next search match</description>
 		</action>
 		<action>
 			<name>find-previous</name>
 			<label>Find Pre_vious</label>
+			<stock>revelation-previous</stock>
 			<accel>&lt;Shift&gt;&lt;Control&gt;G</accel>
 			<description>Find the previous search match</description>
 		</action>

src/lib/dialog.py

 
 
 
-RESPONSE_NEXT		= 10
-RESPONSE_PREVIOUS	= 11
-
 EVENT_FILTER		= None
 UNIQUE_DIALOGS		= {}
 
 
 
 
-class Find(Utility):
-	"A find dialog"
-
-	def __init__(self, parent, cfg):
-		Utility.__init__(
-			self, parent, "Find an entry",
-			( ( gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE ), ( ui.STOCK_PREVIOUS, RESPONSE_PREVIOUS ), ( ui.STOCK_NEXT, RESPONSE_NEXT ) )
-		)
-
-		self.config = cfg
-		self.set_modal(False)
-
-		section = self.add_section("Find an entry")
-
-		# search string entry
-		self.entry_string = ui.Entry()
-		self.entry_string.connect("changed", lambda w: self.__state_buttons(self.entry_string.get_text() != ""))
-
-		section.append_widget("Search for", self.entry_string)
-		self.tooltips.set_tip(self.entry_string, "The text to search for")
-
-		# account type dropdown
-		self.dropdown = ui.EntryDropDown()
-		self.dropdown.insert_item(0, "Any", "gnome-stock-about")
-
-		eventbox = ui.EventBox(self.dropdown)
-		section.append_widget("Account type", eventbox)
-		self.tooltips.set_tip(eventbox, "The account type to search for")
-
-		# folders checkbutton
-		self.check_folders = ui.CheckButton("Search for folders as well")
-		ui.config_bind(self.config, "search/folders", self.check_folders)
-
-		section.append_widget(None, self.check_folders)
-		self.tooltips.set_tip(self.check_folders, "When enabled, folder names and descriptions will also be searched")
-
-		# namedesc checkbutton
-		self.check_namedesc = ui.CheckButton("Only search in name and description")
-		ui.config_bind(self.config, "search/namedesc", self.check_namedesc)
-
-		section.append_widget(None, self.check_namedesc)
-		self.tooltips.set_tip(self.check_namedesc, "When enabled, only entry names and descriptions will be searched")
-
-		# case sensitive checkbutton
-		self.check_casesensitive = ui.CheckButton("Case sensitive")
-		ui.config_bind(self.config, "search/casesens", self.check_casesensitive)
-
-		section.append_widget(None, self.check_casesensitive)
-		self.tooltips.set_tip(self.check_casesensitive, "When enabled, searches will be case sensitive")
-
-		# set initial state
-		self.__state_buttons(False)
-
-
-	def __state_buttons(self, active):
-		"Sets button sensitivity based on entry contents"
-
-		self.get_button(0).set_sensitive(active)
-		self.get_button(1).set_sensitive(active)
-
-
-	def run(self):
-		"Displays the dialog"
-
-		self.show_all()
-		self.entry_string.grab_focus()
-
-		if EVENT_FILTER != None:
-			self.window.add_filter(EVENT_FILTER)
-
-
-
 class PasswordChecker(Utility):
 	"A password checker dialog"
 
 	def __init__(self):
 		gtk.Toolbar.__init__(self)
 
-
-	def append_widget(self, widget):
+		self.tooltips	= gtk.Tooltips()
+
+
+	def append_space(self):
+		"Appends a space to the toolbar"
+
+		space = gtk.SeparatorToolItem()
+		space.set_draw(False)
+
+		self.insert(space, -1)
+
+
+	def append_widget(self, widget, tooltip = None):
 		"Appends a widget to the toolbar"
 
 		toolitem = gtk.ToolItem()
 		toolitem.add(widget)
 
+		if tooltip != None:
+			toolitem.set_tooltip(self.tooltips, tooltip)
+
 		self.insert(toolitem, -1)
 
 
 			( STOCK_LOCK,		"_Lock",	"stock_lock" ),
 			( STOCK_NEW_ENTRY,	"_Add Entry",	gtk.STOCK_ADD ),
 			( STOCK_NEW_FOLDER,	"_Add Folder",	"stock_folder" ),
-			( STOCK_NEXT,		"Ne_xt",	gtk.STOCK_GO_FORWARD ),
+			( STOCK_NEXT,		"Next",		gtk.STOCK_GO_DOWN ),
 			( STOCK_OVERWRITE,	"_Overwrite",	gtk.STOCK_SAVE_AS ),
 			( STOCK_PASSWORD_CHANGE,"_Change",	"stock_lock-ok" ),
 			( STOCK_PASSWORD_CHECK,	"_Check",	"stock_lock-ok" ),
 			( STOCK_PASSWORD_STRONG,"",		"stock_lock-ok" ),
 			( STOCK_PASSWORD_WEAK,	"",		"stock_lock-broken" ),
-			( STOCK_PREVIOUS,	"Pre_vious",	gtk.STOCK_GO_BACK ),
+			( STOCK_PREVIOUS,	"Previous",	gtk.STOCK_GO_UP ),
 			( STOCK_RELOAD,		"_Reload",	gtk.STOCK_REFRESH ),
 			( STOCK_REMOVE,		"Re_move",	gtk.STOCK_DELETE ),
 			( STOCK_UNKNOWN,	"Unknown",	gtk.STOCK_DIALOG_QUESTION ),
 	def __init__(self):
 		Toolbar.__init__(self)
 
-		self.label	= Label("  Search for: ")
-		self.entry	= Entry()
-		self.button	= Button(" Find ")
+		self.label		= Label("  Find: ")
+		self.entry		= Entry()
+		self.dropdown		= EntryDropDown()
+		self.dropdown.insert_item(0, "Any type", "gnome-stock-about")
+		self.button_next	= Button(STOCK_NEXT)
+		self.button_prev	= Button(STOCK_PREVIOUS)
 
 		self.append_widget(self.label)
-		self.append_widget(self.entry)
-		self.append_widget(self.button)
-
-		self.entry.connect("changed", lambda w: self.button.set_sensitive(self.entry.get_text() != ""))
+		self.append_widget(self.entry, "Text to search for")
+		self.append_widget(EventBox(self.dropdown), "The type of account to search for")
+		self.append_space()
+		self.append_widget(self.button_next, "Find the next match")
+		self.append_widget(self.button_prev, "Find the previous match")
+
+		self.connect("show", self.__cb_show)
+
+		self.entry.connect("changed", self.__cb_entry_changed)
 		self.entry.connect("key-press-event", self.__cb_key_press)
 
-		self.button.set_sensitive(False)
+		self.button_next.set_sensitive(False)
+		self.button_prev.set_sensitive(False)
+
+
+	def __cb_entry_changed(self, widget, data = None):
+		"Callback for entry changes"
+
+		s = self.entry.get_text() != ""
+
+		self.button_next.set_sensitive(s)
+		self.button_prev.set_sensitive(s)
 
 
 	def __cb_key_press(self, widget, data = None):
 
 		# return
 		if data.keyval == 65293 and widget.get_text() != "":
-			self.button.activate()
+			if data.state & gtk.gdk.SHIFT_MASK == gtk.gdk.SHIFT_MASK:
+				self.button_prev.activate()
+
+			else:
+				self.button_next.activate()
+
 			return True
 
+
+	def __cb_show(self, widget, data = None):
+		"Callback for widget display"
+
+		self.entry.select_region(0, -1)
+		self.entry.grab_focus()
+

src/revelation.in

 			if self.__check_config() == False:
 				raise config.ConfigError
 
-
-		self.config.monitor("search/folders",		lambda k,v,d: setattr(self.entrysearch, "folders", v))
-		self.config.monitor("search/namedesc",		lambda k,v,d: setattr(self.entrysearch, "namedesconly", v))
-		self.config.monitor("search/casesens",		lambda k,v,d: setattr(self.entrysearch, "casesensitive", v))
 		self.config.monitor("file/autolock_timeout",	lambda k,v,d: self.locktimer.start(v * 60))
 
 		dialog.EVENT_FILTER = self.__cb_event_filter
 		self.__state_clipboard(self.entryclipboard.has_contents())
 		self.__state_entry([])
 		self.__state_file(None)
-		self.__state_find(self.entrysearch.string)
+		self.__state_find(self.searchbar.entry.get_text())
 		self.__state_undo(None, None)
 
 		# set states from config
 			"file-save"		: lambda w: self.file_save(self.datafile.get_file(), self.datafile.get_password()),
 			"file-save-as"		: lambda w: self.file_save(None, None),
 			"find"			: lambda w: self.entry_find(),
-			"find-next"		: lambda w: self.__entry_find(self, self.entrysearch.string, self.entrysearch.type, data.SEARCH_NEXT),
-			"find-previous"		: lambda w: self.__entry_find(self, self.entrysearch.string, self.entrysearch.type, data.SEARCH_PREVIOUS),
+			"find-next"		: lambda w: self.__entry_find(self, self.searchbar.entry.get_text(), self.searchbar.dropdown.get_active_type(), data.SEARCH_NEXT),
+			"find-previous"		: lambda w: self.__entry_find(self, self.searchbar.entry.get_text(), self.searchbar.dropdown.get_active_type(), data.SEARCH_PREVIOUS),
 			"help-about"		: lambda w: self.about(),
 			"help-homepage"		: lambda w: gnome.url_show(config.URL),
 			"prefs"			: lambda w: self.prefs(),
 		self.tree.connect("drag_data_received", self.__cb_tree_drag_received)
 
 		# set up callbacks
-		self.searchbar.button.connect("clicked", self.__cb_searchbar_button_clicked)
+		self.searchbar.connect("key-press-event", self.__cb_searchbar_key_press)
+		self.searchbar.button_next.connect("clicked", self.__cb_searchbar_button_clicked, data.SEARCH_NEXT)
+		self.searchbar.button_prev.connect("clicked", self.__cb_searchbar_button_clicked, data.SEARCH_PREVIOUS)
+		self.searchbar.entry.connect("changed", lambda w: self.__state_find(self.searchbar.entry.get_text()))
 
 		self.tree.connect("popup", lambda w,d: self.popup(self.uimanager.get_widget("/popup-tree"), d.button, d.time))
 		self.tree.connect("doubleclick", self.__cb_tree_doubleclick)
 			return False
 
 
-	def __cb_searchbar_button_clicked(self, widget):
+	def __cb_searchbar_button_clicked(self, widget, direction = data.SEARCH_NEXT):
 		"Callback for searchbar button clicks"
 
-		self.__entry_find(self, self.searchbar.entry.get_text(), None)
+		self.__entry_find(self, self.searchbar.entry.get_text(), self.searchbar.dropdown.get_active_type(), direction)
 		self.searchbar.entry.select_region(0, -1)
 
 
+	def __cb_searchbar_key_press(self, widget, data):
+		"Callback for searchbar key presses"
+
+		# escape
+		if data.keyval == 65307:
+			self.config.set("view/searchbar", False)
+
+
 	def __cb_session_save(self, widget, phase, what, end, interaction, fast, data = None):
 		"Handles session saves"
 
 
 		match = self.entrysearch.find(string, entrytype, self.tree.get_active(), direction)
 
-		self.entrysearch.string	= string
-		self.entrysearch.type	= entrytype
-
-		self.__state_find(string)
-
-		if match is not None:
+		if match != None:
 			self.tree.select(match)
+			self.statusbar.set_status("Match found for '%s'" % string)
 
 		else:
-			dialog.Error(parent, "No match found", "The string you searched for did not match any entries. Try searching for a different phrase.").run()
+			self.statusbar.set_status("No match found for '%s'" % string)
+			dialog.Error(parent, "No match found", "The string '%s' does not match any entries. Try searching for a different phrase." % string).run()
 
 
 	def __file_autosave(self):
 	def entry_find(self):
 		"Searches for an entry"
 
-		if dialog.present_unique(dialog.Find) == True:
-			return
-
-
-		def cb_response(widget, response):
-			string = widget.entry_string.get_text()
-			entrytype = widget.dropdown.get_active_type()
-
-			if response == dialog.RESPONSE_NEXT:
-				self.__entry_find(widget, string, entrytype, data.SEARCH_NEXT)
-				widget.entry_string.grab_focus()
-
-			elif response == dialog.RESPONSE_PREVIOUS:
-				self.__entry_find(widget, string, entrytype, data.SEARCH_PREVIOUS)
-				widget.entry_string.grab_focus()
-
-			else:
-				widget.destroy()
-
-
-		d = dialog.create_unique(dialog.Find, self, self.config)
-		d.entry_string.set_text(self.entrysearch.string)
-		d.dropdown.set_active_type(self.entrysearch.type)
-		d.connect("response", cb_response)
-		d.run()
+		self.config.set("view/searchbar", True)
+		self.searchbar.entry.select_region(0, -1)
+		self.searchbar.entry.grab_focus()
 
 
 	def entry_folder(self, e = None, parent = None, sibling = None):