# HG changeset patch # User Erik Grinaker # Date 1089321092 0 # Node ID 4787d15f40a47ecd4912e428c6d04ddd0dcb28e6 # Parent 1558109939775523da9cdb7fbb44960cf583cec7 cleaned up the EntryStore code diff -r 1558109939775523da9cdb7fbb44960cf583cec7 -r 4787d15f40a47ecd4912e428c6d04ddd0dcb28e6 ChangeLog --- a/ChangeLog Thu Jul 08 11:54:12 2004 +0000 +++ b/ChangeLog Thu Jul 08 21:11:32 2004 +0000 @@ -7,6 +7,9 @@ * the OK button in the password dialogs is inactive when it's missing input + * cleaned up the EntryStore code, and merged the DataStore + and EntryStore classes + 2004-06-30 Erik Grinaker * file-selectors and the about dialog are set as transients diff -r 1558109939775523da9cdb7fbb44960cf583cec7 -r 4787d15f40a47ecd4912e428c6d04ddd0dcb28e6 TODO --- a/TODO Thu Jul 08 11:54:12 2004 +0000 +++ b/TODO Thu Jul 08 21:11:32 2004 +0000 @@ -1,9 +1,5 @@ 0.3.x: - password strength check (cracklib?) -- use a combo box for the username field -- use a fileentry widget for file fields (key file, certificate) -- use a spin button for integer fields (port) -- add a dropdown widget for list fields (like email protocol etc) - option for autolocking the file after a period of inactivity - don't use modal dialogs unless absolutely necessary - add a password generator dialog (under Tools/Password Generator menu) @@ -17,6 +13,7 @@ 0.4.x: - will introduce a gnome 2.6 dependency +- remove the import/export druids, use normal file selector instead - gnome integration (gnome-vfs, session management, recent docs etc) - add support for "copy username/password to clipboard", useful when hiding the passwords @@ -28,6 +25,11 @@ - use themed icons when possible - make the EntryDropdown display the icon on the button as well as in the menu +- use a combo box for the username field +- use a fileentry widget for file fields (key file, certificate) +- use a spin button for integer fields (port) +- add a dropdown widget for list fields (like email protocol etc) +- use the row= arg to the TreeStore functions to avoid column indexes 0.5.x: - remove support for version 0 data files diff -r 1558109939775523da9cdb7fbb44960cf583cec7 -r 4787d15f40a47ecd4912e428c6d04ddd0dcb28e6 src/lib/data.py --- a/src/lib/data.py Thu Jul 08 11:54:12 2004 +0000 +++ b/src/lib/data.py Thu Jul 08 21:11:32 2004 +0000 @@ -111,32 +111,57 @@ class EntryStore(revelation.widget.TreeStore): + "A basic class structure for handling a tree of entries" def __init__(self): revelation.widget.TreeStore.__init__(self, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_PYOBJECT) + self.changed = gtk.FALSE - def add_entry(self, parent, entry = None): - iter = self.append(parent) + def add_entry(self, parent, entry = None, sibling = None): + "Adds an entry" + + # place after "parent" if it's not a folder + if parent is not None and self.get_entry(parent).type != revelation.entry.ENTRY_FOLDER: + iter = self.insert_after(self.iter_parent(parent), parent) + + # place before sibling, if given + elif sibling is not None: + iter = self.insert_before(parent, sibling) + + # otherwise, append to parent + else: + iter = self.append(parent) + + self.update_entry(iter, entry) + self.changed = gtk.TRUE + return iter - def export_entrystore(self, iters = [], entrystore = None, parent = None): - if entrystore == None: - entrystore = EntryStore() + def clear(self): + "Removes all entries in the EntryStore" - for iter in iters: - child = entrystore.add_entry(parent, self.get_entry(iter)) + revelation.widget.TreeStore.clear(self) + self.changed = gtk.FALSE - for i in range(self.iter_n_children(iter)): - self.export_entrystore([self.iter_nth_child(iter, i)], entrystore, child) - return entrystore + def export_entry(self, iter, dest, destparent = None, destsibling = None): + "Exports an entry, and all its children, into a different EntryStore" + + destchild = dest.add_entry(destparent, self.get_entry(iter), destsibling) + + for i in range(self.iter_n_children(iter)): + self.export_entry(self.iter_nth_child(iter, i), dest, destchild) + + return destchild def get_entry(self, iter): - if iter == None: + "Fetches data for an entry" + + if iter is None: return None entry = revelation.entry.Entry() @@ -151,173 +176,102 @@ return entry - def get_entry_type(self, iter): - if iter is None: - return None - else: - return self.get_value(iter, ENTRYSTORE_COL_TYPE) + def import_entrystore(self, source, parent = None, sibling = None): + "Imports entries from a different entrystore" + newiters = [] - def import_entrystore(self, entrystore, parent = None, sibling = None, importiter = None): - baseiters = [] + # go through each base entry in the source, and export it + # from the source to self + for i in range(source.iter_n_children(None)): + sourceiter = source.iter_nth_child(None, i) + newiter = source.export_entry(sourceiter, self, parent, sibling) - for i in range(entrystore.iter_n_children(importiter)): - importchild = entrystore.iter_nth_child(importiter, i) + newiters.append(newiter) - if sibling == None: - childiter = self.add_entry(parent, entrystore.get_entry(importchild)) - else: - childiter = self.insert_entry_before(parent, sibling, entrystore.get_entry(importchild)) - - baseiters.append(childiter) - - if entrystore.iter_has_child(importchild): - self.import_entrystore(entrystore, childiter, None, importchild) - - return baseiters - - - def import_entrystore_after(self, entrystore, parent, sibling): - return self.import_entrystore(entrystore, parent, self.iter_next(sibling)) - - - def import_entrystore_before(self, entrystore, parent, sibling): - return self.import_entrystore(entrystore, parent, sibling) - - - def insert_entry_after(self, parent, sibling, entry = None): - iter = self.insert_after(parent, sibling) - self.update_entry(iter, entry) - return iter - - - def insert_entry_before(self, parent, sibling, entry = None): - iter = self.insert_before(parent, sibling) - self.update_entry(iter, entry) - return iter + return newiters def remove_entry(self, iter): - while self.iter_has_child(iter): - self.remove_entry(self.iter_nth_child(iter, 0)) + "Removes an entry, and its children if any" + + parent = self.iter_parent(iter) self.remove(iter) - - - def update_entry(self, iter, entry): - if entry is not None: - self.set_value(iter, ENTRYSTORE_COL_NAME, entry.name) - self.set_value(iter, ENTRYSTORE_COL_TYPE, entry.type) - self.set_value(iter, ENTRYSTORE_COL_DESC, entry.description) - self.set_value(iter, ENTRYSTORE_COL_UPDATED, entry.updated) - self.set_value(iter, ENTRYSTORE_COL_FIELDS, entry.fields) - self.set_value(iter, ENTRYSTORE_COL_ICON, entry.icon) - - - -class DataStore(EntryStore): - - def __init__(self): - EntryStore.__init__(self) - self.changed = gtk.FALSE - - - def add_entry(self, parent, entry = None): - - # place inside parent if folder - if self.get_entry_type(parent) in (revelation.entry.ENTRY_FOLDER, None): - iter = EntryStore.add_entry(self, parent, entry) - - # place after "parent" if not folder - else: - iter = EntryStore.insert_entry_after(self, self.iter_parent(parent), parent, entry) - self.changed = gtk.TRUE - return iter - - - def clear(self): - EntryStore.clear(self) - self.changed = gtk.FALSE - - - def get_entry(self, iter): - entry = EntryStore.get_entry(self, iter) - - # always return the normal, closed folder icon for folders. - # the open folder icon is only for tree-internal use. - if entry is not None and entry.icon == revelation.stock.STOCK_FOLDER_OPEN: - entry.icon = revelation.stock.STOCK_FOLDER - - return entry - - - def remove_entry(self, iter): - parent = self.iter_parent(iter) - EntryStore.remove_entry(self, iter) - # collapse parent if empty if self.iter_n_children(parent) == 0: self.set_folder_state(parent, gtk.FALSE) - self.changed = gtk.TRUE - def set_folder_state(self, iter, open): - if iter == None or self.get_entry_type(iter) != revelation.entry.ENTRY_FOLDER: + "Sets the state of a folder (collapsed or expanded)" + + if iter is None or self.get_entry(iter).type != revelation.entry.ENTRY_FOLDER: return - if open == gtk.TRUE: - icon = revelation.stock.STOCK_FOLDER_OPEN + if open: + self.set_value(iter, ENTRYSTORE_COL_ICON, revelation.stock.STOCK_FOLDER_OPEN) else: - icon = revelation.stock.STOCK_FOLDER - - self.set_value(iter, ENTRYSTORE_COL_ICON, icon) + self.set_value(iter, ENTRYSTORE_COL_ICON, revelation.stock.STOCK_FOLDER) def update_entry(self, iter, entry): - if entry is None: + "Updates data for an entry" + + if iter is None or entry is None: return - EntryStore.update_entry(self, iter, entry) + self.set_value(iter, ENTRYSTORE_COL_NAME, entry.name) + self.set_value(iter, ENTRYSTORE_COL_TYPE, entry.type) + self.set_value(iter, ENTRYSTORE_COL_DESC, entry.description) + self.set_value(iter, ENTRYSTORE_COL_UPDATED, entry.updated) + self.set_value(iter, ENTRYSTORE_COL_FIELDS, entry.fields) # keep icon if current is folder-open and the type still is folder - if entry.type == revelation.entry.ENTRY_FOLDER and self.get_value(iter, ENTRYSTORE_COL_ICON) == revelation.stock.STOCK_FOLDER_OPEN: - self.set_value(iter, ENTRYSTORE_COL_ICON, revelation.stock.STOCK_FOLDER_OPEN) + if entry.type != revelation.entry.ENTRY_FOLDER or self.get_value(iter, ENTRYSTORE_COL_ICON) != revelation.stock.STOCK_FOLDER_OPEN: + self.set_value(iter, ENTRYSTORE_COL_ICON, entry.icon) self.changed = gtk.TRUE class EntryClipboard(EntryStore): + "Copies/cuts/pastes entries to/from another entrystore" def __init__(self): EntryStore.__init__(self) - def copy(self, datastore, iters): + def copy(self, entrystore, iters): + "Copies a group of nodes from an entrystore" + if len(iters) > 0 and None not in iters: self.clear() - datastore.export_entrystore(iters, self) + + for iter in iters: + entrystore.export_entry(iter, self) + self.emit("copy") - def cut(self, datastore, iters): - self.copy(datastore, iters) + def cut(self, entrystore, iters): + "Cuts a group of nodes from an entrystore" + + self.copy(entrystore, iters) for iter in iters: - datastore.remove_entry(iter) + entrystore.remove_entry(iter) self.emit("cut") - def paste(self, datastore, parent, sibling = None): - if sibling == None: - iters = datastore.import_entrystore(self, parent) - else: - iters = datastore.import_entrystore_after(self, parent, sibling) + def paste(self, entrystore, parent, sibling = None): + "Pastes the clipboard contents into an entrystore" + iters = entrystore.import_entrystore(self, parent, sibling) self.emit("paste") + return iters diff -r 1558109939775523da9cdb7fbb44960cf583cec7 -r 4787d15f40a47ecd4912e428c6d04ddd0dcb28e6 src/lib/ui.py --- a/src/lib/ui.py Thu Jul 08 11:54:12 2004 +0000 +++ b/src/lib/ui.py Thu Jul 08 21:11:32 2004 +0000 @@ -73,7 +73,7 @@ def __init_facilities(self): self.icons = revelation.stock.IconFactory(self) - self.data = revelation.data.DataStore() + self.data = revelation.data.EntryStore() self.gconf = gconf.client_get_default() self.gconf.add_dir("/apps/revelation", gconf.CLIENT_PRELOAD_NONE) diff -r 1558109939775523da9cdb7fbb44960cf583cec7 -r 4787d15f40a47ecd4912e428c6d04ddd0dcb28e6 src/lib/widget.py --- a/src/lib/widget.py Thu Jul 08 11:54:12 2004 +0000 +++ b/src/lib/widget.py Thu Jul 08 21:11:32 2004 +0000 @@ -384,13 +384,21 @@ class TreeStore(gtk.TreeStore): + "An enhanced gtk.TreeStore" + + def __init__(self, *args): + gtk.TreeStore.__init__(self, *args) + def filter_parents(self, iters): + "Get only the topmost nodes of a group of iters (no descendants)" + parents = [] for child in iters: for parent in iters: if self.is_ancestor(parent, child): break + else: parents.append(child) @@ -398,35 +406,44 @@ def get_iter(self, path): + "Gets an iter from a path" + if path in [ None, "", () ]: return None - try: iter = gtk.TreeStore.get_iter(self, path) - except ValueError: iter = None + try: + iter = gtk.TreeStore.get_iter(self, path) + + except ValueError: + iter = None return iter def get_path(self, iter): + "Gets a path from an iter" + if iter is None: return None + else: return gtk.TreeStore.get_path(self, iter) def has_contents(self): + "Checks if the TreeStore contains any nodes" + return self.iter_n_children(None) > 0 - def is_empty(self): - return self.iter_n_children(None) == 0 + def iter_compare(self, iter1, iter2): + "Checks if two iters point to the same node" - - def iter_compare(self, iter1, iter2): return self.get_path(iter1) == self.get_path(iter2) def iter_traverse_next(self, iter): + "Gets the 'logically next' iter" # get the first child, if any child = self.iter_nth_child(iter, 0) @@ -448,6 +465,7 @@ def iter_traverse_prev(self, iter): + "Gets the 'logically previous' iter" # get the previous sibling, or parent, of the iter - if any if iter is not None: diff -r 1558109939775523da9cdb7fbb44960cf583cec7 -r 4787d15f40a47ecd4912e428c6d04ddd0dcb28e6 src/revelation --- a/src/revelation Thu Jul 08 11:54:12 2004 +0000 +++ b/src/revelation Thu Jul 08 21:11:32 2004 +0000 @@ -79,7 +79,7 @@ def __cb_doubleclick_tree(self, widget, iter): - if self.data.get_entry_type(iter) != revelation.entry.ENTRY_FOLDER: + if iter is not None and self.data.get_entry(iter).type != revelation.entry.ENTRY_FOLDER: self.entry_edit() @@ -169,19 +169,10 @@ def clip_paste(self): - if self.clipboard.is_empty(): + if not self.clipboard.has_contents(): return - iter = self.tree.get_active() - - if self.data.get_entry_type(iter) in [ revelation.entry.ENTRY_FOLDER, None ]: - parent = iter - sibling = None - else: - parent = self.data.iter_parent(iter) - sibling = iter - - iters = self.clipboard.paste(self.data, parent, sibling) + iters = self.clipboard.paste(self.data, self.tree.get_active()) self.undo_add_action(self.clip_paste, iters) self.tree.select(iters[0]) @@ -560,7 +551,7 @@ elif method == revelation.data.REDO: for item in data: - newiters = self.data.import_entrystore_before(item["data"], self.data.get_iter(item["parent"]), self.data.get_iter(item["path"])) + newiters = self.data.import_entrystore(item["data"], self.data.get_iter(item["parent"]), self.data.get_iter(item["path"])) iters.extend(newiters) @@ -569,7 +560,7 @@ if method == revelation.data.UNDO: for item in data: - newiters = self.data.import_entrystore_before(item["data"], self.data.get_iter(item["parent"]), self.data.get_iter(item["path"])) + newiters = self.data.import_entrystore(item["data"], self.data.get_iter(item["parent"]), self.data.get_iter(item["path"])) iters.extend(newiters) @@ -629,7 +620,8 @@ }) if action in [ self.entry_add, self.entry_remove, self.clip_cut, self.clip_paste, self.file_import ]: - item["data"] = self.data.export_entrystore([iter]) + item["data"] = revelation.data.EntryStore() + self.data.export_entry(iter, item["data"]) elif action == self.entry_edit: item["data"] = self.data.get_entry(iter)