3 # Unix SMB/CIFS implementation.
4 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """Simple GTK+ frontend for LDB."""
28 class LdbURLDialog(gtk.Dialog):
29 """Dialog that prompts for a LDB URL.
31 Ideally this should remember LDB urls and list them in a combo box.
33 def __init__(self, parent=None):
34 """Create a new LdbURLDialog.
36 :param parent: Parent window.
38 super(LdbURLDialog, self).__init__(parent=parent,
39 buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)
41 self.vbox.add(gtk.Label("Enter URL:"))
42 self.url = gtk.Entry()
43 self.vbox.add(self.url)
47 return self.url.get_text()
51 """Create a new LDB object.
53 :param url: LDB URL to connect to.
56 path = os.getenv("LDB_MODULES_PATH")
58 ret.set_modules_dir(path)
63 class LdbBrowser(gtk.Window):
64 """GTK+ based LDB browser.
66 def set_ldb(self, ldb):
67 """Change the LDB object displayed.
69 Will refresh the window.
71 :param ldb: New LDB object to use.
74 self.menu_disconnect.set_sensitive(True)
77 def _cb_connect(self, button):
78 dialog = LdbURLDialog()
79 if dialog.run() == gtk.RESPONSE_OK:
80 self.set_ldb(Ldb(dialog.get_url()))
83 def _cb_open(self, button):
84 dialog = gtk.FileChooserDialog(title="Please choose a file",
86 buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
87 if dialog.run() == gtk.RESPONSE_OK:
88 self.set_ldb(Ldb(dialog.get_filename()))
92 def _cb_disconnect(self, button):
93 self.treemodel.clear()
94 self.attributemodel.clear()
95 self.menu_disconnect.set_sensitive(False)
98 def _fill_tree(self, hide_special=False):
99 self.treemodel.clear()
102 if dn.is_special() and hide_special:
104 if paths.has_key(str(dn)):
105 return paths[str(dn)]
106 parent_dn = dn.parent()
108 if parent_dn is not None and str(parent_dn) != '':
109 parent = add_node(parent_dn)
110 text = text[:-len(str(parent_dn))].rstrip(",")
113 paths[str(dn)] = self.treemodel.append(parent, [text, dn])
115 for msg in self.ldb.search(None, ldb.SCOPE_SUBTREE, None, ["dn"]):
118 def _toggle_special_entries(self, item):
119 self._fill_tree(item.get_active())
121 def _treeview_cursor_cb(self, item):
122 (model, iter) = item.get_selection().get_selected()
123 dn = model.get_value(iter, 1)
124 self.attributemodel.clear()
125 msg = self.ldb.search(dn, ldb.SCOPE_BASE)[0]
129 self.attributemodel.append([name, val, el])
132 super(LdbBrowser, self).__init__()
133 vbox = gtk.VBox(spacing=0)
136 self.menu = gtk.MenuBar()
137 menuitem_db = gtk.MenuItem("_Database")
139 menuitem_db.set_submenu(menu_db)
140 self.menu.add(menuitem_db)
143 menu_connect = gtk.MenuItem("Connect to _URL...")
144 menu_connect.connect('activate', self._cb_connect)
145 menu_db.add(menu_connect)
147 menu_open = gtk.MenuItem("Open _File...")
148 menu_open.connect('activate', self._cb_open)
149 menu_db.add(menu_open)
151 self.menu_disconnect = gtk.MenuItem("_Disconnect")
152 self.menu_disconnect.connect('activate', self._cb_disconnect)
153 self.menu_disconnect.set_sensitive(False)
154 menu_db.add(self.menu_disconnect)
156 menu_db.add(gtk.SeparatorMenuItem())
157 menu_hide_special = gtk.CheckMenuItem("_Hide special entries")
158 menu_hide_special.connect('toggled', self._toggle_special_entries)
159 menu_db.add(menu_hide_special)
161 menu_db.add(gtk.SeparatorMenuItem())
162 menu_exit = gtk.ImageMenuItem(gtk.STOCK_QUIT)
163 menu_exit.connect('activate', lambda x: gtk.main_quit())
165 menu_db.add(menu_exit)
167 vbox.pack_start(self.menu, expand=False)
169 self.treeview = gtk.TreeView()
170 self.treemodel = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
171 self.treeview.set_model(self.treemodel)
172 self.treeview.set_headers_visible(False)
173 self.treeview.append_column(gtk.TreeViewColumn("_Dn",
174 gtk.CellRendererText(), text=0))
175 self.treeview.connect("cursor-changed", self._treeview_cursor_cb)
176 self.attributeview = gtk.TreeView()
177 self.attributemodel = gtk.ListStore(str, str, gobject.TYPE_PYOBJECT)
178 self.attributeview.set_model(self.attributemodel)
179 self.attributeview.append_column(gtk.TreeViewColumn("_Name",
180 gtk.CellRendererText(), text=0))
181 self.attributeview.append_column(gtk.TreeViewColumn("_Value",
182 gtk.CellRendererText(), text=1))
184 pane.set_position(200)
185 treeview_window = gtk.ScrolledWindow()
186 treeview_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
187 treeview_window.add(self.treeview)
188 pane.pack1(treeview_window, resize=False, shrink=True)
189 attributeview_window = gtk.ScrolledWindow()
190 attributeview_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
191 attributeview_window.add(self.attributeview)
192 pane.pack2(attributeview_window, shrink=True)
193 vbox.pack_start(pane, fill=True, expand=True)
195 self.statusbar = gtk.Statusbar()
196 vbox.pack_end(self.statusbar, expand=False)
199 self.set_default_size(700, 500)
203 browser = LdbBrowser()
204 if len(sys.argv) > 1:
205 browser.set_ldb(Ldb(sys.argv[1]))